> 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
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=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
