签名算法
为保证数据在传输过程中的真实性和完整性,当请求一个API时,你必须对发送的请求加签,并且在获得响应后对响应内容验签。具体的流程请查看消息传输流程图。
准备工作
生成签名需要先创建一对RSA的非对称密钥。非对称密钥包含私钥和公钥,其中私钥用于生成签名,公钥则用于AlphaPay对请求的签名进行验签。
在商户后台进入ECommerce页面,点击编辑公钥,在弹窗中点击点击前往生成打开RSA秘钥生成工具。
在RSA秘钥生成工具中,Key Length
选择2048
后点击Generate key pair生成。请将生成好的公钥Public key
复制回编辑公钥弹窗的输入框中
构建签名
Open API接口需要用SHA256withRSA
算法生成签名,转换成Base64编码
后再使用URLEncoder
进行编码。 签名请求流程:
1. 构建用于签名的内容
签名内容Content_To_Be_Signed
的格式为:
<HTTP-Method> <HTTP-URI> <Merchant-Code>.<Request-Time>.<Nonce>.<Request-Body>
例如:String.format("%s %s\n%s.%s.%s.%s", method, requestURI, merchantCode, requestTime, nonce, body);
其中:
HTTP-Method
:POST
HTTP-URI
: 例如完整请求URL是https://openapi.alphapay.ca/api/v2.0/payments/pay
, 那么URI就是/api/v2.0/payments/pay
Merchant-Code
: AlphaPay为商户分配的商户编码,例如:CXVJIU
Request-Time
: 请求时间,格式为ISO 8601,精确到秒,例如:2019-05-28T12:12:12+08:00
Nonce
: 随机字符串,长度为32位,例如:b111bcf0dfb54d4e8bae68c293d85e2e
Request-Body
: 请求的body,为JSON 格式,例如:
{ "scenarioCode": "ONLINE_QRCODE", "paymentRequestId": "50", "order": { "orderAmount": { "value": "45366", "currency": "CNY" }, "description": "This is a test order", "notifyUrl": "https://alphapay.com/success", "redirectUrl": "https://alphapay.com/successPage" }, "paymentMethod": { "paymentMethodType": "Alipay" } }
依照上述规则拼接后的Content_To_Be_Signed
则为:
POST /api/v2.0/payments/pay CXVJIU.2019-05-28T12:12:12+08:00.b111bcf0dfb54d4e8bae68c293d85e2e.{ "scenarioCode": "ONLINE_QRCODE", "paymentRequestId": "50", "order": { "orderAmount": { "value": "45366", "currency": "CNY" }, "description": "This is a test order", "notifyUrl": "https://alphapay.com/success", "redirectUrl": "https://alphapay.com/successPage" }, "paymentMethod": { "paymentMethodType": "Alipay" } }
2. 生成签名
签名生成的方式如下:
generatedSignature=urlEncode(base64Encode(sha256withrsa(<Content_To_Be_Signed>), <privateKey>)))
其中:
sha256withrsa
: 通过签名内容生成签名的算法base64Encode
: 将签名转为base64编码
的算法urlEncode
: 为Http请求准备的编码操作Content_To_Be_Signed
: 在第一步拼接的签名内容privateKey
: 在准备工作部分生成好的私钥
生成完成的签名例子如下:
KrwDE9tAPJYBb4cUZU6ALJxGIZgwDXn5UkFPMip09n%2FkYKPhEIII%2Fki2rYY2lPtuKVgMNz%2BtuCU%2FjzRpohDbrOd8zYriiukpGAxBQDIVbatGI7WYOcc9YVQwdCR6ROuRQvr%2FD1AfdhHd6waAASu5Xugow9w1OW7Ti93LTd0tcyEWQYd2S7c3A73sHOJNYl8DC1PjasiBozZ%2FADgb7ONsqHo%2B8fKHsLygX9cuMkQYTGIRBQsvfgICnJhh%2BzXV8AQoecJBTrv6p%xxxx
3. 在请求头添加签名
基于以下格式组装签名字符串:'Signature: algorithm=<algorithm>, keyVersion=<keyVersion>, signature=<generatedSignature>'
例如:
'Signature: algorithm=RS256, keyVersion=1, signature=d%2FqFC126U57guKgRRXnd4colw5Ed5tpq3NDh2M5JOtfDivAze4X%2BYEaUCWHNW7h02sSed7hsnsDtM2rjtYe8kqAJTV9fMLzraeUZvWBh4j8Sf2D%2Bcz4bJ23S4F7VtoWaxMWjySwWuS0nMQweg%2BM7MY1HQFz2EXZjAa4CVflxU1I61NuEURfiYJGW%2BLEf%2FPVPEgzBLO8LopYMovmgO7Fl97E9UVFZnFW37bSaEdkNCffJlBU00AYWKaXbsARLarETkY9NA8nTJ5yDwjKm4rH3O%2FUhwGYnwLAvozKKjfWLU4m15LoAUF30Tap6d7IGFfewnLxdY34sVYG3Nx6m0Mit%2Bg%3D%3D'
发送请求
构造完成一个包含Merchant-Code
, Request-Time
, Nonce
和Signature
的请求头的请求后,可以使用一些通用工具,如cURL或Postman来发送请求。下面是一个cURL发送请求的例子:
curl --location --request POST 'https://openapi.alphapay.ca/api/v2.0/payments/pay' \ --header 'Accept: application/json' \ --header 'Merchant-Code: CXVJIU' \ --header 'Request-Time: 2023-03-15T22:37:47Z' \ --header 'Nonce: b111bcf0dfb54d4e8bae68c293d85e2e' \ --header 'Signature: algorithm=RS256, keyVersion=1, signature=d%2FqFC126U57guKgRRXnd4colw5Ed5tpq3NDh2M5JOtfDivAze4X%2BYEaUCWHNW7h02sSed7hsnsDtM2rjtYe8kqAJTV9fMLzraeUZvWBh4j8Sf2D%2Bcz4bJ23S4F7VtoWaxMWjySwWuS0nMQweg%2BM7MY1HQFz2EXZjAa4CVflxU1I61NuEURfiYJGW%2BLEf%2FPVPEgzBLO8LopYMovmgO7Fl97E9UVFZnFW37bSaEdkNCffJlBU00AYWKaXbsARLarETkY9NA8nTJ5yDwjKm4rH3O%2FUhwGYnwLAvozKKjfWLU4m15LoAUF30Tap6d7IGFfewnLxdY34sVYG3Nx6m0Mit%2Bg%3D%3D' \ --header 'Content-Type: application/json' \ --data-raw '{ "scenarioCode": "ONLINE_QRCODE", "paymentRequestId": "50", "order": { "orderAmount": { "value": "45366", "currency": "CNY" }, "description": "This is a test order", "notifyUrl": "https://alphapay.com/success", "redirectUrl": "https://alphapay.com/successPage" }, "paymentMethod": { "paymentMethodType": "Alipay" } }'
处理响应
在接收到AlphaPay的响应后,需要验证响应的签名。首先要组装待验证的内容,然后使用URLDecode
来解码签名,再进行Base64解码
,最后使用SHA256withRSA
算法来验证签名。
验签流程如下:
1. 获取AlphaPay公钥
在商户后台中进入ECommerce中可以查看AlphaPay公钥,如图所示:
2. 构建用于验证的内容
需验证的内容Content_To_Be_Validate
的格式为:
<HTTP-Method> <HTTP-URI> <Merchant-Code>.<Response-Time>.<Nonce>.<Response-Body>
HTTP-Method
:POST
HTTP-URI
: 例如完整请求URL是https://openapi.alphapay.ca/api/v2.0/payments/pay
, 那么URI就是/api/v2.0/payments/pay
Merchant-Code
: AlphaPay为商户分配的商户编码,例如:CXVJIU
Response-Time
: 响应时间,格式为ISO 8601,精确到秒,例如:2019-05-28T12:12:12+08:00
Nonce
: 随机字符串,长度为32位,例如:b111bcf0dfb54d4e8bae68c293d85e2e
Response-Body
: 响应的body,为JSON 格式
依照上述规则拼接后的Content_To_Be_Validate
则为:
POST /api/v2.0/payments/pay CXVJIU.2019-05-28T12:12:12+08:00.b111bcf0dfb54d4e8bae68c293d85e2e.{ "result": { "resultCode":"SUCCESS", "resultStatus":"S", "resultMessage":"success" } }
3. 从响应头获取签名
目标签名target_signature
可以通过响应头的Signature
字段获取,详情请查看响应结构部分。
Signature的结构如下:
Signature: algorithm=RSA256, keyVersion=1, signature=<target_signature>
完整的Signature例子如下:
Signature: algorithm=RS256, keyVersion=1, signature=d%2FqFC126U57guKgRRXnd4colw5Ed5tpq3NDh2M5JOtfDivAze4X%2BYEaUCWHNW7h02sSed7hsnsDtM2rjtYe8kqAJTV9fMLzraeUZvWBh4j8Sf2D%2Bcz4bJ23S4F7VtoWaxMWjySwWuS0nMQweg%2BM7MY1HQFz2EXZjAa4CVflxU1I61NuEURfiYJGW%2BLEf%2FPVPEgzBLO8LopYMovmgO7Fl97E9UVFZnFW37bSaEdkNCffJlBU00AYWKaXbsARLarETkY9NA8nTJ5yDwjKm4rH3O%2FUhwGYnwLAvozKKjfWLU4m15LoAUF30Tap6d7IGFfewnLxdY34sVYG3Nx6m0Mit%2Bg%3D%3D
则所需的签名target_signature
为其中signature
的值:
d%2FqFC126U57guKgRRXnd4colw5Ed5tpq3NDh2M5JOtfDivAze4X%2BYEaUCWHNW7h02sSed7hsnsDtM2rjtYe8kqAJTV9fMLzraeUZvWBh4j8Sf2D%2Bcz4bJ23S4F7VtoWaxMWjySwWuS0nMQweg%2BM7MY1HQFz2EXZjAa4CVflxU1I61NuEURfiYJGW%2BLEf%2FPVPEgzBLO8LopYMovmgO7Fl97E9UVFZnFW37bSaEdkNCffJlBU00AYWKaXbsARLarETkY9NA8nTJ5yDwjKm4rH3O%2FUhwGYnwLAvozKKjfWLU4m15LoAUF30Tap6d7IGFfewnLxdY34sVYG3Nx6m0Mit%2Bg%3D%3D
4. 验证签名
根据以下方法进行签名的验证:
IS_SIGNATURE_VALID=sha256withrsa_verify(base64Decode(urlDecode(<target_signature>)), <Content_To_Be_Validated>, <serverPublicKey>)