> ## 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.

# 批量下发

批量下发有两级事件：一级是批次，一级是批次里的每个条目。只需要批次结论就订阅批次事件，需要逐条对账就订阅条目事件。请先阅读[事件概述](/payments/cn/guides/events/overview)了解外层结构、去重方式以及所有事件通用的规则。

## 本页的事件

| 事件 | 通知什么 | 类型 |
| - | - | - |
| [`payment.bulk_send.updated`](#payment-bulk_send-updated) | 批量下发批次状态发生变更：已创建、校验中、执行中、完成、部分完成或失败，附带金额和条目数量汇总。 | **标准事件** |
| [`payment.bulk_send.item.updated`](#payment-bulk_send-item-updated) | 批量下发条目状态发生变更：待执行、执行中、完成、失败或未执行。 | **标准事件** |

## `payment.bulk_send.updated`

批次级事件。

### 批次的事件触发条件

**批次 `status` 每变化一次发一条事件。** 逐条进度不在这里，在条目事件里。

![批量下发批次状态变化](https://mintcdn.com/mcpnow/mlWrRJ_rKxcpt9Zx/payments/cn/images/payments/events/bulk-batch-status.svg?fit=max\&auto=format\&n=mlWrRJ_rKxcpt9Zx\&q=85\&s=394f5d31c8cc06ef1973dafa4ca8c5f3)

上图为主要的状态变化路径，绿色框为终态。`Validating` 也可能直接变为 `Failed`。事件可能不按顺序送达，参见[事件顺序](/payments/cn/guides/events/overview#事件顺序)。

| 触发条件 | `status` | 您该做什么 |
| - | - | - |
| 批次创建成功 | `Pending` | 建立批次记录并等待。 ⚠️ 如果您的组织启用了审批流，批次会先在此状态等待审批。审批过程不发事件，如果批次长时间停留在 `Pending`，请在 Cobo Portal 查看审批进度。 |
| 批次进入逐项校验（如启用了审批流，则在审批通过后） | `Validating` | 等待。 |
| 校验通过，开始准备资金并逐项执行 | `Transferring` | 等待。 |
| 全部条目成功 | `Completed`（终态） | 在您的系统中将该批次标记为已完成。 |
| 批次结果确定，部分条目未成功 | `PartiallyCompleted`（终态） | 按两个计数分流：`failed_item_count` 为已提交执行但失败的条目，`not_executed_item_count` 为从未提交执行的条目。 |
| 批次整体失败 | `Failed`（终态） | 读取 `failed_reason.code`——**执行前后都可能失败**，见[批次的失败原因](#批次的失败原因)。 审批被拒绝或被撤销时，批次也会进入此状态，批次和条目的 `failed_reason.code` 均为 `payment.app_workflow_approval_rejected` 或 `payment.app_workflow_approval_revoked`。 |

### 批次的事件内容

| 字段 | 类型 | 说明 |
| - | - | - |
| `data_type` | `string` | 固定为 `PaymentBulkSendUpdate`。 |
| `bulk_send_id` | `string` | 批量下发 ID。 |
| `request_id` | `string` | **选填**。请求 ID。 |
| `source_account` | `string` | 付款账户： • 商户账户：值为商户 ID，例如 `M1001`。 • 开发者账户：值为 `developer`。 |
| `status` | `string` | 批次当前状态，含义见[批次的事件触发条件](#批次的事件触发条件)： • `Pending` • `Validating` • `Transferring` • `Completed` • `PartiallyCompleted` • `Failed` |
| `execution_mode` | `string` | 批次如何处理条目校验失败： • `Strict`：任一条目校验失败，所有条目都不执行，全部标记为 `NotExecuted`，批次失败。 • `Partial`：校验失败只影响对应条目，这些条目标记为 `NotExecuted`，其余已通过校验的条目正常执行。 无论哪种模式，资金归集失败时整个批次都会失败。 |
| `item_count` | `integer` | 批次包含的条目数。 |
| `failed_item_count` | `integer` | 已提交执行但失败的条目数。这些条目的资金曾被锁定、手续费曾被扣收，现已释放和退回。能否直接重发取决于各条目的 `failed_reason.code`。 |
| `not_executed_item_count` | `integer` | 从未提交执行的条目数，这些条目的资金未被使用。不修正原因就重发会以同样方式失败。 |
| `requested_amounts` | `array` | 全部条目的请求金额合计，按 `token_id` 分组。 |
| `requested_amounts.amount` | `string` | 金额，格式见[金额](/payments/cn/guides/events/overview#金额)。 |
| `requested_amounts.token_id` | `string` | 币种 ID。 |
| `requested_amounts.chain_id` | `string` | 链 ID。 |
| `completed_amounts` | `array` | 已完成条目的金额合计，按 `token_id` 分组。 |
| `completed_amounts.amount` | `string` | 金额，格式见[金额](/payments/cn/guides/events/overview#金额)。 |
| `completed_amounts.token_id` | `string` | 币种 ID。 |
| `completed_amounts.chain_id` | `string` | 链 ID。 |
| `failed_amounts` | `array` | 未成功条目的金额合计，按 `token_id` 分组，已提交执行的与从未提交的合并计算。区分两者请看 `failed_item_count` 与 `not_executed_item_count`。 |
| `failed_amounts.amount` | `string` | 金额，格式见[金额](/payments/cn/guides/events/overview#金额)。 |
| `failed_amounts.token_id` | `string` | 币种 ID。 |
| `failed_amounts.chain_id` | `string` | 链 ID。 |
| `description` | `string` | 整个批次的描述。 |
| `commission_fee` | `object` | Cobo 收取的佣金，未产生时为 `null`。 |
| `commission_fee.fee_amount` | `string` | 佣金金额，**单位为美元**。佣金从 Fee Station 扣，余额按美元计。批次涉及多个币种时，此处为各币种佣金的合计。 |
| `failed_reason` | `object` | `status` 为 `Failed` 时有值，其余情况为 `null`。 |
| `failed_reason.code` | `string` | 失败原因代码。取值见[批次的失败原因](#批次的失败原因)。 |
| `failed_reason.message` | `string` | 失败原因。 |
| `created_timestamp` | `integer` | 该批次的创建时间，Unix 时间戳（秒）。 |
| `updated_timestamp` | `integer` | 该批次最近一次状态更新时间，Unix 时间戳（秒）。 |

批次事件**不携带条目列表**。逐条信息只通过条目事件送达，且两者的到达顺序不作保证。

### 批次的失败原因

请根据 `failed_reason.code` 决定如何处理。批次也可能因为审批被拒绝或被撤销而失败。

| `code` | 发生了什么 | 怎么处理 |
| - | - | - |
| `payment.bulk_send_no_valid_items` | 没有任何条目通过校验。 | 修正条目后创建新批次。 |
| `payment.bulk_send_strict_validation_failed` | `execution_mode` 为 `Strict` 且有条目未通过校验，批次因此中止。 | 修正那些条目后创建新批次。 |
| `payment.bulk_send_commission_fee_all_failed` | 所有条目的佣金都未能扣收。 | 处理 Fee Station 后创建新批次。 |
| `payment.bulk_send_strict_commission_fee_failed` | `execution_mode` 为 `Strict` 且有条目的佣金扣收失败。 | 处理 Fee Station 后创建新批次。 |
| `payment.sweep_task_failed` | 批量下发前的资金归集失败，所有条目均未执行。 | 创建新批次。 |
| `payment.app_workflow_approval_rejected` | 审批流拒绝了该批次。 | 向审批人确认原因，然后创建新批次。 |
| `payment.app_workflow_approval_revoked` | 审批被撤销。 | 创建新批次并重新审批。 |
| `payment.bulk_send_all_items_failed` | 已提交执行的条目全部失败。 | 逐条读条目事件的原因，修正后创建新批次。 |

### 批次的示例事件

以下示例只展示 `data` 对象。外层结构所有事件都一样，参见[事件结构](/payments/cn/guides/events/overview#事件结构)。

#### 批次已受理

记录批次，不要重复提交。注意 `Pending` 也可能表示批次在等审批。

```json theme={null}
{
  "data_type": "PaymentBulkSendUpdate",
  "bulk_send_id": "bulk_001",
  "request_id": "request_bulk_001",
  "source_account": "developer",
  "execution_mode": "Partial",
  "status": "Pending",
  "item_count": 3,
  "failed_item_count": 0,
  "not_executed_item_count": 0,
  "requested_amounts": [
    { "amount": "300.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "completed_amounts": [],
  "failed_amounts": [],
  "description": "September affiliate payouts",
  "commission_fee": null,
  "failed_reason": null,
  "created_timestamp": 1744710000,
  "updated_timestamp": 1744710000
}
```

#### 批次完成

在您的系统中将该批次标记为已完成。

```json theme={null}
{
  "data_type": "PaymentBulkSendUpdate",
  "bulk_send_id": "bulk_001",
  "request_id": "request_bulk_001",
  "source_account": "developer",
  "execution_mode": "Partial",
  "status": "Completed",
  "item_count": 3,
  "failed_item_count": 0,
  "not_executed_item_count": 0,
  "requested_amounts": [
    { "amount": "300.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "completed_amounts": [
    { "amount": "300.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "failed_amounts": [],
  "description": "September affiliate payouts",
  "commission_fee": { "fee_amount": "0.6" },
  "failed_reason": null,
  "created_timestamp": 1744710000,
  "updated_timestamp": 1744711200
}
```

#### 批次部分完成

按两个计数分流处理。本例有一个条目已提交执行但失败，另一个从未提交。

```json theme={null}
{
  "data_type": "PaymentBulkSendUpdate",
  "bulk_send_id": "bulk_002",
  "request_id": "request_bulk_002",
  "source_account": "developer",
  "execution_mode": "Partial",
  "status": "PartiallyCompleted",
  "item_count": 3,
  "failed_item_count": 1,
  "not_executed_item_count": 1,
  "requested_amounts": [
    { "amount": "300.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "completed_amounts": [
    { "amount": "100.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "failed_amounts": [
    { "amount": "200.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "description": "September affiliate payouts",
  "commission_fee": { "fee_amount": "0.2" },
  "failed_reason": null,
  "created_timestamp": 1744712000,
  "updated_timestamp": 1744713000
}
```

#### Strict 模式在执行前中止了批次

本例中，有条目未通过校验，因此 `Strict` 模式下整个批次在执行前中止，所有条目都未执行，资金未被使用。请根据条目事件找到未通过校验的条目，修正后创建新批次。

```json theme={null}
{
  "data_type": "PaymentBulkSendUpdate",
  "bulk_send_id": "bulk_003",
  "request_id": "request_bulk_003",
  "source_account": "developer",
  "execution_mode": "Strict",
  "status": "Failed",
  "item_count": 3,
  "failed_item_count": 0,
  "not_executed_item_count": 3,
  "requested_amounts": [
    { "amount": "300.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "completed_amounts": [],
  "failed_amounts": [
    { "amount": "300.00", "token_id": "ETH_USDC", "chain_id": "ETH" }
  ],
  "description": "September affiliate payouts",
  "commission_fee": null,
  "failed_reason": {
    "code": "payment.bulk_send_strict_validation_failed",
    "message": "Cannot complete bulk send: one or more items failed validation when 'execution_mode' is 'Strict'."
  },
  "created_timestamp": 1744714000,
  "updated_timestamp": 1744714100
}
```

## `payment.bulk_send.item.updated`

条目级事件。

### 条目的事件触发条件

**条目 `status` 每变化一次发一条事件。**

![批量下发条目状态变化](https://mintcdn.com/mcpnow/mlWrRJ_rKxcpt9Zx/payments/cn/images/payments/events/bulk-item-status.svg?fit=max\&auto=format\&n=mlWrRJ_rKxcpt9Zx\&q=85\&s=8d3b5c0ed00db9e8b847f7ad54ff8276)

上图为主要的状态变化路径，绿色框为终态。事件可能不按顺序送达，参见[事件顺序](/payments/cn/guides/events/overview#事件顺序)。

| 触发条件 | `status` | 您该做什么 |
| - | - | - |
| 条目已创建，等待校验或执行 | `Pending` | 建立条目记录并等待。 |
| 该条目的转出已提交 | `Processing` | 等待结果，不要标记完成。 |
| 转出成功 | `Completed`（终态） | 保存金额和 `tx_hash`，并在您的系统中将该条目标记为已完成。 |
| 转出已提交但失败 | `Failed`（终态） | 锁定资金已释放、手续费已退回。能否原样重发取决于 `failed_reason.code`。 |
| 该条目从未提交执行 | `NotExecuted`（终态） | **资金未被使用。** 读取 `failed_reason.code`，不修正原因就重发会再次失败。 |

### 条目的事件内容

| 字段 | 类型 | 说明 |
| - | - | - |
| `data_type` | `string` | 固定为 `PaymentBulkSendItemUpdate`。 |
| `bulk_send_item_id` | `string` | 批量下发条目 ID。 |
| `bulk_send_id` | `string` | 该条目所属的批次 ID。 |
| `request_id` | `string` | **选填**。所属批次的请求 ID。 |
| `source_account` | `string` | 付款账户： • 商户账户：值为商户 ID，例如 `M1001`。 • 开发者账户：值为 `developer`。 |
| `status` | `string` | 该条目的当前状态，含义见[条目的事件触发条件](#条目的事件触发条件)： • `Pending` • `Processing` • `Completed` • `Failed` • `NotExecuted` |
| `requested_amount` | `object` | 向收款方发送的金额。 |
| `requested_amount.amount` | `string` | 金额，格式见[金额](/payments/cn/guides/events/overview#金额)。 |
| `requested_amount.token_id` | `string` | 币种 ID。 |
| `requested_amount.chain_id` | `string` | 链 ID。 |
| `receiving_address` | `string` | 收款地址。 |
| `tx_hash` | `string` | 该条目的链上交易哈希。 |
| `description` | `string` | 该条目的备注。 |
| `failed_reason` | `object` | `status` 为 `Failed` 或 `NotExecuted` 时有值，其余情况为 `null`。 |
| `failed_reason.code` | `string` | 失败原因代码。取值见[条目的失败原因](#条目的失败原因)。 |
| `failed_reason.message` | `string` | 失败原因。 |
| `created_timestamp` | `integer` | 该条目的创建时间，Unix 时间戳（秒）。 |
| `updated_timestamp` | `integer` | 该条目最近一次状态更新时间，Unix 时间戳（秒）。 |

### 条目的失败原因

请根据 `failed_reason.code` 决定如何处理。下面是条目可能携带的 code。

| `code` | 发生了什么 | 怎么处理 |
| - | - | - |
| `payment.bulk_send_invalid_address` | 收款地址不合法，或与付款地址相同。 | 修正后在新批次中重发该条目。 |
| `payment.address_kya_failed` | 收款地址未通过 KYA 合规筛查。 | 不要再向该地址发送。 |
| `payment.strict_mode_other_items_validation_failed` | 该条目本身没有问题。`Strict` 模式下有别的条目未通过校验。 | 修正那个条目后重发本条目。 |
| `payment.strict_mode_other_items_commission_fee_failed` | 该条目本身没有问题。`Strict` 模式下有别的条目佣金扣收失败。 | 处理 Fee Station 后重发。 |
| `payment.bulk_send_commission_fee_charge_failed` | Fee Station 余额不足。 | 充值后重发。 |
| `payment.bulk_send_commission_fee_station_not_configured` | 未配置 Fee Station。 | 联系 Cobo，配置完成后重发。 |
| `payment.app_workflow_approval_rejected` | 审批流拒绝了该批次。 | 向审批人确认原因，然后创建新批次。 |
| `payment.app_workflow_approval_revoked` | 审批被撤销。 | 创建新批次并重新审批。 |
| `payment.sweep_task_failed` | 批量下发前的资金归集失败，所有条目均未执行。 | 在新批次中重发。 |
| `payment.batch_payouts_execution_failed` | 转账失败且原因无法归类。 | 不要重试，联系 Cobo。 |
| `transaction.rejected_by_policy` | 这笔转账命中了您自己配置的交易策略。 | 在 Cobo Portal 中调整该策略，然后重发。 |
| `transaction.rejected_by_approval` | 这笔转账在您组织的审批环节被拒绝——审批人拒绝，或您的回调服务器拒绝。 | 向对方确认原因，然后重发。 |
| `transaction.rejected_by_signer` | 这笔转账在签名环节被拒绝——co-signer 拒绝签名。 | 向 co-signer 确认原因，然后重发。 |
| `transaction.rejected_by_screening_app` | 您的合规团队在 [Screening App](https://manuals.cobo.com/cn/apps/screening/introduction) 中拒绝了这笔转账。 | 到该应用查看原因，然后重发。 |
| `transaction.rejected_by_compliance` | Cobo 的合规检查拒绝了这笔转账。 | 不要重试，联系 Cobo。 |
| `transaction.failed` | 原因无法归类。 | 联系 Cobo 并提供 `bulk_send_item_id`。 |

### 条目的示例事件

以下示例只展示 `data` 对象。外层结构所有事件都一样，参见[事件结构](/payments/cn/guides/events/overview#事件结构)。

#### 某个条目完成

保存金额和 `tx_hash`，通过 `bulk_send_item_id` 关联到您系统中的收款人记录，并将该条目标记为已完成。

```json theme={null}
{
  "data_type": "PaymentBulkSendItemUpdate",
  "bulk_send_item_id": "bulk_item_0001",
  "bulk_send_id": "bulk_002",
  "request_id": "request_bulk_002",
  "source_account": "developer",
  "status": "Completed",
  "requested_amount": { "amount": "100.00", "token_id": "ETH_USDC", "chain_id": "ETH" },
  "receiving_address": "0xaffiliate001",
  "tx_hash": "0xbulkitem001",
  "description": "affiliate 001",
  "failed_reason": null,
  "created_timestamp": 1744712000,
  "updated_timestamp": 1744712900
}
```

#### 某个条目在提交转账后失败

资金曾被锁定，现已释放，手续费已退回。能否原样重发取决于 `failed_reason.code`。

```json theme={null}
{
  "data_type": "PaymentBulkSendItemUpdate",
  "bulk_send_item_id": "bulk_item_0002",
  "bulk_send_id": "bulk_002",
  "request_id": "request_bulk_002",
  "source_account": "developer",
  "status": "Failed",
  "requested_amount": { "amount": "100.00", "token_id": "ETH_USDC", "chain_id": "ETH" },
  "receiving_address": "0xaffiliate002",
  "tx_hash": null,
  "description": "affiliate 002",
  "failed_reason": {
    "code": "transaction.rejected_by_approval",
    "message": "This transaction was rejected during your organization's approval process, either by an approver or by your callback server. Please confirm the reason with the relevant party before resubmitting."
  },
  "created_timestamp": 1744712000,
  "updated_timestamp": 1744712950
}
```

#### 某个条目从未执行

**未使用任何资金。** 修正原因后再重发，否则会以同样的方式失败。本例条目自身没有问题，是 `Strict` 模式下同批的其他条目出错导致它没有执行。

```json theme={null}
{
  "data_type": "PaymentBulkSendItemUpdate",
  "bulk_send_item_id": "bulk_item_0003",
  "bulk_send_id": "bulk_003",
  "request_id": "request_bulk_003",
  "source_account": "developer",
  "status": "NotExecuted",
  "requested_amount": { "amount": "100.00", "token_id": "ETH_USDC", "chain_id": "ETH" },
  "receiving_address": "0xaffiliate003",
  "tx_hash": null,
  "description": "affiliate 003",
  "failed_reason": {
    "code": "payment.strict_mode_other_items_validation_failed",
    "message": "Cannot execute bulk send item: one or more other items failed validation when 'execution_mode' is 'Strict'."
  },
  "created_timestamp": 1744714000,
  "updated_timestamp": 1744714100
}
```

## 高级事件

需要批次和条目的链上交易细节时，可订阅高级事件 `payment.bulk_send.status.updated` 和 `payment.bulk_send.item.status.updated`，参见[高级事件](/payments/cn/guides/events/advanced#payment-bulk_send-status-updated)。
