> ## Documentation Index
> Fetch the complete documentation index at: https://cobo.com/payments/llms.txt
> Use this file to discover all available pages before exploring further.

# 设置 Callback Endpoint

本指南介绍如何创建和注册 Callback Endpoint，用于接收和处理来自 Cobo 支付服务的 Callback 消息。

## 创建 Endpoint

选择支持接收和处理 HTTP POST 请求的服务器环境，例如 AWS、Google Cloud 等云服务或自托管服务器。在您的服务器上定义一个 Endpoint URL，Cobo 将向该地址发送 Callback 消息。

## 实现处理逻辑

创建 Endpoint 后，在您的服务器上实现处理 Callback 消息的逻辑。

### 解析 Callback 请求

Cobo 向您注册的 Callback Endpoint 发送 HTTP POST 请求，请求正文即交易对象，包含以下字段：

| 字段                     | 类型               | 是否必填 | 描述                                                            |
| ---------------------- | ---------------- | ---- | ------------------------------------------------------------- |
| `transaction_id`       | string           | 是    | 交易 ID。                                                        |
| `wallet_id`            | string           | 是    | 钱包 ID。                                                        |
| `type`                 | string           | 是    | 交易类型。                                                         |
| `status`               | string           | 是    | 交易状态。                                                         |
| `initiator_type`       | string           | 是    | 交易发起方类型。                                                      |
| `source`               | object           | 是    | 交易来源。                                                         |
| `destination`          | object           | 是    | 交易目标。                                                         |
| `created_timestamp`    | integer          | 是    | 交易创建时间，Unix 时间戳格式，单位为毫秒。                                      |
| `updated_timestamp`    | integer          | 是    | 交易最近更新时间，Unix 时间戳格式，单位为毫秒。                                    |
| `cobo_id`              | string           | 否    | 交易的 Cobo ID。                                                  |
| `request_id`           | string           | 否    | 交易的请求 ID。                                                     |
| `sub_status`           | string           | 否    | 交易的子状态。                                                       |
| `failed_reason`        | string           | 否    | 交易失败原因（如适用）。                                                  |
| `chain_id`             | string           | 否    | 链 ID。                                                         |
| `token_id`             | string           | 否    | 代币 ID。                                                        |
| `asset_id`             | string           | 否    | 资产 ID。                                                        |
| `result`               | object           | 否    | 交易签名结果。                                                       |
| `fee`                  | object           | 否    | 交易手续费信息。                                                      |
| `initiator`            | string           | 否    | 交易发起方。                                                        |
| `confirmed_num`        | integer          | 否    | 区块确认数。                                                        |
| `confirming_threshold` | integer          | 否    | 所需最小确认数。                                                      |
| `transaction_hash`     | string           | 否    | 交易哈希。                                                         |
| `block_info`           | object           | 否    | 区块信息。                                                         |
| `raw_tx_info`          | object           | 否    | 原始交易信息。                                                       |
| `replacement`          | object           | 否    | 替换交易数据（如果该交易被替换）。                                             |
| `fueling_info`         | object           | 否    | Gas 代付信息。                                                     |
| `category`             | array of strings | 否    | 用户自定义的交易类别。                                                   |
| `cobo_category`        | array of strings | 否    | Cobo 定义的交易类别。                                                 |
| `description`          | string           | 否    | 对于批量下发交易，此字段包含批量下发的 `request_id`，可用于判断该 Callback 是否由某笔批量下发触发。 |
| `is_loop`              | boolean          | 否    | 是否为 Cobo Loop 转账。默认值为 `false`。                                |
| `extra`                | array of strings | 否    | 附加信息。                                                         |

### 验证签名

为防止未经授权的访问，请通过验证签名来确认每条 Callback 请求的真实性。

验证步骤如下：

1. 获取请求包体的原始数据和时间戳。

   从请求 Payload 中提取包体的原始字符串，并从请求头中提取时间戳。

   ```python theme={null}
   raw_body = request.body().decode('utf8')
   timestamp = request.headers.get("BIZ_TIMESTAMP")
   ```

2. 获取签名。

   从请求头中获取签名值。

   ```python theme={null}
   signature = request.headers.get('BIZ_RESP_SIGNATURE')
   ```

3. 拼接消息并对其进行哈希处理。

   ```python theme={null}
   import hashlib

   # Concatenate raw body and timestamp to form the message.
   message = "raw_body|timestamp"

   # Compute double SHA-256 hash.
   sha256_hash = hashlib.sha256(hashlib.sha256(message.encode()).digest()).digest()
   ```

4. 选择 Cobo 的公钥。

   根据您使用的环境，选择相应的公钥进行验证：

   * 开发环境：`a04ea1d5fa8da71f1dcfccf972b9c4eba0a2d8aba1f6da26f49977b08a0d2718`
   * 生产环境：`8d4a482641adb2a34b726f05827dba9a9653e5857469b8749052bf4458a86729`

5. 使用 Ed25519 算法验证签名。

   ```python theme={null}
   import ed25519

   # Obtain the verifying key from Cobo's public key.
   vk = ed25519.VerifyingKey(bytes.fromhex(public_key))

   # Verify the signature against the computed message hash.
   vk.verify(bytes.fromhex(signature), sha256_hash)
   ```

### 响应 Callback 请求

您的 Endpoint 必须在 10 秒内响应。返回包含 `result` 字段的 JSON 正文：

* 批准操作：

  ```json theme={null}
  {"result": "ok"}
  ```

* 拒绝操作：

  ```json theme={null}
  {"result": "deny"}
  ```

如果您的 Endpoint 未能及时响应或返回其他响应，Callback 消息的状态将变为 `Failed`。

## 注册 Endpoint

回调地址在 Cobo Portal 创建 API 密钥时注册，与 API 密钥绑定。Cobo 会将使用该 API 密钥发起的所有操作的 Callback 消息发送到该地址。

1. 前往 **Cobo Portal** > **开发者** > **API Keys**。
2. 点击**注册 API Key**。
3. 在**回调地址**部分，点击**添加回调地址**。
4. 输入您的 Endpoint URL 和可选的描述信息。
5. 点击**注册**保存回调地址。
6. 点击**注册密钥**完成 API 密钥注册。

<Note>
  * 未配置回调地址时，所有提币请求将被自动批准。
  * 所有已配置的回调地址必须返回 `ok`，请求才会继续执行。任一地址返回 `deny` 将立即阻断该交易。
  * 每个 API 密钥最多可关联 3 个回调地址。
</Note>

## 注意事项

<Warning>
  * 您的 Endpoint 必须快速响应。请立即返回 `ok` 或 `deny` 响应，然后异步执行其他处理逻辑，以避免超时。
  * 由于重试机制的存在，您的 Endpoint 可能多次收到同一条 Callback 消息。为防止重复处理，请记录已处理的 Callback 消息的 `transaction_id`，并跳过已记录的消息。
</Warning>
