# YDP 充值前端对接文档

面向 App/H5。协议约定与 [Splay 2.0 前端对接文档](./splay_2_0_frontend_integration.md) 第 2 节相同：`POST`、登录态、`snake_case`、枚举可传数字或字符串名。

YDP 是印尼站新增法币充值渠道。对接方式和现有 Jaya / EasyPay 一样：**先拉渠道列表，再创订单，再调对应 create 拿收银台 URL。**

提现仍走用户已绑定的银行卡，**前端不用改提现绑卡/提现申请。**

## 1. 新增枚举

| 枚举 | 数字值 | 含义 |
| --- | ---: | --- |
| `PAY_TYPE_YDP` | 20 | YDP 充值 |

网关响应可能返回 `"PAY_TYPE_YDP"` 或 `20`，前端两种都要认。

## 2. 推荐流程

```text
1. POST /v1/order/deposit/channel/list   传入要买的硬币数
2. 展示返回的 channels（已按后台启用状态和 IDR 限额过滤）
3. 用户点某条 YDP 渠道
4. POST /v1/order/create                 pay_type = 20
5. POST /v1/order/ydp/create             payment = 该渠道 params.payment（必传）
6. 跳转 redirect_to_url 到 YDP 收银台
7. 用户支付完成回到 return_url
8. POST /v1/order/ydp/check              确认入账
```

不要写死「只有 QRIS / DANA / VA」。列表里没有的渠道不要展示，也不要自己拼 `payment`。

## 3. 拉可用渠道

`POST /v1/order/deposit/channel/list`

```json
{ "coins": 100 }
```

响应里每条渠道：

| 字段 | 说明 |
| --- | --- |
| `pay_type` | `20` / `PAY_TYPE_YDP` 时走 YDP create 接口 |
| `display_name` | 按钮文案，例如 `YDP QRIS` |
| `params` | **原样传给 create**。YDP 使用 `params.payment` |
| `min_amount` / `max_amount` | 单笔 IDR 限额，`0` 表示不限；列表已按金额过滤，仅展示用 |

当前后台种子渠道（均默认禁用，运营打开后才会出现在列表里）：

| display_name | `params.payment` |
| --- | --- |
| YDP QRIS | `ydidnqris` |
| YDP DANA | `ydidndana` |
| YDP VA | `ydidnva` |

```ts
function isYdpChannel(payType: string | number) {
  return payType === 20 || payType === "PAY_TYPE_YDP";
}

function ydpPayment(params: Record<string, string> | undefined) {
  const payment = (params?.payment ?? "").trim();
  if (!payment) throw new Error("missing params.payment");
  return payment;
}
```

## 4. 创建订单

`POST /v1/order/create`

`pay_type` **必须传 20**。不传或传成 Jaya/EasyPay，后续 `ydp/create` 会失败。

```json
{
  "ref_id": 0,
  "pay_type": 20,
  "quantity": 1,
  "product_type": "PRODUCT_TYPE_POINT_PACK",
  "quantity_decimal": "100"
}
```

`product_type`、`ref_id`、`quantity_decimal` 与现有法币买币保持一致，以你们当前充值页为准。

响应：

```json
{ "no": "O123456" }
```

记下 `no`，后面 create / check 都用它。

## 5. 创建 YDP 支付

`POST /v1/order/ydp/create`

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `order_no` | 是 | 上一步的 `no` |
| `payment` | 是 | 渠道 `params.payment`，不要留空，不要写死 |
| `return_url` | 否 | 支付完成后的回跳页（H5 建议传） |

```json
{
  "order_no": "O123456",
  "payment": "ydidnqris",
  "return_url": "https://your.app/pay/result?order_no=O123456"
}
```

成功：

```json
{
  "redirect_to_url": "https://pay.example/checkout/...",
  "platform_order_no": "Pxxxx"
}
```

用 WebView / 浏览器打开 `redirect_to_url`。`platform_order_no` 仅作展示或排查，入账以 check / 订单状态为准。

失败常见原因：

| 情况 | 前端处理 |
| --- | --- |
| `payment` 为空或不是列表里的值 | 检查是否漏传 `params.payment` |
| 渠道已禁用 / 金额不在该渠道限额 | 重新拉渠道列表，不要继续用旧 `payment` |
| 订单 `pay_type` 不是 YDP | `create` 时必须带 `pay_type: 20` |
| 服务端未开通 YDP | 列表不应出现 YDP；若出现则提示稍后重试 |

## 6. 回跳后验单

`POST /v1/order/ydp/check`

```json
{ "order_no": "O123456" }
```

成功返回空对象，表示已入账。失败表示仍未支付或金额校验未过，保持待支付，可稍后重试 check，也可轮询订单列表看 `status`。

建议：

1. 回跳到 `return_url` 后立刻 check 一次
2. 失败则间隔 2～3 秒再 check，最多几次
3. 仍失败就展示「支付结果确认中」，引导去订单页

服务端还有异步回调，check 不是唯一入账路径；check 成功即可认为到账。

## 7. 和现有渠道的分流

按 `pay_type` 选 create 接口，不要所有法币都打 Jaya：

| `pay_type` | create | check |
| --- | --- | --- |
| `15` Jaya | `/v1/order/jaya/create` | `/v1/order/jaya/check` |
| `19` EasyPay | `/v1/order/easypay/create` | `/v1/order/easypay/check` |
| **`20` YDP** | **`/v1/order/ydp/create`** | **`/v1/order/ydp/check`** |

YDP 和 Jaya 的差别：Jaya 传 `method`，YDP 传 **`payment`**，值来自 `params.payment`。

## 8. 不要做的事

- 不要前端写死三条渠道；以后台列表为准
- 不要把 `display_name` 当 `payment` 传
- 不要用 QRIS 渠道的订单去调 DANA 的 `payment`
- 不要在 create 订单时漏传 `pay_type: 20`
- 提现页不需要加 YDP 选项
