1.配置新版支付模块-菜单和接口都已重构
2.优化充值提现页面 3.菜单翻译问题 4.备份数据库
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
- **请求方法**:所有移动端业务接口(`/api/*`,不含 `/api/v1/authToken`)一律使用 `POST` 调用;查询类接口同时兼容 `GET`(便于浏览器/调试工具直接访问),客户端统一走 `POST`
|
||||
- `POST` 时请求头 `Content-Type: application/json`,参数放在 JSON body
|
||||
- `GET` 兼容模式下,参数走 URL query string
|
||||
- **例外**:公告模块 `/api/notice/noticeList`、`/api/notice/noticeDetail`、`/api/notice/noticeConfirm` 与模拟收银台页 `/api/finance/depositMockPayPage` **仅支持 `GET`**,参数一律走 URL query string
|
||||
- **例外**:公告模块 `/api/notice/noticeList`、`/api/notice/noticeDetail`、`/api/notice/noticeConfirm` **仅支持 `GET`**,参数一律走 URL query string
|
||||
- 鉴权类接口 `/api/v1/authToken` 仍为 `GET`
|
||||
- 时间:UTC 时间戳(秒) + 服务端时区配置
|
||||
- 金额:数字传输(如 `"100.00"`),客户端展示统一保留两位小数(存储仍为 `decimal(18,2)`)
|
||||
@@ -426,28 +426,66 @@
|
||||
- `processing_note`:string(到账提示文案)
|
||||
- `fee_note`:string(手续费提示文案)
|
||||
- `rate_mode`:string(`fixed` / `live`)
|
||||
- `fields`:object(提现表单必填项开关)
|
||||
- `fields`:object(**与 DDPay / `withdrawCreate` 一致**,不由后台「支付/收款配置」开关维护;用于客户端展示必填项)
|
||||
- `receive_type_bank_only`:bool(当前固定 `true`,仅支持银行卡出金)
|
||||
- `require_receiver_name`:bool(固定 `true`,对应 `receiver_name`)
|
||||
- `require_receive_account`:bool(固定 `true`,对应 `receive_account`)
|
||||
- `require_bank_code`:bool(固定 `true`,对应 `bank_code`)
|
||||
- `require_bank_branch`:bool(固定 `false`,`bank_branch` 选填,不传时服务端按 `N/A` 提交 DDPay)
|
||||
|
||||
### 5.4 创建充值订单
|
||||
- **POST** `/api/finance/depositCreate`
|
||||
- `Content-Type: application/json`(推荐)、`application/x-www-form-urlencoded` 或 **`multipart/form-data`**(如 Apifox 的 form-data);字段名与下表一致即可,服务端通过统一参数名读取,**不限制**为某一种 body 类型。
|
||||
|
||||
说明(与真实「创建订单 → 调起三方 → 异步回调」一致):
|
||||
- **创建单**:`depositCreate` 仅写入 **待支付** 订单(`status=pending`),**不在此请求内入账**。返回体中 `paid=false`,`pay_url` 为 **模拟第三方收银台** 完整 URL(HMAC 防篡改,见下 §5.4.1)。
|
||||
- **客户端**:在 WebView/系统浏览器中打开 `pay_url`;用户完成支付后(模拟页为「确认支付」按钮),由服务端 `depositMockNotify` 验签后调用 `DepositSettlement::settle` 入账,并推送 `wallet.changed`;客户端可轮询 `depositDetail` 或依赖推送更新余额。
|
||||
- **未来接入真实第三方支付**:将 `pay_url` 与回调 URL 替换为真网关,入账仍**仅**在回调/验签成功路径中调用 `DepositSettlement::settle`(与当前模拟回调一致)。
|
||||
- 档位与渠道取自 `depositTierList`:创建订单时须选择返回 `channels` 中某一渠道的 `code` 作为 `channel_code` 传入;服务端会校验档位存在、启用且渠道已启用。
|
||||
- **HMAC 密钥**:模拟链路与签名校验使用环境变量 **`DEPOSIT_MOCK_HMAC_KEY`**(或 `config('app.deposit_mock_hmac_key')`);生产环境务必配置,与代码中默认值区分。
|
||||
- **并发上限**:同一用户最多同时存在 **3 笔待支付充值单**(`status=0`);超过后创建接口返回 `code=2005`。
|
||||
- **超时失效**:充值单创建后 **60 秒内未支付**将自动置为失败(`status=failed`),并在订单备注记录失败原因(`[timeout] unpaid over 60s`)。
|
||||
- **定时任务兜底**:服务端进程 `depositOrderExpireTicker` 每 **10 秒**主动扫描超时待支付单,保证即使用户不访问任何充值接口也会准时失效。
|
||||
说明:
|
||||
- **仅支持 DDPay**:`channel_code` 必须为 **`ddpay`**,否则返回 `code=2004`。
|
||||
- `depositCreate` 先创建 `status=pending` 的充值单,再调用 DDPay「入金发起」;若成功返回 `payment_url`,则 `pay_url=payment_url`。
|
||||
- 入账由 **`POST /api/finance/ddpayDepositNotify`** 验签后结算,或网关同步返回 `transaction_status=completed` 时结算。
|
||||
- 档位与渠道取自 `depositTierList`:`channels` 中仅会出现 `ddpay`(与后台「支付/收款配置」一致)。
|
||||
- 同一用户最多 3 笔待支付充值单;创建后 60 秒未支付会超时失败。
|
||||
|
||||
请求参数(**三者缺一不可**,任一为空或空白即 `code=1001` 参数缺失):
|
||||
- `tier_id`:string,必填(含义:玩家选择的充值档位 ID,取自 `depositTierList` 的 `id`;也可用同义字段名 `tier_key`)
|
||||
- `channel_code`:string,必填(含义:支付渠道代码,**小写**;须与所选档位在 `depositTierList` 返回的 `channels[].code` 之一一致,例如默认内置渠道常为 `directpay`)
|
||||
- `idempotency_key`:string,必填,≤64(含义:客户端生成的唯一键,短时间内同 `idempotency_key` 不会重复下单;建议 UUID。**调试工具中若使用变量,请确保解析后非空**)
|
||||
请求参数:
|
||||
|
||||
> **常见 1001 原因**:只传了 `tier_id` + `idempotency_key`,**漏传 `channel_code`**。请先调 `depositTierList`,用对应档位下 `channels` 中某项的 `code` 作为 `channel_code`。
|
||||
**A. 通用必填参数**
|
||||
- `tier_id`:string,必填(充值档位 ID;同义字段:`tier_key`)
|
||||
- `channel_code`:string,必填,固定传 **`ddpay`**
|
||||
- `idempotency_key`:string,必填,≤64(客户端幂等键,建议 UUID)
|
||||
|
||||
**B. DDPay 渠道必填参数(`channel_code=ddpay`)**
|
||||
|
||||
> **依据**:DDPay 官方《Payment Gateway》接口说明(与仓库内 `docs/DDPay Payment Gateway_v1.1.3_zh.md` / `docs/DDPay Payment Gateway_v1.1.3.pdf` 一致;以下「官方」均指该文档)。
|
||||
|
||||
- `payment_type`:string,必填(DDPay 字段 **`payment_type`,支付方式选择**)
|
||||
- **取值须为官方枚举字符串**(文档 §3.1):**`01`** = FPX,**`02`** = duitnow,**`03`** = ewallet;**其他取值须向 DDPay 商户支持另行确认**,勿自行臆造。
|
||||
- 兼容字段:`paymentType`
|
||||
- **注意**:若传入 `FPX`、`duitnow` 等**非官方编码**,网关可能直接拒绝;移动端应传 **`01` / `02` / `03`**。
|
||||
- `payer_name`:string,必填(**付款账户持有人姓名**,须与银行登记信息一致)
|
||||
- 兼容字段:`payerName`
|
||||
- `payer_bank_name`:string,必填(对应官方字段 **`payer_bank[name]`,付款银行名称**)
|
||||
- 须使用 **DDPay 银行列表中的银行全称**(与官方附录一致):**MYR** 参考官方附录「入金银行列表(MYR)」中 **英文全称**(如 `Public Bank`、`Maybank2U`);**THB** 参考「入金银行列表(THB)」中 **英文全称**(如 `BANGKOK BANK PUBLIC COMPANY LTD.`)。勿使用简称或与列表不一致的拼写,否则可能被网关拒单。
|
||||
- 兼容字段:`payer_bank[name]`、`payerBankName`
|
||||
|
||||
**B.1 服务端代传、客户端无需传的 DDPay 字段(供联调对照)**
|
||||
|
||||
以下由服务端在调用 DDPay「入金发起」时自动组装(来自环境/配置),移动端**不要**也无法通过本接口覆盖:
|
||||
|
||||
- `client_id`、`identifier`(若项目环境已配置 `DDPAY_IDENTIFIER`)、`order_id`(即本系统 `order_no`)
|
||||
- `transaction_amount`:取自所选档位的 **`pay_amount`**(法币应付额,类型为 Decimal),币种以商户在 DDPay **onboarding 时约定币种**为准;官方示例表写 **MYR**,若贵司为 THB 等,以 DDPay 后台为准。
|
||||
- `callback_url`、`redirect_url`:由服务端拼接,根地址优先读取环境变量 **`DDPAY_PUBLIC_BASE_URL`**(见 `.env-example`),未配置时按请求 `Host` 推导;官方要求 **HTTPS**(生产务必配置公网 HTTPS 根地址)。
|
||||
|
||||
> **常见 1001 原因(DDPay)**:只传了通用参数,漏传 `payment_type / payer_name / payer_bank_name` 之一;或 `payment_type` 未使用官方 `01/02/03`。
|
||||
|
||||
推荐请求示例(DDPay,MYR + FPX):
|
||||
```json
|
||||
{
|
||||
"tier_id": "t_xxxxxxxx",
|
||||
"channel_code": "ddpay",
|
||||
"idempotency_key": "dp_20260429_xxx",
|
||||
"payment_type": "01",
|
||||
"payer_name": "ZHANG SAN",
|
||||
"payer_bank_name": "Public Bank"
|
||||
}
|
||||
```
|
||||
|
||||
返回参数:
|
||||
- `order_no`:string(含义:充值订单号)
|
||||
@@ -456,31 +494,38 @@
|
||||
- `total_amount`:string(2 位小数,含义:实际入账总额 = amount + bonus_amount)
|
||||
- `pay_channel`:string(含义:支付通道标识,与请求中选择的 `channel_code` 一致,落库在订单上)
|
||||
- `paid`:bool(含义:当前单据是否已到账;`true` 表示钱包已入账、`status=paid`;`false` 表示待玩家在第三方支付页面完成支付)
|
||||
- `pay_url`:string(含义:第三方支付收银台地址;**`paid=false`(待支付)** 时返回**完整 URL**(如 `https://你的域名/api/finance/depositMockPayPage?order_no=...&sign=...`);`paid=true` 时为空串)
|
||||
- `pay_url`:string(含义:DDPay 返回的收银台地址;**`paid=false`(待支付)** 时为三方 **`payment_url`(完整 URL)**;`paid=true` 时为空串)
|
||||
- `status`:string(`pending`/`paid`/`failed`,含义:本接口创建成功时为 `pending`,入账完成后为 `paid`)
|
||||
- `create_time`:int(含义:订单创建时间,秒级时间戳)
|
||||
- `pay_time`:int(含义:订单到账时间,未到账为 0)
|
||||
|
||||
#### 5.4.1 模拟第三方:收银台页与「异步通知」回调(开发/无真网关时使用)
|
||||
#### 5.4.1 DDPay 回调与状态说明(当前实现)
|
||||
|
||||
- **GET** `/api/finance/depositMockPayPage`
|
||||
- **Query**:`order_no`(与 `depositCreate` 返回一致)、`sign`(HMAC,与 `pay_url` 中一致;**不要自行拼接,须完整使用 `depositCreate` 返回的 `pay_url` 或同接口再次查询到的地址**)
|
||||
- 无需 `auth-token` / `user-token`(外跳浏览器使用)。
|
||||
- 返回:HTML 页面,用户点击 **「确认支付(模拟成功)」** 即提交到下方 `depositMockNotify`。
|
||||
- 回调地址:`POST /api/finance/ddpayDepositNotify`(由服务端在 DDPay 发起请求时作为 **`callback_url`** 传给三方;须 **HTTPS**)。
|
||||
- 官方 Webhook 负载字段(文档 §3.5,处理前**必须先验签**):
|
||||
|
||||
- **POST** `/api/finance/depositMockNotify`
|
||||
- **Body**(`application/x-www-form-urlencoded` 或 JSON 均可,字段名一致即可):`order_no`、`sign`(与上页/支付链接一致)
|
||||
- 无需 `user-token`;`auth-token` 可选(当前实现不校验)。
|
||||
- 验签成功后:对 `status=0` 的订单执行入账(`DepositSettlement::settle`,`source=third_party` 语义),并推送 `wallet.changed`。已入账订单**幂等**再调返回当前订单信息。
|
||||
- 成功响应:与 `depositCreate` 成功体相同结构(`code=1` + `data` 为统一充值订单结构)。
|
||||
| 参数 | 说明 |
|
||||
|---|---|
|
||||
| `client_id` | 商户标识 |
|
||||
| `order_id` | 交易引用号(与本系统充值 `order_no` 对应) |
|
||||
| `transaction_status` | 最终状态:`pending` / `completed` / `failed`(含义见官方 §4.1) |
|
||||
| `timestamp` | 通知时间 |
|
||||
| `transaction_amount` | 支付金额(配置币种下) |
|
||||
| `signature` | 通知校验签名 |
|
||||
|
||||
- 我方验签通过后:
|
||||
- `transaction_status=completed`:执行入账结算,订单转 `paid`
|
||||
- `transaction_status=failed`:订单转 `failed`
|
||||
- 官方要求:收到通知后应尽快返回 HTTP **200**,响应体为纯文本 **`{"status":"ok"}`**;未收到确认时平台最多重试 **6** 次(以官方文档为准)。
|
||||
- 若三方暂未提供/未打通回调,`pending` 订单将保持待处理;官方另提供「**入金状态查询**」接口(请求需含 `query_time`,格式 **`YYYY-MM-DD HH:MM:SS`**),当前移动端未单独暴露,由服务端按需扩展。
|
||||
|
||||
错误码约定:
|
||||
- `1001`:缺少必填参数(`tier_id`(或 `tier_key`)、`channel_code`、`idempotency_key` 任一未传或为空字符串)
|
||||
- `1001`(DDPay):缺少 `payment_type` / `payer_name` / `payer_bank_name`,或 `payment_type` 非官方允许取值
|
||||
- `1002`:`idempotency_key` 过长,或与其他玩家的订单冲突
|
||||
- `1003`:模拟回调/链接参数非法(如 `sign` 与 `order_no` 不匹配)——`depositMockNotify` 与无效支付链接
|
||||
- `2000`:订单落库或入账失败(事务回滚后返回原始错误描述)
|
||||
- `2000`:**通用**:订单落库或入账失败(事务回滚等,可能带原始错误描述);**DDPay**:调用「入金发起」失败(网络/HTTP/JSON/验签/`status_code≠0` 等),对外文案为「DDPay 充值发起失败」,**具体原因可查看该笔 `deposit_order.remark`(前缀 `[ddpay]`)或服务端日志**
|
||||
- `2003`:所选 `tier_id` 不存在、已停用或不在启用列表中
|
||||
- `2004`:`channel_code` 未配置或已禁用
|
||||
- `2004`:`channel_code` 非 `ddpay`;或 `ddpay` 未启用;或当前档位币种与该渠道不允许的组合
|
||||
- `2005`:待支付充值单超过上限(`data.max_pending`、`data.pending_count`、`data.expire_seconds`)
|
||||
|
||||
### 5.5 查看充值订单详情
|
||||
@@ -526,13 +571,32 @@
|
||||
|
||||
请求参数:
|
||||
- `withdraw_coin`:string(含义:申请提现金额,必须 > 0)
|
||||
- `receive_account`:string(含义:收款账号)
|
||||
- `receive_type`:string(`bank`/`ewallet`/`crypto`,含义:收款类型)
|
||||
- `receive_account`:string(含义:收款账号;对接 DDPay 出金时对应官方字段 **`receiver_account`**,为收款账户号/手机号,须与银行登记一致)
|
||||
- `receive_type`:string(含义:收款类型;当前版本仅支持 `bank`)
|
||||
- `idempotency_key`:string(含义:防重复提交提现)
|
||||
- `receiver_name`:string(含义:收款账户持有人姓名;`receive_type=bank` 必填,对应官方 **`receiver_name`**,须与银行登记一致)
|
||||
- `bank_code`:string(含义:银行代码;`receive_type=bank` 必填。取值来自收银台配置 `withdraw_banks[].code`;服务端会映射为 DDPay 所需的 **`bank[name]`** 银行全称发起出金)
|
||||
- `bank_branch`:string(含义:银行支行名称;`receive_type=bank` 可选。官方 **`bank_branch`** 为必填项,若客户端不传则服务端按 **`N/A`** 提交,与 DDPay 文档「若缺失则默认值为 `N/A`」一致)
|
||||
|
||||
**DDPay 出金(Payout)官方请求字段对照(文档 §3.2,由服务端在审核通过后组装)**
|
||||
|
||||
| 官方参数 | 说明 |
|
||||
|---|---|
|
||||
| `client_id` | 商户账号标识 |
|
||||
| `bill_number` | 出金唯一引用号(与本系统提现 `order_no` 对应) |
|
||||
| `amount` | 出金金额(Decimal,配置币种下) |
|
||||
| `receiver_name` | 收款账户持有人姓名 |
|
||||
| `receiver_account` | 收款账户号/手机号 |
|
||||
| `bank[name]` | 银行全称(须参考官方附录「出金银行列表」) |
|
||||
| `bank_branch` | 支行名称;缺失为 `N/A` |
|
||||
| `callback_url` | 异步通知地址,须 **HTTPS** |
|
||||
| `signature` | MD5 签名(小写) |
|
||||
|
||||
出金成功响应中,官方还可能返回 `transaction_fee`、`transaction_total`、`transaction_status`、`remark` 等;最终以 DDPay 文档为准。
|
||||
|
||||
返回参数:
|
||||
- `order_no`:string(含义:提现订单号)
|
||||
- `status`:string(`pending_review`/`processing`,含义:提现状态)
|
||||
- `status`:string(`pending_review`/`approved`/`rejected`,含义:提现状态;已打款合并到 `approved`)
|
||||
- `fee_coin`:string(含义:手续费)
|
||||
- `actual_arrival_coin`:string(含义:实到账金额)
|
||||
- `risk_review_required`:bool(含义:是否命中人工审核)
|
||||
@@ -548,7 +612,7 @@
|
||||
- `coin_balance`、`bet_flow_coin`、`total_withdraw_coin`、`ratio`
|
||||
- `max_withdraw_by_flow`:仅按打码量折算的上限(= `max(0, bet_flow_coin / ratio - total_withdraw_coin)`);`ratio=0` 时为 `null`
|
||||
5. 以上全通过后在同一事务内:
|
||||
- `withdraw_order` 写入:`amount` / `fee`(默认 0.5%) / `actual_amount = amount - fee` / `status=0`(待审核) / `channel_id` 取自用户归属渠道快照。
|
||||
- `withdraw_order` 写入:`amount` / `fee`(默认 0.5%) / `actual_amount = amount - fee` / `status=0`(待审核) / `channel_id` 取自用户归属渠道快照;同时写入收款字段(`receive_type/receive_account/receiver_name/bank_code/bank_branch`)。
|
||||
- `user` 表原子更新:`coin -= withdraw_coin` 且 `total_withdraw_coin += withdraw_coin`(WHERE `coin >= withdraw_coin` 防止并发超额扣减)。
|
||||
- `user_wallet_record` 写入 `biz_type=withdraw`、`direction=2`、`amount=withdraw_coin`、`ref_type=withdraw_order`、`idempotency_key=wd_apply_{order_no}`,代表"冻结"动作。
|
||||
|
||||
@@ -556,7 +620,8 @@
|
||||
- 单笔最大可提现 `max_withdrawable = min(coin_balance, max_withdraw_by_flow)`;每笔提现按 `withdraw_coin × ratio` 消耗打码配额,已消耗部分累积在 `total_withdraw_coin`。
|
||||
- `ratio = 0` 时视为"不限打码",单笔上限仅受 `coin_balance` 约束。
|
||||
- 采用"申请即冻结"语义:提现在移动端提交后立即从 `user.coin` 中扣减并写出金流水;后台审核 **拒绝** 时由管理端在同一事务中回冲余额、`total_withdraw_coin` 与流水,不出现"等待审核期间用户还能把这笔钱再下注"的漏洞。
|
||||
- 后台审核 **通过** 时不再额外触碰余额;若管理员调整了 `amount` 或 `fee`,按新旧差额再生成一条 `withdraw` / `withdraw_refund` 流水以保持账务平衡,并同步修正 `total_withdraw_coin`。
|
||||
- 后台审核 **通过** 时会触发三方出金(DDPay Payout);出金 **失败** 会自动回冲余额、`total_withdraw_coin` 与流水(`withdraw_refund`),并将订单标记为 `rejected`(内部 `status=2`)。
|
||||
- 后台审核 **通过** 且出金完成后,订单内部 `status=3`(已打款),移动端对外仍合并展示为 `approved`。
|
||||
- `withdraw_bet_flow_ratio` 由后台「游戏配置」维护,默认 `1.00`,修改后对新请求立即生效。
|
||||
|
||||
### 5.8 查看提现订单详情
|
||||
@@ -728,9 +793,8 @@
|
||||
|
||||
## 8.2 充值到下注到提现闭环
|
||||
1. 拉取档位:`POST /api/finance/depositTierList`(玩家选择一档,并记下该档 `channels[].code`)
|
||||
2. 创建订单:`POST /api/finance/depositCreate`(`tier_id` + `channel_code` + `idempotency_key`,三者为必填;可用 JSON / form-data / x-www-form-urlencoded)
|
||||
- 返回 `paid=false`、`status=pending`、**非空 `pay_url`**:客户端在 WebView/浏览器中打开 `pay_url`(`GET /api/finance/depositMockPayPage`);用户在模拟页点击确认后,由 `POST /api/finance/depositMockNotify` 完成入账,或轮询 `depositDetail` / 等 `wallet.changed` 再刷新余额
|
||||
- 未来接真实第三方:将 `pay_url` 换为真网关,入账仅在支付平台 **异步通知** 中调用 `DepositSettlement::settle`(与当前 `depositMockNotify` 路径一致)
|
||||
2. 创建订单:`POST /api/finance/depositCreate`(`tier_id` + **`channel_code=ddpay`** + `idempotency_key` + DDPay 入金必填字段;可用 JSON / form-data / x-www-form-urlencoded)
|
||||
- 返回 `paid=false`、`status=pending`、**非空 `pay_url`**:客户端在 WebView/浏览器中打开 **`pay_url`(DDPay `payment_url`)** 完成支付;入账由 **`ddpayDepositNotify`** Webhook 驱动,可轮询 `depositDetail` 或等待 `wallet.changed` 刷新余额
|
||||
3. 客户端可选轮询 `POST /api/finance/depositDetail` 兜底确认状态;入账成功后会收到 `wallet.changed`
|
||||
4. 下注:`POST /api/game/placeBet`
|
||||
5. 监听余额:`wallet.changed`(或按订单详情接口核对)
|
||||
|
||||
BIN
docs/DDPay Payment Gateway_v1.1.3.pdf
Normal file
BIN
docs/DDPay Payment Gateway_v1.1.3.pdf
Normal file
Binary file not shown.
319
docs/DDPay Payment Gateway_v1.1.3_zh.md
Normal file
319
docs/DDPay Payment Gateway_v1.1.3_zh.md
Normal file
@@ -0,0 +1,319 @@
|
||||
## DDPay 支付网关接口对接文档
|
||||
|
||||
> 文档名称:DDPay Payment Gateway
|
||||
> 版本:1.1.0(文末“Document Version”标注为 1.1.2;文件命名为 v1.1.3)
|
||||
> 最后更新:2026-03-20
|
||||
> 版权:© 2025 DDPay
|
||||
|
||||
## 目录
|
||||
|
||||
- 1. 概述(Overview)
|
||||
- 2. 认证与安全(Authentication & Security)
|
||||
- 3. API 接口(API Endpoints)
|
||||
- 3.1 入金发起(Deposit Initiation)
|
||||
- 3.2 出金发起(Payout Initiation)
|
||||
- 3.3 入金状态查询(Deposit Status Inquiry)
|
||||
- 3.4 出金状态查询(Payout Status Inquiry)
|
||||
- 3.5 Webhook 回调(Webhook Notifications)
|
||||
- 4. 返回码(Response Codes)
|
||||
- 5. 附录
|
||||
- 5.1 入金银行列表(MYR)
|
||||
- 5.2 出金银行列表(MYR)
|
||||
- 5.3 入金银行列表(THB)
|
||||
|
||||
## 1. 概述(Overview)
|
||||
|
||||
### 1.1 目的
|
||||
|
||||
本文件提供与 DDPay Payment Gateway API 集成的完整技术规范,涵盖:
|
||||
|
||||
- 请求/响应字段结构
|
||||
- 认证机制
|
||||
- 集成协议(包括签名与回调处理)
|
||||
|
||||
### 1.2 术语(Terminology)
|
||||
|
||||
| 术语 | 定义 |
|
||||
|---|---|
|
||||
| Merchant Account | 允许通过 DDPay 处理交易的已注册商户主体 |
|
||||
| Client ID | 每个商户在平台注册时分配的唯一标识 |
|
||||
| API Secret | 用于请求认证与签名校验的保密密钥 |
|
||||
|
||||
## 2. 认证与安全(Authentication & Security)
|
||||
|
||||
### 2.1 通信协议(Communication Protocol)
|
||||
|
||||
- 传输方式:`HTTPS POST` 请求
|
||||
- Content-Type:`application/json`
|
||||
- 字符编码:`UTF-8`
|
||||
- 响应格式:`JSON`
|
||||
|
||||
要求:
|
||||
|
||||
- 所有 API 通信必须使用安全 HTTPS。
|
||||
- 发起交易接口由平台提供同步响应;最终交易状态需要通过“状态查询接口”或“状态回调(Webhook)”确认。
|
||||
|
||||
### 2.2 请求签名(Request Signing)
|
||||
|
||||
DDPay 使用加密签名以保证请求的真实性与数据完整性。签名算法为 **MD5**,流程如下:
|
||||
|
||||
1. 收集请求参数(**不包含**签名字段本身)
|
||||
2. 按参数 key 名进行字典序排序(ASCII 顺序)
|
||||
3. 将所有 `key=value` 使用字符 `&` 连接(中间用 `&` 分隔)
|
||||
4. 在末尾追加:`&key=YOUR_API_SECRET`
|
||||
5. 对得到的字符串执行 `MD5`
|
||||
6. 将 MD5 哈希结果转为小写
|
||||
7. 将该哈希值填入签名字段
|
||||
|
||||
重要注意:
|
||||
|
||||
- **空值或 null 参数值应排除在签名计算之外**。
|
||||
|
||||
## 3. API 接口(API Endpoints)
|
||||
|
||||
> 生产环境的 Endpoint URL:请联系商户支持获取。
|
||||
|
||||
### 3.1 入金发起(Deposit Initiation)
|
||||
|
||||
目的:提交一笔新的支付入金请求
|
||||
|
||||
- HTTP Method:`POST`
|
||||
- Endpoint URL:联系商户支持获取生产地址
|
||||
|
||||
#### 请求参数(Request Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 备注 |
|
||||
|---|---|---|---|---|
|
||||
| `client_id` | 商户账号标识 | String | 是 | onboarding 提供 |
|
||||
| `order_id` | 交易唯一引用号 | String | 是 | 每笔交易必须唯一 |
|
||||
| `payment_type` | 支付方式选择 | String | 是 | `01`=FPX,`02`=duitnow,`03`=ewallet;其他请咨询获取 |
|
||||
| `transaction_amount` | 支付金额 | Decimal | 是 | 币种:MYR |
|
||||
| `payer_name` | 付款账户持有人姓名 | String | 是 | 按银行登记信息 |
|
||||
| `payer_bank[name]` | 付款银行名称 | String | 是 | 请参考银行列表获取全称 |
|
||||
| `callback_url` | 异步通知地址 | String | 是 | 必须使用 HTTPS 协议 |
|
||||
| `redirect_url` | 用户返回地址 | String | 是 | 必须使用 HTTPS 协议 |
|
||||
| `signature` | 请求认证签名哈希 | String | 是 | 小写字母数字 MD5 |
|
||||
|
||||
#### 响应参数(Response Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 条件/备注 |
|
||||
|---|---|---|---|
|
||||
| `status_code` | 操作结果指示 | Integer | 非 0 表示失败 |
|
||||
| `status_message` | 可读状态说明 | String | 永远返回 |
|
||||
| `details` | 失败细节(如适用) | String | 仅失败时适用 |
|
||||
| `client_id` | 商户标识回显 | String | 成功时回显 |
|
||||
| `order_id` | 入金订单号回显 | String | 成功时回显,用于关联 |
|
||||
| `transaction_amount` | 支付金额确认 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_status` | 当前处理状态 | String | 成功时返回;参考“状态码” |
|
||||
| `payment_url` | 支付界面 URL | String | 成功时返回,跳转到该 URL 完成支付 |
|
||||
| `timestamp` | 响应生成时间 | DateTime | ISO 8601 |
|
||||
| `signature` | 响应校验签名哈希 | String | 成功时返回(使用同方法校验) |
|
||||
|
||||
### 3.2 出金发起(Payout Initiation)
|
||||
|
||||
目的:提交一笔新的出金请求
|
||||
|
||||
- HTTP Method:`POST`
|
||||
- Endpoint URL:联系商户支持获取生产地址
|
||||
|
||||
#### 请求参数(Request Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 备注 |
|
||||
|---|---|---|---|---|
|
||||
| `client_id` | 商户账号标识 | String | 是 | onboarding 提供 |
|
||||
| `bill_number` | 交易唯一引用号 | String | 是 | 每笔出金请求必须唯一 |
|
||||
| `amount` | 出金金额 | Decimal | 是 | 币种:配置币种 |
|
||||
| `receiver_name` | 收款账户持有人姓名 | String | 是 | 按银行登记信息 |
|
||||
| `receiver_account` | 收款账户号/手机号 | String | 是 | 按银行登记信息 |
|
||||
| `bank[name]` | 银行名称 | String | 是 | 请参考银行列表获取全称 |
|
||||
| `bank_branch` | 银行支行名称 | String | 是 | 若缺失则默认值为 `N/A` |
|
||||
| `callback_url` | 异步通知地址 | String | 是 | 必须使用 HTTPS 协议 |
|
||||
| `signature` | 请求认证签名哈希 | String | 是 | 小写字母数字 MD5 |
|
||||
|
||||
#### 响应参数(Response Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 条件/备注 |
|
||||
|---|---|---|---|
|
||||
| `status_code` | 操作结果指示 | Integer | 非 0 表示失败 |
|
||||
| `status_message` | 可读状态说明 | String | 永远返回 |
|
||||
| `details` | 失败细节(如适用) | String | 仅失败时适用 |
|
||||
| `client_id` | 商户标识回显 | String | 成功时回显 |
|
||||
| `bill_number` | 出金订单号回显 | String | 成功时回显,用于关联 |
|
||||
| `transaction_amount` | 出金金额确认 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_fee` | 出金手续费 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_total` | 出金总金额 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_status` | 当前处理状态 | String | 成功时返回;参考“状态码” |
|
||||
| `timestamp` | 响应生成时间 | DateTime | ISO 8601 |
|
||||
| `signature` | 响应校验签名哈希 | String | 成功时返回(使用同方法校验) |
|
||||
| `remark` | 出金备注 | String | 成功时回显(文档描述为 OK 状态下返回) |
|
||||
|
||||
### 3.3 入金状态查询(Deposit Status Inquiry)
|
||||
|
||||
目的:查询已提交入金的当前状态
|
||||
|
||||
- HTTP Method:`POST`
|
||||
|
||||
#### 请求参数(Request Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 备注 |
|
||||
|---|---|---|---|---|
|
||||
| `client_id` | 商户账号标识 | String | 是 | |
|
||||
| `order_id` | 入金订单号/交易引用 | String | 是 | 原始订单标识 |
|
||||
| `query_time` | 请求时间戳 | DateTime | 是 | 格式:`YYYY-MM-DD HH:MM:SS` |
|
||||
| `signature` | 请求认证签名哈希 | String | 是 | |
|
||||
|
||||
#### 响应参数(Response Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 条件/备注 |
|
||||
|---|---|---|---|
|
||||
| `status_code` | 查询结果指示 | Integer | 永远返回 |
|
||||
| `status_message` | 查询结果说明 | String | 永远返回 |
|
||||
| `client_id` | 商户标识回显 | String | 成功时回显 |
|
||||
| `order_id` | 订单号回显 | String | 成功时回显 |
|
||||
| `transaction_amount` | 支付金额 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_status` | 当前处理状态 | String | 参考“状态码” |
|
||||
| `timestamp` | 响应时间 | DateTime | 仅返回 ISO 8601 |
|
||||
| `signature` | 响应校验签名哈希 | String | 成功时返回(使用同方法校验) |
|
||||
|
||||
### 3.4 出金状态查询(Payout Status Inquiry)
|
||||
|
||||
目的:查询已提交出金的当前状态
|
||||
|
||||
- HTTP Method:`POST`
|
||||
|
||||
#### 请求参数(Request Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 备注 |
|
||||
|---|---|---|---|---|
|
||||
| `client_id` | 商户账号标识 | String | 是 | |
|
||||
| `bill_number` | 出金引用号 | String | 是 | 原始出金标识 |
|
||||
| `signature` | 请求认证签名哈希 | String | 是 | |
|
||||
|
||||
#### 响应参数(Response Parameters)
|
||||
|
||||
| 参数 | 描述 | 类型 | 条件/备注 |
|
||||
|---|---|---|---|
|
||||
| `status_code` | 查询结果指示 | Integer | 永远返回 |
|
||||
| `status_message` | 查询结果说明 | String | 永远返回 |
|
||||
| `client_id` | 商户标识回显 | String | 成功时回显 |
|
||||
| `bill_number` | 出金引用号回显 | String | 成功时回显 |
|
||||
| `transaction_amount` | 出金金额 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_fee` | 出金手续费 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_total` | 出金总金额 | Decimal | 成功时在配置币种下返回 |
|
||||
| `transaction_status` | 当前处理状态 | String | 参考“状态码” |
|
||||
| `remark` | 出金备注 | String | 成功时回显 |
|
||||
| `timestamp` | 响应时间 | DateTime | ISO 8601 |
|
||||
| `signature` | 响应校验签名哈希 | String | 成功时返回(使用同方法校验) |
|
||||
|
||||
### 3.5 Webhook 回调(Webhook Notifications)
|
||||
|
||||
目的:接收异步交易状态更新
|
||||
|
||||
说明:
|
||||
|
||||
- 平台通过 `callback_url` 在交易状态变化时向你系统发送 `POST` 通知
|
||||
- 通知发送范围:成功与失败交易都会发送
|
||||
- 格式:通过 `HTTPS POST` 发送 `JSON`
|
||||
- 重试机制:如果未收到确认,最多重试 6 次
|
||||
- 你需要的响应:返回纯文本 `{"status":"ok"}` 并确保 HTTP 状态码为 `200`
|
||||
|
||||
#### 通知负载(Notification Payload)
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 备注 |
|
||||
|---|---|---|---|---|
|
||||
| `client_id` | 商户标识 | String | 是 | |
|
||||
| `order_id` | 交易引用号 | String | 是 | |
|
||||
| `transaction_status` | 最终状态 | String | 是 | 参考状态码 |
|
||||
| `timestamp` | 通知时间 | DateTime | 是 | |
|
||||
| `transaction_amount` | 支付金额 | Decimal | 是 | 配置币种下返回 |
|
||||
| `signature` | 通知校验签名哈希 | String | 是 | 处理前必须校验签名 |
|
||||
|
||||
#### 集成要求(Implementation Requirements)
|
||||
|
||||
- 在处理 webhook 之前先验证签名
|
||||
- 收到后应立刻响应纯文本 `{"status":"ok"}`(HTTP 200)
|
||||
- 使用 HTTPS endpoint,并确保 SSL 证书有效
|
||||
|
||||
## 4. 返回码(Response Codes)
|
||||
|
||||
### 4.1 入金状态值(Deposit Status Values)
|
||||
|
||||
| 状态码 | 描述 | 最终状态 | 是否需要操作 | 处理建议 |
|
||||
|---|---|---|---|---|
|
||||
| `pending` | 交易正在处理中 | 否 | 否 | 无需调用轮询接口或等待通知 |
|
||||
| `completed` | 交易成功 | 是 | 是 | 履约订单/服务(fulfill order/service) |
|
||||
| `failed` | 交易失败 | 是 | 是 | 通知客户,可选允许重试(allow retry) |
|
||||
|
||||
> 文档中 `transaction_status` 建议参考本节状态码定义。
|
||||
|
||||
## 5. 附录(Appendices)
|
||||
|
||||
### 5.1 入金银行列表(MYR)
|
||||
|
||||
- `pbb` : Public Bank
|
||||
- `br` : Bank Rakyat
|
||||
- `alb` : Alliance Bank
|
||||
- `mbb` : Maybank2U
|
||||
- `bi` : Bank Islam
|
||||
- `bm` : Bank Muamalat
|
||||
- `afb` : Affin Bank
|
||||
- `rhb` : RHB Bank
|
||||
- `ocbc` : OCBC Bank
|
||||
- `scb` : Standard Chartered
|
||||
- `hlb` : Hong Leong Bank
|
||||
- `uob` : UOB Bank
|
||||
- `cimb` : CIMB Clicks
|
||||
- `amb` : AmBank
|
||||
- `bsn` : Bank Simpanan Nasional
|
||||
- `hsbc` : HSBC Bank
|
||||
- `cob` : Bank of China
|
||||
|
||||
### 5.2 出金银行列表(MYR)
|
||||
|
||||
> 与入金 MYR 银行列表一致
|
||||
|
||||
- `pbb` : Public Bank
|
||||
- `br` : Bank Rakyat
|
||||
- `alb` : Alliance Bank
|
||||
- `mbb` : Maybank2U
|
||||
- `bi` : Bank Islam
|
||||
- `bm` : Bank Muamalat
|
||||
- `afb` : Affin Bank
|
||||
- `rhb` : RHB Bank
|
||||
- `ocbc` : OCBC Bank
|
||||
- `scb` : Standard Chartered
|
||||
- `hlb` : Hong Leong Bank
|
||||
- `uob` : UOB Bank
|
||||
- `cimb` : CIMB Clicks
|
||||
- `amb` : AmBank
|
||||
- `bsn` : Bank Simpanan Nasional
|
||||
- `hsbc` : HSBC Bank
|
||||
- `cob` : Bank of China
|
||||
- `tng` : Touch & Go
|
||||
|
||||
### 5.3 入金银行列表(THB)
|
||||
|
||||
- `105` : BANK OF THAILAND
|
||||
- `106` : BANGKOK BANK PUBLIC COMPANY LTD.
|
||||
- `107` : KASIKORNBANK PUBLIC COMPANY LIMITED
|
||||
- `108` : KRUNG THAI BANK PUBLIC COMPANY LTD.
|
||||
- `109` : TMB THANACHART BANK PUBLIC COMPANY LIMITED
|
||||
- `110` : SIAM COMMERCIAL BANK PUBLIC COMPANY LTD.
|
||||
- `111` : CITIBANK, N.A.
|
||||
- `112` : STANDARD CHARTERED BANK (THAI) PUBLIC COMPANY LIMITED
|
||||
- `113` : CIMB THAI BANK PUBLIC COMPANY LIMITED
|
||||
- `114` : UNITED OVERSEAS BANK (THAI) PUBLIC COMPANY LIMITED
|
||||
- `115` : BANK OF AYUDHYA PUBLIC COMPANY LTD.
|
||||
- `116` : GOVERNMENT SAVINGS BANK
|
||||
- `117` : THE GOVERNMENT HOUSING BANK
|
||||
- `118` : BANK FOR AGRICULTURE AND AGRICULTURAL COOPERATIVES
|
||||
- `119` : BANK OF CHINA (THAI) PUBLIC COMPANY LIMITED
|
||||
- `120` : ISLAMIC BANK OF THAILAND
|
||||
- `121` : KIATNAKIN PHATRA BANK PUBLIC COMPANY LIMITED
|
||||
- `122` : INDUSTRIAL AND COMMERCIAL BANK OF CHINA (THAI) PUBLIC COMPANY LIMITED
|
||||
- `123` : LAND AND HOUSES BANK PUBLIC COMPANY LIMITED
|
||||
- `158` : TISCO BANK PUBLIC COMPANY LIMITED
|
||||
- `357` : RHB BANK BERHAD
|
||||
- `358` : INDIAN OVERSEA BANK
|
||||
- `359` : ANZ BANK (THAI) PUBLIC COMPANY LIMITED
|
||||
|
||||
Reference in New Issue
Block a user