Files
webman-buildadmin-mall/docs/PlayX-调用积分商城接口说明.md

448 lines
14 KiB
Markdown
Raw Permalink 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.
# PlayX 调用积分商城接口说明
本文档描述 **PlayX 平台(或 PlayX 侧脚本/服务)如何调用积分商城已开放的 HTTP 接口**:基础约定、推荐流程、鉴权方式、请求参数与返回结构。
实现依据:`config/route.php``app/api/controller/v1/Playx.php``config/playx.php`
---
## 1. 基础约定
### 1.1 Base URL
将下列路径拼在积分商城对外域名之后,例如:
`https://{商城域名}/api/v1/mall/dailyPush`
(联调时请向商城方索取正式环境与测试环境地址。)
### 1.2 通用响应结构JSON
所有接口成功或失败,响应体均为:
| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | int | `1` 表示业务成功;`0` 表示业务失败 |
| `msg` | string | 提示信息(失败时为错误原因) |
| `time` | int | Unix 时间戳(秒) |
| `data` | object/array/null | 业务数据;失败时可能为 `null` |
部分错误场景会通过 HTTP 状态码区分(如 **401**),此时 `code` 仍为 `0`,请同时判断 HTTP 状态与 `code`
**成功示例:**
```json
{
"code": 1,
"msg": "",
"time": 1730000000,
"data": { }
}
```
**失败示例:**
```json
{
"code": 0,
"msg": "错误原因",
"time": 1730000000,
"data": null
}
```
### 1.3 Content-Type
- 本文档中 **POST** 且带 JSON Body 的接口,请使用:`Content-Type: application/json`
### 1.4 多语言(响应文案)
可通过请求头 `lang` 控制返回文案语言:
| Header | 值 | 说明 |
|--------|----|------|
| `lang` | `zh` / `zh-cn` | 返回中文(默认) |
| `lang` | `en` | 返回英文 |
---
## 2. 使用流程(推荐)
### 2.1 PlayX 服务端 → 商城:每日数据推送(主流程)
适用于 T+1 等业务数据由 **PlayX 服务端**主动推送到积分商城。
```mermaid
sequenceDiagram
participant PX as PlayX 服务端
participant M as 积分商城
Note over PX,M: 按约定配置 HMAC 密钥
PX->>M: POST /api/v1/mall/dailyPushJSON Body
M-->>PX: code=1, data.accepted / deduped
```
1. 与商城方约定 **商城 Base URL****HMAC**`X-Signature` 等)密钥。
2.**§3** 构造请求并推送。
3. 根据返回 `data.deduped` 判断是否为幂等重复推送。
### 2.2 用户侧H5 / 内嵌页)→ 商城:会话与业务接口
以下接口多由 **用户在浏览器内**打开积分商城 H5 后调用,通过 **`session_id`**(先调 `verifyToken` 获取)或 **`token`**(商城 `muser` 类 token标识用户**不一定由 PlayX 后端直接调用**
- `POST /api/v1/mall/verifyToken`:用 PlayX token 换商城 `session_id`
- `GET /api/v1/mall/assets`:查询资产
- `POST /api/v1/mall/claim`:领取积分
- `GET /api/v1/mall/items`:商品列表
- `POST /api/v1/mall/bonusRedeem` / `physicalRedeem` / `withdrawApply`:兑换与提现申请
- `GET /api/v1/mall/orders`:订单列表
若 PlayX 后端需要代替用户调用上述接口,须同样携带有效的 `session_id``token`,并遵守同一用户身份规则(见 **§4 身份说明**)。
### 2.3 代理鉴权(非 PlayX 通用)
`GET /api/v1/authToken` 为 **渠道/代理**签名换 JWT`authtoken`),与 PlayX 用户体系不同一般不在本文「PlayX 平台对接」主流程中展开;需要时由运营向商城索取单独说明。
---
## 3. PlayX 服务端推送Daily Push
### 3.1 概要
| 项目 | 值 |
|------|-----|
| 方法 | `POST` |
| 路径 | `/api/v1/mall/dailyPush` |
### 3.2 鉴权(按商城部署配置,可组合)
#### 推荐方案:仅启用 HMAC当前对接采用
商城侧配置:设置环境变量 **`PLAYX_DAILY_PUSH_SECRET`** 为非空(启用 HMAC 校验)。
#### HMAC 签名(必填)
当商城配置 **`PLAYX_DAILY_PUSH_SECRET`** 非空时,需同时携带:
| Header | 说明 |
|--------|------|
| `X-Request-Id` | 请求 ID建议与 Body 内可追溯字段一致) |
| `X-Timestamp` | Unix 时间戳(秒,字符串) |
| `X-Signature` | 签名(十六进制小写或大写需与实现一致,以下为十六进制字符串) |
签名原文与计算:
```
canonical = X-Timestamp + "\n" + X-Request-Id + "\nPOST\n/api/v1/mall/dailyPush\n" + sha256(json_body)
expected = HMAC_SHA256( canonical , PLAYX_DAILY_PUSH_SECRET )
```
其中 `json_body`**实际发送的 JSON 原始字符串** 计算出的 SHA256十六进制与 PHP `hash('sha256', $rawBody)` 一致。
校验:`hash_equals(expected, X-Signature)`
#### Header 填写清单HMAC 模式)
- 必填:`X-Request-Id``X-Timestamp``X-Signature`
#### 重要注意:`json_body` 必须与实际发送一致
为了保证签名可验通过:用于计算 sha256 的 `json_body` 必须是**实际发送到 HTTP body 的原始 JSON 字符串**(字节级一致)。\
建议:在发送端先序列化 JSON 得到字符串 `rawBody`,用该 `rawBody` 做 sha256 与 HMAC再把同一个 `rawBody` 作为请求 body 发送。
### 3.3 Body 参数JSON
`/api/v1/mall/dailyPush` 支持 **两种入参格式**(按字段自动识别):
#### 格式 A旧版单条上报兼容
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `request_id` | string | 是 | 本次推送请求号;响应中原样返回 |
| `date` | string | 是 | 业务日期,格式 `YYYY-MM-DD` |
| `user_id` | string | 是 | PlayX 用户 ID幂等键之一 |
| `username` | string | 否 | 展示名;用于同步/创建商城侧用户资产展示信息 |
| `yesterday_win_loss_net` | number | 否 | 昨日净输赢;**小于 0** 时按配置比例计入待领取保障金(`locked_points` |
| `yesterday_total_deposit` | number | 否 | 昨日总充值;用于计算当日可领取上限等 |
| `lifetime_total_deposit` | number | 否 | 历史总充值(冗余入库) |
| `lifetime_total_withdraw` | number | 否 | 历史总提现(冗余入库) |
#### 格式 B新版批量上报你图中格式
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `report_date` | string/number | 是 | 报表日期;可以为 Unix 秒时间戳(如 `1700000000`)或 `YYYY-MM-DD` |
| `member` | array | 是 | 成员列表,每个成员包含一名 PlayX 用户数据 |
成员元素字段:
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `member_id` | string | 是 | PlayX 用户 ID幂等键之一 |
| `login` | string | 否 | 用户展示名 |
| `yesterday_total_w` | number | 否 | 昨日净输赢;小于 0 才会累加到 `locked_points` |
| `yesterday_total_deposit` | number | 否 | 昨日总充值;用于计算 `today_limit` |
| `lty_deposit` | number | 否 | 历史总充值(冗余入库) |
| `lty_withdrawal` | number | 否 | 历史总提现(冗余入库) |
#### Body 填写要求(批量模式)
- **必须有**`report_date``member`(数组且至少 1 个元素)、`member[].member_id`
- **允许缺省**:成员的 `login/yesterday_total_w/yesterday_total_deposit/lty_deposit/lty_withdrawal`;缺省时按 `0` 或空字符串处理。
- **日期**`report_date` 传 Unix 秒会自动转换成 `YYYY-MM-DD`;如果直接传 `YYYY-MM-DD` 也支持。
### 3.4 幂等
- 幂等键:**`user_id` + `date`**
- 重复推送:不重复入账,返回 `data.deduped = true`
### 3.5 返回 `data` 字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `request_id` | string | 与请求一致 |
| `accepted` | bool | 是否受理成功 |
| `deduped` | bool | 是否为重复推送(幂等命中) |
| `message` | string | 说明文案 |
#### 格式 B批量上报的返回补充
批量模式会在 `data` 中增加:`results`
`data.results` 为数组,元素字段如下:
| 字段 | 类型 | 说明 |
|------|------|------|
| `user_id` | string | 对应成员的 `member_id` |
| `accepted` | bool | 是否受理成功 |
| `deduped` | bool | 该成员是否为重复推送 |
| `message` | string | `ok``duplicate input` |
**HTTP 401**HMAC 不通过(签名缺失/不完整/校验失败)。
### 3.6 请求示例
```bash
curl -X POST 'https://{商城域名}/api/v1/mall/dailyPush' \
-H 'Content-Type: application/json' \
-H 'X-Request-Id: req_1700000000_123456' \
-H 'X-Timestamp: 1700000000' \
-H 'X-Signature: <按本文档 canonical 计算出的 HMAC_SHA256>' \
-d '{
"report_date": "1700000000",
"member": [
{
"member_id": "123456",
"login": "john",
"lty_deposit": 15230.75,
"lty_withdrawal": 12400.50,
"yesterday_total_w": -320.25,
"yesterday_total_deposit": 500.00
}
]
}'
```
响应示例(首次写入,至少有一个成员非重复):
```json
{
"code": 1,
"msg": "",
"time": 0,
"data": {
"request_id": "report_2023-11-14",
"accepted": true,
"deduped": false,
"message": "Ok",
"results": [
{
"user_id": "123456",
"accepted": true,
"deduped": false,
"message": "Ok"
}
]
}
}
```
---
## 4. 身份说明(`session_id` / `token` / `user_id`
以下接口通过 **`resolvePlayxAssetIdFromRequest`** 解析当前用户,优先级如下:
1. **`session_id`**POST/GET对应商城表 `mall_playx_session`,未过期则映射到 `mall_playx_user_asset`
2.`session_id` 实际是 **`muser` 类型 token**(历史兼容),也会按 token 解析。
3. **`token`**POST/GET 或标准鉴权头):商城 token 表内类型为会员或 **`muser`** 且未过期时,`user_id`**`mall_playx_user_asset.id`**(资产表主键)。
4. **`user_id`**POST/GET
- 若**纯数字**:视为 **`mall_playx_user_asset.id`**
- 否则:按 **`playx_user_id`** 查找资产行。
无法解析身份时,通常返回 **401** 或参数错误提示。
---
## 5. 其他接口一览(摘要)
> 下列均为 **BuildAdmin 通用 `code/msg/time/data` 结构**;成功时 `code=1`。
### 5.1 `POST /api/v1/mall/verifyToken`
用于将 **PlayX token**(或本地联调 token**商城 `session_id`**
| 参数位置 | 名称 | 说明 |
|----------|------|------|
| POST/GET | `token``session` | PlayX 或商城 token |
**说明:**`playx.verify_token_local_only=true`(默认),商城**仅本地校验** token不请求 PlayX 远程接口;远程模式需配置 `PLAYX_API_BASE_URL` 等。
**成功 `data` 示例:**
| 字段 | 说明 |
|------|------|
| `session_id` | 后续接口可带此字段 |
| `user_id` | PlayX 用户 ID 或映射后的标识 |
| `username` | 用户名 |
| `token_expire_at` | ISO8601 过期时间 |
---
### 5.2 `GET /api/v1/mall/assets`
查询积分资产;需 **§4** 身份。
**成功 `data`**
| 字段 | 说明 |
|------|------|
| `locked_points` | 待领取积分 |
| `available_points` | 可用积分 |
| `today_limit` | 今日可领取上限 |
| `today_claimed` | 今日已领取 |
| `withdrawable_cash` | 可提现现金(由积分×配置比例换算,保留小数) |
---
### 5.3 `POST /api/v1/mall/claim`
领取积分;需 **§4** 身份。
| 参数 | 必填 | 说明 |
|------|------|------|
| `claim_request_id` | 是 | 幂等请求号 |
**成功 `data`** 与资产结构一致(含 `locked_points``available_points``today_limit``today_claimed``withdrawable_cash` 等)。
---
### 5.4 `GET /api/v1/mall/items`
商品列表。
| 参数 | 必填 | 说明 |
|------|------|------|
| `type` | 否 | `BONUS` / `PHYSICAL` / `WITHDRAW`,筛选类型 |
**成功 `data`** `{ "list": [ ... ] }`
---
### 5.5 `POST /api/v1/mall/bonusRedeem`
红利兑换;需 **§4** 身份。
| 参数 | 必填 | 说明 |
|------|------|------|
| `item_id` | 是 | 商品 ID |
**成功 `data`**`order_id``status`(如 `PENDING`)等。
---
### 5.6 `POST /api/v1/mall/physicalRedeem`
实物兑换;需 **§4** 身份。
| 参数 | 必填 | 说明 |
|------|------|------|
| `item_id` | 是 | 实物商品 ID |
| `address_id` | 是 | `mall_address.id`(当前用户下地址);订单保存 `mall_address_id` 与地址快照 |
---
### 5.7 `POST /api/v1/mall/withdrawApply`
提现类兑换申请;需 **§4** 身份。
| 参数 | 必填 | 说明 |
|------|------|------|
| `item_id` | 是 | 提现档位商品 ID |
---
### 5.8 `GET /api/v1/mall/orders`
订单列表;需 **§4** 身份。
**成功 `data`** `{ "list": [ ... ] }`(含关联商品等,以实际返回为准)。
---
### 5.9 收货地址(`mall_address`
> 下列接口均需携带 **§4 身份参数**`session_id` / `token` / `user_id` 之一)。
#### 5.9.1 获取收货地址列表
- **方法**`GET`
- **路径**`/api/v1/mall/addressList`
返回 `data.list`:地址数组(按 `default_setting` 优先,其次 id 倒序)。
#### 5.9.2 添加收货地址
- **方法**`POST`
- **路径**`/api/v1/mall/addressAdd`
Body表单或 JSON 均可,建议 JSON
| 字段 | 必填 | 说明 |
|------|------|------|
| `receiver_name` | 是 | 收货人 |
| `phone` | 是 | 联系电话 |
| `region` | 是 | 地区(可传数组或逗号分隔字符串) |
| `detail_address` | 是 | 详细地址(短文本) |
| `default_setting` | 否 | `1` 设为默认地址;`0` 或不传为非默认 |
成功返回:`data.id` 为新地址 id。
#### 5.9.3 修改收货地址(含设置默认)
- **方法**`POST`
- **路径**`/api/v1/mall/addressEdit`
Body
| 字段 | 必填 | 说明 |
|------|------|------|
| `id` | 是 | 地址 id |
| `receiver_name/phone/region/detail_address/default_setting` | 否 | 需要修改的字段(只更新传入项) |
`default_setting=1`:会自动把该用户其他地址的 `default_setting` 置为 0。
#### 5.9.4 删除收货地址
- **方法**`POST`
- **路径**`/api/v1/mall/addressDelete`
Body
| 字段 | 必填 | 说明 |
|------|------|------|
| `id` | 是 | 地址 id |
若删除的是默认地址:服务端会将剩余地址里 id 最大的一条自动设为默认(若存在)。
---
## 6. 配置项(供运维/对方技术对照)
| 环境变量 / 配置 | 作用 |
|-----------------|------|
| `PLAYX_DAILY_PUSH_SECRET` | 非空则 Daily Push 必须带合法 HMAC 头 |
| `PLAYX_VERIFY_TOKEN_LOCAL_ONLY` | 为 true 时 verifyToken 不请求 PlayX 远程 |
| `PLAYX_API_BASE_URL` | 商城调用 PlayX 接口时使用与「PlayX 调商城」方向相反) |
---
## 7. 版本与变更
- 文档与仓库代码同步维护;接口路径以 `config/route.php` 为准。
- 若后续升级鉴权策略(例如叠加 JWT以部署环境变量与最新文档为准。