接收回调通知
回调通知支付消息通知
介绍了接收 Spell 回调通知的相关信息,以及如何正确处理通知的方法。
Spell 发出的所有回调通知均通过 POST
请求发送到您指定的回调地址。请求的内容为:
- 请求头
Content-Type
:application/json
。SPELL-Callback-Signature
:请求签名,您可以用于验证请求的真伪。
- 请求体
callback
:回调通知 ID。event
:事件ID。order
:订单ID。timestamp
:请求时间戳。user
:用户ID。
验证签名有效性
为了确保请求的真实性,防止被篡改或伪造,Spell 会对信息进行签名,以便您进行验证。您需要使用对应的已注册事件的回调密钥(在注册时记录下来的,不是您的账户API Secret)对请求体进行签名,并与请求头中的 SPELL-Callback-Signature
进行对比。以下是完整的验证步骤:
1. 序列化数据
首先,你需要将请求体中的所有字段序列化成一个特定的字符串。这个过程包括:
- 按字段名排序:请求体中的所有字段按照字段名进行字母排序。
- 格式化:将每个字段转换为
key=value
格式的字符串。 - 拼接:使用
&
符号将所有格式化后的字符串连接起来。
您可以使用下面的 serializeData()
函数来完成这一步:
/**
* 序列化数据对象,用于生成签名字符串
* @param data - 需要序列化的数据对象
* @returns 序列化后的字符串,格式为 key1=value1&key2=value2...
*/
function serializeData(data: Record<string, any>): string {
return Object.keys(data)
.sort()
.map(key => {
const value = data[key];
const strValue = typeof value === 'object'
? JSON.stringify(value)
: String(value);
return `${key}=${strValue}`;
})
.join('&');
}
2. 计算签名
使用 crypto
模块,创建一个 HMAC
对象,并使用 SHA-256
算法和你的密钥对序列化后的数据进行签名计算。
以下为 Node.js
示例代码:
import * as crypto from 'crypto';
/**
* 计算签名
* @param serializedData - 经过序列化处理的字符串
* @param secretKey - 你的回调通知密钥
* @returns 十六进制的签名字符串
*/
function calculateSignature(serializedData: string, secretKey: string): string {
const hmac = crypto.createHmac('sha256', secretKey);
hmac.update(serializedData);
return hmac.digest('hex');
}
3. 对比签名
最后,将你计算出的签名与回调请求头中的 SPELL-Callback-Signature
字段对应的值进行对比。如果两者完全一致,则表明请求是真实有效的。
以下是完整的示例代码:
// 从请求头中获取签名
const cbSignature = request.headers['SPELL-Callback-Signature'];
// 假设这是你收到的请求体
const requestBody = {
callback: 'callback_id',
event: 'event_id',
order: 'order_id',
timestamp: 1700000000000,
user: 'user_id',
};
// 将请求体序列化
const serializedData = serializeData(requestBody);
// 计算签名
// CALLBACK_SECRET_KEY 是在回调注册时生成的
const mySignature = calculateSignature(serializedData, CALLBACK_SECRET_KEY);
// 对比签名
if (mySignature === cbSignature) {
console.log("签名验证成功,请求有效!");
// 处理你的业务逻辑
} else {
console.log("签名验证失败,请求可能被篡改或伪造,您应该重新创建一个回调接收地址!");
// 忽略请求
}
处理响应
为了确保回调通知被成功接收,Spell 会在一定时间范围内对于未接收到成功指令的回调进行间隔重试。同样的,为了避免重复收到 Spell 的通知,您的服务器需要在收到通知并确认签名有效后返回一个 HTTP
成功响应:
- 状态码:
200
- 响应头:
Content-Type: text/plain
- 响应内容:
success
响应内容为文本形式的全小写
success
,不包含任何其他字符