游戏内购订单验证过程和发送接口
因为SDK调用三方支付渠道的多样性,有些支付渠道是通过服务端(side-by-side)通知方式告知我们玩家充值成功,也有些支付渠道是通过客户端的(callback)回调方式告诉我们订单完成。所以,在此基础上,游戏需要针对这2种方式都要提供校验的方式,哪种方式先告知到游戏,游戏就先进行订单信息的校验和内购物品的发放;后告知的方式,需要有一个防重发的机制返回给SDK。
内购商品购买整体流程
游戏创建内购订单
以下代码作为上面流程图中的步骤1、2的参考
创建SDK内购订单示例代码
// 配置在服务端
$instanceSecret = 'a5e283b0b4267f3dc9c36203eaf88cae';
// 游戏创建SDK需要的订单参数
$params['instanceKey'] = '7160996c01ff76310ae52e28587269ee';
$params['uid'] = '3245443534';
$params['token'] = 'ae6d9fd3326f200d99cbf0721b235719';
$params['productId'] = 'iap001';
$params['roleId'] = '12000501';
$params['serverId'] = '12';
$params['amount'] = '0.99';
$params['currency'] = 'USD';
$params['gameOrderId'] = '950345231111822';
// 按参数名字母升序排序,并连接字符串,生成sign
ksort($params);
$linkString = '';
foreach ($params as $k => $v) {
$linkString .= $k.'='.$v.'&';
}
$linkString = rtrim($linkString, '&');
// 加密前字符串
// amount=0.99¤cy=USD&gameOrderId=950345231111822&instanceKey=7160996c01ff76310ae52e28587269ee&productId=iap001
// &roleId=12000501&serverId=12&token=ae6d9fd3326f200d99cbf0721b235719&uid=3245443534a5e283b0b4267f3dc9c36203eaf88cae
$gameSign = md5($linkString.$instanceSecret);
// 订单参数里的sign赋值
$params['sign'] = $gameSign;
商品发送验证方式
服务端通知方式
以下接口作为上面流程图中的步骤13(2)、14(2)的参考
请求方式
请求方式 | 请求地址 | 返回content-type | 请求方 | 接收方 |
---|---|---|---|---|
POST | {GAME_IAP_NOTIFICATION_URL} |
application/json | 发行SDK服务端 | 游戏服务端 |
请求参数
参数名 | 是否必填 | 类型 | 签名因子? | 说明 |
---|---|---|---|---|
instanceKey | 是 | String | 是 | 发行SDK平台分配的游戏实例key |
uid | 是 | String | 是 | 发行SDK平台帐号ID |
orderId | 是 | String | 是 | 发行SDK平台订单号 |
productId | 是 | String | 是 | 商品ID |
orderType | 是 | String | 是 | 订单类型 |
realPrice | 是 | String | 是 | 金额 0.99。注意:此参数如果价格低于商品的正常价格,也需要发送物品给玩家 |
realCurrency | 是 | String | 是 | 商品支付货币类型 |
sandbox | 是 | Int | 是 | 是否是沙盒测试订单。1:是、0:否 |
ts | 是 | Int | 是 | 服务器时间戳(秒),请求服务器与响应服务器时间戳相差超过1小时,则返回错误 |
gameOrderId | 是 | String | 是 | 游戏生成的订单号 |
extra | 否 | String | 否 | 游戏开发商保留字段,回调时保持原样返回 |
sign | 是 | String | 否 | 签名 参考签名规则 |
返回结果
返回结果code值请参考返回值信息。
客户端返回SDK订单信息验证方式
以下代码作为上面流程图中的步骤15、16的参考
SDK订单信息验证示例代码
// 配置在服务端
$instanceSecret = 'a5e283b0b4267f3dc9c36203eaf88cae';
// 客户端传递的SDK生成的sign参数
$sdkSign = '07db03e2a2cd8148bc0a7d581a02c2f2';
// 客户端传递的SDK参数
$params['instanceKey'] = '7160996c01ff76310ae52e28587269ee';
$params['uid'] = '3245443534';
$params['orderId'] = '800003242356';
$params['productId'] = 'zs600';
$params['orderType'] = 'apple';
$params['realPrice'] = '0.99';
$params['realCurrency'] = 'USD';
$params['sandbox'] = '1';
$params['ts'] = '1555255757';
$params['gameOrderId'] = '950345231111822';
// 先判断时间戳是否相差超过1小时
if (abs(intval($params['ts']) - time()) > 3600) {
return '订单信息超时,等待SDK补单再次调用';
}
// 按参数名字母升序排序,并连接字符串,生成sign
ksort($params);
$linkString = '';
foreach ($params as $k => $v) {
$linkString .= $k.'='.$v.'&';
}
$linkString = rtrim($linkString, '&');
// 加密前字符串
// gameOrderId=950345231111822&instanceKey=7160996c01ff76310ae52e28587269ee&orderId=800003242356&orderType=apple&productId=zs600
// &realCurrency=USD&realPrice=0.99&sandbox=1&ts=1555255757&uid=3245443534a5e283b0b4267f3dc9c36203eaf88cae
$gameSign = md5($linkString.$instanceSecret);
// 比对sign
if (strcmp($gameSign, $sdkSign) == 0) {
return "支付成功,发送内购物品给玩家";
} else {
return "签名不匹配";
}