> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/common/monetization/toss-pay/toss-pay-subscription.md).

# 开发定期订阅

本页介绍在迷你应用中对接 Toss Pay 定期支付的方法。按“创建 billing key → 用户认证 → 支付批准 → 解除”顺序说明整个流程。

### 预先准备事项

#### 需要进行控制台设置

在调用 API 之前，需要先完成以下步骤。

1. 请先进行签约。
2. 请在控制台注册 Toss Pay key 值。

{% hint style="info" %}
**请务必确认**

* 即使之前已经在使用 Toss Pay， **在 Apps in Toss 中需要另外发放 Toss Pay 商户密钥。**
* 即使在 Apps in Toss 中正在使用 Toss Pay， **定期支付（自动扣款）需要额外签约。**
  {% endhint %}

签约/手续费/设置方法请见 [Toss Pay 介绍](https://developers-apps-in-toss.toss.im/documentation/common/monetization/toss-pay) 文档。

#### 识别支付对象用户

Toss Pay 会通过以下两种方法之一来识别支付对象。请不要同时传递两个值，只选择一个。

| 区分                | 获取方式                                                                                                                  |
| ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| `x-toss-user-key` | [通过 Toss 登录](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)中获得的 `userKey` 值。 |
| `x-anon-key`      | [用户识别键发放](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)获得的 hash 值。            |

请根据目的选择。

* 如果已经接入 Toss 登录，或想与姓名、邮箱等会员信息绑定并统一管理，就使用 Toss 登录。
* 如果不接入登录，只想轻量识别用户，就使用用户识别密钥发放功能。

`x-anon-key`如果想提前确认 (hash) 是否为有效值， [验证识别键](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key#식별키-검증하기) API。

***

### 基本信息

| 项目           | 值                                      |
| ------------ | -------------------------------------- |
| Base URL     | `https://pay-apps-in-toss-api.toss.im` |
| 服务器认证        | mTLS（客户端证书）                            |
| Content-Type | `application/json`                     |

{% hint style="info" %}
**服务器间通信需要 mTLS 证书**

定期支付 API 是由合作伙伴服务器调用 Apps in Toss 服务器的服务器间通信。为确保安全，请先在服务器上配置 mTLS 证书后再发起调用。证书发放方法请见 [mTLS 证书发放方法](https://developers-apps-in-toss.toss.im/documentation/integration/getting-started)。
{% endhint %}

***

### 测试

在请求创建支付时 `isTestPayment: true`设置为该值后，即可在沙盒环境中测试支付。无需在控制台单独设置，也可以在签约前测试。

不过，沙盒环境有以下限制。

* 只能进行创建 billing key（第 1 步），不支持支付批准（第 3 步）。
* 在沙盒中生成的 `wrappedToken`不能在生产环境中使用。
* 实际支付流程验证需切换为生产密钥后进行。

***

### 1. 创建 billing key

注册用户的定期支付方式。将响应中返回的 `wrappedToken`传递给客户端以进行用户认证。

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/pay/create-billing-key`

**请求头**

用于识别支付对象的 header 使用以下两种之一。不要同时传递两个 header。

| 名称                | 类型     | 必填   | 说明                                                                                                                                                                                                                                   |
| ----------------- | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x-toss-user-key` | string | 任选 1 | [通过 Toss 登录](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)中获得的 `userKey`。 [可通过](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)获取用户信息 |
| `x-anon-key`      | string | 任选 1 | [用户识别键发放](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)中获得的 `hash` 值。                                                                                                                        |

**请求参数**

| 字段              | 类型     | 必填 | 说明                 |
| --------------- | ------ | -- | ------------------ |
| `productDesc`   | String | Y  | 定期支付商品名（例如：“月度订阅”） |
| `isTestPayment` | 布尔值    | Y  | 是否为测试支付            |

```json
{
  "productDesc": "月度订阅",
  "isTestPayment": false
}
```

**响应参数**

| 字段             | 类型     | 说明                             |
| -------------- | ------ | ------------------------------ |
| `wrappedToken` | String | 这是定期支付 token。之后所有 API 调用都会使用它。 |

```json
{
  "resultType": "SUCCESS",
  "success": {
    "wrappedToken": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

{% hint style="info" %}
**请务必确认**

`wrappedToken`在支付批准、状态查询和解除时都会使用，因此必须保存。
{% endhint %}

***

### 2. 进行用户认证

**请通过 SDK 接入。**

从创建 billing key 的响应中获得的 `wrappedToken`传递给客户端。客户端使用 Apps in Toss SDK 执行 Toss Pay 认证。

```typescript
import { TossPay } from '@apps-in-toss/web-framework';

const { success, reason } = await TossPay.requestTossPayPaysBilling({ wrappedToken });

if (success) {
  // 认证成功 → 向服务器请求支付批准
} else {
  // 认证失败（reason 中包含失败原因）
}
```

**返回值**

| 字段        | 类型      | 说明     |
| --------- | ------- | ------ |
| `success` | boolean | 是否认证成功 |
| `reason`  | string? | 失败时的原因 |

{% hint style="info" %}
**SDK 最低支持版本**

* Android: `5.256.0`
* iOS: `5.256.0`
  {% endhint %}

***

### 3. 执行定期支付

使用已登记的支付方式批准支付。

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/pay/execute-billing`

**请求头**

用于识别支付对象的 header 使用以下两种之一。不要同时传递两个 header。

| 名称                | 类型     | 必填   | 说明                                                                                                                                                                                                                                   |
| ----------------- | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x-toss-user-key` | string | 任选 1 | [通过 Toss 登录](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)中获得的 `userKey`。 [可通过](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)获取用户信息 |
| `x-anon-key`      | string | 任选 1 | [用户识别键发放](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)中获得的 `hash` 值。                                                                                                                        |

**请求参数**

| 字段                       | 类型     | 必填 | 说明                        |
| ------------------------ | ------ | -- | ------------------------- |
| `wrappedToken`           | String | Y  | 创建 billing key 时获得的 token |
| `orderNo`                | String | Y  | 订单号                       |
| `productDesc`            | String | Y  | 商品说明                      |
| `spreadOut`              | Int    | Y  | 分期月数（0=一次性支付）             |
| `amount`                 | Long   | Y  | 支付金额                      |
| `amountTaxFree`          | Long   | Y  | 免税金额                      |
| `amountTaxable`          | Long   | N  | 应税金额                      |
| `amountVat`              | Long   | N  | 增值税                       |
| `amountServiceFee`       | Long   | N  | 服务费                       |
| `cashReceipt`            | 布尔值    | N  | 是否开具现金收据（默认：true）         |
| `sendFailPush`           | 布尔值    | N  | 失败时是否发送推送（默认：true）        |
| `cashReceiptTradeOption` | String | N  | 现金收据类型（默认：GENERAL）        |
| `isTestPayment`          | 布尔值    | Y  | 是否为测试支付                   |

```json
{
  "wrappedToken": "550e8400-e29b-41d4-a716-446655440000",
  "orderNo": "ORDER-20260416-001",
  "productDesc": "月度订阅支付",
  "spreadOut": 0,
  "amount": 9900,
  "amountTaxFree": 0,
  "isTestPayment": false
}
```

**响应参数**

| 字段                    | 类型     | 说明                                                                                                                                          |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `code`                | Int    | 这是响应代码。为 0 时表示成功。                                                                                                                           |
| `mode`                | String | 这是支付模式。                                                                                                                                     |
| `payToken`            | String | 是支付令牌。                                                                                                                                      |
| `orderNo`             | String | 这是订单号。                                                                                                                                      |
| `payMethod`           | String | 这是支付方式。（CARD、TOSS\_MONEY 等）                                                                                                                 |
| `amount`              | Int    | 这是批准金额。                                                                                                                                     |
| `transactionId`       | String | 这是交易 ID。                                                                                                                                    |
| `approvalTime`        | String | 这是批准时间。                                                                                                                                     |
| `discountedAmount`    | Int    | 这是折扣金额。                                                                                                                                     |
| `paidAmount`          | Int    | 这是实际支付金额。                                                                                                                                   |
| `cardCompanyName`     | String | 确认的发卡公司名称。                                                                                                                                  |
| `cardCompanyCode`     | String | 确认的发卡公司代码。                                                                                                                                  |
| `cardAuthorizationNo` | String | 买家可确认的发卡公司授权号。在 Live Key 支付中可查看。                                                                                                            |
| `salesCheckLinkUrl`   | String | 信用卡销售小票调用 URL。                                                                                                                              |
| `noInterest`          | String | 是否适用信用卡免息。 `true`: 免息, `false`: 普通                                                                                                          |
| `cardNumber`          | String | 已脱敏的卡号。16 位卡号中间部分会被脱敏。                                                                                                                      |
| `cardUserType`        | String | 卡用户类型。 `PERSONAL`: 本人卡, `PERSONAL_FAMILY`: 家庭卡, `CORP_PERSONAL`: 法人指定结算账户员工, `CORP_PRIVATE`: 法人共用, `CORP_COMPANY`: 法人指定结算账户公司（仅限 Hana Card） |
| `cardBinNumber`       | String | 卡 BIN 号。                                                                                                                                    |
| `cardNum4Print`       | String | 用户选择的卡的末 4 位。                                                                                                                               |

```json
{
  "resultType": "SUCCESS",
  "success": {
    "code": 0,
    "mode": "LIVE",
    "payToken": "7W3000019000001",
    "orderNo": "ORDER-20260416-001",
    "payMethod": "CARD",
    "amount": 9900,
    "transactionId": "20260416000001",
    "approvalTime": "20260416120000",
    "discountedAmount": 0,
    "paidAmount": 9900,
    "cardCompanyName": "三星",
    "cardCompanyCode": 3,
    "cardAuthorizationNo": "87654321",
    "salesCheckLinkUrl": "https://pay.toss.im/payfront/web/external/sales-check?payToken=example-payToken",
    "noInterest": false,
    "cardNumber": "654321******1234",
    "cardUserType": "NONE",
    "cardBinNumber": "654321",
    "cardNum4Print": "1234"
  }
}
```

***

### 4. 退还定期支付

退还定期支付订单。

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/pay/refund-billing`

**请求头**

用于识别支付对象的 header 使用以下两种之一。不要同时传递两个 header。

| 名称                | 类型     | 必填   | 说明                                                                                                                                                                                                                                   |
| ----------------- | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x-toss-user-key` | string | 任选 1 | [通过 Toss 登录](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)中获得的 `userKey`。 [可通过](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)获取用户信息 |
| `x-anon-key`      | string | 任选 1 | [用户识别键发放](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)中获得的 `hash` 值。                                                                                                                        |

**请求参数**

| 字段              | 类型     | 必填 | 说明                            |
| --------------- | ------ | -- | ----------------------------- |
| `payToken`      | String | Y  | 从执行定期支付（第 3 步）的响应中获得的支付 token |
| `reason`        | String | Y  | 退款原因                          |
| `isTestPayment` | 布尔值    | Y  | 是否为测试支付                       |

```json
{
  "payToken": "string",
  "reason": "string",
  "isTestPayment": true
}
```

**响应参数**

| 名称                       | 类型      | 说明                                                                                                                                          |
| ------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `refundNo`               | String  | 退款编号。                                                                                                                                       |
| `approvalTime`           | String  | 退款处理时间。 (yyyy-MM-dd HH:flag\_mm:ss)                                                                                                         |
| `cashReceiptMgtKey`      | String  | 现金收据管理编号标识值。                                                                                                                                |
| `refundableAmount`       | Integer | 可退款金额。                                                                                                                                      |
| `discountedAmount`       | Integer | 折扣金额。                                                                                                                                       |
| `paidAmount`             | Integer | 支付方式确认金额。                                                                                                                                   |
| `refundedAmount`         | Integer | 退款请求金额。                                                                                                                                     |
| `refundedDiscountAmount` | Integer | 退款请求金额中实际扣除的折扣金额。                                                                                                                           |
| `refundedPaidAmount`     | Integer | 退款请求金额中实际扣除的支付方式金额。                                                                                                                         |
| `payToken`               | String  | 已退款的支付令牌。                                                                                                                                   |
| `transactionId`          | String  | 交易事务 ID。                                                                                                                                    |
| `cardMethodType`         | String  | 卡类型。 `CREDIT`: 信用卡, `CHECK`: 借记卡, `PREPAYMENT`: 预付卡                                                                                         |
| `cardNumber`             | String  | 已脱敏的卡号。                                                                                                                                     |
| `cardUserType`           | String  | 卡用户类型。 `PERSONAL`: 本人卡, `PERSONAL_FAMILY`: 家庭卡, `CORP_PERSONAL`: 法人指定结算账户员工, `CORP_PRIVATE`: 法人共用, `CORP_COMPANY`: 法人指定结算账户公司（仅限 Hana Card） |
| `cardNum4Print`          | String  | 用户选择的卡的末 4 位。                                                                                                                               |
| `cardBinNumber`          | String  | 卡 BIN 号。                                                                                                                                    |
| `accountBankCode`        | String  | 银行代码。若为 Toss Money 支付，则传递 Toss 定义的银行代码。                                                                                                     |
| `accountBankName`        | String  | 银行名称。                                                                                                                                       |
| `accountNumber`          | String  | 已脱敏的账号。                                                                                                                                     |

```json
{
  "resultType": "SUCCESS",
  "success": {
    "refundNo": "string",
    "approvalTime": "string",
    "cashReceiptMgtKey": "string",
    "refundableAmount": 0,
    "discountedAmount": 0,
    "paidAmount": 0,
    "refundedAmount": 0,
    "refundedDiscountAmount": 0,
    "refundedPaidAmount": 0,
    "payToken": "string",
    "transactionId": "string",
    "cardMethodType": "string",
    "cardNumber": "string",
    "cardUserType": "string",
    "cardNum4Print": "string",
    "cardBinNumber": "string"
    "accountBankCode": "string",
    "accountBankName": "string",
    "accountNumber": "string"
  }
}
```

***

### 5. 查询 billing key 状态

查询已登记定期支付方式的状态。

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/pay/get-billing-key-status`

**请求头**

用于识别支付对象的 header 使用以下两种之一。不要同时传递两个 header。

| 名称                | 类型     | 必填   | 说明                                                                                                                                                                                                                                   |
| ----------------- | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x-toss-user-key` | string | 任选 1 | [通过 Toss 登录](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)中获得的 `userKey`。 [可通过](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)获取用户信息 |
| `x-anon-key`      | string | 任选 1 | [用户识别键发放](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)中获得的 `hash` 值。                                                                                                                        |

**请求参数**

| 字段              | 类型     | 必填 | 说明         |
| --------------- | ------ | -- | ---------- |
| `wrappedToken`  | String | Y  | 定期支付 token |
| `isTestPayment` | 布尔值    | Y  | 是否为测试支付    |

```json
{
  "wrappedToken": "550e8400-e29b-41d4-a716-446655440000",
  "isTestPayment": false
}
```

**响应参数**

| 字段                 | 类型     | 说明                                      |
| ------------------ | ------ | --------------------------------------- |
| `code`             | Int    | 这是响应代码。为 0 时表示成功。                       |
| `billingKeyStatus` | String | 这是 billing key 状态。                      |
| `cardCompanyName`  | String | 确认的发卡公司名称。                              |
| `cardCompanyNo`    | String | 确认的发卡公司代码。                              |
| `cardNumber`       | String | 已脱敏的卡号。16 位卡号中间部分会被脱敏。                  |
| `cardImgUrl`       | String | 这是卡片图片。                                 |
| `accountBankName`  | String | 银行名称。                                   |
| `accountBankCode`  | String | 银行代码。若为 Toss Money 支付，则传递 Toss 定义的银行代码。 |
| `accountNumber`    | String | 账号。包含部分脱敏。                              |
| `accountName`      | String | 银行名称。                                   |
| `accountImgUrl`    | String | 这是银行图片。                                 |

***

### 6. 解除 billing key

解除已登记的定期支付方式。解除后，该 `wrappedToken`token 将无法再用于支付批准。

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/pay/remove-billing-key`

**请求头**

用于识别支付对象的 header 使用以下两种之一。不要同时传递两个 header。

| 名称                | 类型     | 必填   | 说明                                                                                                                                                                                                                                   |
| ----------------- | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x-toss-user-key` | string | 任选 1 | [通过 Toss 登录](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)中获得的 `userKey`。 [可通过](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)获取用户信息 |
| `x-anon-key`      | string | 任选 1 | [用户识别键发放](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)中获得的 `hash` 值。                                                                                                                        |

**请求参数**

| 字段              | 类型     | 必填 | 说明         |
| --------------- | ------ | -- | ---------- |
| `wrappedToken`  | String | Y  | 定期支付 token |
| `isTestPayment` | 布尔值    | Y  | 是否为测试支付    |

```json
{
  "wrappedToken": "550e8400-e29b-41d4-a716-446655440000",
  "isTestPayment": false
}
```

**响应参数**

| 字段     | 类型     | 说明                |
| ------ | ------ | ----------------- |
| `code` | Int    | 这是响应代码。为 0 时表示成功。 |
| `msg`  | String | 这是结果消息。           |

***

### 代码及错误列表

**银行代码列表**

在 Toss Money 支付时，会一并传递用户选择的账户信息。

| 银行代码 | 银行名称       |
| ---- | ---------- |
| 002  | KDB产业银行    |
| 003  | IBK企业银行    |
| 004  | KB国民银行     |
| 005  | KEB韩亚银行    |
| 007  | 水协银行       |
| 011  | NH农协银行     |
| 020  | 友利银行       |
| 023  | SC银行       |
| 027  | 花旗银行       |
| 031  | 大邱银行       |
| 032  | 釜山银行       |
| 034  | 光州银行       |
| 035  | 济州银行       |
| 037  | 全北银行       |
| 039  | 庆南银行       |
| 045  | MG新村金库     |
| 048  | 新协         |
| 050  | 储蓄银行       |
| 064  | 山林组合       |
| 071  | 邮局         |
| 081  | 韩亚银行       |
| 088  | 新韩银行       |
| 089  | K银行        |
| 090  | Kakao银行    |
| 092  | Toss银行     |
| 103  | SBI储蓄银行    |
| 218  | KB证券       |
| 230  | 未来资产证券     |
| 238  | 未来资产证券     |
| 240  | 三星证券       |
| 243  | 韩国投资证券     |
| 247  | NH投资证券     |
| 261  | 教保证券       |
| 262  | HI投资证券     |
| 263  | 现代汽车投资证券   |
| 264  | Kiwoom证券   |
| 265  | Ebest证券    |
| 266  | SK证券       |
| 267  | 大信证券       |
| 269  | 韩华投资证券     |
| 270  | 韩亚证券       |
| 271  | Toss证券     |
| 278  | 新韩投资证券     |
| 279  | DB金融投资     |
| 280  | Eugene投资   |
| 287  | Meritz证券   |
| 888  | Toss Money |
| 889  | Toss积分     |

**卡公司代码列表**

| 卡公司名称   | 卡（收单行）代码 |
| ------- | -------- |
| 新韩      | 1        |
| 现代      | 2        |
| 三星      | 3        |
| 国民      | 4        |
| 乐天      | 5        |
| 韩亚      | 6        |
| 友利      | 7        |
| 农协      | 8        |
| 花旗（不支持） | 9        |
| BC（BC）  | 10       |

**billing key 状态列表**

| 状态               | billing key 状态代码 |
| ---------------- | ---------------- |
| billing key 创建完成 | CREATED          |
| 用户认证进行中          | AUTHENTICATING   |
| 用户认证完成           | ACTIVE           |
| billing key 删除   | REMOVED          |
| 无效的 billing key  | FAILED           |

**错误情况**

| code  | 情况                  | 错误消息                   |
| ----- | ------------------- | ---------------------- |
| 5001  | 尚未完成 Toss Pay 签约的状态 | 尚未签约 Toss Pay。         |
| 5005  | 尝试使用已解除的 token 支付   | 这是已停用的 billing key。    |
| 5006  | 使用无效 token 调用       | 找不到 billing key。       |
| 40000 | 请求数据无效时             | 请求数据无效。                |
| -     | Toss Pay 侧错误        | 会返回 Toss Pay 的错误代码和消息。 |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/common/monetization/toss-pay/toss-pay-subscription.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
