快游戏的非托管商品支付

未匹配的标注

1 组装请求参数

文档地址:developer.huawei.com/consumer/cn/d...

由支付文档可知必填的参数有哪些,以下是组装好的请求参数:

/**
 * 组装前端调起支付需要的数据
 */
public function getPayData ()
{
    // 必填,需要参与签名的字段
    $data = [
        'amount'        => '100.00',                          // 商品金额(单位元),一定要保留小数点后两位
        'applicationID' => "这里填你的appid",                  // 应用ID
        'url'           => "http://your.domain.com/notify",   // 回调通知URL
        'productDesc'   => "商品描述",                         // 商品描述
        'productName'   => "商品名称",                         // 商品名称
        'requestId'     => uniqid(),                          // 订单号
        'merchantId'    => "在华为开发者联盟上获取的支付ID",     // 商户ID
        'sdkChannel'    => 3,                                 // 渠道信息(快游戏为3)
    ];

    $data['sign'] = $this->getSign($data);                    // 签名

    // 必填,但不参与签名
    $data['serviceCatalog'] = 'X6';                           // 商品类型(游戏为 X6)
    $data['merchantName']   = "开发者注册的公司名";             // 商户名称
    $data['extReserved']    = "回调时需要的数据可以填在这里";    // 华为支付服务器回调接口中原样返回。
}
  • getSign():对数据进行签名,具体代码见 1.1。

1.1 对数据进行签名


/**
 * 使用支付私钥对数据进行签名
 *
 * @param $data array 需要签名的数据
 *
 * @return mixed
 */
public function getSign($data)
{
    ksort($data);
    $signStr = urldecode(http_build_query(array_filter($data, 'strlen')));

    $formatPK = $this->formatPrivateKey("这里填支付私钥");
    openssl_sign($signStr, $signature, $formatPK, OPENSSL_ALGO_SHA256);

    return base64_encode($signature);
}


/**
 * 格式化私钥
 * PKCS#8通用密钥格式:
 * -----BEGIN PRIVATE KEY-----
 * 64字节长度的 base64 内容
 * -----END PRIVATE KEY-----
 */
private function formatPrivateKey($privateKeyString)
{
    $formatedStr = $privateKeyString;

    //  字符串没有以标准格式头开始时,认为是非格式化的
    if (false === strpos($formatedStr, '-----BEGIN PRIVATE KEY-----')) {
        $formatedStr = "-----BEGIN PRIVATE KEY-----\n";
        $formatedStr .= wordwrap($privateKeyString, 64, "\n", true);
        $formatedStr .= "\n-----END PRIVATE KEY-----";
    }

    $key = openssl_get_privatekey($formatedStr);
    return $key;
}

2 支付回调

文档地址(不是真的废弃):developer.huawei.com/consumer/cn/d...

用户支付完成后,华为快游戏会通知商户,商户需要在接受数据、处理数据后,返回应答。
回调地址是在步骤1中的url字段填写的。

public function notify()
{
    $notifyData = request()->post();

    // 检查回调参数是否正确
    if (!isset($notifyData['result']) || $notifyData['result'] != 0 
        || !isset($notifyData['requestId']) || !isset($notifyData['sign'])) {
        return json(['result' => 98]);  // 参数错误
    }

    // 如果 signType 有传值默认是 OPENSSL_ALGO_SHA256,如果没传值默认是 OPENSSL_ALGO_SHA1
    $signType = $notifyData['signType'] ? OPENSSL_ALGO_SHA256 : OPENSSL_ALGO_SHA1;

    // 获取回调传来的签名
    $huaweiSign = base64_decode($notifyData['sign']);
    unset($notifyData['sign'], $notifyData['signType']); // 不参与验签的字段

    // 排序,拼接参数
    ksort($notifyData);
    $verifyStr = urldecode(http_build_query(array_filter($notifyData, 'strlen')));

    // 格式化支付公钥
    $formatPK  = $this->formatPublicKey('这里填支付公钥');

    // 验签
    $verifyRes = openssl_verify($verifyStr, $huaweiSign, $formatPK, $signType);
    if ($verifyRes == false) {
        return json(['result' => 1]); // 验签失败
    }

    // TODO:按照业务更新订单支付状态等等

    return json(['result' => 0]); // 通知华为回调成功
}
  • formatPublicKey():格式化公钥,具体代码见 2.1。

2.1 格式化公钥

/**
 * 格式化公钥
 * PKCS#8通用密钥格式:
 * -----BEGIN PUBLIC KEY-----
 * 64字节长度的 base64 内容
 * -----END PUBLIC KEY-----
 */
private function formatPublicKey($_str)
{
    $formatedStr = $_str;

    //  字符串没有以标准格式头开始时,认为是非格式化的
    if (false === strpos($formatedStr, '-----BEGIN PUBLIC KEY-----')) {
        $formatedStr = "-----BEGIN PUBLIC KEY-----\n";
        $formatedStr .= wordwrap($_str, 64, "\n", true);
        $formatedStr .= "\n-----END PUBLIC KEY-----";
    }
    $key = openssl_pkey_get_public($formatedStr);
    return $key;
}

如果文章有帮到你的话,别忘了点赞收藏噢 :smile:

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

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


暂无话题~