bug修改

This commit is contained in:
Billy 2025-10-22 21:42:09 +08:00
parent 7d4c2b246d
commit 8c693b3f83

View File

@ -82,139 +82,178 @@ class CcbPaymentService
throw new \Exception('支付流水号不能为空');
}
// ✅ 构建完整的48个支付参数按照建行文档5.4完整参数定义)
// 基础商户参数(必须二选一:建行商户号组合 或 外部平台商户号)
$paymentParams = [
'MERCHANTID' => $this->config['merchant_id'], // 商户代码F=可选,但不用外部商户号时必填)
'POSID' => $this->config['pos_id'], // 柜台代码F
'BRANCHID' => $this->config['branch_id'], // 分行代码F
'ORDERID' => $payFlowId, // 支付流水号T=必送)
'USER_ORDERID' => $order['order_sn'], // 用户订单号T
'PAYMENT' => number_format($order['pay_fee'], 2, '.', ''), // 支付金额T
'CURCODE' => '01', // 币种T01=人民币)
'TXCODE' => '520100', // 交易码T520100=即时支付)
'REMARK1' => '', // 备注1T
'REMARK2' => $this->config['service_id'], // 备注2T服务方编号
'TYPE' => '1', // 接口类型T1=防钓鱼)
'GATEWAY' => '0', // 网关类型T
'CLIENTIP' => $this->getClientIp(), // 客户端IPT
'REGINFO' => '', // 客户注册信息T中文需escape编码
'PROINFO' => $this->buildProductInfo($order), // 商品信息T中文已escape编码
'REFERER' => '', // 商户URLT
'THIRDAPPINFO' => 'comccbpay1234567890cloudmerchant', // 客户端标识T固定值
'TIMEOUT' => date('YmdHis', strtotime('+30 minutes')), // 超时时间F格式YYYYMMDDHHmmss
];
// ⚠️ 关键建行要求参数按照文档表格定义的顺序拼接不是ASCII排序
// 根据建行文档4.1和4.2,必须严格按照参数表顺序构建签名字符串
// ✅ 可选参数(根据实际场景添加)
// 外部平台商户号(与建行商户号二选一)
if (!empty($this->config['plat_mct_id'])) {
$paymentParams['PLATMCTID'] = $this->config['plat_mct_id'];
// 使用外部商户号时,删除建行商户号
unset($paymentParams['MERCHANTID'], $paymentParams['POSID'], $paymentParams['BRANCHID']);
// 1. 定义参与MAC签名的参数数组按文档表格顺序
$macParams = [];
// 1.1 商户信息(必填,二选一:建行商户号组合 或 外部平台商户号)
$usePlatMctId = !empty($this->config['plat_mct_id']);
if ($usePlatMctId) {
// 使用外部平台商户号
$macParams['PLATMCTID'] = $this->config['plat_mct_id'];
} else {
// 使用建行商户号组合
$macParams['MERCHANTID'] = $this->config['merchant_id'];
$macParams['POSID'] = $this->config['pos_id'];
$macParams['BRANCHID'] = $this->config['branch_id'];
}
// 微信支付19位终端号
if (!empty($this->config['pos_id_19'])) {
$paymentParams['POSID19'] = $this->config['pos_id_19'];
}
// 支付位图(控制支付方式:生活钱包/龙支付/微信/数币/信用付/快贷)
if (!empty($this->config['pay_bitmap'])) {
$paymentParams['PAYBITMAP'] = $this->config['pay_bitmap'];
}
// 1.2 订单信息(必填)
$macParams['ORDERID'] = $payFlowId; // 支付流水号
$macParams['USER_ORDERID'] = $order['order_sn']; // 用户订单号
$macParams['PAYMENT'] = number_format($order['pay_fee'], 2, '.', ''); // 支付金额
$macParams['CURCODE'] = '01'; // 币种01=人民币)
$macParams['TXCODE'] = '520100'; // 交易码
$macParams['REMARK1'] = ''; // 备注1空字符串也要传
$macParams['REMARK2'] = $this->config['service_id']; // 备注2服务方编号
$macParams['TYPE'] = '1'; // 接口类型1=防钓鱼)
$macParams['GATEWAY'] = '0'; // 网关类型
$macParams['CLIENTIP'] = ''; // 客户端IP建行生活环境送空
$macParams['REGINFO'] = ''; // 客户注册信息(空字符串)
$macParams['PROINFO'] = $this->buildProductInfo($order); // 商品信息escape编码
$macParams['REFERER'] = ''; // 商户URL空字符串
$macParams['THIRDAPPINFO'] = 'comccbpay1234567890cloudmerchant'; // 客户端标识(固定值)
// 账户位图(控制支付账户:建行借记卡/贷记卡/他行借记卡/贷记卡/建行钱包)
if (!empty($this->config['account_bitmap'])) {
$paymentParams['ACCOUNTBITMAP'] = $this->config['account_bitmap'];
}
// 1.3 可选参数按文档表格顺序有值才参与MAC
// ⚠️ 注意根据文档4.2橙色字段有值时才参与MAC空值不参与
// 分期期数
// 分期期数在THIRDAPPINFO之后
if (!empty($this->config['install_num'])) {
$paymentParams['INSTALLNUM'] = $this->config['install_num'];
$macParams['INSTALLNUM'] = $this->config['install_num'];
}
// 积分二级活动编号
// 超时时间
if (!empty($this->config['timeout'])) {
$macParams['TIMEOUT'] = $this->config['timeout'];
} else {
// 默认30分钟超时
$macParams['TIMEOUT'] = date('YmdHis', strtotime('+30 minutes'));
}
// 中国建设银行App环境参数
if (!empty($this->config['user_id'])) {
$macParams['USERID'] = $this->config['user_id'];
}
if (!empty($this->config['token'])) {
$macParams['TOKEN'] = $this->config['token'];
}
if (!empty($this->config['pay_success_url'])) {
$macParams['PAYSUCCESSURL'] = urlencode($this->config['pay_success_url']);
}
// 支付位图和账户位图
if (!empty($this->config['pay_bitmap'])) {
$macParams['PAYBITMAP'] = $this->config['pay_bitmap'];
}
if (!empty($this->config['account_bitmap'])) {
$macParams['ACCOUNTBITMAP'] = $this->config['account_bitmap'];
}
// 积分相关
if (!empty($this->config['point_avy_id'])) {
$paymentParams['POINTAVYID'] = $this->config['point_avy_id'];
$macParams['POINTAVYID'] = $this->config['point_avy_id'];
}
if (!empty($this->config['fixed_point_val'])) {
$macParams['FIXEDPOINTVAL'] = $this->config['fixed_point_val'];
}
if (!empty($this->config['min_point_limit'])) {
$macParams['MINPOINTLIMIT'] = $this->config['min_point_limit'];
}
// 有价券相关
if (!empty($this->config['coupon_avy_id'])) {
$macParams['COUPONAVYID'] = $this->config['coupon_avy_id'];
}
if (!empty($this->config['only_credit_pay_flag'])) {
$macParams['ONLY_CREDIT_PAY_FLAG'] = $this->config['only_credit_pay_flag'];
}
// 数字人民币参数
if (!empty($this->config['dcep_mct_type'])) {
$paymentParams['DCEP_MCT_TYPE'] = $this->config['dcep_mct_type'];
$macParams['DCEP_MCT_TYPE'] = $this->config['dcep_mct_type'];
if ($this->config['dcep_mct_type'] == '2') {
// 非融合商户需要填写数币商户号
$paymentParams['DCEP_MERCHANTID'] = $this->config['dcep_merchant_id'] ?? '';
$paymentParams['DCEP_POSID'] = $this->config['dcep_pos_id'] ?? '';
$paymentParams['DCEP_BRANCHID'] = $this->config['dcep_branch_id'] ?? '';
if (!empty($this->config['dcep_merchant_id'])) {
$macParams['DCEP_MERCHANTID'] = $this->config['dcep_merchant_id'];
}
if (!empty($this->config['dcep_pos_id'])) {
$macParams['DCEP_POSID'] = $this->config['dcep_pos_id'];
}
if (!empty($this->config['dcep_branch_id'])) {
$macParams['DCEP_BRANCHID'] = $this->config['dcep_branch_id'];
}
}
if (!empty($this->config['dcep_dep_acc_no'])) {
$paymentParams['DCEPDEPACCNO'] = $this->config['dcep_dep_acc_no'];
$macParams['DCEPDEPACCNO'] = $this->config['dcep_dep_acc_no'];
}
}
// 有价券活动编号
if (!empty($this->config['coupon_avy_id'])) {
$paymentParams['COUPONAVYID'] = $this->config['coupon_avy_id'];
}
// 限制信用卡支付标志
if (!empty($this->config['only_credit_pay_flag'])) {
$paymentParams['ONLY_CREDIT_PAY_FLAG'] = $this->config['only_credit_pay_flag'];
}
// 固定抵扣积分值
if (!empty($this->config['fixed_point_val'])) {
$paymentParams['FIXEDPOINTVAL'] = $this->config['fixed_point_val'];
}
// 最小使用积分抵扣限制
if (!empty($this->config['min_point_limit'])) {
$paymentParams['MINPOINTLIMIT'] = $this->config['min_point_limit'];
}
// 扩展域JSON格式需encodeURI
if (!empty($this->config['extend_params'])) {
$paymentParams['EXTENDPARAMS'] = urlencode($this->config['extend_params']);
}
// 二级商户参数(平台类服务方使用)
// 二级商户参数
if (!empty($this->config['sub_mct_id'])) {
$paymentParams['SUB_MCT_ID'] = $this->config['sub_mct_id'];
$macParams['SUB_MCT_ID'] = $this->config['sub_mct_id'];
}
if (!empty($this->config['sub_mct_name'])) {
$paymentParams['SUB_MCT_NAME'] = $this->config['sub_mct_name'];
$macParams['SUB_MCT_NAME'] = $this->config['sub_mct_name'];
}
if (!empty($this->config['sub_mct_mcc'])) {
$paymentParams['SUB_MCT_MCC'] = $this->config['sub_mct_mcc'];
$macParams['SUB_MCT_MCC'] = $this->config['sub_mct_mcc'];
}
// 扩展域
if (!empty($this->config['extend_params'])) {
$macParams['EXTENDPARAMS'] = urlencode($this->config['extend_params']);
}
// 特殊字段(中石化专用)
if (!empty($this->config['identity_code'])) {
$macParams['IDENTITYCODE'] = $this->config['identity_code'];
}
if (!empty($this->config['notify_url'])) {
$macParams['NOTIFY_URL'] = urlencode($this->config['notify_url']);
}
// 2. 构建签名字符串(按照定义顺序拼接,不排序!)
$signString = http_build_query($macParams);
// 3. 添加PLATFORMPUB参与MD5签名但不作为HTTP参数传递
$platformPubKey = $this->config['public_key']; // 服务方公钥
$macSignString = $signString . '&PLATFORMPUB=' . $platformPubKey;
// 4. 生成MAC签名32位小写MD5
$mac = strtolower(md5($macSignString));
// 5. 构建不参与MAC的参数
$nonMacParams = [];
// 微信支付19位终端号不参与MAC校验
if (!empty($this->config['pos_id_19'])) {
$nonMacParams['POSID19'] = $this->config['pos_id_19'];
}
// 场景编号埋点使用不参与MAC校验
if (!empty($this->config['scn_id'])) {
$paymentParams['SCNID'] = $this->config['scn_id'];
$nonMacParams['SCNID'] = $this->config['scn_id'];
}
if (!empty($this->config['scn_pltfrm_id'])) {
$paymentParams['SCN_PLTFRM_ID'] = $this->config['scn_pltfrm_id'];
$nonMacParams['SCN_PLTFRM_ID'] = $this->config['scn_pltfrm_id'];
}
// 按ASCII排序
ksort($paymentParams);
// 生成签名字符串
$signString = http_build_query($paymentParams);
// ⚠️ 建行支付串签名规则(v2.2版本):
// 1. PLATFORMPUB字段仅参与MD5计算,不作为HTTP参数传递
// 2. 签名 = MD5(参数字符串 + &PLATFORMPUB= + 服务方公钥内容)
// 3. 生成32位小写MD5字符串(根据建行文档5.4.1要求)
$platformPubKey = $this->config['public_key']; // 服务方公钥
$mac = strtolower(md5($signString . '&PLATFORMPUB=' . $platformPubKey));
// ✅ 修复:使用 CcbRSA 加密商户公钥后30位用于ENCPUB字段
// 删除 CcbEncryption 类,统一使用 CcbRSA 处理密钥格式化
// 6. 生成ENCPUB商户公钥密文不参与MAC校验
$encpub = $this->encryptPublicKeyLast30();
// 组装最终支付串
$finalPaymentString = $signString . '&MAC=' . $mac . '&PLATFORMID=' . $this->config['service_id'] . '&ENCPUB=' . urlencode($encpub);
// 7. 组装最终支付串
// 格式参与MAC的参数 + 不参与MAC的参数 + MAC + PLATFORMID + ENCPUB
$finalPaymentString = $signString;
// 添加不参与MAC的参数
if (!empty($nonMacParams)) {
$finalPaymentString .= '&' . http_build_query($nonMacParams);
}
// 添加MAC、PLATFORMID、ENCPUB
$finalPaymentString .= '&MAC=' . $mac . '&PLATFORMID=' . $this->config['service_id'] . '&ENCPUB=' . urlencode($encpub);
// 保存支付流水号到订单
Order::where('id', $orderId)->update([