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

# 订阅（历史导航 V20260628）

> 历史订阅支付指南：对比收银台模式与在一个容器内展示 Google Pay、Apple Pay 和信用卡的前置组件模式，并说明上线要求与争议费用。

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

> **[快速开始](#quick-start)**
>
> 先看接入步骤、必备能力和推荐阅读路径。

> **[集成模式](#integration-modes)**
>
> 对比 Apple Pay / Google Pay、信用卡组件和组合模式。

> **[核心 API](#core-apis)**
>
> 直接进入订阅申请、查询、取消和退款接口。

> [!WARNING]
>
> * 提供明确的订阅入口、扣款周期说明和退订入口。
> * 在订阅成功以及每次扣款前后，通过邮件或其他站外方式通知用户。
> * 提供可确认的订阅协议，并在用户明确授权后再发起订阅。
> * 保持客服可用，至少覆盖主要运营地区的服务时间。

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

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

## 快速开始

**1. 确认业务模式与前置条件**

先阅读 [接口说明](https://doc.haipay.net/zh/history/V20260628/get-started/api-conventions.md) 和 [订阅流程](https://doc.haipay.net/zh/history/V20260628/payments/subscriptions/workflow.md)，确认你的场景是自动续费而不是代收支付。

**2. 选择接入模式**

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

**3. 接入 API、通知与取消能力**

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

## 集成模式

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

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

**收银台模式**

最简单的接入方式。商户服务端调用订阅申请接口后，使用返回的 `payUrl` 将用户跳转到 HaiPay 托管的支付页面，用户在该页面完成授权和首笔支付。

**接入流程**

**1. 服务端调用订阅申请接口**

商户服务端向 HaiPay 发起 [订阅申请](https://doc.haipay.net/zh/history/V20260628/api-reference/subscription/api/subscriptionApply.md)，在请求中传入订阅金额、周期、回调地址等必要参数。

**2. 获取 payUrl 并跳转**

接口返回中包含 `payUrl` 字段，商户将用户浏览器重定向到该地址。

**3. 用户完成支付**

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

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

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

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

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

**适用建议**

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

**前置组件模式**

通过引入 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);
});
```

## 核心 API

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

> **[订阅申请](https://doc.haipay.net/zh/history/V20260628/api-reference/subscription/api/subscriptionApply.md)**
>
> 创建订阅订单，拉起用户授权并完成首笔订阅支付。

> **[查询订阅](https://doc.haipay.net/zh/history/V20260628/api-reference/subscription/subscription-query.md)**
>
> 查询订阅状态、平台订阅号和扣款记录。

> **[取消订阅](https://doc.haipay.net/zh/history/V20260628/api-reference/subscription/subscription-cancel.md)**
>
> 由商户主动发起取消，停止后续周期扣款。

## 异步通知

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

> [!TIP]
>
> 为保障接口的扩展性和兼容性，请遵循以下回调参数接收方式：
>
> 1. **禁止**声明具体 POJO 对象接收回调参数。
> 2. **必须**使用通用数据结构（如 JSONObject、Map 等）进行参数解析。
> 3. 此设计可确保后续扩展回调字段时，不会影响验签逻辑。

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

**订阅状态通知**

当订阅状态发生变更时触发（如订阅成功、订阅取消、订阅失败等）。

| 参数名 | 类型 | 说明 |
| :- | :- | :- |
| `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 | 签名（需要使用币种对应的业务密钥信息进行验签） |

**订阅扣款通知**

当每期周期扣款成功或失败时触发。

| 参数名 | 类型 | 说明 |
| :- | :- | :- |
| `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 | 签名（需要使用币种对应的业务密钥信息进行验签） |

## 关键业务规则

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

> [!TIP]
>
> 测试卡号请参考 [测试卡号](https://doc.haipay.net/zh/history/V20260628/testing/test-cards.md)

## 常见理解问题

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

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

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

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

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

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

## 相关主题

* [Apple Pay 订阅](https://doc.haipay.net/zh/history/V20260628/api/version2/ApplePay.md)
* [Google Pay 订阅](https://doc.haipay.net/zh/history/V20260628/api/version2/GooglePay.md)
* [商户发起交易 (MIT)](https://doc.haipay.net/zh/history/V20260628/payments/cards/merchant-initiated-transactions.md)
* [国际信用卡支付](https://doc.haipay.net/zh/history/V20260628/api/version2/creditcard.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.