签名规则

更新时间:2026-07-01

支持的签名算法

算法类型适用版本推荐程度说明
RSA21.0推荐SHA256WithRSA,从应用读取密钥
SM21.0推荐国密 SM2,从应用读取密钥
版本与签名算法对应关系:
  • 1.0 版本:支持 RSA2 与 SM2 两种签名方式,均从应用(appid)读取密钥及加密方式

签名基本规则

交互方式:POST: application/x-www-form-urlencoded;charset=utf-8

3.3 请求签名(RSA2 / SM2)

1.0 版本支持 RSA2 与 SM2 两种签名方式,密钥及加密方式均从应用(appid)读取。

签名内容

对所有公共请求参数(appIdsubMerchantNobizContentversionnoncecontentHashtimestamp)按 key 字典序排序后,JSON 序列化(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),对该字符串签名。

签名类型签名方式输出格式
RSA2商户私钥签名,SHA256base64
SM2商户 SM2 私钥签名base64

3.4 contentHash 计算

// bizContent 规范 $bizContentNorm = preg_replace('/[\\x00-\\x1F\\x7F]/u', '', html_entity_decode($bizContent)); $contentHash = hash('sha256', $bizContentNorm);

bizContent 规范:去除控制字符(0x00-0x1F、0x7F),并对 HTML 实体解码后的字符串取 SHA256。

RSA2 签名算法(1.0版本)

RSA2 签名方式,从应用(appid)读取商户密钥,使用前需先创建应用。。

密钥配置说明

密钥类型来源用途
商户 RSA2 私钥从应用列表一键生成请求签名;
平台 RSA2 公钥从应用详情获取平台RSA2公钥验签平台响应

签名流程

  1. 生成密钥:使用支付宝工具生成 RSA2#PKCS8 密钥,上传公钥至商户后台
  2. 参数排序:将所有参数按 ASCII 码排序
  3. JSON 序列化:将排序后的参数转为 JSON 字符串
  4. RSA2 签名:使用商户私钥对 JSON 字符串进行 SHA256WithRSA 签名
  5. Base64 编码:将签名结果进行 Base64 编码
// PHP RSA2 签名示例 function generateSign($params, $private_key) { unset($params['sign']); ksort($params); // 参数排序 // 注意:必须同时使用 JSON_UNESCAPED_UNICODE 和 JSON_UNESCAPED_SLASHES $json_data = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); openssl_sign($json_data, $signature, $private_key, OPENSSL_ALGO_SHA256); return base64_encode($signature); }

SM2 签名算法(1.0版本)

SM2 签名方式,从应用(appid)读取商户密钥,使用前需先创建应用。。

密钥配置说明

密钥类型来源用途
商户 SM2 私钥从应用列表一键生成请求签名;
平台 SM2 公钥从应用详情获取平台SM2公钥验签平台响应

签名步骤说明

以下是 SM2 签名的通用逻辑,适用于所有编程语言:

步骤操作详细说明
1构建业务参数将业务参数按 ASCII 码排序,转为 JSON 字符串作为 bizContent
2计算 contentHash对 bizContent 进行 SHA256 哈希,生成 64 位十六进制字符串
3构建请求参数添加 appId、userId、bizContent、version、nonce、contentHash、timestamp 等参数
4参数排序将所有参数按 ASCII 码升序排列
5JSON 序列化将排序后的参数转为 JSON 字符串(不转义中文、不转义斜杠)
6SM2 签名使用商户 SM2 私钥对 JSON 字符串进行签名,输出 Base64 格式
7添加签名参数将签名结果作为 sign 参数加入请求

关键点说明

PHP 签名示例

依赖说明:示例代码使用封装好的 Sm2Helper 类,基于 lpilp/guomi: ^2.0 库实现。
// PHP SM2 签名示例 $bizContent = ['channel_type' => 'WECHAT', 'total_fee' => '100.00']; ksort($bizContent); $bizContentStr = json_encode($bizContent, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $param = [ 'appId' => '平台应用ID', 'userId' => '用户账户编号', 'bizContent' => $bizContentStr, 'version' => '1.0', 'nonce' => bin2hex(random_bytes(16)), 'contentHash' => hash('sha256', $bizContentStr), 'timestamp' => date('Y-m-d H:i:s'), ]; ksort($param); $json = json_encode($param, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $param['sign'] = Sm2Helper::sign($json, $merchantPrivateKey);

Sm2Helper 类参考实现

以下是 Sm2Helper 类的完整实现,仅供参考。
<?php namespace app\\common\\service; use Rtgm\\sm\\RtSm2; use Exception; /** * SM2加密解密辅助类 * 依赖:composer require lpilp/guomi:^2.0 */ class Sm2Helper { protected static $sm2Instance = null; protected static function getInstance() { if (self::$sm2Instance === null) { self::$sm2Instance = new RtSm2(); } return self::$sm2Instance; } /** * 生成SM2密钥对 */ public static function generateKeyPair(): array { $sm2 = self::getInstance(); list($privateKey, $publicKey) = $sm2->generatekey(); return [ 'privateKey' => strtoupper($privateKey), 'publicKey' => strtoupper($publicKey) ]; } /** * SM2签名 */ public static function sign(string $data, string $privateKey): string { $sm2 = self::getInstance(); // doSign 返回十六进制,转换为 Base64 $hexSignature = $sm2->doSign($data, strtolower($privateKey)); return base64_encode(hex2bin($hexSignature)); } /** * SM2验证签名 */ public static function verify(string $data, string $signature, string $publicKey): bool { $sm2 = self::getInstance(); // 将 Base64 签名转换为十六进制 $hexSignature = bin2hex(base64_decode($signature)); return $sm2->verifySign($data, $hexSignature, strtolower($publicKey)); } /** * SM2加密 */ public static function encrypt(string $data, string $publicKey): string { $sm2 = self::getInstance(); $encrypted = $sm2->doEncrypt($data, strtolower($publicKey)); return strtoupper($encrypted); } /** * SM2解密 */ public static function decrypt(string $encryptedData, string $privateKey): string { $sm2 = self::getInstance(); return $sm2->doDecrypt(strtolower($encryptedData), strtolower($privateKey)); } }