Files
frontend-app/utils/1.md
T
2026-09-09 11:46:36 +08:00

234 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 抖音支付:前端调用商城后端接口文档
日期:2026-09-05。适用:商城 App 前端。本文只描述前端调用我们后端的接口,不涉及抖音官方服务端接口、证书配置或插件开发。
## 一、公共约定
测试环境 Base URL:`https://api.o.tbmall.xin`。生产环境沿用项目正式用户端 API 配置,不要使用后台管理 API 地址。
请求头沿用现有登录请求封装:
```http
Authorization: <项目当前环境的应用授权值>
HSM-AUTH: <当前用户登录令牌>
Content-Type: application/x-www-form-urlencoded
```
POST 参数以表单提交,不是 JSON body;GET 使用 URL 查询参数。不要把后台管理 Token 填到 HSM-AUTH。
业务响应统一格式:
```json
{ "bizcode": 100, "errcode": 0, "msg": "成功", "data": {} }
```
`bizcode=100` 表示本次接口调用成功,不等于用户已付款。其他业务码按 msg 提示;HTTP 错误、超时或网络失败不能视作付款成功。以下所有 ID、金额、签名均为示例。
## 二、调用顺序
1. 调用 `/cart/getSupportPay`,判断返回列表是否包含 `type=douyin`。
2. 根据业务场景选择一个下单/支付接口,提交 `payway=douyin`。
3. 保存返回的 `data.orderNum`,把 `data.douyin` 中的支付参数交给 App 支付能力拉起抖音。
4. 用户返回 App 后调用 `/payment/queryResult` 查询结果,只有 `data.state=2` 才提示支付成功。
**重点:支付方式筛选传 `types=6`;实际支付传 `payway=douyin`,不是 `payway=6`。**
## 三、查询支付方式
**POST `/cart/getSupportPay`**
| 参数 | 类型 | 必填 | 说明 |
| ----------- | ------- | ---- | -------------------------------------------- |
| types | string | 否 | 只查抖音传 `6`;多种传 `1,2,6`;全部传 `ALL` |
| isDeduction | boolean | 否 | 默认 false,沿用现有抵扣券结算逻辑 |
请求表单:
```text
types=6&isDeduction=false
```
已启用抖音支付时的响应示例:
```json
{
"bizcode": 100,
"errcode": 0,
"msg": "成功",
"data": [{ "type": "douyin", "name": "抖音支付", "balance": 0 }]
}
```
没有启用对应配置时,列表可能为空。显示名称使用 name,提交支付方式使用 type;balance 不是抖音钱包余额。
## 四、发起支付(按场景选一个)
### 4.1 已创建订单,继续支付
**POST `/order/payment`**
| 参数 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ----------------------- |
| id | long | 是 | 待支付的商城业务订单 ID |
| payway | string | 是 | 固定 `douyin` |
```text
id=123456&payway=douyin
```
后端接口还接受可选 password/code,但抖音支付不需要提交。成功响应见第五节。
### 4.2 商品直接购买并支付
**POST `/cart/settlementOrder`**
| 参数 | 类型 | 必填 | 说明 |
| ------------ | ------- | -------- | ------------------------------------ |
| addrId | long | 是 | 收货地址 ID |
| goodsId | long | 是 | 商品 ID |
| specsId | long | 是 | 规格 ID |
| goodsNum | decimal | 是 | 购买数量 |
| payway | string | 本流程是 | `douyin` |
| payway2 | string | 否 | `vcoin` 表示抵扣券,沿用现有结算选择 |
| couponUserId | long | 否 | 已选用户优惠券 ID |
| remark | string | 否 | 现有分组备注 JSON 字符串 |
```text
addrId=10001&goodsId=20001&specsId=30001&goodsNum=1&payway=douyin
```
remark 格式为 `[{"gkey":"结算返回的分组标识","rmk":"备注内容"}]`,通过现有请求封装表单编码。金额由后端计算,不传前端自算金额。优惠券、抵扣券沿用结算规则,不因选择抖音改变适用范围。
### 4.3 购物车结算并支付
**POST `/cart/settle`**
| 参数 | 类型 | 必填 | 说明 |
| ------------ | ------ | ---- | ---------------------------------- |
| addrId | long | 是 | 收货地址 ID |
| cartIds | string | 是 | 购物车 ID 逗号分隔,`ALL` 表示全选 |
| payway | string | 是 | `douyin` |
| couponUserId | long | 否 | 用户优惠券 ID |
| remark | string | 否 | 分组备注 JSON 字符串,同上一接口 |
```text
addrId=10001&cartIds=40001,40002&payway=douyin
```
购物车可能拆分业务订单并合并支付,查询支付结果仍使用本次返回的 orderNum。
### 4.4 余额充值
**POST `/finance/recharge`**
| 参数 | 类型 | 必填 | 说明 |
| -------- | ------- | ---- | -------------------- |
| category | string | 是 | 余额充值传 `balance` |
| amount | decimal | 是 | 充值金额,单位元 |
| payway | string | 是 | `douyin` |
```text
category=balance&amount=1.00&payway=douyin
```
注意:上述四个 POST 都可能创建支付单,请勿反复点击或自动重试创建。新下单接口已经返回支付参数时,不要紧接着再调用 `/order/payment`。
## 五、下单/支付接口统一返回
上述四个接口均返回 PayInfoDto。抖音待支付响应示例(省略其他业务字段):
```json
{
"bizcode": 100,
"errcode": 0,
"msg": "成功",
"data": {
"orderId": 123456,
"orderNum": "PAY_EXAMPLE_001",
"amount": 1.0,
"status": 0,
"douyin": {
"appId": "EXAMPLE_APP_ID",
"mchId": "EXAMPLE_MERCHANT_ID",
"prepayId": "EXAMPLE_PREPAY_ID",
"callbackScheme": "trustbridgeapp",
"packageValue": "Sign=DYPay",
"nonceStr": "0123456789abcdef0123456789abcdef",
"timeStamp": "1788585600",
"sign": "EXAMPLE_BASE64_SIGNATURE"
}
}
}
```
| 字段 | 类型 | 前端用途 |
| --------------------- | ------- | ---------------------------------------------- |
| orderId | long | 后端返回的订单 ID |
| orderNum | string | 保存下来,支付结果查询必须用它 |
| amount | decimal | 实际支付金额(元) |
| status | integer | 此 DTO 中 0=待支付、1=已支付;不同于查单 state |
| douyin | object | App 拉起抖音所需参数 |
| douyin.appId | string | 抖音应用 ID |
| douyin.mchId | string | 抖音商户 ID |
| douyin.prepayId | string | 预支付 ID |
| douyin.callbackScheme | string | App 返回 Scheme |
| douyin.packageValue | string | `Sign=DYPay` |
| douyin.nonceStr | string | 随机字符串 |
| douyin.timeStamp | string | 秒级时间戳,保留字符串类型 |
| douyin.sign | string | 后端生成的签名,原样使用 |
后端已处理签名,前端无需请求商户私钥或另调签名接口。参数缺失时停止拉起,提示支付参数异常并反馈后端,不要自行伪造字段。
若 App 支付桥接要求 SDK 小写字段,映射如下;这不是另一个 HTTP 请求:
```js
const d = response.data.douyin;
const payInfo = {
appid: d.appId,
partnerid: d.mchId,
prepayid: d.prepayId,
package: d.packageValue,
noncestr: d.nonceStr,
timestamp: d.timeStamp,
sign: d.sign,
};
```
## 六、查询支付结果
**GET `/payment/queryResult`**
| 参数 | 类型 | 必填 | 说明 |
| -------- | ------ | ---- | ------------------------------------------------------- |
| orderNum | string | 是 | 发起支付接口返回的 data.orderNum,不是 orderId/prepayId |
```http
GET https://api.o.tbmall.xin/payment/queryResult?orderNum=PAY_EXAMPLE_001
```
```json
{
"bizcode": 100,
"errcode": 0,
"msg": "成功",
"data": { "state": 2 }
}
```
| state | 含义 | 前端处理 |
| ----- | ---------- | -------------------------------- |
| 0 | 订单不存在 | 核对支付编号及环境,不能提示成功 |
| 1 | 支付处理中 | 稍后再次查询 |
| 2 | 支付成功 | 展示成功,刷新订单或充值余额 |
| 3 | 支付失败 | 提示失败,刷新订单状态 |
当前 App 采用最多 5 次、间隔 1.5 秒的查询;这属于前端策略,不是后端强制限制。暂未确认、断网或超时应显示“支付结果确认中”,保存编号以便回前台再次查询,避免直接重复付款。
用户取消或支付 SDK 提示成功后,都需要以服务端查询结果为准。不要调用 `/payment/feedback` 上报成功来替代查单;前端也不需要调用后端的抖音通知/退款回调接口。
## 七、对接范围与发布注意
- 本文按当前工作区后端代码整理;SDK 签名新增字段(packageValue、nonceStr、timeStamp、sign)尚未确认已部署到测试/生产服务器。
- 后台配置已完成不代表预下单、签名、支付回调均验收通过,实际支付链路仍需联调。
- 本次抖音支付是 App 原生支付;H5 仅可检查适用的后端业务请求,不能凭网页调用拉起此原生能力。