1、 使用说明
联想联运SDK分为:网游SDK、单机SDK、广告SDK
本指南用于指导游戏CP接入《网游SDK》的流程和实现。
2、接入流程
2.1、接入前准备
A) 注册联想开放平台开发者帐号(访问http://open.lenovo.com)并通过开发者审核。
-务必确保资料均填写并填写正确,否则将影响第三方认证的资料填报;
B) 通过第三方证书授权中心的企业认证(流程如下)。
-管理员认证、企业信息两步信息均自动同步自您的开发者账号资料,如需修改需要通过修改开发者信息进行调整;
-若信息调整后仍无法通过信息审核,则联系对接商务同学进行处理;
C) 确定游戏联运合作后,需要签署相关游戏联运协议。
D) 在联想开放平台创建应用,获取应用Open AppID
-创建应用时,适配设备当选择Phone/Pad,应用类型当选择 游戏,支付合作选择是;
-填写应用包名及应用名称,包名在联想开放平台全局唯一,不可重复,保存后不可修改。
游戏包名必须为.lenovo后缀;保存,获取应用Open AppID
(可在获取Open AppID后先进行保存,待游戏打包完成后进行后续完善步骤)
E) 进入移动应用内计费系统完善结算信息并通过财务审核
(点击计费设置进入移动应用内计费系统)
(完善结算信息并通过审核)
F) 结算信息审核通过后,在移动应用内计费系统配置应用的支付通知地址、备案识别码、添加应用内计费商品信息
(商品编码最多支持9个字符,且首字符不能为0)
2.2、接入SDK
a) 网游SDK资源下载地址:http://open.lenovo.com/sdk/category/gamesdk/
b) 在网游SDK 接入和自测过程中,如有问题可联系联想游戏技术支持
姓名 | QQ号 | 邮箱 |
李涛 | 2938495177 | litao22@lenovo.com |
c) 完成集成SDK的游戏安装包,在联想开放平台开发者管理后台自助上传应用
(点击完善信息,上传APK游戏安装包)
d) 审核通过后,自动上架
3、联想网游SDK介绍
3.1、隐私政策
SDK本身不会弹出任何隐私协议,隐私协议游戏内自行设计实现,并且在游戏隐私协议中附加联想游戏SDK隐私协议,本游戏接入了联想游戏SDK,提供登录和支付以及实名认证防沉迷服务,所收集信息请阅读《联想游戏隐私政策》
3.2、登录流程
a) 集成联想网游 SDK,登录取得 ST(token)
b) 将获取到的 token 传递到游戏服务器
c) 通过 Lenovo ID Web API 验证 ST 的有效性,同时获取用户的唯一 ID
3.3、支付流程
支付结果通知的详细介绍请参照 5.2服务端支付通知接口说明。
具体支付流程如下:
3.4、实名认证防沉迷
CP 可以调用实名认证接口获取当前用户实名认证的年龄及网络游戏防沉迷实名认证系统返回的PI,如用户未进行实名认证,会先弹出实名认证的界面,如用户已认证则会返回年龄(age)可以通过年龄来判断用户是否成年。
3.5、资源压缩包组成
文件名 | 内容介绍 |
AS_Demo | AS项目demo |
gamesdk.aar | AS项目依赖库 |
oaid_sdk_1.0.25.aar | AS项目依赖库 |
alidns-android-sdk-2.0.5.jar | AS项目依赖库 |
EclipseDemo | eclipse项目demo |
SDK | eclipse项目依赖库 |
联想游戏联运SDK接入指南_v3.2.0.docx | SDK开发指南,该文档 |
3.6、集成资源工程
Android Stuio项目集成:
1,游戏工程目录下的gradle需要导入依赖库:
api 'com.android.support:support-v4:28.0.0'
api (name:'gamesdk', ext:'aar')
api (name:'miit_mdid_1.0.13', ext:'jar')
2,参考AS_Demo\app\src\main\AndroidManifest.xml和章节3.7配置游戏工程目录下的AndroidManifest.xml
3,参考AS_Demo\app \bulid.gradle文件,配置游戏工程目录下gradle中有关Ndk声明配置:
defaultConfig {
applicationId "com.pay.sample.lenovo"
minSdkVersion 19
targetSdkVersion 28
ndk {
abiFilters "armeabi", "arm64", "armeabi-v7a", "arm64-v8a", "x86" }
}
在android标签下配置JDK版本配置:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
在工程根目录下,如AS_Demo下bulid.gradle文件配置的编译版本为3.6.0及以上
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.0'
}
}
Eclipse项目集成:
参考3.3章节种资源目录介绍,将“SDK”目录导入到 eclipse 工程中:
1,右键SDK ->properties->Android,选择Is Library
2,右键自己的工程->properties->Android,点击 add 添加即可
3,参考Demo_Src\src\main\AndroidManifest.xml和章节3.7配置游戏工程目录下的AndroidManifest.xml
3.7、配置游戏AndroidManifest.xml文件
• 权限配置:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<!--oadi start-->
<uses-permission android:name="com.asus.msa.SupplementaryDID.ACCESS" />
<!--oadi end-->
<!-- pay start -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- pay end -->
<!—targetversion >= 30 android R以上访问需要添加-->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
• 权限介绍:
权限 | 使用场景 |
GET_ACCOUNTS | 申请用户账户权限,用于获取设备账户,用于登录时获取账户名 |
USE_CREDENTIALS | 申请账号管理权限,用于验证登录的账号信息 |
AUTHENTICATE_ACCOUNTS | 通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息,登录时能够使用系统账号安全管理 |
WRITE_EXTERNAL_STORAGE | 申请存储权限,用于程序运行配置信息的存储 |
EXPAND_STATUS_BAR | 申请状态栏扩展权限,用于实现界面全屏展示 |
ACCESS_NETWORK_STATE | 申请网络状态权限,用于检查网络是否可用 |
ACCESS_WIFI_STATE | 申请WIFI网络权限,用于检查网络是否可用 |
READ_PHONE_STATE | 申请读取设备状态权限,用于程序对不同设备的适配 |
INTERNET | 申请网络连接权限,用于程序正常访问网络 |
- Open App ID配置:
<meta-data android:name="lenovo.open.appid" android:value="在此处填入申请的lenovo open AppID " />
<meta-data android:name="lenovo.gamesdk.new" android:value="此处填写sdk版本号" />
<!-- 游戏接入时请写申请的openappid;其他应用此处填写该apk的渠道标识,用于某渠道的用户数等指标统计。渠道标识请使用字母和数字组合,不超过64个字符 -->
<meta-data android:name="lenovo:channel" android:value="在此处填入申请的lenovo open AppID " />
<meta-data android:name="lenovo:applicationToken" android:value="WQMF9HG8J5WZ" />
Apache公共库配置:添加Application子标签<uses-library>配置
<uses-library android:name="org.apache.http.legacy" android:required="false" />
• 登录配置:
<!-- 登录配置开始 -->
<activity
android:name="com.lenovo.login.ui.LgPsLoginCommonActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgFindPasswordActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgFindPasswordConfirmActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgRegistByPhoneActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgRegistByPhoneConfirmActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgStartGameErrorActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgStartLoginingGameActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.login.ui.LgWebViewActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateVisible" >
</activity>
<activity
android:name="com.lenovo.game.ui.KeyLoginActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_Title_Dialog"
android:exported="false"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity
android:name="com.lenovo.game.ui.LeGameAcShowActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:screenOrientation="portrait"
android:exported="false"
android:theme="@style/lenovo_pay_theme"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity
android:name="com.lenovo.game.ui.AdvertisementActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="standard"
android:exported="false"
android:screenOrientation="behind"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity
android:name="com.lenovo.game.ui.FlexibleActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTop"
android:screenOrientation="behind"
android:exported="false"
android:windowSoftInputMode="stateHidden"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog" >
</activity>
<activity
android:name="com.lenovo.game.ui.QuiteActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:launchMode="singleTop"
android:screenOrientation="behind"
android:exported="false"
android:theme="@style/com_lenovo_lsf_Translucent_NoTitle_Dialog" >
</activity>
<!-- 登录过程界面结束 -->
<!-- 登录配置结束 -->
• 收银台配置:
<!-- 收银台 begin -->
<activity
android:name="com.lenovo.payplussdk.api.PayH5Activity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@android:style/Theme.Translucent.NoTitleBar" >
</activity>
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:exported="false"
android:screenOrientation="behind" >
</activity>
<activity
android:name="com.alipay.sdk.app.H5AuthActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:exported="false"
android:screenOrientation="behind" >
</activity>
<activity
android:name="com.lenovo.payplus.ui.PayActionActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:theme="@style/lenovo_theme_dialog" >
</activity>
<activity
android:name="com.lenovo.payplus.ui.PayPhoneCardActivity"
android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale|layoutDirection"
android:exported="false"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="@style/lenovo_pay_theme" >
</activity>
<!-- 收银台 end -->
注意:以上配置文件也可以参考3.5章节中示例demo的AndroidManifest.xml
3.8、SDK快速接入
通常情况下,推荐开发者使用如下的快速方式集成代码。快速接入只需要调用以下 4个主要API,每个 API 的详细说明见本文3章部分。
• 第一步:调用 SDK 初始化: LenovoGameApi.doInit()
游戏应用初始启动时,调用 LenovoGameApi.doInit()接口进行游戏 sdk 的初始化。
• 第二步:调用自动登录: LenovoGameApi.doAutoLogin()
在原主入口 Activity 中调用快速登录接口 LenovoGameApi.doAutoLogin(),进行自动登录操作。游戏启动时,联想游戏欢迎页会效果持续 1s,之后会进入到游戏原初始页面。
• 第三步:调用支付: LenovoGameApi.doPay()
游戏中需要支付时,调用联想网游 SDK 的 LenovoGameApi.doPay()接口进行支付。
• 第四步:调用退出: LenovoGameApi. doQuit ()
游戏中需要调用联想的退出接口 LenovoGameApi.doQuit 实现退出操作,并且出现联想的广告位。
注意:以上API调用请参考3.5章节中示例demo
4、联想网游SDK API介绍
4.1、SDK 初始化 API (必接)
• API:LenovoGameApi.doInit(Activity activity,String appid)
• 功能:进行 gamesdk 使用前的初始化工作
• 注意:此接口必须主线程调用。如果 manifest中 Targetsdkversion>=26的话请在初始化之前 调用原生接口 requestPermissions 申请读写 sd 卡权限,否则会无法显示广告。强烈建议 Targetsdkversion>=26.
• 参数:
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
Activity | activity | Y | Activity | activity | 注意这里一定要传 Activity 实例 |
应用ID | appId | Y | String | 1703160552988.app.ln | 2.1章节获取的Open AppID |
• 代码示例:
LenovoGameApi.doInit(GameLauncherActivity.this, Config.appid);
4.2、自动登录 API (必接)
• LenovoGameApi.doAutoLogin(Activity activity, final IAuthResult callback)功能进行
gamesdk 使用前的初始化工作
• 功能:执行用户登录,获取 ST 并通过 IAuthResult 返回给应用
• 注意:此接口必须主线程调用,接口里面已经启动线程,IAuthResult 必须设置。不要在回调函数中执行 UI 操作,如果需要操作 UI,请发消息到主线程处理。
• 参数:
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
Activity | activity | Y | Activity | activity | 注意这里一定要传 Activity 实例 |
回调返回 | callback | Y | IAuthResult | 通过 onfinished() 函数来取得登录结果数据 | 返回值ret:true登录成功,false登录失败 返回值data:登录ST |
• 代码示例:
private void getTokenByQuickLogin() {
LenovoGameApi.doAutoLogin(this, new IAuthResult() {
@Override
// 登录回调,处理登录结果
public void onFinished(boolean ret, String data) {
if (ret) {
// 登录成功
} else {
// 登录失败(失败原因开启飞行模式、 网络不通等)
}
}
});
}
4.3、获取 ST API(不常用)
• API:LenovoGameApi .getStData(Activity context, IAuthResult callback)
• 功能:一般情况下,登录成功后,ST 会由回调接口返回,App 不需要单独调用此接口。如果游戏在其他时间需要使用 ST,可以调用此接口再次获取。
• 注意:此接口必须主线程调用,接口里面已经启动线程,IAuthResult 必须设置。不要在回调函数中执行 UI 操作,如果需要操作 UI,请发消息到主线程处理。
• 参数:
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
Activity | activity | Y | Activity | activity | 注意这里一定要传 Activity 实例 |
回调返回 | callback | Y | IAuthResult | 通过 onfinished() 函数来取得登录结果数据 | 返回值ret:true成功,false失败 返回值data:登录ST |
• 代码示例:
LenovoGameApi.getStData(GameLauncherActivity.this,
new LenovoGameApi.IAuthResult() {
@Override
public void onFinished(boolean ret, String data) {
if (ret) {
//登录并且获取ST成功
} else {
//获取ST失败
}
});
4.4、支付和结果校验 API (必接)
• API:LenovoGameApi.doPay(Activity activity, String appkey, GamePayRequest request, IPayResult callback)
• 功能:调起收银台支付并返回支付结果
• 参数:设置参数的时候请注意参数字段的类型
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
Activity | activity | Y | Activity | activity | 注意这里一定要传 Activity 实例 |
appkey | appkey | Y | String | 设置为”” | 设置为”” |
商品编码 | waresid | Y | String | 接入时商户自建 | 参考章节2.1 |
外部订单号 | exorderno | Y | String | 外部订单号,长度小于 50字节的字符串,本字段不能为空,且字段中不能有”&”或者”=”字符。 | 外部订单号作为区分订单的标志,同时作为在线支付成功后,应用对支付结果签名的校验字段,关系到支付安全,请务必定义 |
商品价格 | price | Y | int | 开放价格的商品必须传商品金额(单位为分)。按次计费的商品传0。 | |
商品数量 | quantity | N | int | 如果不填写默认商品数量为1 | |
附加信息 | cpprivateinfo | N | String | 商户私有信息。最大长度128。本字段不能为空。 | 可选字段,商户私有信息在做交易结果同步的时候回传给开发者 |
• IPayResult支付结果返回参数:
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
回调接口 | onPayResult | Y | 接口 | onPayResult() | IPayResult 回调接口 |
结果状态 | resultCode | Y | int | LenovoGameApi.PAY_SUCCESS | 支付成功: LenovoGameApi.PAY_SUCCESS 支付失败: LenovoGameApi.PAY_FAIL |
结果验证信息 | signValue | Y | String | 支付结果返回的订单信息 | 数据格式: exorderno(外部订单号)& resultCode(结果状态) |
结果信息 | resultInfo | Y | String | 支付结果返回的订单信息 | 数据格式: Open AppID& waresid(商品编码)& exorderno(外部订单号) |
• 示例代码:
GamePayRequest payRequest = new GamePayRequest();
// 请填写商品自己的参数
payRequest.addParam("waresid", waresid);// 即chargepoint
payRequest.addParam("exorderno", orderid);
payRequest.addParam("price", price);
payRequest.addParam("cpprivateinfo", "123456");
LenovoGameApi.doPay(GoodsListActivity.this, Config.appkey, payRequest, new IPayResult() {
public void onPayResult(int resultCode, String signValue, String resultInfo) {
if (LenovoGameApi.PAY_SUCCESS == resultCode) {
// 支付成功
String[] strResult = resultInfo.split("&");
} else {
String[] strResult = resultInfo.split("&");
// 支付失败处理
}
}
});
• 支付结果通知说明:
支付成功后,支付平台通过两种方式告知游戏支付结果
1) 客户端支付结果通知:
在判断支付的结果是LenovoGameApi.PAY_SUCCESS或LenovoGameApi.PAY_FAIL之后,调用游戏服务端来验证支付结果是否正确,只有在验证通过情况下才能算支付成功
2) 服务端支付结果通知:
用户支付成功后,我们会将支付的相关信息同步到您在移动应用内计费系统中设置的地址。
4.5、查询实名认证API
• API:LenovoGameApi.doCheckRealAuth(Activity activity, String st, OnAuthVerifyListener callback)
• 功能:CP 可以调用该接口获取当前登录用户实名认证的年龄;如用户未进行实名认证,会先弹出实名认证的界面;如用户已认证,会返回年龄(age)可以通过年龄来判断用户是否成年.
• 注意:此接口必须主线程调用,接口里面已经启动线程,IAuthResult 必须设置。不要在回调函数中执行 UI 操作,如果需要操作 UI,请发消息到主线程处理。
• 参数:
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
Activity | activity | Y | Activity | activity | 注意这里一定要传 Activity 实例 |
ST | st | Y | String | ||
回调返回 | callback | Y | OnAuthVerifyListener | onBackSuccess(boolean isAuthened, int age, String pi) onBackFailed(int code, String message) | isAuthened:true已实名;false未实名 age:年龄,未实名时为0 pi:网络游戏防沉迷实名认证系统-实名用户身份标识 code:查询失败码(无需处理) message:错误信息(无需处理) |
• 代码示例:
LenovoGameApi.doCheckRealAuth(GameLauncherActivity.this, st, new OnAuthVerifyListener() {
@Override
public void onBackSuccess(boolean isAuthened, int age, String pi) {
}
@Override
public void onBackFailed(int code, String message) {
}
});
4.6、未成年时长限制API
为了响应国家防沉迷要求,我们建议在游戏侧自行对未成年游戏时长进行限制。如果没有该功能,可以使用我们的接口进行限制。
API:LenovoGameApi.isLimitLoginTime(true),默认不开启。
参数:true开启未成年时长限制,时长到期后,弹出限制弹窗,强制引导退出游戏。
false 不开启未成年时长限制,时长到期后,不做任何处理。
默认不调用时,该接口状态为false
5、服务端API介绍
5.1、服务端验证 Lenovo ID Token(ST)
• 接口描述
接口编号 | API-63 |
访问 URL | http://passport.lenovo.com/interserver/authen/1.2/getaccountid |
通讯方式 | HTTP GET |
参数: | 参数: lpsust:LPS user account ticket,用来标志用户身份的一个 ticket,这个值请传入获取到的 ST(Token)realm:服务安全域标识,参数值为联想颁发的 open AppID。 |
描述: | 根据客户端获取的 lpsust 以及获取该 lpsust 的 realm 来获取用户信息,具体信息参见对应的接口文档。如果可以获取该用户信息,证明 lpsust 合法,并且是由该 realm 对应生成,如果不能获取该用户信息,则表明该 lpsust 不合法,或者 realm不正确。 |
• http 示例
http://passport.lenovo.com/interserver/authen/1.2/getaccountid?lpsust=ZAgAAAAAAAGE9MTAwMDM1NTA4MDMmYj0yJmM9NCZkPTExJmU9RTZGM0EzMTY5RjAwQTM2QzE4MzNERDM4QzhCQkU0Q zkxJmg9MTM3MjkxMDg2NDI3NSZpPTQzMjAwJm89MDAwMDAwMDAwMDAwMDAwJnA9aW1laSZxPTExMTExMSZ1c2VybmFtZT0xMzgxMDUzNTg4N6z979s5fL06DibrT5d7D6s=&realm=1410232134 070.app.ln
• 用户信息 Schema
下是使用XSD(xml schema definition )描述的接口返回用户信息的xml结构。实际返回的XML信息见后面的示例。
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
attributeFormDefault="unqualified"
elementFormDefault="qualified" >
<xs:element
name="IdentityInfo"
nillable="false" >
<xs:annotation>
<xs:documentation>
用户信息
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element
name="AccountID"
type="xs:long" >
<xs:annotation>
<xs:documentation>
对于用户帐号,该字段为用户ID。对于PID帐号,该字段为PID值。
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element
name="Username"
minOccurs="0"
type="xs:string" >
<xs:annotation>
<xs:documentation>
用户名(可选项)
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element
name="DeviceID"
minOccurs="0"
type="xs:string" >
<xs:annotation>
<xs:documentation>
登录所用设备ID(可选项)
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element
name="verified"
minOccurs="0" >
<xs:annotation>
<xs:documentation>
帐户是否已激活。0:未激活,1:已激活。
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element
name="Thirdname"
minOccurs="0"
type="xs:string" >
<xs:annotation>
<xs:documentation>
3rd party IDP’s name. see section “Common Data Format”
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
• 实际返回的用户信息 XML 示例:
<IdentityInfo>
<AccountID>
10003550803
</AccountID>
<Username>
13810535887
</Username>
<DeviceID>
123
</DeviceID>
<verified>
1
</verified>
<Identit>
</Identit>
</IdentityInfo>
• 错误信息 Schema
下是使用 XSD(xml schema definition )描述的接口返回错误信息的 xml 格式结构。实际返回的 XML 信息见后面的示例。
<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema” elementFormDefault=”qualified” attributeFormDefault=”unqualified”>
<xs:element name=”Error”>
<xs:annotation>
<xs:documentation>错误信息</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name=”Code” type=”xs:string”> <xs:annotation>
<xs:documentation>错误码</xs:documentation> </xs:annotation>
</xs:element>
<xs:element name=”Timestamp” type=”xs:dateTime”/> <xs:element name=”Message” minOccurs=”0”>
<xs:annotation>
<xs:documentation>错误信息</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base=”xs:string”>
<xs:maxLength value=”512”/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name=”Detail” nillable=”true” minOccurs=”0”> <xs:annotation>
<xs:documentation>错误详细信息</xs:documentation> </xs:annotation>
<xs:simpleType>
<xs:restriction base=”xs:string”>
<xs:maxLength value=”1024”/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name=”Source” minOccurs=”0”> <xs:annotation>
<xs:documentation>错误源</xs:documentation> </xs:annotation>
<xs:simpleType>
<xs:restriction base=”xs:string”>
<xs:maxLength value=”256”/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name=”URL” type=”xs:anyURI” minOccurs=”0”> <xs:annotation>
<xs:documentation>错误描述相关URL</xs:documentation> </xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
• 返回错误信息XML示例:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>
USS-0121
</Code>
<Timestamp>
2014-07-01T17:51:49+08:00
</Timestamp>
</Error>
• 错误码
错误码(Code) | 描述 |
USS-0100 | 无效的用户名,需要检查用户名格式是否正确。 |
USS-0101 | 口令错误。 |
USS-0103 | 无此用户,请检查用户名是否正确 |
USS-0104 | 用户名已存在,不允许重复注册 |
USS-0105 | 帐号必须激活后才能登录 |
USS-0108 | 该用户已激活,请勿重复操作。 |
USS-0110 | 无效的 IMEI,SN 或 MAC |
USS-0111 | 帐号已被 disable |
USS-0113 | 口令类型错误 |
USS-0121 | 无效的 realm |
USS-0122 | 此服务不支持该 realm |
USS-0126 | Ticket 值解析失败。 |
USS-0135 | 无效的请求数据 |
USS-0151 | 账号已锁定 |
USS-0160 | 需要使用验证码(在申请帐号时,如果服务端检测到异常行为,会返回该错误给客户端, |
USS-0170 | 密码格式错误。(密码的限制规则是: 4~20 位字符,包括英文大小写字母、英文数字、减号和下划线) |
USS-0181 | 校验码错误或失效,针对手机账号对账号校验时可能产生 |
USS-0190 | (针对短信注册,服务端不支持该运营商的号码。) 尚未开通,请尝试其他方式注册。 |
USS-0540 | 无效的 lpsust |
USS-0542 | 未提供 lpsust 信息 |
USS-0202 | 用户登录已失效 |
USS-0x0000 | 后台快捷登录使用次数达到 10 次 |
USS-0x0001 | 后台快捷登录失败 |
USS-0x0002 | 后台快捷登录检测到未安装联想通行证 |
5.2、服务端支付通知接口
接口用于交易完成之后,联想支付平台主动向商户服务端发起交易结果同步,结果将通知到您在联想商户服务后台设置的“交易结果通知”URL 地址。
• 接口参数
口均采用 http 协议,POST 方法。POST 参数为 transdata、sign。transdata 为本次支付的具体业务参数,数据格式为 json 格式; sign 为 transdata 的签名数据。具体呈现方式为transdata=xxxx&sign=yyyy,其中 yyyy 就是对 xxxx 的签名数据。
• 应答与签名
户收到平台数据后,需要使用自服务平台提供的支付秘钥 appkey 来验证签名。如果验证签名失败,返回字符串 FAILURE,通过则给支付平台返回字符串 SUCCESS 应答。
• 交易结果通知的重发
台在没有收到商户应答的情况下,会定时重发。但是重发一定次数后,将不再进行重发。
• 验签方式
方法用于支付结果通知的验证签名。收到平台的通知后,解析出 transdata 和 sign 后,请使用 validSign 方法验证签名是否通过。如果不通过,请勿进行其它操作,避免损失。验证签名的方法见服务端接入示例代码。方法依赖的 jar 包 lenovo_pay_sign-1.0.0.jar 包含在联想网游 SDK 发布包中。
验证签名的方法函数原型:
/**
* 密钥验签
* @param transdata 待加密数据
* @param sign 同步签名
* @param appkey CP支付密钥
* @return
*/
public static Boolean validSign(String transdata,String sign,String appkey)
调用方法:
CpTransSyncSignValid.validSign(transdata,sign, appkey);
• 同步数据示例
步数据具体呈现方式(http 包体数据):
transdata={"exorderno":"1","transid":"2","appid":"3","waresid":31,"feetype":4,"money":5,"c ount":6,"result":0,"transtype":0,"transtime":"2012-12-1212:11:10","cpprivate":"7","paytype": 1}&sign=d91cbc584316b9d99919921a9
• 同步数据参数详情:
参数名称 | 参数含义 | 数据类型 | 参数长度 | 参数说明 |
exorderno | 外部订单号 | String | Max(50) | 商户生成的订单号 |
transid | 交易流水号 | String | Max(32) | 计费支付平台的交易 流水号 |
appid | 游戏 id | String | Max(20) | Open AppID |
waresid | 商品编码 | integer | Max(8) | 商品编号 |
feetype | 计费方式 | integer | Max(3) | 计费方式:0、按次;1、开放价格 |
money | 交易金额 | integer | Max(10) | 本次交易的金额,单位:分 |
count | 购买数量 | integer | Max(10) | 本次购买的商品数量 |
result | 交易结果 | integer | Max(2) | 交易结果:0–交易成功;1–交易失败 |
transtype | 交易类型 | integer | Max(2) | 交易类型:0 –交易;1-冲正 |
transtime | 交易时间 | String | Max(20) | 交易时间格式: yyyy-mm-dd hh24:mi:ss |
cpprivate | 商户私有信息 | String | Max(128) | 商户私有信息 |
paytype | 支付方式 | Integer | Max(2) | 支付方式:5-联想V币 |
6、接入注意事项
序号 | 接入关键点 | 备注 |
1 | 配置和使用正确的 key 值 | 要在配置中正确使用 open AppID 信息,在代码中正确使用支付的 open |
2 | 调用初始化接口 | 调用 SDK 初始化接口,初始化 SDK 运行环境 |
3 | 调用自动登录接口 | 代码中调用快速登录接口完成用户登录,获得 token。 |
4 | 服务器验证 Token | 把获取的登录 token 上传到自己的服务器,然后通过后台服务器之间的接口获取用户的 UID 来唯一的标识当前用户。 |
5 | 支付 | 用户点击购买时调用支付接口完成支付。 |
6 | 其他检查 | 导出的 apk 请检查相关资源是否已打包进来(so 文件、res 目录等等) |
7 | AndroidStudio 接入 SDK | 修改 Android studio 编译 SDK 会报出 Duplicate resources 错误,重复定义 style 文件。解决办法:去掉 sdk_res/res/values/com.lenovo.lsf.styles.xml 里的AppBaseTheme 和 AppTheme |
8 | Android9 .0 适配 | 需要 AndroidManifest 文件中 application 配置 android:networkSecurityConfig="@xml/network_security_config"此配置解决 android P 上无法访问网络。 |
9 | 手机在登陆账户界面,锁屏再解锁,登陆窗消失 | 修改 AndroidManifest 文件中PsLoginCommonActivity的configChanges 配置: android:configChanges=“keyboardHidden| orientation| screenSize| navigation|locale|layoutDirection"” |
7、SDK 版本更新日志
SDK 变更内容 | |
收银台界面升级 | 新增VIP权益和活动福利相关提醒 |
支付成功界面添加 | 支付成功新增提示弹窗 |
悬浮球icon修改 | 更换透明icon |
悬浮球新增拖拽删除 | 拖动到底部删除悬浮球 |
解决support-v4兼容问题 | 删除support-v4相关引用 |
自动登录接口新增备案识别码错误提示 | “备案识别码不存在” |
手机游戏联运SDK下载
概述:
面向游戏开发者,供开发者集成到游戏应用中。整合了联想通行证(Lenovo ID)帐户统一认证、游戏应用内计费和支付等多平台支撑能力,接入简单快捷,游戏应用只需集成本SDK即可。
客户端SDK下载:
类别 | 名称 | 开发者 | 版本号 | 主要功能 | 版本描述 | 更新时间 | 个人信息处理规则 | 合规使用说明 | 下载地址 |
---|---|---|---|---|---|---|---|---|---|
Android游戏 | 网游联运SDK V3.2.3 | 北京神奇工场科技有限公司 | V3.2.3 | 登录、实名认证、支付 | 此版本更新内容: 1、修改了隐私文档中关于IMEI获取及个性化推送的说明,补充了使用第三方SDK的说明; 2、删除SDK读取序列号的系统方法,取消了不必要的调用;请下载解压后使用(包括Demo演示和开发文档 | 2023/10/17 | 见 隐私政策-联想游戏 (lenovomm.com) | 见 隐私政策-联想游戏 (lenovomm.com) | 网游联运SDK V3.2.3 |
原文地址:https://open.lenovomm.com/developer/doc?id=1559820567843188738
联想开放平台地址:联想开放平台
联想开发者专属QQ客服(工作日9:30-18:00):联想开发平台首页右侧悬浮的在线客服聊天入口可直接会话,无需添加好友。也可搜索官方客服QQ号2881414004。
联想应用商店微信公众号: