180 lines
5.5 KiB
PHP
Raw Normal View History

2025-10-17 17:18:15 +08:00
<?php
namespace addons\shopro\library\ccblife;
/**
* 建行生活MD5签名类
* 处理API消息签名和支付字符串签名
*/
class CcbMD5
{
/**
* 生成API消息签名
2025-10-18 01:16:25 +08:00
*
* ⚠️ 注意建行API接口签名使用大写MD5
* 签名规则MD5(JSON报文 + 服务方私钥) 转大写
*
* 示例:
* message = '{"CLD_HEADER":{...},"CLD_BODY":{...}}'
* privateKey = 'MIICeAIBA...'
* sign = strtoupper(md5(message + privateKey))
2025-10-17 17:18:15 +08:00
*
* @param string $message JSON格式的源报文
2025-10-18 01:16:25 +08:00
* @param string $privateKey 服务方私钥BASE64格式
2025-10-17 17:18:15 +08:00
* @return string 大写的32位MD5签名
*/
public static function signApiMessage($message, $privateKey)
{
// 移除私钥中的空格和换行
$privateKey = preg_replace('/\s+/', '', $privateKey);
2025-10-18 01:16:25 +08:00
// 计算MD5并转大写建行要求
2025-10-17 17:18:15 +08:00
return strtoupper(md5($message . $privateKey));
}
/**
* 验证API消息签名
*
* @param string $message JSON格式的源报文
* @param string $signature 待验证的签名
* @param string $privateKey 商户私钥BASE64格式
* @return bool 签名是否有效
*/
public static function verifyApiSignature($message, $signature, $privateKey)
{
$expectedSignature = self::signApiMessage($message, $privateKey);
return $expectedSignature === strtoupper($signature);
}
/**
* 生成支付字符串签名
2025-10-18 01:16:25 +08:00
*
* ⚠️ 注意建行收银台支付串签名使用小写MD5
* 签名规则MD5(支付参数按顺序拼接 + 商户私钥) 保持小写
*
* 示例:
* paymentString = 'MERCHANTID=xxx&POSID=xxx&...&TIMEOUT=xxx' + privateKey
* mac = md5(paymentString) // 小写
2025-10-17 17:18:15 +08:00
*
* @param array $params 支付参数
* @param string $privateKey 商户私钥
* @return string 小写的32位MD5签名
*/
public static function signPaymentString($params, $privateKey)
{
// 构建支付字符串(按照建行要求的顺序)
$fields = [
'MERCHANTID',
'POSID',
'BRANCHID',
'ORDERID',
'PAYMENT',
'CURCODE',
'TXCODE',
'REMARK1',
'REMARK2',
'TIMEOUT'
];
$parts = [];
foreach ($fields as $field) {
$value = isset($params[$field]) ? $params[$field] : '';
$parts[] = $field . '=' . $value;
}
// 拼接支付字符串并添加私钥
$paymentString = implode('&', $parts) . $privateKey;
2025-10-18 01:16:25 +08:00
// 计算MD5保持小写建行要求
2025-10-17 17:18:15 +08:00
return md5($paymentString);
}
/**
* 根据完整技术方案生成标准支付字符串签名
* 按照文档要求的格式生成签名
*
* @param string $merchantId 商户号
* @param string $posId POS号
* @param string $branchId 分行号
* @param string $orderId 订单号
* @param string $payment 支付金额
* @param string $privateKey 商户私钥
* @param string $curCode 币种默认01人民币
* @param string $txCode 交易码默认530550
* @param string $timeout 超时时间,默认空
* @return array 包含支付字符串和签名
*/
public static function generatePaymentSignature($merchantId, $posId, $branchId, $orderId, $payment, $privateKey, $curCode = '01', $txCode = '530550', $timeout = '')
{
// 构建支付参数
$params = [
'MERCHANTID' => $merchantId,
'POSID' => $posId,
'BRANCHID' => $branchId,
'ORDERID' => $orderId,
'PAYMENT' => $payment,
'CURCODE' => $curCode,
'TXCODE' => $txCode,
'REMARK1' => '',
'REMARK2' => '',
'TIMEOUT' => $timeout
];
// 生成签名
$mac = self::signPaymentString($params, $privateKey);
// 构建完整的支付字符串(不包含私钥)
$fields = [];
foreach ($params as $key => $value) {
$fields[] = $key . '=' . $value;
}
$paymentString = implode('&', $fields);
return [
'payment_string' => $paymentString,
'mac' => $mac,
'params' => $params
];
}
/**
* 验证支付字符串签名
*
* @param array $params 支付参数
* @param string $mac 待验证的MAC值
* @param string $privateKey 商户私钥
* @return bool 签名是否有效
*/
public static function verifyPaymentSignature($params, $mac, $privateKey)
{
$expectedMac = self::signPaymentString($params, $privateKey);
return $expectedMac === strtolower($mac);
}
/**
* 生成交易流水号
* 格式YYYYMMDDHHMMSS + 6位随机数
*
* @return string 20位交易流水号
*/
public static function generateTransactionSeq()
{
$timestamp = date('YmdHis');
$random = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
return $timestamp . $random;
}
/**
* 生成订单号
* 格式:前缀 + YYYYMMDDHHMMSS + 4位随机数
*
* @param string $prefix 订单号前缀,默认'CCB'
* @return string 订单号
*/
public static function generateOrderId($prefix = 'CCB')
{
$timestamp = date('YmdHis');
$random = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
return $prefix . $timestamp . $random;
}
}