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

# 订阅

> 快速了解 HaiPay 订阅支付的接入方式、关键业务规则、上线要求和核心 API 入口，帮助你更快完成信用卡订阅集成。

HaiPay 订阅支付面向会员、周期性服务、自动续费等定期扣款场景。本文档重点说明接入方式、关键业务规则和上线要求，具体接口字段和调试请查阅对应的 API Reference。

<Columns cols={3}>
  <Card title="快速开始" icon="rocket" href="#quick-start">
    先看接入步骤、必备能力和推荐阅读路径。
  </Card>

  <Card title="集成模式" icon="layer-group" href="#integration-modes">
    对比 Apple Pay / Google Pay、信用卡组件和组合模式。
  </Card>

  <Card title="核心 API" icon="list-check" href="#core-apis">
    直接进入订阅申请、查询、取消和退款接口。
  </Card>
</Columns>

<Warning title="上线前必须满足的产品与服务要求">
  * 提供明确的订阅入口、扣款周期说明和退订入口。
  * 在订阅成功以及每次扣款前后，通过邮件或其他站外方式通知用户。
  * 提供可确认的订阅协议，并在用户明确授权后再发起订阅。
  * 保持客服可用，至少覆盖主要运营地区的服务时间。
</Warning>

<Tip title="信用卡争议与费用提示">
  * 信用卡交易在扣款后 180 天内，消费者可能发起争议。
  * 每笔争议会产生 20 美元争议处理费。
  * 如果选择抗辩，将额外产生 20 美元抗辩费。
  * 抗辩成功时，HaiPay 会退还抗辩费；原始争议处理费默认不退。
</Tip>

<Danger title="PCI DSS 合规要求">
  PCI DSS 严格禁止在 `WebView` 或 `iframe` 中嵌入信用卡输入页。请始终在受信任的浏览器环境中完成卡信息采集与支付授权，避免合规风险和敏感数据泄露。
</Danger>

<a id="quick-start" />

## 快速开始

<Steps>
  <Step title="确认业务模式与前置条件">
    先阅读 [接口说明](/docs/zh/guide/api_description_guide) 和 [订阅流程](/docs/zh/V20260628/api/version2/subscription-process)，确认你的场景是自动续费而不是代收支付。
  </Step>

  <Step title="选择接入模式">
    订阅支付提供两种接入模式：**PayUrl 跳转模式**（服务端获取授权链接，跳转到 HaiPay 托管页面完成支付）和 **前置组件模式**（使用客户端令牌在你自己的页面中嵌入支付组件）。根据你的收银台设计和前端开发能力选择合适的方式。
  </Step>

  <Step title="接入 API、通知与取消能力">
    完成订阅申请后，需要能查询订阅状态、处理扣款回调，并在用户侧提供取消订阅入口。详细字段与调试入口放在本页下方的 API Reference 卡片中。
  </Step>
</Steps>

<a id="integration-modes" />

## 集成模式

订阅支付提供两种接入模式，它们的核心区别在于支付页面由谁承载：

| 对比项    | 收银台模式              | 前置组件                 |
| :----- | :----------------- | :------------------- |
| 支付页面   | 跳转到 HaiPay 托管的支付页面 | 在商户自己的页面中嵌入支付组件      |
| 前端工作量  | 几乎为零，只需处理跳转        | 需要引入 JS 脚本并监听事件      |
| UI 控制力 | 低，页面样式由 HaiPay 控制  | 高，可自定义主题、布局和交互       |
| 关键返回字段 | 使用响应中的 `payUrl`    | 使用响应中的 `clientToken` |
| 适用场景   | 快速接入、对支付页面无定制需求    | 自建收银台、需要沉浸式支付体验      |

<Tabs sync={false}>
  <Tab title="收银台模式" icon="arrow-up-right-from-square">
    最简单的接入方式。商户服务端调用订阅申请接口后，使用返回的 `payUrl` 将用户跳转到 HaiPay 托管的支付页面，用户在该页面完成授权和首笔支付。

    **接入流程**

    <Steps>
      <Step title="服务端调用订阅申请接口">
        商户服务端向 HaiPay 发起 [订阅申请](/docs/zh/api-reference/subscription/api/subscriptionApply)，在请求中传入订阅金额、周期、回调地址等必要参数。
      </Step>

      <Step title="获取 payUrl 并跳转">
        接口返回中包含 `payUrl` 字段，商户将用户浏览器重定向到该地址。
      </Step>

      <Step title="用户完成支付">
        用户在 HaiPay 托管页面完成信用卡信息填写和支付授权。支付完成后，HaiPay 会将用户重定向回商户的 `callBackUrl`，同时向 `notifyUrl` 发送异步通知。
      </Step>
    </Steps>

    **示例代码（服务端获取 payUrl 后的前端跳转）**

    ```javascript theme={null}
    // 假设你的服务端已调用订阅申请接口，并将 payUrl 返回给前端
    const payUrl = response.data.payUrl;

    // 在当前窗口跳转
    window.location.href = payUrl;

    // 或者在新窗口打开
    // window.open(payUrl, '_blank');
    ```

    **适用建议**

    * 希望最快速度完成订阅接入，前端改动最少。
    * 对支付页面的 UI 没有强定制需求。
    * 移动端 H5 场景下，跳转体验通常也能满足需求。
  </Tab>

  <Tab title="前置组件模式" icon="code">
    通过引入 HaiPay 前置组件脚本，在商户自己的页面中嵌入支付组件。商户服务端调用订阅申请接口后，使用返回的 `clientToken` 初始化前端组件，用户无需离开商户页面即可完成支付。

    适合希望在一个容器内同时展示 `Google Pay`、`Apple Pay` 和 `Credit Card` 的现代化订阅收银界面。

    **推荐脚本**

    `https://cashier.haipay.top/js/paymentMethodsSubscribe_1.0.0.min.js`

    **关键参数**

    | 参数                    | 必填 | 说明                                                   |
    | :-------------------- | :- | :--------------------------------------------------- |
    | `sandbox`             | 是  | `true` 为测试环境，`false` 为生产环境                           |
    | `clientToken`         | 是  | 客户端令牌                                                |
    | `themeMode`           | 否  | 主题模式，默认 `light`                                      |
    | `paymentMethodConfig` | 否  | 支付方式组合，默认 `["GOOGLE_PAY","APPLE_PAY","CREDIT_CARD"]` |
    | `applePayButtonType`  | 否  | Apple Pay 按钮文案，如 `buy`、`subscribe`                   |
    | `googlePayButtonType` | 否  | Google Pay 按钮文案，如 `buy`、`subscribe`                  |

    **典型事件**

    * `ready`：按钮渲染完成
    * `error`：初始化或支付错误
    * `paymentStatus`：支付结果回调 (若不监听此事件，组件会默认处理支付结果)

    **适用建议**

    * 新收银台优先选这个模式，页面信息架构更清晰。
    * 如果只开放部分支付方式，可以只传需要的组合。
    * 想减少前端自定义工作量时，这个模式最省成本。
    * 使用前置组件时，订阅申请接口需传 `paymentMethods` 而非 `inBankCode`，例如 `CREDIT_CARD,GOOGLE_PAY,APPLE_PAY`。

    ```javascript theme={null}
    <script src="https://cashier.haipay.top/js/paymentMethodsSubscribe_1.0.0.min.js"></script>

    <div>
      <div id="paymentId"></div>
    </div>

    const elements = paymentMethodsSubscribe.create({
      sandbox: true,
      clientToken: 'your-client-token',
      themeMode: 'light',
      paymentMethodConfig: ['GOOGLE_PAY', 'APPLE_PAY', 'CREDIT_CARD']
    });

    elements.mount('#paymentId');

    elements.on('ready', (data) => {
      console.log('rendered successfully:', data);
    });

    elements.on('error', (data) => {
      console.error('Payment error:', data);
    });

    elements.on('paymentStatus', (data) => {
      console.log('payment status:', data);
    });
    ```
  </Tab>
</Tabs>

<a id="core-apis" />

## 核心 API

详细请求字段、响应结构和在线调试，请直接进入 API Reference：

<Columns cols={2}>
  <Card title="订阅申请" icon="circle-plus" href="/docs/zh/api-reference/subscription/api/subscriptionApply">
    创建订阅订单，拉起用户授权并完成首笔订阅支付。
  </Card>

  <Card title="查询订阅" icon="magnifying-glass" href="/docs/zh/api-reference/subscription/api/subscriptionQuery">
    查询订阅状态、平台订阅号和扣款记录。
  </Card>

  <Card title="取消订阅" icon="ban" href="/docs/zh/api-reference/subscription/api/subscriptionCancel">
    由商户主动发起取消，停止后续周期扣款。
  </Card>
</Columns>

## 异步通知

当订阅状态变更或周期扣款完成时，HaiPay 会向商户在订阅申请时提供的 `notifyUrl` 推送异步通知。

<Tip title="接收建议">
  为保障接口的扩展性和兼容性，请遵循以下回调参数接收方式：

  1. **禁止**声明具体 POJO 对象接收回调参数。
  2. **必须**使用通用数据结构（如 JSONObject、Map 等）进行参数解析。
  3. 此设计可确保后续扩展回调字段时，不会影响验签逻辑。
</Tip>

收到通知后，请在响应体中返回 **SUCCESS**（大写）。

<Tabs sync={false}>
  <Tab title="订阅状态通知" icon="bell">
    当订阅状态发生变更时触发（如订阅成功、订阅取消、订阅失败等）。

    | 参数名                      | 类型      | 说明                                               |
    | :----------------------- | :------ | :----------------------------------------------- |
    | `type`                   | String  | 通知类型，固定为 `SUBSCRIPTION`                          |
    | `appId`                  | Long    | 业务 ID                                            |
    | `currency`               | String  | 币种                                               |
    | `subscriptionOrderId`    | String  | 商户订阅号                                            |
    | `subscriptionNo`         | String  | 平台订阅号                                            |
    | `amount`                 | String  | 订阅金额                                             |
    | `status`                 | Integer | 订阅状态（1: 处理中, 2: 订阅成功, 3: 订阅失败, 4: 订阅取消, 5: 订阅完成） |
    | `recurringInterval`      | String  | 循环周期类型（D/W/M/Y）                                  |
    | `recurringIntervalCount` | Integer | 循环周期间隔                                           |
    | `subject`                | String  | 订阅标题                                             |
    | `sign`                   | String  | 签名（需要使用币种对应的业务密钥信息进行验签）                          |
  </Tab>

  <Tab title="订阅扣款通知" icon="money-bill-wave">
    当每期周期扣款成功或失败时触发。

    | 参数名                   | 类型      | 说明                                 |
    | :-------------------- | :------ | :--------------------------------- |
    | `type`                | String  | 通知类型，固定为 `SUBSCRIPTIONS_DEDUCT`    |
    | `appId`               | Long    | 业务 ID                              |
    | `currency`            | String  | 币种                                 |
    | `subscriptionOrderId` | String  | 商户订阅号                              |
    | `subscriptionNo`      | String  | 平台订阅号                              |
    | `deductNo`            | String  | 扣款编号                               |
    | `orderNo`             | String  | 平台订单号                              |
    | `amount`              | String  | 本次扣款金额                             |
    | `status`              | Integer | 扣款状态（2: 成功, 3: 失败）                 |
    | `startTime`           | String  | 本期扣款周期开始时间，格式: yyyy-MM-dd HH:mm:ss |
    | `endTime`             | String  | 本期扣款周期结束时间，格式: yyyy-MM-dd HH:mm:ss |
    | `sign`                | String  | 签名（需要使用币种对应的业务密钥信息进行验签）            |
  </Tab>
</Tabs>

## 关键业务规则

| 项目     | 说明                                                                                                                                    |
| :----- | :------------------------------------------------------------------------------------------------------------------------------------ |
| 交易限额   | 订阅金额范围为 `0.99 - 1000 USD`                                                                                                             |
| 周期上限   | 无论周期单位是什么，最长订阅时长不能超过 3 年                                                                                                              |
| 周期单位   | Apple Pay 不支持 `W`，周订阅请改用 `D` + `7` 天                                                                                                  |
| 支付类型   | 订阅场景固定使用 `SUBSCRIPTION`                                                                                                               |
| 用户通知   | 订阅成功、扣款前、扣款后都建议向用户发送站外通知                                                                                                              |
| 退订能力   | 生产环境必须在用户侧提供清晰、可访问的取消订阅入口                                                                                                             |
| 支付方式参数 | 订阅申请接口中 `inBankCode` 和 `paymentMethods` 二选一：`inBankCode` 传入单个支付方式编码，`paymentMethods` 传入英文逗号分隔的支付方式列表。`paymentMethods` 暂时仅支持前置组件组合模式使用 |

<Tip title="测试卡号">
  测试卡号请参考 [测试卡号](/docs/zh/V20260628/api/version2/test-cards)
</Tip>

## 常见理解问题

<AccordionGroup>
  <Accordion title="什么时候看这个页面，什么时候看 API Reference？" defaultOpen>
    这个页面用于理解产品能力、选择接入模式和把握业务规则。进入开发联调阶段后，请直接查看 [订阅 API Reference](/docs/zh/api-reference/subscription/api/subscriptionApply) 获取完整字段、示例报文和调试入口。
  </Accordion>

  <Accordion title="为什么订阅业务必须强调退订入口和站外通知？">
    订阅类交易更容易产生用户争议。清晰的授权、通知和退订能力可以显著降低拒付、投诉和风控问题，这也是订阅业务能否稳定上线的关键前置条件。
  </Accordion>

  <Accordion title="生产环境出现 Unsupported region: CN 怎么处理？">
    这通常表示当前生产环境不支持该地区，或当前测试方式与目标地区配置不匹配。请先确认商户配置、目标市场和支付方式组合，再联系 HaiPay 支持团队确认生产可用范围。
  </Accordion>

  <Accordion title="PayUrl 跳转和 前置组件应该怎么选？">
    如果你希望最快上线、前端改动最少，选 PayUrl 跳转模式即可。如果你需要自定义收银台 UI、希望用户不离开你的页面完成支付，选 前置组件模式。两种模式都通过同一个订阅申请接口发起，区别只在于你使用返回的 `payUrl` 还是 `clientToken`。
  </Accordion>

  <Accordion title="inBankCode 和 paymentMethods 应该传哪个？">
    两个参数二选一，不可同时传入，也不可同时为空。如果只使用一种支付方式，传 `inBankCode`；如果需要同时支持多种支付方式（如组合模式），传 `paymentMethods`。注意 `paymentMethods` 暂时仅支持前置组件组合模式使用，其他模式请继续使用 `inBankCode`。
  </Accordion>

  <Accordion title="如果只想尽快做一个现代化订阅页面，推荐哪种模式？">
    如果选择前置组件模式，它能在一个容器内统一呈现多种支付方式，页面更完整，用户理解成本更低，前端开发量也更可控。
  </Accordion>
</AccordionGroup>

## 相关主题

* [Apple Pay 订阅](/docs/zh/V20260628/api/version2/ApplePay)
* [Google Pay 订阅](/docs/zh/V20260628/api/version2/GooglePay)
* [商户发起交易 (MIT)](/docs/zh/V20260628/api/version2/creditcard-mit)
* [国际信用卡支付](/docs/zh/V20260628/api/version2/creditcard)
