Skip to main content

数据签名与验证

生成数据签名

在生成签名之前,请确保以下材料已准备好:

  • 获取您的 商户安全码
  • 生成一个 RSA 密钥对。您可以通过我们的服务或自己生成
  • 上传您的 RSA 公钥 到我们的服务

请按照以下指南生成您的数据签名:

  1. ASCII 顺序按键对请求参数进行排序
  2. 通过 = 连接每个参数的键值,并通过 & 连接所有参数,然后在签名字符串的末尾附加 & 和您的安全码
  3. 使用您的 RSA private key 对签名字符串进行 SHA256 加密
  4. 将加密后的字符串使用 base64 进行编码,以获得最终签名
// 签名前的连接字符串
amount=1&channel=alipay&currency=CNY&merchantid=123456&mid=1&notifyurl=www.abc.com/callback&returnurl=www.abc.com/returnurl&service=Payment&PUT_YOUR_SAFECODE_HERE

签名生成 - 示例代码

function generate_signature($params, $safecode, $sign_type): string
{
$serialize_sign = serialize_sign($params, $safecode, $sign_type);
$private_key = openssl_get_privatekey(file_get_contents('private_key.pem'));
openssl_sign($serialize_sign, $signature, $private_key, 'SHA256');
openssl_free_key($private_key);

return base64_encode($signature);
}

function serialize_sign(array $params, string $safecode, string $sign_type): string
{
switch ($sign_type) {
case 'payment_v2':
case 'withdraw_v2':
$sign_fields = [
'user_id', 'order_id', 'amount', 'currency', 'channel',
'timestamp',
];
break;
case 'payment_query_v2':
case 'withdraw_query_v2':
$sign_fields = ['user_id', 'order_id', 'timestamp'];
break;
case 'balance_v2':
$sign_fields = ['user_id', 'timestamp'];
break;

case 'payment_response':
$sign_fields = [
'user_id', 'order_id', 'transaction_id', 'channel',
'submit_currency', 'submit_amount', 'accept_currency', 'accept_amount',
'exchange_rate', 'pay_url',
];
break;
case 'withdraw_response':
$sign_fields = [
'user_id', 'order_id', 'transaction_id', 'channel',
'submit_currency', 'submit_amount', 'accept_currency', 'accept_amount',
'exchange_rate',
];
break;
case 'payment_query_response':
case 'withdraw_query_response':
$sign_fields = [
'user_id', 'order_id', 'transaction_id', 'channel',
'submit_currency', 'submit_amount', 'accept_currency', 'accept_amount',
'exchange_rate', 'status', 'timestamp',
];
break;
case 'balance_response':
default:
$sign_fields = ['user_id', 'timestamp'];
break;
}

if ($sign_fields) {
$params = array_intersect_key($params, array_flip($sign_fields));
}

ksort($params);

$sign = '';
foreach ($params as $key => $value) {
$sign .= $key.'='.$value.'&';
}
$sign .= $safecode;

return $sign;
}

验证响应签名

在验证签名之前,请确保准备好以下材料:

  • 获取您的 商户安全码
  • 获取 PTSRSA 公钥

请按照以下指南验证从 PTS 发送的签名:

  1. ASCII 顺序对响应参数(除了签名)进行排序。所有参数(除了签名)都应参与验证字符串的构建。
  2. 使用 = 符号连接参数的键/值,然后使用 & 符号连接所有参数。
  3. 在验证字符串的末尾附加 & 和您的 商户安全码
  4. 使用 base64 解码器将响应签名解码为二进制签名。
  5. 使用 SHA256 和验证字符串以及 PTS 的公钥来验证二进制签名。

签名验证 - 示例代码

function verify_signature($response, $safecode, $signType)
{
$params = $response['data'];
$signature = base64_decode($params['sign']);

$serialize_sign = serialize_sign($params, $safecode, $signType);

$pubKey = openssl_get_publickey(file_get_contents('plateform_public_key.pem'));
$verified = openssl_verify($serialize_sign, $signature, $pubKey, OPENSSL_ALGO_SHA256);
openssl_free_key($pubKey);

return $verified !== 0;
}