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

17 KiB
Raw Blame History

playX 调用积分商城接口说明

本文档描述 playX 平台(或 playX 侧脚本/服务)如何调用积分商城已开放的 HTTP 接口:基础约定、推荐流程、鉴权方式、请求参数与返回结构。

实现依据:config/route.phpapp/api/controller/v1/Playx.phpconfig/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

成功示例:

{
  "code": 1,
  "msg": "",
  "time": 1730000000,
  "data": { }
}

失败示例:

{
  "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 服务端主动推送到积分商城。

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 URLHMACX-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_idtoken,并遵守同一用户身份规则(见 §4 身份说明)。


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-IdX-TimestampX-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_datemember(数组且至少 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 okduplicate input

HTTP 401HMAC 不通过(签名缺失/不完整/校验失败)。

3.6 请求示例

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
      }
    ]
  }'

响应示例(首次写入,至少有一个成员非重复):

{
  "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_idPOST/GET对应商城表 mall_playx_session,未过期则映射到 mall_playx_user_asset
  2. session_id 实际是 muser 类型 token(历史兼容),也会按 token 解析。
  3. tokenPOST/GET 或标准鉴权头):商城 token 表内类型为会员或 muser 且未过期时,user_idmall_playx_user_asset.id(资产表主键)。
  4. user_idPOST/GET
    • 纯数字:视为 mall_playx_user_asset.id
    • 否则:按 playx_user_id 查找资产行。

无法解析身份时,通常返回 401 或参数错误提示。


5. 其他接口一览(前端联调版)

下列接口统一返回 code/msg/time/data;成功通常为 code=1
verifyToken 外,其余用户接口均需携带 session_idtoken(见 §4

5.0 POST /api/v1/mall/dailyPush(后端对后端)

用途playX 按日推送用户资产基础数据到商城(前端一般不直接调用)。

请求示例:

{
  "request_id": "report_20260430",
  "rows": [
    {
      "user_id": "U10001",
      "username": "demo_user",
      "yesterday_total_deposit": 1000,
      "yesterday_win_loss_net": -500
    }
  ]
}

5.1 POST /api/v1/mall/verifyToken

用途:把 playX token 换成商城 session_id

前端入参约定(重要)

  • 前端/客户端调用本接口时,只需要传 token(或兼容传 session)。
  • 商城后端调用 playX 校验时:
    • PLAYX_TOKEN_VERIFY_URL 为完整 https:// URL(回调网关):后端只向对方发送 request_id + token(与对端文档一致),无需前端传商户字段。
    • 若为相对路径:后端会拼 PLAYX_ANGPOW_IMPORT_BASE_URL,并生成 merchant_code / request_date / request_id / X-Request-Signature,前端仍不参与签名。
  • 若仅传 token 仍校验失败,多为 token 无效/过期或上游 URL 未放通,并非前端少传字段。

请求示例:

{
  "token": "eyJhbGciOi..."
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
    "user_id": "U10001",
    "username": "demo_user",
    "token_expire_at": "2026-04-30T16:20:00+08:00"
  }
}

5.2 GET /api/v1/mall/assets

用途:查询当前用户积分资产。

请求示例:

GET /api/v1/mall/assets?session_id=fc7f3e3f0d0f4cb29f66e4c8fbab4f66

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "locked_points": 120,
    "available_points": 350,
    "today_limit": 200,
    "today_claimed": 80,
    "withdrawable_cash": 35
  }
}

5.3 POST /api/v1/mall/claim

用途:领取积分(幂等)。

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "claim_request_id": "claim_20260430_0001"
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "locked_points": 60,
    "available_points": 410,
    "today_limit": 200,
    "today_claimed": 140,
    "withdrawable_cash": 41
  }
}

5.4 GET /api/v1/mall/items

用途:获取商城商品列表(可按类型筛选)。

请求示例:

GET /api/v1/mall/items?type=BONUS

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "list": [
      {
        "id": 101,
        "title": "10 MYR Bonus",
        "type": "BONUS",
        "points_cost": 1000
      }
    ]
  }
}

5.5 POST /api/v1/mall/bonusRedeem

用途:兑换红利商品。

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "item_id": 101
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "order_id": "ORD202604300001",
    "status": "PENDING"
  }
}

5.6 POST /api/v1/mall/physicalRedeem

用途:兑换实物商品(需要地址)。

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "item_id": 202,
  "address_id": 12
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "order_id": "ORD202604300002",
    "status": "PENDING"
  }
}

5.7 POST /api/v1/mall/withdrawApply

用途:发起提现档位兑换申请。

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "item_id": 303
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "order_id": "ORD202604300003",
    "status": "PENDING"
  }
}

5.8 GET /api/v1/mall/orders

用途:查询当前用户订单列表。

请求示例:

GET /api/v1/mall/orders?session_id=fc7f3e3f0d0f4cb29f66e4c8fbab4f66

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "list": [
      {
        "order_id": "ORD202604300001",
        "status": "PENDING",
        "item_title": "10 MYR Bonus"
      }
    ]
  }
}

5.9 GET /api/v1/mall/pointsLogs

用途:查询积分变动日志。

请求示例:

GET /api/v1/mall/pointsLogs?session_id=fc7f3e3f0d0f4cb29f66e4c8fbab4f66

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "list": [
      {
        "id": 9001,
        "change_points": 50,
        "type": "CLAIM",
        "remark": "daily claim"
      }
    ]
  }
}

5.10 收货地址(mall_address

用途:用户收货地址 CRUD。

5.10.1 GET /api/v1/mall/addressList

请求示例:

GET /api/v1/mall/addressList?session_id=fc7f3e3f0d0f4cb29f66e4c8fbab4f66

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "list": [
      {
        "id": 12,
        "receiver_name": "Tom",
        "phone": "0123456789",
        "detail_address": "KLCC",
        "default_setting": 1
      }
    ]
  }
}

5.10.2 POST /api/v1/mall/addressAdd

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "receiver_name": "Tom",
  "phone": "0123456789",
  "region": "Kuala Lumpur,KLCC",
  "detail_address": "Tower A, 8F",
  "default_setting": 1
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": {
    "id": 13
  }
}

5.10.3 POST /api/v1/mall/addressEdit

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "id": 13,
  "detail_address": "Tower B, 10F",
  "default_setting": 1
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": null
}

5.10.4 POST /api/v1/mall/addressDelete

请求示例:

{
  "session_id": "fc7f3e3f0d0f4cb29f66e4c8fbab4f66",
  "id": 13
}

成功响应示例:

{
  "code": 1,
  "msg": "Success",
  "time": 1777533000,
  "data": null
}

6. 配置项(供运维/对方技术对照)

环境变量 / 配置 作用
PLAYX_DAILY_PUSH_SECRET 非空则 Daily Push 必须带合法 HMAC 头
PLAYX_VERIFY_TOKEN_LOCAL_ONLY 为 true 时 verifyToken 不请求 playX 远程
PLAYX_ANGPOW_IMPORT_BASE_URL Angpow 推送等接口基地址;相对路径 verify-token 时亦作其基地址
PLAYX_TOKEN_VERIFY_URL 完整 https:// URL回调校验Body 仅 request_id+token相对路径:拼基地址 + 商户签名体
PLAYX_ANGPOW_MERCHANT_CODE 仅相对路径 verify-token 时使用
PLAYX_ANGPOW_IMPORT_AUTH_KEY 仅相对路径 verify-token 时 HMAC 密钥

7. 版本与变更

  • 文档与仓库代码同步维护;接口路径以 config/route.php 为准。
  • 若后续升级鉴权策略(例如叠加 JWT以部署环境变量与最新文档为准。