> For the complete documentation index, see [llms.txt](https://docs.coda.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coda.co/https-coda-payments.gitbook.io-zhong-wen-coda-private-technical-documentation/payout/ru-men-zhi-nan/ru-he-sheng-cheng-xsignature.md).

# 如何生成 x-signature

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

如果signatures不匹配，系统将拒绝请求并返回错误（有关更多详细信息，请参阅 [错误处理](/https-coda-payments.gitbook.io-zhong-wen-coda-private-technical-documentation/payout/api-shuo-ming/cuo-wu-chu-li.md)）

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

Signature生成方式如下：

1. 将Request body压缩，删除所有尾随空格 (trailing spaces) 和换行符(carriage returns)。
2. 然后使用 *<mark style="color:green;">**HmacSHA256**</mark>***&#x20;algorithm** 和共享密钥对payload进行签名。请注意，此密钥与用于 JWT 签名的密钥不同。Coda 将单独提供此密钥。
3. 生成的signature采用 **base64** 格式编码。

## Signature生成示例代码：

```javascript
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示例： <a href="#sample-payload" id="sample-payload"></a>

```javascript
{
  "payout_method": {
       "type": "bank_transfer",
       "payment_method": "bank_transfer",
       "beneficiary": {
           "name": "Steve",
           "payout_method_details": {
               "account_currency": "EGP",
               "account_name": "John doe",
               "account_number": "1234567890",
               "iban": "EG829299835700000000001111111",
               "swift_code": "DEIBEGCX016",
               "bank_code": "AUB"
           }
       }
   },
   "amount": {
       "value": "11.11",
       "currency_code": "EGP"
   },
   "country_code": "EG",
   "purpose": "salaries",
   "reference": "reference john doe",
   "request_id": "request_id_12344545",
 
}
```

## X-signature 密钥示例：

备注：请注意，此密钥将由 Coda 通过邮件分发

```
Ob12@7n2tGVpK^cmrCa$
```

## 预期生成的 x-signature 值： <a href="#expected-generated-x-signature-value" id="expected-generated-x-signature-value"></a>

```
pOsnb4LGor0/iOPsc/7ufSiQHslKkV6/iJ6c6tEpP3k=
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.coda.co/https-coda-payments.gitbook.io-zhong-wen-coda-private-technical-documentation/payout/ru-men-zhi-nan/ru-he-sheng-cheng-xsignature.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
