如何生成 x-signature
对于每笔Payout请求,Coda 系统都会执行验证过程以确保其完整性。Coda 会将请求中的 x-signature header与request body的signature进行比较。
如果signatures不匹配,系统将拒绝请求并返回错误(有关更多详细信息,请参阅 错误处理)
此过程旨在确保payout请求的完整性和安全性,降低任何payload被篡改的风险。
Signature生成方式如下:
将Request body压缩,删除所有尾随空格 (trailing spaces) 和换行符(carriage returns)。
然后使用 HmacSHA256 algorithm 和共享密钥对payload进行签名。请注意,此密钥与用于 JWT 签名的密钥不同。Coda 将单独提供此密钥。
生成的signature采用 base64 格式编码。
Signature生成示例代码:
package com.coda.codapay.payout.model.authorizer;
import com.coda.codapay.payout.util.JWebToken;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SignatureVerifier {
private static String generateSignature(String data, String secret) {
try {
byte[] hash = secret.getBytes(StandardCharsets.UTF_8);
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(hash, "HmacSHA256");
sha256Hmac.init(secretKey);
byte[] signedBytes = sha256Hmac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(signedBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException ex) { Logger.getLogger(JWebToken.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
return null;
}
}
private static String minifyRequestBody(String requestBody) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = null;
try {
jsonNode = objectMapper.readValue(requestBody, JsonNode.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return jsonNode.toString();
}
public static void main(String[] args) {
String secret = "Ob12@7n2tGVpK^cmrCa$";
String payload = "{\n" +
" \"payout_method\": {\n" +
" \"type\": \"bank_transfer\",\n" +
" \"payment_method\": \"bank_transfer\",\n" +
" \"beneficiary\": {\n" +
" \"name\": \"Steve\",\n" +
" \"payout_method_details\": {\n" +
" \"account_currency\": \"EGP\",\n" +
" \"account_name\": \"John doe\",\n" +
" \"account_number\": \"1234567890\",\n" +
" \"iban\": \"EG829299835700000000001111111\",\n" +
" \"swift_code\": \"DEIBEGCX016\",\n" +
" \"bank_code\": \"AUB\"\n" +
" }\n" +
" }\n" +
" },\n" +
" \"amount\": {\n" +
" \"value\": \"11.11\",\n" +
" \"currency_code\": \"EGP\"\n" +
" },\n" +
" \"country_code\": \"EG\",\n" +
" \"purpose\": \"salaries\",\n" +
" \"reference\": \"reference john doe\",\n" +
" \"request_id\": \"request_id_12344545\",\n" +
" \"due_date\": \"2022-04-22\"\n" +
"}";
String minifiedRequestBody = minifyRequestBody(payload);
// minified request body
System.out.println(minifiedRequestBody);
String signature = generateSignature(minifiedRequestBody, secret); // generate and sign signature
System.out.println(signature); // signature value for checksum pOsnb4LGor0_iOPsc_7ufSiQHslKkV6_iJ6c6tEpP3k
}
}Payload示例:
X-signature 密钥示例:
备注:请注意,此密钥将由 Coda 通过邮件分发
预期生成的 x-signature 值:
最后更新于
这有帮助吗?