For the complete documentation index, see llms.txt. This page is also available as Markdown.

如何生成 x-signature

对于每笔Payout请求,Coda 系统都会执行验证过程以确保其完整性。Coda 会将请求中的 x-signature header与request body的signature进行比较。

如果signatures不匹配,系统将拒绝请求并返回错误(有关更多详细信息,请参阅 错误处理

此过程旨在确保payout请求的完整性和安全性,降低任何payload被篡改的风险。

Signature生成方式如下:

  1. 将Request body压缩,删除所有尾随空格 (trailing spaces) 和换行符(carriage returns)。

  2. 然后使用 HmacSHA256 algorithm 和共享密钥对payload进行签名。请注意,此密钥与用于 JWT 签名的密钥不同。Coda 将单独提供此密钥。

  3. 生成的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 值:

最后更新于

这有帮助吗?