概述 #
验证 Wooshpay 发送到 webhook 端点的事件。
Wooshpay 签名头 #
The Wooshpay-Signature
每个签名事件中的标头都包含一个时间戳和签名。
时间戳前缀为 t=
,每个签名的前缀是 v1
.
例如
Wooshpay-Signature:t=1492774577,v1=6fdfb9c357542b8ee07277f5fca2c6f728bae2dce9be2f91412f4de922c1bae4
Webhook 密钥 #
Wooshpay 会生成一个唯一的 秘钥 为每个网络钩子 whsec_
在验证签名之前,您需要从 webhook.secret
在 webhook 对象中。
验证签名 #
通过比较 标题中的签名 到 预期签名您可以验证即使是由 Wooshpay 发送的,而不是由第三方发送的。
要逐步验证签名,您可以按照以下指南进行操作:
步骤 1:从文件头提取时间戳和签名 #
使用 ,
字符作为分隔符,得到一个元素列表。然后使用 =
字符作为分隔符,以获得前缀和值对。
前缀的值 t
对应于时间戳,而 v1
与签名相对应。您可以舍弃所有其他元素。
例如
t=1687845304,v1=6fdfb9c357542b8ee07277f5fca2c6f728bae2dce9be2f91412f4de922c1bae4
步骤 2:准备 签名支付负载
字符串 #
The 签名支付负载
字符串是通过连接创建的:
- 时间戳(字符串)
- 角色
.
- 实际的 JSON 有效负载(请求正文)
例如
1687845304
+.
+JSON 有效负载
1687845304.{
"id":"evt_1NNUrjL6kclEVx6Mb1x5dKJ3",
"对象":"事件"、
"api_version":"2022-11-15"2022-11-15",
"创建":1687845303,
"数据":{
"对象":{
"id":"prod_O9oUVgsSaordCT"、
"对象":"产品"、
"active": true、
"livemode": true、
"名称":"test"、
"类型":"服务"、
"livemode": true、
"pending_webhooks":1,
"type":"product.created
}
步骤 3:确定预期签名 #
使用 SHA256 哈希函数计算 HMAC。
- 使用端点的网络钩子秘密作为 密钥您可以从以下网站获取
webhook.secret
在网络钩子对象中 - 使用
签名支付负载
字符串作为 信息 这是您在第 2 步中已经准备好的。
通过 密钥 + 信息,就可以计算出一个 HMAC 字符串,即 预期签名
例如
public static void main(String[] args) {
String webhookSecret = "whsec_261V2mfsXt1BsOjJbHaQOxnTzhWZKrUE";
String timestamp = "1687845304";
String requestBody = "{\"id\":\"evt_1NNUrjL6kclEVx6Mb1x5dKJ3\",\"object\":\"event\",\"api_version\":\"2022-11-15\",\"created\":1687845303,\"data\":{\"object\":{\"id\":\"prod_O9oUVgsSaordCT\",\"object\":\"product\",\"active\":true,\"livemode\":true,\"name\":\"test\",\"type\":\"service\",\"livemode\":true,\"pending_webhooks\":1,\"type\":\"product.created\"}";
String signedPayload = timestamp+". "+requestBody;
String signature = hmacSha256(webhookSecret,signedPayload);
String WooshpaySignature = "t="+timestamp+",v1="+signature;
}
/**
* HMAC-SHA256
*/
public static String hmacSha256(String secret, String message) {
字符串 res;
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKey secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
mac.init(secretKey);
byte[] hash = mac.doFinal(message.getBytes());
res = Hex.encodeHexString(hash);
} catch (Exception e) {
return null;
}
return res;
}
步骤 4:比较签名 #
比较 标题中的签名 到 预期签名.
对于相等匹配,计算 当前时间戳 和 收到的时间戳然后再决定差异是否在您的承受范围之内。
为了防止定时攻击,可以使用恒定时间字符串比较法,将预期签名与收到的每个签名进行比较。