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

# Coupon 开通与使用

> 开通 Coupon，在 Merchant Portal 配置 Promotion Code，并通过 API 或 Waffo Checkout 应用优惠。

Coupon 定义折扣规则。Promotion Code 是关联到 Coupon、供用户或 Merchant 使用的兑换码。你可以在 Merchant Portal 配置两者，再通过 API 或 Waffo Checkout 应用优惠。

<Info>
  Coupon 功能需要由 Waffo 为每个环境开通。开始接入前，请联系 Waffo 商务或技术支持，并提供 Merchant ID 和需要开通的环境。
</Info>

## 工作方式

```mermaid theme={null}
flowchart LR
  coupon["Coupon<br/>折扣规则"] --> code["Promotion Code<br/>用户兑换凭证"]
  code --> result["Waffo Checkout 或 API<br/>应用折扣"]
  coupon -->|API 传 couponId| result
```

## 支持范围

| 范围                 | 支持方式                                                                                      | 说明                                                          |
| ------------------ | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `ONE_TIME_PAYMENT` | `POST /api/v1/order/create` 的 `promotionInfo`                                             | Merchant 可传 `promotionCode` 或 `couponId`                    |
| Waffo Checkout     | 用户输入 `promotionCode`                                                                      | 仅适用于已开通 Coupon、且 Merchant 未在创建订单时预先应用优惠的一次性支付订单             |
| `SUBSCRIPTION`     | `POST /api/v1/subscription/create` 和 `POST /api/v1/subscription/change` 的 `promotionInfo` | Merchant 可传 `promotionCode` 或 `couponId`；优惠持续期由 Coupon 配置决定 |
| Merchant Portal    | **Marketing → Coupons** 和 **Marketing → Promotion Codes**                                 | 创建、查看和管理 Coupon 与 Promotion Code                            |

## 在 Merchant Portal 配置

<Steps>
  <Step title="开通 Coupon">
    请 Waffo 为 Sandbox 或 Production Merchant 开通 Coupon 功能。两个环境需要分别确认。
  </Step>

  <Step title="创建 Coupon">
    登录 Merchant Portal，打开 **Marketing → Coupons**，并按下表配置折扣规则和适用范围。
  </Step>

  <Step title="创建 Promotion Code">
    如需给用户输入兑换码，创建 Promotion Code 并关联 Coupon。你可以从 Coupon 详情页创建，也可以在 **Marketing → Promotion Codes** 中单个或批量创建。
  </Step>

  <Step title="设置兑换规则">
    按需设置兑换次数、首次交易限制、最低订单金额和失效时间，然后保存。
  </Step>
</Steps>

| Coupon 配置              | 规则                                                                                       |
| ---------------------- | ---------------------------------------------------------------------------------------- |
| Coupon Name            | 用户可见，最多 40 个字符                                                                           |
| Percentage Off         | 输入 1–100；100% 表示订单免费                                                                     |
| Fixed Amount Off       | 按币种分别配置固定折扣金额；未配置的币种不能使用该 Coupon                                                         |
| Duration               | `Once` 只应用于单笔支付；`Repeating` 应用于 Subscription 的指定计费周期数；`Forever` 应用于 Subscription 的每个计费周期 |
| Max Redemptions        | 限制该 Coupon 通过所有关联 Promotion Code 被兑换的总次数                                                 |
| Daily Redemption Limit | 限制同一用户每天可兑换的次数                                                                           |
| Expiry Date            | 到期后不能继续兑换                                                                                |
| Category Tags          | 限制适用商品；留空表示适用于全部商品                                                                       |
| Metadata               | 保存 Merchant 自定义的补充信息                                                                     |

创建后不能修改折扣类型、折扣金额和持续期。创建前请确认这些配置。Coupon Name 和 Metadata 可以继续编辑；如需停止使用，请停用或归档 Coupon。

<Frame caption="固定金额折扣需要为每种适用币种分别配置金额。">
  <img src="https://mintcdn.com/waffo-docs/xORaW9tAcq02K6Cd/images/developer-docs/use-cases/coupons/create-coupon-discount.png?fit=max&auto=format&n=xORaW9tAcq02K6Cd&q=85&s=043b9af59380de2f251b1227b9a2b07a" alt="Merchant Portal 创建 Coupon 页面中的固定金额折扣、多币种金额和实时预览" width="2054" height="766" data-path="images/developer-docs/use-cases/coupons/create-coupon-discount.png" />
</Frame>

<Frame caption="持续期决定折扣应用一次、指定计费周期数或每个 Subscription 计费周期。">
  <img src="https://mintcdn.com/waffo-docs/xORaW9tAcq02K6Cd/images/developer-docs/use-cases/coupons/create-coupon-duration-limits.png?fit=max&auto=format&n=xORaW9tAcq02K6Cd&q=85&s=2f15dfa52cb80b604451d9b54d7b2be3" alt="Merchant Portal 中 Coupon 的持续期、总兑换上限、单用户每日限制和失效时间设置" width="2556" height="874" data-path="images/developer-docs/use-cases/coupons/create-coupon-duration-limits.png" />
</Frame>

如果看不到 **Marketing** 菜单或创建按钮，请让 Merchant 管理员检查账号权限，并联系 Waffo 确认该环境已开通 Coupon。Read-only 账号可以查看 Marketing 数据，但不能执行创建或编辑操作。

创建后，你可以在 **Marketing → Discount Analytics** 查看兑换次数、折扣金额、平均每笔折扣、兑换率和趋势，并按 Coupon 筛选或导出结果。

## 通过 API 应用 Coupon

`promotionInfo` 支持以下两个互斥字段：

| 字段                            | 使用场景                                         | 限制            |
| ----------------------------- | -------------------------------------------- | ------------- |
| `promotionInfo.promotionCode` | Merchant 已获取 Promotion Code，并希望按兑换码应用 Coupon | 字符串，最长 64 个字符 |
| `promotionInfo.couponId`      | Merchant 已持有具体 Coupon 实例 ID，并希望直接应用该 Coupon  | 字符串，最长 64 个字符 |

一次请求只能传其中一个字段。不要同时传 `promotionCode` 和 `couponId`。

### 一次性支付

在 [`POST /api/v1/order/create`](/docs/api-reference/order-create/create-new-order) 请求中加入 `promotionInfo`，并传 `promotionCode` 或 `couponId`（二选一）：

<Tabs>
  <Tab title="promotionCode">
    ```json theme={null}
    {
      "orderCurrency": "USD",
      "orderAmount": "100.00",
      "promotionInfo": {
        "promotionCode": "SAVE20"
      },
      "paymentInfo": {
        "productName": "ONE_TIME_PAYMENT"
      }
    }
    ```
  </Tab>

  <Tab title="couponId">
    ```json theme={null}
    {
      "orderCurrency": "USD",
      "orderAmount": "100.00",
      "promotionInfo": {
        "couponId": "coupon_123"
      },
      "paymentInfo": {
        "productName": "ONE_TIME_PAYMENT"
      }
    }
    ```
  </Tab>
</Tabs>

`orderAmount` 是应用优惠前的订单金额。Coupon 校验通过后，Waffo 重新计算应付金额。通过 [`POST /api/v1/order/inquiry`](/docs/api-reference/order-inquiry/order-inquiry) 查询订单时，`originalAmount` 表示优惠前金额，`orderAmount` 表示优惠后的 Merchant 订单金额。

### Subscription

在 [`POST /api/v1/subscription/create`](/docs/api-reference/subscription-create/create-subscription) 或 [`POST /api/v1/subscription/change`](/docs/api-reference/subscription-change/subscription-change) 请求中加入 `promotionInfo`，并传 `promotionCode` 或 `couponId`（二选一）：

<Tabs>
  <Tab title="promotionCode">
    ```json theme={null}
    {
      "currency": "USD",
      "amount": "100.00",
      "promotionInfo": {
        "promotionCode": "SAVE20"
      }
    }
    ```
  </Tab>

  <Tab title="couponId">
    ```json theme={null}
    {
      "currency": "USD",
      "amount": "100.00",
      "promotionInfo": {
        "couponId": "coupon_123"
      }
    }
    ```
  </Tab>
</Tabs>

Coupon 的持续期决定优惠只应用一次、重复指定周期，还是持续应用。Stripe adapter 不会把 Stripe Coupon 或 Promotion Code 映射到 Waffo；需要优惠时，请调用 Waffo 原生 Subscription API 并传 `promotionInfo`。

## 让用户在 Waffo Checkout 输入 Promotion Code

如果希望用户在 Checkout 自行兑换，请创建一次性支付订单时省略 `promotionInfo`。用户打开 `orderAction.webUrl` 后，可在 Checkout 输入 Promotion Code。

* Waffo 只在 Merchant 已开通 Coupon，且订单没有预先应用优惠时显示输入入口。
* Checkout 只接收 Promotion Code，不接收 `couponId`。
* Waffo 校验 Promotion Code 后重新计算并展示应付金额。
* 无效、已过期、不满足最低金额或超过兑换限制的 Promotion Code 会被拒绝。订单不会静默按原价继续支付。
* 如果 Merchant 已通过 API 应用 Coupon，Checkout 显示优惠后的金额，不再显示 Promotion Code 输入入口。

## 退款和支付结果

* 退款上限以优惠后的实际 Merchant 订单金额为准，不能按优惠前金额退款。
* 以 Webhook 或查询接口返回的终态作为支付结果。不要把浏览器跳转结果作为支付成功依据。
* Merchant 应保存传入的 `promotionCode` 或 `couponId`，并将它与业务订单或 Subscription 关联，便于排查优惠结果。

## 验收清单

* Sandbox 和目标 Production Merchant 均已确认开通 Coupon。
* Merchant Portal 可以访问 **Coupons** 和 **Promotion Codes**，且授权账号可以完成创建和查看。
* 一次性支付使用 `promotionCode` 和 `couponId` 各完成一笔成功订单；每次请求只传一个字段。
* 未预先应用优惠的一次性支付订单可在 Checkout 输入有效 Promotion Code，并展示重新计算后的金额。
* 无效、已过期或不满足使用条件的 Promotion Code 会显示错误，且不会按原价继续支付。
* Subscription 创建或变更请求可以应用 Coupon，后续周期的优惠行为与 Coupon 持续期一致。
* Webhook 或查询结果可确认支付终态；一次性支付查询结果中的 `originalAmount` 和 `orderAmount` 分别对应优惠前和优惠后金额。
* 退款金额不超过优惠后的 Merchant 订单金额。
