外包内用-查询收款二维码信息(CROSS_BORDER_PAY.GET_MCH_INFO)回调(JSON)
境外钱包用户扫码时,微信支付回调从业机构,查询收款二维码对应信息,用于支付页展示。
注意:
- 服务商接收到回调通知报文后,需在3秒内完成对报文的验签,并应答回调通知
- 响应数据需要从业机构进行签名,微信侧验签失败将会打断后续流程
| 请求参数 | 类型 | 描述 |
|---|---|---|
| headers | object | 通知的头参数 |
| Content-Type | string | application/json |
| Request-ID | string | 通知的唯一标识 |
| Wechatpay-Nonce | string | 数据签名使用的随机串 |
| Wechatpay-Serial | string | 微信支付公钥ID/平台证书序列号 |
| Wechatpay-Signature | string | 签名串 |
| Wechatpay-Signature-Type | string | 签名算法WECHATPAY2-SHA256-RSA2048 枚举值 |
| Wechatpay-Timestamp | string | 时间戳 |
| body | object | 通知的JSON数据结构 |
| id | string | 通知的唯一ID |
| create_time | string | 通知创建的时间 |
| event_type | string | 通知的类型CROSS_BORDER_PAY.GET_MCH_INFO 枚举值 |
| resource_type | string | 通知的资源数据类型encrypt-resource 枚举值 |
| summary | string | 回调摘要 |
| resource | object | 通知资源数据 |
| original_type | string | 原始回调类型cross_border_pay 枚举值 |
| algorithm | string | 对数据进行加密的加密算法AEAD_AES_256_GCM 枚举值 |
| associated_data | string | 数据加密的附加数据 |
| nonce | string | 加密使用的随机串 |
| ciphertext | string | 加密后的密文数据 |
| acq_tid | string | 受理网络交易流水号 |
| bank_type | string | 钱包编码 |
| qr_cd_mp | string | 收款码,传递钱包网络扫码解析的url |
php
// 使用Psr标准规范,示例如何处理(取值、验签、解密)「回调通知」事件,WebServer不同,用法略有差异,供参考实现。
function webhookProcessor(\Psr\Http\Message\RequestInterface $request,
array $platformPublicKeyMap, string $apiv3Key): array {
if (!\count($platformPublicKeyMap)) {
throw new \WeChatPay\Exception\InvalidArgumentException('平台证书或者平台公钥数组不能为空');
}
if (\strlen($apiv3Key) !== 32) {
throw new \WeChatPay\Exception\InvalidArgumentException('APIV3密钥为32字节,长度不对');
}
if (!($request->hasHeader(\WeChatPay\WechatpayNonce)
&& $request->hasHeader(\WeChatPay\WechatpaySerial)
&& $request->hasHeader(\WeChatPay\WechatpaySignature)
&& $request->hasHeader(\WeChatPay\WechatpayTimestamp))) {
throw new \WeChatPay\Exception\InvalidArgumentException('通知的头参数缺失必要参数');
}
// 检查通知的时间偏移量,允许5分钟之内的偏移
[$inWechatpayTimestamp] = $request->getHeader(\WeChatPay\WechatpayTimestamp);
if (\WeChatPay\MAXIMUM_CLOCK_OFFSET < \abs(
\WeChatPay\Formatter::timestamp() - (int)$inWechatpayTimestamp)) {
throw new \WeChatPay\Exception\InvalidArgumentException('通知头参数的时间偏移量超过可信阈值');
}
// 检查通知的平台证书/平台公钥实例是否存在
[$inWechatpaySerial] = $request->getHeader(\WeChatPay\WechatpaySerial);
if (!\array_key_exists($inWechatpaySerial, $platformPublicKeyMap)) {
throw new \WeChatPay\Exception\InvalidArgumentException('通知头参数的证书序列号/公钥ID本地不存在');
}
// 验证通知的数据签名
[$inWechatpaySignature] = $request->getHeader(\WeChatPay\WechatpaySignature);
[$inWechatpayNonce] = $request->getHeader(\WeChatPay\WechatpayNonce);
$inBody = (string)$request->getBody();
if (!\WeChatPay\Crypto\Rsa::verify(
\WeChatPay\Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
$inWechatpaySignature, $platformPublicKeyMap[$inWechatpaySerial]
)) {
throw new \WeChatPay\Exception\InvalidArgumentException('通知头参数的数据签名校验未通过');
}
// 转换通知的JSON文本消息为PHP Array数组
$inBodyArray = (array)\json_decode($inBody, true);
// 使用PHP7+的数据解构语法,从Array中解构并赋值变量
['resource' => [
'ciphertext' => $ciphertext,
'nonce' => $nonce,
'associated_data' => $aad
]] = $inBodyArray;
// 加密文本消息解密,有可能解密异常(eg: 平台探测流量)会抛 \UnexpectedValueException
$inBodyResource = \WeChatPay\Crypto\AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
// 把解密后的文本转换为PHP Array数组
$inBodyResourceArray = (array)\json_decode($inBodyResource, true);
// 把解密后的数组定义为'original_data'函数返回
$inBodyArray['resource']['original_data'] = $inBodyResourceArray;
return [
'headers' => $request->getHeaders(),
'body' => $inBodyArray
];
}
// do your business
// ...
// ...
$json = \json_encode([
'code' => 'SUCCESS',
'message' => '',
'acq_tid' => '202507150000000000011008013780',
'fix_recv_amount' => 1,
'mch_id' => '9527',
'sub_mch_id' => '9528',
'limit_bank_acc_type' => 'UNLIMIT',
]);‼️
微信支付收到响应后的验签规则为,从响应头取Authorization的值,其格式为 WECHATPAY2-SHA256-RSA2048 mchid="${mchid}", nonce_str="${nonce}", signature="${signature}", timestamp="${timestamp}", serial_no="${serial}",详细见下文链接。
| 应答规范 | 类型 | 描述 |
|---|---|---|
| status | number | HTTP状态码20X 4XX 5XX 枚举值之一 |
| headers | object | 应答的头参数,需从业机构签名 |
| Authorization | string | 响应签名值 |
| body | object | 应答的JSON数据结构 |
| code | string | 业务处理状态码SUCCESS | FAIL 枚举值之一 |
| message | string | 业务处理附加信息 |
| acq_tid | string | 受理网络交易流水号 |
| fix_recv_amount | integer | 收款金额,固定金额收款码收款金额,单位分 |
| mch_id | string | 商户ID |
| sub_mch_id | string | 特约商户ID,非服务商模式不填 |
| limit_bank_acc_type | string | 限定付款方账户类型UNLIMIT | NO_CREDIT 枚举值之一 |
| client_ip | string | 服务器IP |
参阅 官方文档