This commit is contained in:
Billy 2025-10-23 00:55:42 +08:00
parent f29cfc81a0
commit 2b07fbe5d1

View File

@ -140,7 +140,8 @@ class CcbPaymentService
$macParams['TOKEN'] = $this->config['token'];
}
if (!empty($this->config['pay_success_url'])) {
$macParams['PAYSUCCESSURL'] = urlencode($this->config['pay_success_url']);
// ⚠️ 不要在这里urlencode会在构建最终支付串时统一编码
$macParams['PAYSUCCESSURL'] = $this->config['pay_success_url'];
}
// 支付位图和账户位图
@ -203,7 +204,8 @@ class CcbPaymentService
// 扩展域
if (!empty($this->config['extend_params'])) {
$macParams['EXTENDPARAMS'] = urlencode($this->config['extend_params']);
// ⚠️ 不要在这里urlencode会在构建最终支付串时统一编码
$macParams['EXTENDPARAMS'] = $this->config['extend_params'];
}
// 特殊字段(中石化专用)
@ -211,11 +213,17 @@ class CcbPaymentService
$macParams['IDENTITYCODE'] = $this->config['identity_code'];
}
if (!empty($this->config['notify_url'])) {
$macParams['NOTIFY_URL'] = urlencode($this->config['notify_url']);
// ⚠️ 不要在这里urlencode会在构建最终支付串时统一编码
$macParams['NOTIFY_URL'] = $this->config['notify_url'];
}
// 2. 构建签名字符串(按照定义顺序拼接,不排序!)
$signString = http_build_query($macParams);
// 2. 手动构建签名字符串不能用http_build_query避免URL编码破坏escape格式
// ⚠️ 关键按照建行文档4.2示例签名字符串不进行URL编码
$signParts = [];
foreach ($macParams as $key => $value) {
$signParts[] = $key . '=' . $value;
}
$signString = implode('&', $signParts);
// 3. 添加PLATFORMPUB参与MD5签名但不作为HTTP参数传递
$platformPubKey = $this->config['public_key']; // 服务方公钥
@ -224,6 +232,9 @@ class CcbPaymentService
// 4. 生成MAC签名32位小写MD5
$mac = strtolower(md5($macSignString));
Log::info('[建行支付] MAC签名字符串(前500字符): ' . mb_substr($macSignString, 0, 500));
Log::info('[建行支付] 生成MAC: ' . $mac);
// 5. 构建不参与MAC的参数
$nonMacParams = [];
@ -243,17 +254,33 @@ class CcbPaymentService
// 6. 生成ENCPUB商户公钥密文不参与MAC校验
$encpub = $this->encryptPublicKeyLast30();
// 7. 组装最终支付串
// 7. 组装最终支付串传给建行收银台的URL参数
// ⚠️ 注意最终支付串需要对特殊字符进行URL编码
// 格式参与MAC的参数 + 不参与MAC的参数 + MAC + PLATFORMID + ENCPUB
$finalPaymentString = $signString;
// 添加不参与MAC的参数
if (!empty($nonMacParams)) {
$finalPaymentString .= '&' . http_build_query($nonMacParams);
// 7.1 构建参与MAC的参数部分需要URL编码
$finalParts = [];
foreach ($macParams as $key => $value) {
// 对值进行URL编码建行收银台需要
$finalParts[] = $key . '=' . urlencode($value);
}
// 添加MAC、PLATFORMID、ENCPUB
$finalPaymentString .= '&MAC=' . $mac . '&PLATFORMID=' . $this->config['service_id'] . '&ENCPUB=' . urlencode($encpub);
// 7.2 添加不参与MAC的参数
if (!empty($nonMacParams)) {
foreach ($nonMacParams as $key => $value) {
$finalParts[] = $key . '=' . urlencode($value);
}
}
// 7.3 添加MAC、PLATFORMID、ENCPUBENCPUB已经是base64需要URL编码
$finalParts[] = 'MAC=' . $mac;
$finalParts[] = 'PLATFORMID=' . $this->config['service_id'];
$finalParts[] = 'ENCPUB=' . urlencode($encpub);
// 7.4 拼接最终支付串
$finalPaymentString = implode('&', $finalParts);
Log::info('[建行支付] 最终支付串(前500字符): ' . mb_substr($finalPaymentString, 0, 500));
// 保存支付流水号到订单
Order::where('id', $orderId)->update([