小游戏支付

未匹配的标注

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 组装米大师支付数据

文档地址:q.qq.com/wiki/develop/game/API/pay...

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:

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~