Appearance
服务端接入指引
接入说明
本文档面向需要接入和使用SDK的游戏服务端开发者;
所有通信均采用
UTF-8编码;通信过程中,凡是包含
sign字段的请求都必须进行签名验证;接入前请向运营方获取
callbackKey和md5Key参数;本文档还提供了SDK服务端助手方便游戏开发者调试;
验证用户信息(必接)
1. 接口说明
游戏客户端从SDK登录回调中获取到uid后,为防止用户篡改客户端而伪造用户uid标识从而登录他人账号,游戏客户端应将此信息传入给游戏服务端。游戏服务端调用此接口向SDK服务端验证uid的真实性。若uid通过验证则允许此用户登录,若无法通过验证应拒绝此用户的登录授权。
2.接口地址
https://api.x6xy.com/webapi/checkUserInfo3.请求方式
GET/POST4.参数列表
| 参数 | 必要性 | 说明 |
|---|---|---|
| uid | 必传 | 从SDK登录回调中获取的uid |
| token | 必传 | 从SDK登录回调中获取的token,请注意token的长度不要被截断 |
5.返回字段
该接口会返回JSON格式字符串,如下所示:
未通过验证:
json
{"status":false,"message":"tokenUidError"}通过验证:
json
{"status":true,"message":""}接口返回参数说明:
| 参数 | 类型 | 必要性 | 说明 |
|---|---|---|---|
| status | bool | 必有 | 接口验证状态,若通过验证为true,否则为false |
| message | string | 必有 | status为false时,message有值,为错误提示语 |
| data | object | 必有 | status为true时才有data字段,为用户信息,对象包含(uid:用户uid)(isGuest:是否为游客账号,1是,0否)(age:用户年龄,如果用户已实名认证返回认证的年龄,未实名认证返回0) |
6.请求示例
https://api.x6xy.com/webapi/checkUserInfo?token=@171@174@188@127@182@163@148@179@166@168@132@179@165@222@169@116@109@166@96@212@152@156@116@121@106@139@170@154@203@134@124@118@108@164@205@126@173@151@172@169@169@140@158@215@138@153@164@136@160@162@154@197@114@212@159@143@126@125@154@179@168@151@135@155@121@148@215@146@181@100@158@219@161@112@106@184@108@189@121@129@120@158@141@186@129@177@169@140@105@136@128@176@205@124@124@166@163@179@213@151@175@124@185@140@155@124@171@160&uid=523充值同步(必接)
1.接口说明
当玩家完成充值后,SDK服务端会按照协议向游戏方提供的充值同步接口发送POST请求(简称发送通知)。游戏服务端在接收到请求后,需要验证相关信息并向玩家发送道具,同时应符合以下要求:
- 严格按照
签名验证算法验证签名数据的合法性; - 发货的金额应当以
通知中的金额为准发放道具; - 判断是否
重复发放道具,若已发放则不能再次发放; - 成功发放道具后返回
SUCCESS字符串,否则SDK服务端将持续重试通知; - 如需继续接收通知,返回非
SUCCESS的任意字符串;
2.接口地址
发放道具接口由游戏方提供,SDK服务端会主动向此接口发起POST请求
3.请求方式
POST4.POST参数列表
SDK服务端发送的三个参数nt_data、sign、md5Sign均为加密密文。
游戏服务端收到后将三个参数原样拼接,计算本地签名localSign = md5(nt_data+ sign+ md5Key),localSign签名与SDK服务端通知中的md5Sign对比,若不一致应返回失败。
参数nt_data使用callbackKey可进行解码,nt_data解码后为XML格式。
nt_data解码后的XML字符串如下:
xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<quick_message>
<message>
<uid>50848343</uid>
<login_name>GG366822889</login_name>
<out_order_no>13420170114150053861611313</out_order_no>
<order_no>0720170114150059110833</order_no>
<pay_time>2024-01-10 15:01:17</pay_time>
<amount>0.01</amount>
<coupon_amount>0</coupon_amount>
<status>0</status>
<extras_params>13420170114150053861611313</extras_params>
</message>
</quick_message>nt_data解码后的XML各字段含义如下:
| 参数 | 必要性 | 说明 |
|---|---|---|
| uid | 必有 | 购买道具的用户uid |
| login_name | 必有 | 购买道具的用户账号名username |
| out_order_no | 可为空 | 游戏下单时传递的游戏订单号,原样返回 |
| order_no | 必有 | SDK唯一订单号 |
| pay_time | 必有 | 用户支付时间,例如:2025-01-01 10:00:00 |
| amount | 必有 | 用户支付金额(元) |
| coupon_amount | 必有 | 当前订单由研发承担的代金券金额(元) |
| status | 必有 | 当前订单支付状态,0成功 1失败 |
| extras_params | 必有 | 客户端下单时透传参数(原样返回) |
5.接口调试
模拟SDK服务端向游戏服务端发送充值同步通知,游戏开发者可参考该返回结果进行调试。
玩家返利(选接)
1.接口说明
玩家单日(七日)累计充值达到预设返利要求,用户领取返利奖励时,SDK服务端会按照此接口协议向游戏方提供的返利接口发送POST数据(简称发送通知),游戏服务端在收到SDK服务端发送的POST数据后,应验证相关信息并向玩家发放返利奖励,同时应符合以下要求:
- 严格按照
签名验证算法验证签名数据的合法性; - 判断是否
重复发放奖励,若已发放则不能再次发放; - 成功发放奖励后返回
SUCCESS字符串,否则SDK服务端将持续重试通知; - 如需继续接收通知,返回非
SUCCESS的任意字符串;
2.接口地址
返利接口由游戏方提供,SDK服务端会主动向此接口发起POST请求
3.请求方式
POST4.POST参数列表
SDK服务端发送的三个参数nt_data、sign、md5Sign均为加密密文。
游戏服务端收到后将三个参数原样拼接,计算本地签名localSign = md5(nt_data+ sign+ md5Key),localSign签名与SDK服务端通知中的md5Sign对比,若不一致应返回失败。
参数nt_data使用callbackKey可进行解码,nt_data解码后为XML格式。
nt_data解码后的XML字符串如下:
xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<quick_message>
<message>
<uid>50848343</uid>
<role_id>50848343</role_id>
<server_id>50848343</server_id>
<reward_id>50848343</reward_id>
</message>
</quick_message>nt_data解码后的XML各字段含义如下:
| 参数 | 必要性 | 说明 |
|---|---|---|
| uid | 必有 | 购买道具的用户uid |
| role_id | 必有 | 玩家角色id |
| server_id | 必有 | 玩家角色所在的区服id |
| reward_id | 必有 | 与游戏方协商定制的返利奖励id |
5.接口调试
模拟SDK服务端向游戏服务端发送返利请求,方便游戏开发者调试返利回调。
获取玩家游戏角色列表(选接)
1.接口说明
在公众号网页充值时,平台玩家登录账号后选择游戏角色列表,玩家选择角色后向该角色充值。
2.接口地址
该接口由游戏方提供,SDK服务端会主动向此接口发起POST请求
3.请求方式
POST4.POST参数列表
| 参数 | 必要性 | 说明 |
|---|---|---|
| uid | 必有 | 用户uid |
| username | 必有 | 用户账号名username |
| productCode | 必有 | SDK ProductCode |
| sign | 必有 | 签名值,游戏应根据签名约定,本地计算后与此值进行比对。 |
5.返回字段说明
游戏方在接收到SDK请求之后,返回玩家的角色信息列表,数据格式为json,返回字段如下:
| 参数 | 必要性 | 说明 |
|---|---|---|
| code | 必有 | 200:请求成功,其余值均为失败 |
| data | 必有 | 玩家角色列表集合,每个子集包含如下字段:serverId:区服ID serverName:区服名 roleId:角色ID roleName:角色名 roleLevel:角色等级 |
提示:由于公众号网页支付的订单没有经过游戏下单,所以通知发货接口无法获取游戏的具体订单号。此时游戏给玩家发货时可获取SDK服务端通知回调的extras_params参数的信息给具体玩家角色发放道具。extras_params返回的格式为“区服ID|@|角色ID|@|商品ID”
6.签名算法
通信时
SDK服务端会在请求中附带sign字段;游戏服务端收到POST参数后,移除sign字段并且将参数按首字母升序排序;将排序后的所有键值对按
(key1=val1&key2=val2&key3=val3)格式进行拼接;将
callbackKey拼接在键值对的后边,此时格式为:(key1=val1&key2=val2&key3=val3&callbackKey);对以上处理的字符串进行
md5编码,得到32位md5值;将得到的
md5值与SDK服务端传递的sign值进行对比,一致则验证通过;
签名验证参考代码:
java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.TreeMap;
public class SignatureUtils {
// 游戏的callbackKey
private static final String CALLBACK_KEY = "your_callback_key";
public static boolean verifySignature(Map<String, String> params) {
// 移除sign字段
params.remove("sign");
// 按首字母升序排序
TreeMap<String, String> sortedParams = new TreeMap<>(params);
// 拼接参数
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
// 添加callbackKey
sb.append("callbackKey=").append(CALLBACK_KEY);
// 计算MD5
String md5 = calculateMD5(sb.toString());
// 从SDK传递的参数中获取原始签名
String originalSign = params.get("sign");
// 对比签名
return md5.equals(originalSign);
}
private static String calculateMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(input.getBytes());
byte[] digest = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}php
class SignatureUtils {
// 游戏的callbackKey
private const CALLBACK_KEY = 'your_callback_key';
public static function verifySignature($params) {
// 移除sign字段
unset($params['sign']);
// 按首字母升序排序
ksort($params);
// 拼接参数
$queryString = http_build_query($params);
// 添加callbackKey
$queryString .= '&callbackKey=' . self::CALLBACK_KEY;
// 计算MD5
$md5 = md5($queryString);
// 从SDK传递的参数中获取原始签名
$originalSign = isset($params['sign']) ? $params['sign'] : null;
// 对比签名
return $md5 === $originalSign;
}
}