跳转至

游戏内购订单验证过程和发送接口

因为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&currency=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值请参考返回值信息

{
    "code": 200,
    "msg": "OK"
}
{
    "code": 400,
    "msg": "Item is not match"
}

客户端返回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 "签名不匹配";
}