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

# 付款状态跟踪

> 监控和处理付款状态

## 状态概览

付款从创建到最终结算会经历多个阶段。每个阶段有三个状态——待处理、处理中和已完成——让您在整个流程的每个步骤都能获得精细的可见性。

## 状态流转

```mermaid theme={null}
graph TD
    CREATED --> CASH_IN_PENDING
    CASH_IN_PENDING --> CASH_IN_PROCESSING
    CASH_IN_PROCESSING --> CASH_IN_COMPLETED
    CASH_IN_COMPLETED --> KYT_OUT_PENDING
    KYT_OUT_PENDING --> KYT_OUT_PROCESSING
    KYT_OUT_PROCESSING --> KYT_OUT_COMPLETED
    KYT_OUT_COMPLETED --> CASH_OUT_PENDING
    CASH_OUT_PENDING --> CASH_OUT_PROCESSING
    CASH_OUT_PROCESSING --> CASH_OUT_COMPLETED
    CASH_OUT_COMPLETED --> COMPLETED

    KYT_OUT_PROCESSING -.-> REVIEW_NEEDED
    REVIEW_NEEDED -.->|已解决| KYT_OUT_COMPLETED
    REVIEW_NEEDED -.->|已拦截| REJECTED

    FAILED --> REFUND_PENDING
    ERROR --> REFUND_PENDING
    REJECTED --> REFUND_PENDING
    REFUND_PENDING --> REFUND_PROCESSING
    REFUND_PROCESSING --> REFUNDED

    CASH_IN_PROCESSING -.-> FAILED
    CASH_IN_PROCESSING -.-> ERROR

    KYT_OUT_PROCESSING -.-> FAILED
    KYT_OUT_PROCESSING -.-> ERROR
    CASH_OUT_PROCESSING -.-> FAILED
    CASH_OUT_PROCESSING -.-> REJECTED
    CASH_OUT_PROCESSING -.-> ERROR

    style COMPLETED fill:#22c55e,color:#fff
    style REJECTED fill:#f97316,color:#fff
    style FAILED fill:#ef4444,color:#fff
    style ERROR fill:#ef4444,color:#fff
    style REFUNDED fill:#6366f1,color:#fff
    style REVIEW_NEEDED fill:#eab308,color:#000
```

<Warning>
  在\*\*收款（Cash In）\*\*阶段，`FAILED` 和 `ERROR` 是终态——未收集到任何资金，因此不会发起退款。对于所有后续阶段（KYT 出账、出款），`FAILED` 和 `ERROR` 是过渡状态：付款将转入退款流程（`REFUND_PENDING` → `REFUND_PROCESSING` → `REFUNDED`）。`REJECTED` 也会触发退款流程，因为它仅在收款阶段之后发生。
</Warning>

## 状态说明

| 状态                    | 阶段     | 说明                                      | 建议提示语            |
| --------------------- | ------ | --------------------------------------- | ---------------- |
| `CREATED`             | 初始     | 付款已接收并持久化，等待进入处理队列                      | "付款已提交"          |
| `CASH_IN_PENDING`     | 收款     | 入账资金收集已入队                               | "正在处理付款"         |
| `CASH_IN_PROCESSING`  | 收款     | 正在从预存余额收集资金                             | "正在收集资金"         |
| `CASH_IN_COMPLETED`   | 收款     | 资金已成功收集                                 | "资金已收集"          |
| `KYT_OUT_PENDING`     | KYT 出账 | 出账交易已入队等待合规检查                           | "出账检查待处理"        |
| `KYT_OUT_PROCESSING`  | KYT 出账 | 出账合规审查进行中                               | "出账检查进行中"        |
| `KYT_OUT_COMPLETED`   | KYT 出账 | 出账合规检查通过                                | "准备转账"           |
| `CASH_OUT_PENDING`    | 出款     | 向收款方的付款已入队                              | "转账已入队"          |
| `CASH_OUT_PROCESSING` | 出款     | 资金已提交至支付服务商                             | "转账处理中"          |
| `CASH_OUT_COMPLETED`  | 出款     | 支付服务商已确认交付                              | "转账已交付"          |
| `COMPLETED`           | 终态     | 付款已完全结算                                 | "付款已送达！"         |
| `REVIEW_NEEDED`       | 审查     | 交易已标记为需要人工合规审查                          | "审查中——我们会通知您"    |
| `FAILED`              | 错误状态   | 操作失败。收款阶段发生时为终态（未收集资金）；后续阶段发生时转入退款流程。   | "转账失败——请检查收款方信息" |
| `REJECTED`            | 错误状态   | 付款因合规审查被拦截。始终触发退款流程，因为它仅在收款阶段之后发生。      | "转账被拒绝——合规问题"    |
| `ERROR`               | 错误状态   | 内部系统错误。收款阶段发生时为终态（未收集资金）；后续阶段发生时转入退款流程。 | "内部错误——请联系支持"    |
| `REFUND_PENDING`      | 退款     | 退回预存余额的退款已入队                            | "退款已发起"          |
| `REFUND_PROCESSING`   | 退款     | 退款进行中                                   | "退款进行中"          |
| `REFUNDED`            | 终态     | 资金已退回预存余额                               | "资金已退回余额"        |

## 获取付款状态

```bash theme={null}
GET /api/v2/payouts/{id}
```

```javascript theme={null}
const getPayoutStatus = async (payoutId) => {
  const response = await fetch(
    `https://sandbox.killb.app/api/v2/payouts/${payoutId}`,
    {
      headers: { 'Authorization': `Bearer ${token}` }
    }
  );

  const payout = await response.json();
  return payout.status;
};
```

## 轮询状态

当 webhooks 不可用时，使用轮询作为备选方案：

```javascript theme={null}
const waitForPayout = async (payoutId, timeoutMs = 300000) => {
  const terminalStatuses = ['COMPLETED', 'FAILED', 'REJECTED', 'ERROR', 'REFUNDED'];
  const start = Date.now();

  while (Date.now() - start < timeoutMs) {
    const response = await fetch(
      `https://sandbox.killb.app/api/v2/payouts/${payoutId}`,
      { headers: { 'Authorization': `Bearer ${token}` } }
    );

    const payout = await response.json();
    console.log('状态:', payout.status);

    if (terminalStatuses.includes(payout.status)) {
      return payout;
    }

    // 等待 15 秒后再次检查
    await new Promise(resolve => setTimeout(resolve, 15000));
  }

  throw new Error(`付款 ${payoutId} 在超时时间内未完成结算`);
};

const result = await waitForPayout('payout-abc123');

if (result.status === 'COMPLETED') {
  console.log('资金已成功交付');
} else {
  console.error('付款以状态结束:', result.status);
}
```

<Tip>
  优先使用 webhooks 作为主要通知方式。每 15–30 秒轮询一次适合作为备用方案。
</Tip>

## 通过 Webhooks 获取状态更新

订阅 `PAYOUT` 事件类型，在每次状态变更时实时收到通知：

```javascript theme={null}
// 订阅付款事件
await fetch('/api/v2/webhooks', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://your-app.com/webhooks/killb',
    secret: 'your-webhook-secret',
    events: ['PAYOUT'],
    active: true
  })
});
```

处理收到的付款 webhook 事件：

```javascript theme={null}
app.post('/webhooks/killb', (req, res) => {
  const { event, data } = req.body;

  switch (event) {
    // 阶段进度事件——更新您界面中的状态指示器
    case 'payout.cash_in_pending':
    case 'payout.cash_in_processing':
    case 'payout.cash_in_completed':
    case 'payout.kyt_out_pending':
    case 'payout.kyt_out_processing':
    case 'payout.kyt_out_completed':
    case 'payout.cash_out_pending':
    case 'payout.cash_out_processing':
    case 'payout.cash_out_completed':
    case 'payout.refund_pending':
    case 'payout.refund_processing': {
      const status = event.replace('payout.', '').toUpperCase();
      updatePayoutStatus(data.id, status);
      break;
    }

    case 'payout.completed':
      updatePayoutStatus(data.id, 'COMPLETED');
      notifyRecipient(data);
      break;

    case 'payout.review_needed':
      // 交易已标记为人工审查——无需操作，付款将在审查完成后自动恢复
      updatePayoutStatus(data.id, 'REVIEW_NEEDED');
      alertComplianceTeam(data);
      break;

    case 'payout.error':
      // 内部系统错误——未进行任何付款
      updatePayoutStatus(data.id, 'ERROR');
      alertOpsTeam(data);
      break;

    case 'payout.failed':
      // 收款方账户信息无效或不正确
      updatePayoutStatus(data.id, 'FAILED');
      notifyInvalidBeneficiary(data);
      break;

    case 'payout.rejected':
      // 因合规审查被拦截
      updatePayoutStatus(data.id, 'REJECTED');
      escalateToCompliance(data);
      break;

    case 'payout.refunded':
      // 资金已退回预存余额
      updatePayoutStatus(data.id, 'REFUNDED');
      reconcileBalance(data);
      break;
  }

  res.status(200).json({ received: true });
});
```

## 最佳实践

<AccordionGroup>
  <Accordion title="Webhooks 作为主要渠道" icon="bell">
    始终为 `PAYOUT` 事件配置 webhook 端点。这可以即时获取状态更新，无需轮询开销，并减少不必要的 API 调用。
  </Accordion>

  <Accordion title="轮询作为备用方案" icon="rotate">
    如果 webhook 交付失败，每 15–30 秒查询一次 `GET /api/v2/payouts/{id}`。设置合理的超时时间（例如 5 分钟），如果付款在任何处理状态停留时间超过预期，及时通知团队。
  </Accordion>

  <Accordion title="区分失败状态" icon="circle-xmark">
    每种失败状态都有不同的原因。`FAILED` 或 `ERROR` 发生的阶段决定是否发起退款：

    * **收款阶段的 `FAILED` / `ERROR`** — 终态。未收集到任何资金，不会发起退款。`ERROR` 若持续出现请联系支持。
    * **收款阶段之后的 `FAILED` / `ERROR`**（KYT 出账、出款）— 过渡状态。由于资金已收集，付款自动转入 `REFUND_PENDING` → `REFUND_PROCESSING` → `REFUNDED`。
    * **`REJECTED`** — 因合规审查被拦截。不可自动重试，应在内部升级处理。由于资金已收集，始终会触发退款流程。
    * **`REVIEW_NEEDED`** — KYT 检查标记了该交易需要人工审查。审查完成后付款将自动恢复或转为 `REJECTED`，您无需采取任何行动。
  </Accordion>

  <Accordion title="每日对账" icon="calculator">
    通过 `GET /api/v2/payouts` 获取前一天的所有付款，并与内部账本核对。比较预期与实际的终态，及早发现差异。

    ```javascript theme={null}
    const { payouts } = await listPayouts({ limit: 100 });
    const needsAttention = payouts.filter(p =>
      ['ERROR', 'FAILED', 'REJECTED'].includes(p.status)
    );

    if (needsAttention.length > 0) {
      console.warn(`${needsAttention.length} 笔付款需要处理`, needsAttention);
    }
    ```
  </Accordion>
</AccordionGroup>

## 下一步

<CardGroup cols={2}>
  <Card title="配置 Webhooks" icon="bell" href="/zh/guides/webhooks/setup">
    配置并保护 webhook 通知
  </Card>

  <Card title="错误处理" icon="shield" href="/zh/resources/error-handling">
    优雅地处理 API 错误
  </Card>
</CardGroup>
