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

# 恢复

> 当发生购物车遗弃恢复或订阅催缴事件时，发送到您的 webhook 端点的有效负载。

## 遗弃的购物车恢复事件

以下 webhook 事件跟踪遗弃购物车恢复生命周期：

| Event                          | Description                                       |
| ------------------------------ | ------------------------------------------------- |
| `abandoned_checkout.detected`  | 检测到遗弃的结账。当付款被识别为遗弃（失败或未完成）且恢复工作流程开始时发送。           |
| `abandoned_checkout.recovered` | 顾客通过恢复链接完成付款。`recovered_payment_id` 字段包含成功的付款 ID。 |

### 遗弃结账负载字段

<ParamField body="payment_id" type="string" required>
  遗弃的原始付款。使用此功能查找产品、金额和货币详情。
</ParamField>

<ParamField body="customer_id" type="string" required>
  遗弃结账的顾客。
</ParamField>

<ParamField body="abandonment_reason" type="string" required>
  遗弃结账的原因之一：

  * `payment_failed` — 顾客尝试付款但失败
  * `checkout_incomplete` — 顾客访问了结账页面但从未尝试付款
</ParamField>

<ParamField body="status" type="string" required>
  此恢复尝试的当前生命周期状态之一：

  * `abandoned` — 检测到，但尚未发送电子邮件
  * `recovering` — 已发送至少一封恢复电子邮件
  * `recovered` — 顾客完成支付
  * `exhausted` — 所有电子邮件已发送或发现较新的结账
  * `opted_out` — 顾客取消订阅
</ParamField>

<ParamField body="abandoned_at" type="string" required>
  检测到结账被遗弃的 ISO 8601 时间戳。
</ParamField>

<ParamField body="recovered_payment_id" type="string | null">
  成功恢复付款的付款 ID。在结账恢复之前是 `null`。
</ParamField>

### 示例：处理 ACR Webhooks

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

  switch (event.type) {
    case 'abandoned_checkout.detected':
      console.log(`Checkout abandoned: ${event.data.payment_id}`);
      console.log(`Reason: ${event.data.abandonment_reason}`);
      // Track abandonment in your analytics
      await trackAbandonment(event.data);
      break;

    case 'abandoned_checkout.recovered':
      console.log(`Checkout recovered: ${event.data.payment_id}`);
      console.log(`Recovery payment: ${event.data.recovered_payment_id}`);
      // Grant access, update records
      await handleRecovery(event.data);
      break;
  }

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

***

## 催缴事件

以下 webhook 事件跟踪订阅催缴生命周期：

| Event               | Description                                     |
| ------------------- | ----------------------------------------------- |
| `dunning.started`   | 为进入 `on_hold` 的订阅或被顾客取消创建催缴尝试。                  |
| `dunning.recovered` | 顾客更新了他们的付款方式并且结果付款成功。`payment_id` 字段包含成功的付款 ID。 |

### 催缴尝试负载字段

<ParamField body="subscription_id" type="string" required>
  触发催缴尝试的订阅。
</ParamField>

<ParamField body="customer_id" type="string" required>
  拥有该订阅的顾客。
</ParamField>

<ParamField body="trigger_state" type="string" required>
  触发催缴的订阅状态之一：

  * `on_hold` — 由于付款失败暂停订阅
  * `cancelled` — 顾客从顾客门户取消
</ParamField>

<ParamField body="status" type="string" required>
  此催缴尝试的当前生命周期状态之一：

  * `recovering` — 正在发送催缴电子邮件
  * `recovered` — 顾客更新了支付方式，支付成功
  * `exhausted` — 所有电子邮件已发送或订阅状态已更改
</ParamField>

<ParamField body="created_at" type="string" required>
  创建催缴尝试时的 ISO 8601 时间戳。
</ParamField>

<ParamField body="payment_id" type="string | null">
  成功恢复付款的付款 ID。在恢复过程中是 `null`。
</ParamField>

### 示例：处理催缴 Webhooks

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

  switch (event.type) {
    case 'dunning.started':
      console.log(`Dunning started for subscription: ${event.data.subscription_id}`);
      console.log(`Trigger: ${event.data.trigger_state}`);
      // Track dunning in your system
      await trackDunning(event.data);
      break;

    case 'dunning.recovered':
      console.log(`Subscription recovered: ${event.data.subscription_id}`);
      console.log(`Recovery payment: ${event.data.payment_id}`);
      // Reactivate access, update records
      await handleDunningRecovery(event.data);
      break;
  }

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

<Tip>
  订阅 `dunning.started` 和 `dunning.recovered`，以跟踪完整的催缴生命周期。使用 `dunning.started` 暂停宽限期或在系统中标记有风险的订阅。
</Tip>

<CardGroup cols={2}>
  <Card title="Abandoned Cart Recovery" icon="cart-shopping" href="/features/recovery/abandoned-cart-recovery">
    配置 ACR 邮件序列和折扣激励。
  </Card>

  <Card title="Subscription Dunning" icon="rotate" href="/features/recovery/subscription-dunning">
    配置迟延订阅的催缴邮件序列。
  </Card>

  <Card title="Subscription Webhooks" icon="repeat" href="/developer-resources/webhooks/intents/subscription">
    相关订阅生命周期事件，如 `subscription.on_hold` 和 `subscription.cancelled`。
  </Card>
</CardGroup>

## Webhook 负载架构
