快游戏的非托管商品支付
1 组装请求参数
由支付文档可知必填的参数有哪些,以下是组装好的请求参数:
/**
* 组装前端调起支付需要的数据
*/
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: