切换主题
签名和验签
为了确保数据传输后的完整性和真实性,点点易付 要求所有请求进行签名,并对通知签名进行验证:
- 请求:调用点点易付的 API 时,必须对请求参数进行签名。
- 通知:接收到点点易付发送的 Webhook 通知时,必须验证签名的合法性。
调用接口
在调用接口之前,请确保已生成了一对非对称的公钥和私钥,并符合以下标准。
- 密钥格式:PKCS#8
- 密钥长度:至少 2048 位
请求签名
以下图示说明了如何对请求进行签名:
步骤1:构建待签名内容
待签名内容的语法如下:
plain
merchant_id.timestamp.timezone.request_body
注意: 中间用英文符号的(点)进行连接
merchant_id
: 商家唯一标识符,一个示例值是acct_8NRyElotSWv5F08m
timestamp
: 此参数在请求头中是必需的,表示请求发送时的时间戳。该字段的值必须精确到毫秒。一个示例值是1742308640331
。timezone
: 此参数在请求头中是必需的,用于识别时间戳时区。一个示例值是Asia/Shanghai
。request_body
: HTTP 请求正文。 请参考下面的示例代码:
json
{
"merchant_id": "1",
"env": {
"terminal_type": "WEB",
"client_ip": "143.45.4.222",
"browser_info": {
"user_agent": "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/5.1)"
}
},
"order": {
"merchant_order_id": "99999999999",
"shipping": {
"shipping_name": {
"first_name": "KING",
"last_name": "MIsa",
"full_name": "KING MIsa"
},
"shipping_address": {
"country": "US",
"state": "TX",
"city": "Austin",
"address1": "789 Oak Ave",
"address2": "",
"zip_code": "78701"
},
"email": "example@example.com",
"phone": "+864-281-1794",
"carrier": "USPS"
},
"payment_amount": {
"currency": "USD",
"value": 1000
},
"payment_method": {
"payment_type": "CARD",
"payment_data": {
"country": "US",
"card_number": "4111111111111111",
"expiry_year": "30",
"expiry_month": "03",
"cvv": "737",
"card_holder_name": {
"first_name": "KING",
"last_name": "MIsa",
"full_name": "KING MIsa"
},
"billing_address": {
"country": "US",
"state": "TX",
"city": "Austin",
"address1": "789 Oak Ave",
"address2": "",
"zip_code": "78701"
},
"requires_3ds": false
}
},
"metadata": {
"shop": "happy",
"domain": "example.com"
}
},
"redirect_url": "https://example.com/reutrn"
}
通过遵循 构建内容
的语法规则,构建上述请求体如下
json
acct_8NRyElotSWv5F08m.1742308640331.Asia/Shanghai.{"merchant_id":"1","env":{"terminal_type":"WEB","client_ip":"143.45.4.222","browser_info":{"user_agent":"Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/5.1)"}},"order":{"merchant_order_id":"99999999999","shipping":{"shipping_name":{"first_name":"KING","last_name":"MIsa","full_name":"KING MIsa"},"shipping_address":{"country":"US","state":"TX","city":"Austin","address1":"789 Oak Ave","address2":"","zip_code":"78701"},"email":"example@example.com","phone":"+864-281-1794","carrier":"USPS"},"payment_amount":{"currency":"USD","value":1000},"payment_method":{"payment_type":"CARD","payment_data":{"country":"US","card_number":"4111111111111111","expiry_year":"30","expiry_month":"03","cvv":"737","card_holder_name":{"first_name":"KING","last_name":"MIsa","full_name":"KING MIsa"},"billing_address":{"country":"US","state":"TX","city":"Austin","address1":"789 Oak Ave","address2":"","zip_code":"78701"},"requires_3ds":false}},"metadata":{"shop":"happy","domain":"example.com"}},"redirect_url":"https://example.com/reutrn"}
步骤2:生成签名
生成签名的语法如下:
plain
signature = base64_encode(sha256withRSA(<构建内容>, <private_key>))
signature
: 生成的签名字符串。base64_encode
: 对生成的数字签名进行 Base64 编码的方法。sha256withrsa
: 使用 SHA-256 哈希算法和 RSA 私钥 对提供的内容进行数字签名的方法。构建内容
: 从步骤 1 获取的内容。private_key
: 私钥值。
生成签名的示例如下:
plain
M8jbljAHTkw9Vn/4JnFvsrIQIxU98ktYUFAYVgKJ7403Td4I2J0Aq3Y4qy6u2Og+n9HpL8g9bU9OCcA+iEGPhYoB3uWVJuMtjFLvV6z/Yey2JbmK6gjVKap1CRGmlfzgHHx7Qdvrf6ExsULQMtFeRwp3iczmjuBcq1YhjfooNq5ktbq/oI4UO7DI1OjqCdb1ZBpD6ZgqLAmxuiIkYFUK4AmrpqhvE/jrAzWCVPotm9VoMB4iivVj+sUGOken0/s35YFYgD1PUZPBUAlMCfEr3seq9J/E+oRHSbBrgQPjw+Muv8VQ21K9rvRSf6oUt0rxNITzcnJl/Z9SgRIOsPPEXA==
步骤3:将生成的签名添加到请求头中
plain
'signature:M8jbljAHTkw9Vn/4JnFvsrIQIxU98ktYUFAYVgKJ7403Td4I2J0Aq3Y4qy6u2Og+n9HpL8g9bU9OCcA+iEGPhYoB3uWVJuMtjFLvV6z/Yey2JbmK6gjVKap1CRGmlfzgHHx7Qdvrf6ExsULQMtFeRwp3iczmjuBcq1YhjfooNq5ktbq/oI4UO7DI1OjqCdb1ZBpD6ZgqLAmxuiIkYFUK4AmrpqhvE/jrAzWCVPotm9VoMB4iivVj+sUGOken0/s35YFYgD1PUZPBUAlMCfEr3seq9J/E+oRHSbBrgQPjw+Muv8VQ21K9rvRSf6oUt0rxNITzcnJl/Z9SgRIOsPPEXA=='
处理响应
响应由响应头和响应体组成。以下代码展示了响应头和响应体的示例。
- 响应头代码示例
plain
timezone: Asia/Shanghai
signature:h8zwMT0uBQJa/IDCg4ifIOchBFft9AvLkokjrrIiYtkf8fsk3A8wDqSdB2c66ks9gJqARafZ0MygnWOUU9NbVPCUixHvDFl8Z3238ADzhb29+S4S3fn7XTFV7DUtCMd9aFUvKLXGr6z4/GBog80yynGHDL6Ygjde7xI9D/x/OXiLOBGN1AuopTj7zL6TEvp/646T5PzZg8w9pnWA7r4ZxHplZrG0SKTLtZRloCtLk3kC3EwI0/m8obG4pptiPjY/8PuuLQUzbaPfd57wQP7tLUEhTr0LY2hSRYbdAtHwiPcmMY9QoW0rnHj/a/4nCqZNTrBwqiHJhdsKEZflA2KPjw==
timestamp:1742311500484
DD-Request-Id:req_oVJMRLT7dzs8inRB9xYTYuLo
- 响应体代码示例:
json
{
"data": {
"id": "pi_aDNwWGfls1vcPLUHJDykYwmR",
"amount": 7698,
"result": {
"result_code": "FAILED",
"result_status": "F",
"result_message": "card_velocity_exceeded"
},
"currency": "USD",
"merchant_id": "acct_8NRyElotSW15F08m",
"merchant_order_id": "21064044592225646561337"
}
}
以下步骤展示了如何使用上述示例处理Antom的响应。
步骤1:获取点点易付公钥
通过点点 Dashboard > 开发人员 > API密钥 > 查看详情 获取 点点 公钥。
步骤2:构造待验证的内容
构建内容
的语法如下:
plain
merchant_id.timestamp.timezone.response_body
merchant_id
: 商家唯一标识符,一个示例值是acct_8NRyElotSW15F08m
timestamp
: 此参数在响应头中是必需的,表示请求发送时的时间戳。该字段的值必须精确到毫秒。一个示例值是1742311500484
。timezone
: 此参数在响应头中是必需的,用于识别时间戳时区。一个示例值是Asia/Shanghai
。response_body
: HTTP 响应体
通过遵循 构建内容
的语法规则,构建上述响应如下:
plain
acct_8NRyElotSW15F08m.1742311500484.Asia/Shanghai.{"data":{"id":"pi_aDNwWGfls1vcPLUHJDykYwmR","amount":7698,"result":{"result_code":"FAILED","result_status":"F","result_message":"card_velocity_exceeded"},"currency":"USD","merchant_id":"acct_8NRyElotSW15F08m","merchant_order_id":"21064044592225646561337"}}
步骤3:从响应头获取签名
可以从响应头中的 signature
字段提取出签名。
步骤4:验证签名
验证签名的语法如下:
plain
is_signature_valid = sha256withrsa_verify_signature(<构建内容>, base64_decode(received_signature), <public_key>)
is_signature_validate
: 一个布尔值,表示签名是否有效。true : 签名有效。
false: 签名无效。可能的原因是私钥和公钥不匹配,或者
构建内容
没有正确构建。sha256withrsa_verify_signature
: 签名验证的方法。base64_decode
: 对生成的数字签名进行 Base64 解码的方法。received_signature
: 从 步骤 3 中获取的目标签名。public_key
: 从 步骤 1 中获取的 点点 公钥。