游戏接入指南
接入前准备
开始接入前,请先向对接运营确认以下信息:
- SDK 包和 Demo 工程
- 渠道 ID、应用 ID、应用 Key
- OnlySDK 服务端请求域名
- 游戏服务端登录校验和支付回调地址
SDK下载
下载地址:http://wiki.begindcc.com/download/onlysdk/android/
引入jar包
将 onlysdk-core-*.jar 和 android-support-multidex.jar 放到游戏接入工程的 libs 目录下。
修改only_developer_config.properties里面相关参数
从 Demo 工程复制配置文件到游戏接入工程的 assets 目录下,然后按实际渠道信息修改。
具体位置:app/src/main
├── assets
│ ├── only_developer_config.properties
│ └── only_plugin_config.xml
需要在 only_developer_config.properties 中,根据实际接入信息修改以下参数:
ONLY_CHANNEL:渠道 IDONLY_APPID:游戏在该渠道的应用 IDONLY_APPKEY:游戏在该渠道的应用密钥ONLY_SERVER_URL:请求域名地址(例如https://xxx.xxx.com)
以上参数请向对接运营确认后再填写。
配置Application
如果游戏没有自己的 Application,需要将 AndroidManifest.xml 中的 application 指定为 com.only.sdk.OnlyApplication。

如果游戏有自己的 Application,请参阅:自定义 Application。
必须调用的接口
所有接口调用都通过 com.only.sdk.platform.OnlyPlatform 单例类完成。
1、初始化(必接)
该方法必须在游戏启动Activity的onCreate方法中调用
OnlyPlatform.getInstance().init(this, new OnlyInitListener() {
@Override
public void onSwitchAccount(OToken data) {
//游戏收到该回调,需要引导用户重新登录,重新加载该新用户对应的角色数据
//参考 onLoginResult 回调,使用OToken参数进行登录验证
}
@Override
public void onPayResult(int code, String msg) {
Log.d("OnlySDK", "pay result. code:" + code + ";msg:" + msg);
switch (code) {
case OnlyCode.CODE_PAY_SUCCESS:
//"支付成功"
break;
case OnlyCode.CODE_PAY_FAIL:
//"支付失败"
break;
case OnlyCode.CODE_PAY_CANCEL:
//"支付取消"
break;
case OnlyCode.CODE_PAY_UNKNOWN:
//"未知错误"
break;
}
}
@Override
public void onLogout() {
//用户已经登出了
//收到该回调需要返回游戏登录界面,并调用login接口,打开SDK登录界面
}
//游戏的服务端需要将以下相关参数发送到OnlySDK服务端进行登录校验
//OToken中的参数如下:
//userID:OnlyServer生成的唯一用户ID,游戏服务器需要将游戏账户ID和该userID进行绑定。
//sdkUserID:渠道SDK平台用户唯一ID,一般不需要使用
//username:OnlyServer生成的用户名,比如234234234.uc,4353453453.baidu,65756756756.360
//sdkUserName:渠道SDK平台用户名,可能为空,部分渠道SDK没有返回用户名
//token:OnlyServer生成的会话ID,游戏服务器拿该字段去OnlyServer做二次登录验证
//extension:OnlyServer返回的扩展字段,部分渠道SDK需要,游戏中无需使用该字段的值
//timestamp:OnlyServer生成的时间戳,游戏服务器去OnlyServer做二次登录验证时,传给OnlyServer
@Override
public void onLoginResult(int code, OToken data) {
switch (code) {
case OnlyCode.CODE_LOGIN_SUCCESS:
//进入游戏
//从OToken中获取用户信息
break;
case OnlyCode.CODE_LOGIN_FAIL:
Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_LONG).show();
break;
}
}
@Override
public void onInitResult(int code, String msg) {
Log.d("OnlySDK", "init result.code:" + code + ";msg:" + msg);
if (code == OnlyCode.CODE_INIT_SUCCESS) {
log("初始化成功" + code + " ...." + msg);
} else {
log("初始化失败..." + code);
}
}
@Override
public void onResult(int code, String msg) {
if (code == OnlyCode.CODE_REAL_NAME_REG_SUC){
//实名认证成功
//该状态对应的msg内容:{"age": 18,"msg": "实名认证成功"}
} else if (code == OnlyCode.CODE_REAL_NAME_REG_FAILED) {
//实名认证失败
}
}
});
2、登录接口(必接)
打开SDK登录界面,登录成功或者失败,会触发上面初始化监听器中的onLoginResult回调函数
OnlyPlatform.getInstance().login(this);
3、登出接口(选接)
游戏方驱动SDK进行登出
OnlyPlatform.getInstance().logout();
4、提交扩展数据(必接)
部分渠道要求在选择服务器,创建角色,登录游戏,角色升级,登出游戏等时刻,必须要上报游戏中玩家数据,以便渠道后台统计用户数据。所以,游戏层需要在特定的地方多次调用该方法。
private void stat(final int dataType){
StatData data = new StatData();
data.setDataType(dataType);
data.setMoneyNum(100);
data.setRoleCreateTime(System.currentTimeMillis()/1000);
data.setRoleID("role_100");
data.setRoleName("test_112");
data.setRoleLevel("10");
data.setRoleLevelUpTime(System.currentTimeMillis()/1000);
data.setServerID(10);
data.setServerName("server_10");
data.setTotalRechargeAmount("648.00");
OnlyPlatform.getInstance().stat(data);
}
该方法将调用的时机分为几种类型:
1:创建角色 2:进入游戏 3:等级提升 4:登出游戏 6:充值到账
所以在上面 5 个地方,都需要调用:
OnlyPlatform.getInstance().stat(StatData statData);
其中,StatData就是游戏内玩家的数据, 比如在创建角色时,statData中的dataType为1;(StatData.TYPE_CREATE_ROLE) 进入游戏时,dataType为2;(StatData.TYPE_ENTER_GAME) 等级提升时,dataType为3;(StatData.TYPE_LEVEL_UP) 登出游戏时,dataType为4;(StatData.TYPE_EXIT_GAME) 充值到账时,dataType为6;(StatData.TYPE_PAY_SUCCESSFUL)
关于StatData 数据结构:
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| dataType | int | 调用时机 |
| serverID | String | 玩家所在服务器的ID |
| serverName | String | 玩家所在服务器的名称 |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
| roleLevel | String | 玩家角色等级 |
| moneyNum | String | 当前角色身上拥有的游戏币数量 |
| roleCreateTime | long | 角色创建时间,从1970年到现在的时间,单位秒,必须传入真实的数据,否则UC审核不过 |
| roleLevelUpTime | long | 角色等级变化时间,从1970年到现在的时间,单位秒 |
| vip | String | 玩家VIP等级 |
| totalRechargeAmount | String | 角色充值总金额(单位:元) |
5、退出游戏(必接)
游戏方驱使SDK来关闭游戏. 通常的调用场景:玩家按下返回键时、玩家点击游戏内的“退出游戏”按钮.
OnlyPlatform.getInstance().exitSDK(new OnlyExitListener() {
@Override
public void onGameExit() {
//请在这个回调中,实现你自己的弹窗,询问玩家是否退出游戏(当渠道没有自己的退出弹框时,会使用该弹框)
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("退出确认");
builder.setMessage("在 onGameExit 回调中,你需要实现你自己的弹窗,询问玩家是否退出游戏");
builder.setCancelable(true);
builder.setPositiveButton("继续游玩", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//这里什么都不用做
}
});
builder.setNeutralButton("关闭游戏", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//退出游戏
MainActivity.this.finish();
System.exit(0);
}
});
builder.show();
}
});
6、支付充值(必接)
调用充值接口,打开SDK充值界面。 充值成功或者失败,会触发上面初始化监听器中的onPayResult接口
PayParams params = new PayParams();
params.setOrderID("接入方订单id");
params.setCoinNum(100); //当前玩家身上拥有的游戏币数量
params.setExtension(System.currentTimeMillis()+""); //游戏自定义数据,充值成功,回调游戏服的时候,会原封不动返回
params.setPrice(100); //单位 整数 分
params.setRatio(10); //兑换比率(比如1元等于10元宝填10,1元等于1元宝填1)
params.setProductId("1"); //产品ID
params.setProductName("元宝"); //产品名称
params.setProductDesc("购买100元宝"); //产品描述
params.setRoleId("1"); //角色ID
params.setRoleLevel(1); //角色等级
params.setRoleName("测试角色名"); //角色名称
params.setServerId("10"); //服务器ID
params.setServerName("测试"); //服务器名称
params.setVip("vip1"); //角色VIP等级
params.setPayType(0); //支付类型 默认为0:消耗性商品 1:订阅支付
params.setPayNotifyUrl("https://game.example.com/pay/callback"); //支付成功,OnlyServer异步通知该地址,告诉游戏服务器发货
OnlyPlatform.getInstance().pay(this, params);
关于PayParams对象:
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| productId | String | 充值商品ID,游戏内的商品ID |
| productName | String | 商品名称,比如100元宝,500钻石... |
| productDesc | String | 商品描述,比如 充值100元宝,赠送20元宝 |
| currency | String | 货币类型,比如CNY,ISO4217 |
| price | int | 充值金额(单位:分) |
| ratio | int | 兑换比率(比如1元等于10元宝填10,1元等于1元宝填1) |
| coinNum | int | 玩家当前身上剩余的游戏币 |
| serverID | String | 玩家所在服务器的ID |
| serverName | String | 玩家所在服务器的名称 |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
| roleLevel | String | 玩家角色等级 |
| vip | String | 玩家vip等级 |
| payType | int | 支付类型 默认为0:消耗性商品 1:订阅支付 |
| payNotifyUrl | String | 游戏服务器支付回调地址,渠道SDK支付成功,异步通知OnlyServer,OnlyServer根据该地址,通知游戏服务器发货 |
| extension | String | 支付成功之后,OnlyServer原样返回给游戏服务器 |
生命周期函数(必接)
在游戏启动Activity的如下生命周期函数中,调用对应的方法。
@Override
protected void onStart() {
OnlySDK.getInstance().onStart();
super.onStart();
}
@Override
protected void onResume() {
OnlySDK.getInstance().onResume();
super.onResume();
}
@Override
protected void onPause() {
OnlySDK.getInstance().onPause();
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
OnlySDK.getInstance().onStop();
}
@Override
protected void onDestroy() {
OnlySDK.getInstance().onDestroy();
super.onDestroy();
}
@Override
protected void onRestart() {
OnlySDK.getInstance().onRestart();
super.onRestart();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
OnlySDK.getInstance().onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onNewIntent(Intent intent) {
OnlySDK.getInstance().onNewIntent(intent);
super.onNewIntent(intent);
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
OnlySDK.getInstance().onConfigurationChanged(newConfig);
super.onConfigurationChanged(newConfig);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
OnlySDK.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
OnlySDK.getInstance().onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
OnlySDK.getInstance().onRestoreInstanceState(savedInstanceState);
super.onRestoreInstanceState(savedInstanceState);
}
打开客服聊天(选接)
调用客服聊天功能,需要传入角色以下信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| serverID | String | 玩家所在服务器的ID |
| serverName | String | 玩家所在服务器的名称 |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
| roleLevel | String | 玩家角色等级 |
| totalRechargeAmount | String | 角色充值总金额(单位:元) |
调用方法
UserExtraData userExtraData = new UserExtraData();
userExtraData.setServerID("1");
userExtraData.setServerName("测试1服");
userExtraData.setRoleID("123456");
userExtraData.setRoleName("测试");
userExtraData.setRoleLevel("5");
userExtraData.setTotalRechargeAmount("648.00");
OnlyPlatform.getInstance().openCustomerService(userExtraData);
打开问卷调查(选接)
调用问卷调查功能,需要以下信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| formKey | String | 问卷表单Key(由运营提供) |
| extra | String | 扩展参数 |
| userExtraData | UserExtraData | 玩家角色信息 |
UserExtraData 角色信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| serverID | String | 玩家所在服务器的ID |
| serverName | String | 玩家所在服务器的名称 |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
| roleLevel | String | 玩家角色等级 |
调用方法
UserExtraData userExtraData = new UserExtraData();
userExtraData.setServerID("1");
userExtraData.setServerName("测试1服");
userExtraData.setRoleID("123456");
userExtraData.setRoleName("测试");
userExtraData.setRoleLevel("5");
OnlyPlatform.getInstance().openSurvey("问卷表单Key","", userExtraData);
推送通知开关(选接)
通知服务端,用户是否开启推送服务,需要以下信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| consent | String | true 允许推送 false 不允许推送 |
| userExtraData | UserExtraData | 玩家角色信息 |
UserExtraData 角色信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| serverID | String | 玩家所在服务器的ID |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
调用方法
UserExtraData testdata = new UserExtraData();
testdata.setServerID("1234");
testdata.setRoleID("567");
testdata.setRoleName("小明");
OnlyPlatform.getInstance().canPush(true, testdata, new OnlyPushConsentListener() {
@Override
public void onConsentReported(ConsentResult response) {
android.util.Log.e("onlysdk","test push相关="+response);
if (response.code == 1) {
// 成功
android.util.Log.e("onlysdk","成功");
} else {
// 失败,result.msg 有详细信息
}
}
});
获取用户可填写问卷列表(选接)
在游戏中,用户可能需要填写问卷以提供反馈或参与调查。此接口用于获取当前用户可填写的问卷列表,需要以下信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| extra | String | 扩展参数 |
| userExtraData | UserExtraData | 玩家角色信息 |
UserExtraData 角色信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| serverID | String | 玩家所在服务器的ID |
| serverName | String | 玩家所在服务器的名称 |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
| roleLevel | String | 玩家角色等级 |
响应格式为JSON,参数如下
| 参数 | 类型 | 描述 |
|---|---|---|
| code | int | 状态码 |
| msg | String | 提示信息 |
| data | List | 问卷表单列表 |
data数据结构
| 参数 | 类型 | 描述 |
|---|---|---|
| appId | int | 游戏id |
| formKey | String | 问卷唯一标识(主要通过该参数控制显示) |
| formUrl | String | 问卷表单链接 |
| formName | String | 问卷表单名称 |
| formDesc | String | 问卷表单描述 |
| expireTime | long | 问卷链接过期时间Unix时间戳秒 |
| order | int | 问卷表单排序 |
调用方法
UserExtraData userExtraData = new UserExtraData();
userExtraData.setServerID("1");
userExtraData.setServerName("测试1服");
userExtraData.setRoleID("2199157473354");
userExtraData.setRoleName("夏侯尔曼");
userExtraData.setRoleLevel("5");
OnlyPlatform.getInstance().getSurveyForms("", userExtraData, new OnlySurveyListener() {
@Override
public void onSurveyForms(String json) {
Log.e("OnlySdk", "json: " + json);
}
});
获取企业微信-福利站信息(选接)
在游戏中,用户可能需要展示福利站信息。此接口用于获取平台配置的福利站信息,需要以下信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| extra | String | 扩展参数 |
| userExtraData | UserExtraData | 玩家角色信息 |
UserExtraData 角色信息
| 参数名称 | 参数类型 | 参数说明 |
|---|---|---|
| serverID | String | 玩家所在服务器的ID |
| serverName | String | 玩家所在服务器的名称 |
| roleID | String | 玩家角色ID |
| roleName | String | 玩家角色名称 |
| roleLevel | String | 玩家角色等级 |
响应格式为JSON,参数如下
| 参数 | 类型 | 描述 |
|---|---|---|
| code | int | 状态码 |
| msg | String | 提示信息 |
| data | json | 福利站信息 |
- 返回的json数据
data数据结构
| 参数 | 类型 | 描述 |
|---|---|---|
| mpUrl | String | 小程序跳转连接 |
| qwPicUrl | String | 添加企微图片 |
| templatePic | String | 模板图片 |
调用方法
UserExtraData userExtraData = new UserExtraData();
userExtraData.setServerID("1");
userExtraData.setServerName("测试1服");
userExtraData.setRoleID("2199157473354");
userExtraData.setRoleName("夏侯尔曼");
userExtraData.setRoleLevel("5");
OnlyPlatform.getInstance().getWelfareInfo("", userExtraData, new OnlyRequestListener() {
@Override
public void onResponse(String result) {
Log.e("OnlySdk", "response: " + result);
}
});
代金券上报数据(选接)
用于上报代金券支付数据,主要用于数据分析统计。
调用时机:需要上报代金券支付数据时
请求参数:
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| productName | String | 是 | 商品名称 |
| productId | String | 是 | 商品ID |
| price | int | 是 | 价格(单位:分) |
| orderID | String | 是 | 订单ID |
| isPayed | boolean | 是 | 是否已支付 |
调用示例:
OnlyPlatform.getInstance().trackVoucher(
"100元宝", // 商品名称
"com.game.coin100", // 商品ID
600, // 价格:6元(600分)
"order_123456", // 订单ID
true // 是否已支付
);
自定义事件上报(选接)
用于上报自定义事件数据,支持灵活的事件属性配置。
调用时机:需要上报自定义事件时
请求参数:
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| eventName | String | 是 | 事件名称 |
| properties | JSONObject | 是 | 事件属性对象 |
调用示例:
try {
JSONObject properties = new JSONObject();
properties.put("level", "10");
properties.put("server_id", "1001");
properties.put("item_type", "weapon");
properties.put("item_name", "传说之剑");
OnlyPlatform.getInstance().setTrackEvent("item_obtain", properties);
} catch (JSONException e) {
e.printStackTrace();
}
具体上报事件需要跟运营沟通
激励视频广告(选接)
- 调用时机:需要播放激励视频广告时
- 请求参数:
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| userId | String | 是 | 用户ID |
| posId | String | 是 | 广告ID |
| cpOrderId | String | 是 | 广告发货订单号 |
| rewardName | String | 是 | 商品名称 |
| rewardAmount | String | 是 | 商品数量 |
| serverId | String | 是 | 区服id |
| serverName | String | 是 | 区服信息 |
| roleId | String | 是 | 角色ID |
| roleName | String | 是 | 角色名称 |
| roleLevel | String | 是 | 角色等级 |
| extension | String | 是 | 扩展信息 没有传“无” |
| notifyUrl | String | 是 | 游戏发货地址 |
调用方法
AdvertiseEntity advertiseEntity = new AdvertiseEntity();
advertiseEntity.setUserId("userId123");
advertiseEntity.setPosId("1");
advertiseEntity.setCpOrderId("111111");
advertiseEntity.setRewardName("仙缘");
advertiseEntity.setRewardAmount("60");
advertiseEntity.setServerId("10");
advertiseEntity.setServerName("黄鹤");
advertiseEntity.setRoleId("roleId111");
advertiseEntity.setRoleName("role123");
advertiseEntity.setRoleLevel("1");
advertiseEntity.setExtension("extension");
advertiseEntity.setNotifyUrl("https://game.example.com/ad/callback");
OnlyPlatform.getInstance().showVideoAd(advertiseEntity);
扫码授权PC登录(选接)
拉起摄像头,扫描PC端的登录二维码,授权PC登录
OnlyPlatform.getInstance().authByScanQrCode(new IComputer.Listener() {
@Override
public void callback(boolean isSuccessful, String msg) {
if (isSuccessful){
// 扫码授权成功
}else {
// 扫码授权失败
}
}
});
获取用户商品订阅状态(选接)
获取用户维度的商品订阅状态,主要用于华为等渠道订阅支付状态查询,需要以下信息
| 参数 | 类型 | 描述 |
|---|---|---|
| productId | String | 渠道订阅商品ID(如华为后台配置的商品ID,由我方运营提供) |
OnlyPlatform.getInstance().getSubscriptionState("com.blrpj.hnhy.huawei.dy30", new OnlySubscriptionListener(){
@Override
public void onSuccess(int state) {
// state=0,标识该订阅型商品为已购状态
}
});
- 返回值
| 参数 | 类型 | 描述 |
|---|---|---|
| state | int | 订单交易状态。 -1:初始化 0:已购买 1:已取消 2:已退款 3:待处理 |
注意:
(选接)游戏重启,如游戏热更完成后需要重启,该方法会保存之前登录状态,用于静默登录
OnlyPlatform.getInstance().hotReboot();
其它:
打开商店评分
OnlyPlatform.getInstance().openStoreReview();
打开首页
OnlyPlatform.getInstance().startHome(MainActivity.this);
打开分享,系统分享
OnlyPlatform.getInstance().showShare(MainActivity.this);
获取商品本地化价格
OnlyPlatform.getInstance().getPrice(MainActivity.this, hashMap -> {
for (String key: hashMap.keySet()) {
Log.i(TAG, "查询到商品ID:" + key + "的本地价格为" + hashMap.get(key));
}
});
切换SDK语言,每次启动调用一次
OnlyPlatform.getInstance().switchLanguage(this, "zh-TW")
打开应用内评分功能
OnlyPlatform.getInstance().showInAppReview(this);
打开Facebook首页
OnlyPlatform.getInstance().showFacebookHome(this);
打开个人中心
OnlyPlatform.getInstance().openCenter();
打开用户协议
OnlyPlatform.getInstance().userAgreement();
打开隐私政策
OnlyPlatform.getInstance().privacyPolicy();
打开官方微信公众号二维码/跳转企微
OnlyPlatform.getInstance().officialAccount();