小游戏支付
1 组装预下单数据
文档地址:q.qq.com/wiki/develop/game/server/...
code2Session:q.qq.com/wiki/develop/game/server/...
由支付文档可知必填的参数有哪些,以下是组装好的请求参数:
/**
* 组装预下单数据
*/
public function getPreOrderData ()
{
$data = [
'openid' => '这里填code2Session接口返回的openid', // 用户唯一标识符
'appid' => "这里填小程序appID", // 小程序appID
'zone_id' => "1", // 游戏服务器大区,固定值为 1
'pf' => 'qq_m_qq-2001-android-2011', // 平台,只支持安卓
'ts' => time(), // 时间戳
'amt' => intdiv(100, 10), // 扣除游戏币数量,不能为 0
'bill_no' => uniqid(), // 订单号
'goodid' => "道具的id", // 在开发者管理端上架道具的id
'good_num' => 1, // 要购买的道具数量
'app_remark' => "支付回调时会原样返回" // 附加信息
];
$data['sig'] = $this->getPreOrderSig($data, "这里填code2Session接口返回的session_key"); // 计算签名
return $data;
}
getPreOrderSig()
:对数据进行签名,具体代码见 1.1。
1.1 对预下单数据进行签名
/**
* 对数据进行签名
*
* @param $data array 需要签名的数据
* @param $session_key string 通过code2session获取到的session_key
*
* @return string
*/
public function getPreOrderSig(array $data, string $session_key)
{
ksort($data);
$uri = urlencode('/api/json/openApiPay/GamePrePay');
$params = "POST&".$uri.'&'.http_build_query($data).'&session_key='.$session_key;
return hash_hmac('sha256', $params, $session_key, false);
}
2 请求预下单接口
获取 access_token:q.qq.com/wiki/develop/game/server/...
拿步骤 1 组装好的数据 $data 去请求预下单接口,接口返回的 prepayId 值为订单号,我们需要先保存起来,因为在支付回调的时候不会再返回 prepayId,而是返回我们的订单号 bill_no。
/**
* 请求预下单接口,获取预下单订单号
*
* @param $data array 请求数组
*
* @return false|mixed
*/
public function postCurlPrePay($data)
{
// 预下单接口
$prePayUrl = 'https://api.q.qq.com/api/json/openApiPay/GamePrePay?access_token='."这里填获取到的access_token";
// 请求下单
$curl = curl_init($prePayUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-type' => 'application/json']);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
$output = curl_exec($curl);
curl_close($ch);
$output = json_decode($output, true);
return $output['errcode'] !== 0 ? false : $output;
}
3 组装米大师支付数据
public function order()
{
$data = $this->getPreOrderData(); // 步骤 1
$output = $this->postCurlPrePay($data); // 步骤 2
// 返回给前端去调起米大师支付页面
return [
'prepayId' => $output['prepayId'], // 订单号
'starCurrency' => $data['amt'], // 金额(单位为角)
'setEnv' => 1, // 运行环境(0为正式,1为开发)
];
}
4 支付回调
用户支付完成后,QQ小游戏会通过回调地址通知开发者,商户需要在接受数据、处理数据后,返回应答。
回调地址是在开发者在管理端配置的。
public function notify()
{
$notifyData = request()->post();
// 对回调数据进行验签
$signRes = $this->getNotifySig($notifyData);
if ($signRes === false || $notifyData['sig'] !== $signRes) {
return json(['code' => 500, 'msg' => '验证签名失败']);
}
// TODO:按照业务更新订单支付状态等等
return json(['code' => 0, 'msg' => 'success']); // 通知qq小游戏回调成功
}
getNotifySig()
:对数据进行签名,具体代码见 4.1。
4.1 对通知数据签进行名
如果开发者管理端配置的回调地址为:http://your.domain.com/notify/qq/midas, 那么$callback
为/notify/qq/midas
。
/**
* 对支付回调的参数进行签名计算
*
* @param $notifyData array 支付回调的请求参数
*/
public function getNotifySig($notifyData)
{
ksort($notifyData);
unset($notifyData['sig']); // 不参与签名
$secret = "用户的AppSecret";
$callback = urlencode('回调地址中的path部分');
$params = "POST&".$callback.'&'.http_build_query($notifyData).'&AppSecret='.$secret;
return hash_hmac('sha256', $params, $secret, false);
}
如果文章有帮到你的话,别忘了点赞收藏噢 :smile: