Compare commits
2 Commits
0fdc1e2e88
...
4cf84ca083
| Author | SHA1 | Date | |
|---|---|---|---|
| 4cf84ca083 | |||
| 9f6358a3f2 |
@@ -679,6 +679,210 @@ class Playx extends Api
|
|||||||
return $this->success('', ['list' => $list->toArray()]);
|
return $this->success('', ['list' => $list->toArray()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 积分流水(领取/兑换/退回)
|
||||||
|
* GET /api/v1/mall/pointsLogs
|
||||||
|
*
|
||||||
|
* 鉴权:token / session_id / user_id(同 assets/orders)
|
||||||
|
*
|
||||||
|
* 参数:
|
||||||
|
* - limit: 每页条数(默认 20,最大 100)
|
||||||
|
* - cursor: 游标(上一页返回的 next_cursor)
|
||||||
|
* - direction: IN | OUT(可选,不传返回全部)
|
||||||
|
*/
|
||||||
|
public function pointsLogs(Request $request): Response
|
||||||
|
{
|
||||||
|
$response = $this->initializeApi($request);
|
||||||
|
if ($response !== null) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$assetId = $this->resolvePlayxAssetIdFromRequest($request);
|
||||||
|
if ($assetId === null) {
|
||||||
|
return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]);
|
||||||
|
}
|
||||||
|
$asset = $this->getAssetById($assetId);
|
||||||
|
if (!$asset || ($asset->playx_user_id ?? '') === '') {
|
||||||
|
return $this->success('', [
|
||||||
|
'list' => [],
|
||||||
|
'next_cursor' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$playxUserId = $asset->playx_user_id;
|
||||||
|
|
||||||
|
$limit = $request->get('limit', $request->post('limit', '20'));
|
||||||
|
if (!is_string($limit) || $limit === '' || !ctype_digit($limit) || $limit === '0') {
|
||||||
|
$limit = '20';
|
||||||
|
}
|
||||||
|
if (strlen($limit) > 3 || $limit > '100') {
|
||||||
|
$limit = '100';
|
||||||
|
}
|
||||||
|
|
||||||
|
$cursor = $request->get('cursor', $request->post('cursor', ''));
|
||||||
|
if (!is_string($cursor)) {
|
||||||
|
$cursor = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$direction = $request->get('direction', $request->post('direction', ''));
|
||||||
|
$direction = is_string($direction) ? strtoupper(trim($direction)) : '';
|
||||||
|
if ($direction !== '' && $direction !== 'IN' && $direction !== 'OUT') {
|
||||||
|
$direction = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = <<<SQL
|
||||||
|
SELECT
|
||||||
|
t.biz_type,
|
||||||
|
t.direction,
|
||||||
|
t.points,
|
||||||
|
t.ts,
|
||||||
|
t.ref_id,
|
||||||
|
t.order_no,
|
||||||
|
t.order_status,
|
||||||
|
t.item_id,
|
||||||
|
t.item_title,
|
||||||
|
t.item_type,
|
||||||
|
t.item_score,
|
||||||
|
t.item_amount,
|
||||||
|
t.item_multiplier,
|
||||||
|
t.item_category,
|
||||||
|
t.item_category_title,
|
||||||
|
t.sort_key
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
'CLAIM' AS biz_type,
|
||||||
|
'IN' AS direction,
|
||||||
|
cl.claimed_amount AS points,
|
||||||
|
cl.create_time AS ts,
|
||||||
|
cl.claim_request_id AS ref_id,
|
||||||
|
'' AS order_no,
|
||||||
|
'' AS order_status,
|
||||||
|
0 AS item_id,
|
||||||
|
'' AS item_title,
|
||||||
|
0 AS item_type,
|
||||||
|
0 AS item_score,
|
||||||
|
0 AS item_amount,
|
||||||
|
0 AS item_multiplier,
|
||||||
|
'' AS item_category,
|
||||||
|
'' AS item_category_title,
|
||||||
|
CONCAT(LPAD(cl.create_time, 10, '0'), '_1_', LPAD(cl.id, 10, '0')) AS sort_key
|
||||||
|
FROM mall_claim_log cl
|
||||||
|
WHERE cl.user_id = :user_id_claim
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CONCAT('REDEEM_', o.type) AS biz_type,
|
||||||
|
'OUT' AS direction,
|
||||||
|
o.points_cost AS points,
|
||||||
|
o.create_time AS ts,
|
||||||
|
o.external_transaction_id AS ref_id,
|
||||||
|
o.external_transaction_id AS order_no,
|
||||||
|
o.status AS order_status,
|
||||||
|
o.mall_item_id AS item_id,
|
||||||
|
COALESCE(i.title, '') AS item_title,
|
||||||
|
COALESCE(i.type, 0) AS item_type,
|
||||||
|
COALESCE(i.score, 0) AS item_score,
|
||||||
|
COALESCE(i.amount, 0) AS item_amount,
|
||||||
|
COALESCE(i.multiplier, 0) AS item_multiplier,
|
||||||
|
COALESCE(i.category, '') AS item_category,
|
||||||
|
COALESCE(i.category_title, '') AS item_category_title,
|
||||||
|
CONCAT(LPAD(o.create_time, 10, '0'), '_2_', LPAD(o.id, 10, '0')) AS sort_key
|
||||||
|
FROM mall_order o
|
||||||
|
LEFT JOIN mall_item i ON i.id = o.mall_item_id
|
||||||
|
WHERE o.user_id = :user_id_redeem AND o.points_cost > 0
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
'REFUND' AS biz_type,
|
||||||
|
'IN' AS direction,
|
||||||
|
o.points_cost AS points,
|
||||||
|
o.update_time AS ts,
|
||||||
|
o.external_transaction_id AS ref_id,
|
||||||
|
o.external_transaction_id AS order_no,
|
||||||
|
o.status AS order_status,
|
||||||
|
o.mall_item_id AS item_id,
|
||||||
|
COALESCE(i.title, '') AS item_title,
|
||||||
|
COALESCE(i.type, 0) AS item_type,
|
||||||
|
COALESCE(i.score, 0) AS item_score,
|
||||||
|
COALESCE(i.amount, 0) AS item_amount,
|
||||||
|
COALESCE(i.multiplier, 0) AS item_multiplier,
|
||||||
|
COALESCE(i.category, '') AS item_category,
|
||||||
|
COALESCE(i.category_title, '') AS item_category_title,
|
||||||
|
CONCAT(LPAD(o.update_time, 10, '0'), '_3_', LPAD(o.id, 10, '0')) AS sort_key
|
||||||
|
FROM mall_order o
|
||||||
|
LEFT JOIN mall_item i ON i.id = o.mall_item_id
|
||||||
|
WHERE o.user_id = :user_id_refund AND o.status = 'REJECTED' AND o.points_cost > 0 AND o.update_time IS NOT NULL
|
||||||
|
) t
|
||||||
|
WHERE 1=1
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'user_id_claim' => $playxUserId,
|
||||||
|
'user_id_redeem' => $playxUserId,
|
||||||
|
'user_id_refund' => $playxUserId,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($cursor !== '') {
|
||||||
|
$sql .= "\n AND t.sort_key < :cursor";
|
||||||
|
$params['cursor'] = $cursor;
|
||||||
|
}
|
||||||
|
if ($direction !== '') {
|
||||||
|
$sql .= "\n AND t.direction = :direction";
|
||||||
|
$params['direction'] = $direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= "\nORDER BY t.sort_key DESC";
|
||||||
|
$sql .= "\nLIMIT " . $limit;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$rows = Db::query($sql, $params);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error($e->getMessage(), null, 0, ['statusCode' => 500]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = [];
|
||||||
|
$nextCursor = null;
|
||||||
|
if (is_array($rows)) {
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
if (!is_array($row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$list[] = [
|
||||||
|
'biz_type' => $row['biz_type'] ?? '',
|
||||||
|
'direction' => $row['direction'] ?? '',
|
||||||
|
'points' => $row['points'] ?? 0,
|
||||||
|
'ts' => $row['ts'] ?? null,
|
||||||
|
'ref_id' => $row['ref_id'] ?? '',
|
||||||
|
'order_no' => $row['order_no'] ?? '',
|
||||||
|
'order_status' => $row['order_status'] ?? '',
|
||||||
|
'item_id' => $row['item_id'] ?? 0,
|
||||||
|
'item_title' => $row['item_title'] ?? '',
|
||||||
|
'item_type' => $row['item_type'] ?? 0,
|
||||||
|
'item_score' => $row['item_score'] ?? 0,
|
||||||
|
'mallItem' => ($row['item_id'] ?? 0) ? [
|
||||||
|
'id' => $row['item_id'] ?? 0,
|
||||||
|
'title' => $row['item_title'] ?? '',
|
||||||
|
'type' => $row['item_type'] ?? 0,
|
||||||
|
'score' => $row['item_score'] ?? 0,
|
||||||
|
'amount' => $row['item_amount'] ?? 0,
|
||||||
|
'multiplier' => $row['item_multiplier'] ?? 0,
|
||||||
|
'category' => $row['item_category'] ?? '',
|
||||||
|
'category_title' => $row['item_category_title'] ?? '',
|
||||||
|
] : null,
|
||||||
|
'cursor' => $row['sort_key'] ?? '',
|
||||||
|
];
|
||||||
|
$nextCursor = $row['sort_key'] ?? $nextCursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success('', [
|
||||||
|
'list' => $list,
|
||||||
|
'next_cursor' => $nextCursor,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收货地址列表
|
* 收货地址列表
|
||||||
* GET /api/v1/playx/address/list?session_id=xxx
|
* GET /api/v1/playx/address/list?session_id=xxx
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ Route::post('/api/v1/mall/bonusRedeem', [\app\api\controller\v1\Playx::class, 'b
|
|||||||
Route::post('/api/v1/mall/physicalRedeem', [\app\api\controller\v1\Playx::class, 'physicalRedeem']);
|
Route::post('/api/v1/mall/physicalRedeem', [\app\api\controller\v1\Playx::class, 'physicalRedeem']);
|
||||||
Route::post('/api/v1/mall/withdrawApply', [\app\api\controller\v1\Playx::class, 'withdrawApply']);
|
Route::post('/api/v1/mall/withdrawApply', [\app\api\controller\v1\Playx::class, 'withdrawApply']);
|
||||||
Route::get('/api/v1/mall/orders', [\app\api\controller\v1\Playx::class, 'orders']);
|
Route::get('/api/v1/mall/orders', [\app\api\controller\v1\Playx::class, 'orders']);
|
||||||
|
Route::get('/api/v1/mall/pointsLogs', [\app\api\controller\v1\Playx::class, 'pointsLogs']);
|
||||||
Route::get('/api/v1/mall/addressList', [\app\api\controller\v1\Playx::class, 'addressList']);
|
Route::get('/api/v1/mall/addressList', [\app\api\controller\v1\Playx::class, 'addressList']);
|
||||||
Route::post('/api/v1/mall/addressAdd', [\app\api\controller\v1\Playx::class, 'addressAdd']);
|
Route::post('/api/v1/mall/addressAdd', [\app\api\controller\v1\Playx::class, 'addressAdd']);
|
||||||
Route::post('/api/v1/mall/addressEdit', [\app\api\controller\v1\Playx::class, 'addressEdit']);
|
Route::post('/api/v1/mall/addressEdit', [\app\api\controller\v1\Playx::class, 'addressEdit']);
|
||||||
|
|||||||
@@ -159,6 +159,47 @@ curl "https://{域名}/api/v1/temLogin?username=test001"
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 3.9 积分流水(领取/兑换/退回)
|
||||||
|
|
||||||
|
**GET** ` /api/v1/mall/pointsLogs `
|
||||||
|
|
||||||
|
鉴权:携带 `token` 或 `session_id` 或 `user_id`
|
||||||
|
|
||||||
|
参数(Query):
|
||||||
|
- `limit`:可选,每页条数(默认 20,最大 100)
|
||||||
|
- `cursor`:可选,游标(上一页响应返回的 `next_cursor`,传入后获取下一页)
|
||||||
|
- `direction`:可选,`IN`(入账)/`OUT`(扣减),不传返回全部
|
||||||
|
|
||||||
|
返回(成功 `data`):
|
||||||
|
- `list[]`:流水数组(按时间倒序)
|
||||||
|
- `biz_type`:`CLAIM`(领取入账)/ `REDEEM_BONUS|REDEEM_PHYSICAL|REDEEM_WITHDRAW`(兑换扣分)/ `REFUND`(订单驳回或终态失败退回)
|
||||||
|
- `direction`:`IN` / `OUT`
|
||||||
|
- `points`:积分变动值(正数,方向由 `direction` 表示)
|
||||||
|
- `ts`:时间戳(Unix 秒)
|
||||||
|
- `ref_id`:关联业务号(领取为 `claim_request_id`;订单为 `external_transaction_id`)
|
||||||
|
- `order_no`:订单号(非订单类为空)
|
||||||
|
- `order_status`:订单状态(非订单类为空)
|
||||||
|
- `mallItem`:商品信息(非订单类为 null)
|
||||||
|
- `id`:商品ID
|
||||||
|
- `title`:商品名
|
||||||
|
- `type`:商品类型(`1=BONUS 2=PHYSICAL 3=WITHDRAW`)
|
||||||
|
- `score`:所需积分
|
||||||
|
- `amount`:现金面值(红利/提现档位)
|
||||||
|
- `multiplier`:流水倍数
|
||||||
|
- `category`:红利业务类别
|
||||||
|
- `category_title`:类别展示名
|
||||||
|
- `item_id/item_title/item_type/item_score`:兼容字段(建议优先使用 `mallItem`)
|
||||||
|
- `cursor`:当前记录游标(用于分页)
|
||||||
|
- `next_cursor`:下一页游标(为本页最后一条的 `cursor`;若本页为空则为 null)
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -G "https://{域名}/api/v1/mall/pointsLogs" \
|
||||||
|
-H "token: <muser_token>" \
|
||||||
|
--data-urlencode "limit=20"
|
||||||
|
```
|
||||||
|
|
||||||
## 4. 地址管理(H5)
|
## 4. 地址管理(H5)
|
||||||
|
|
||||||
> 地址与资产主体通过 `playx_user_asset_id` 关联(即 `mall_user_asset.id`)。
|
> 地址与资产主体通过 `playx_user_asset_id` 关联(即 `mall_user_asset.id`)。
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ flowchart LR
|
|||||||
|
|
||||||
### 4.1 登录鉴权(Iframe + token)
|
### 4.1 登录鉴权(Iframe + token)
|
||||||
|
|
||||||
> **接口与字段细节**以代码为准,完整说明见同目录《PlayX-接口文档.md》(§3 H5、§3.2 `temLogin`、§3.3 `verify-token`)。
|
> **接口与字段细节**以代码为准,完整说明见同目录《PlayX-接口文档.md》(§3 H5、§3.2 `temLogin`、§3.3 `verifyToken`)。
|
||||||
|
|
||||||
#### 4.1.1 身份与数据模型(商城侧)
|
#### 4.1.1 身份与数据模型(商城侧)
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ flowchart LR
|
|||||||
|
|
||||||
1. 用户在 PlayX 内打开积分商城入口(iframe)。
|
1. 用户在 PlayX 内打开积分商城入口(iframe)。
|
||||||
2. PlayX 前端通过 postMessage 将 **PlayX 下发的 token**(及必要上下文)传给商城 H5。
|
2. PlayX 前端通过 postMessage 将 **PlayX 下发的 token**(及必要上下文)传给商城 H5。
|
||||||
3. 商城 H5 调用商城后端 **`POST /api/v1/playx/verify-token`**,由商城向 PlayX 的 **Token Verification API**(`playx.api.base_url` + `playx.api.token_verify_url`)发起校验。
|
3. 商城 H5 调用商城后端 **`POST /api/v1/mall/verifyToken`**,由商城向 PlayX 的 **Token Verification API**(`playx.api.base_url` + `playx.api.token_verify_url`)发起校验。
|
||||||
4. **前提**:配置 **`playx.verify_token_local_only = false`**,且 **`playx.api.base_url`** 已配置为可访问的 PlayX 基地址。
|
4. **前提**:配置 **`playx.verify_token_local_only = false`**,且 **`playx.api.base_url`** 已配置为可访问的 PlayX 基地址。
|
||||||
5. PlayX 返回 **`user_id`、`username`**(及可选会话过期时间等)。
|
5. PlayX 返回 **`user_id`、`username`**(及可选会话过期时间等)。
|
||||||
6. 商城写入 **`mall_playx_session`**(`session_id` + 上述 `user_id`/`username` + 过期时间),后续 H5 可用 **`session_id`** 或 **`token`(商城临时 token,见模式 B)** 调用资产/领取等接口。
|
6. 商城写入 **`mall_playx_session`**(`session_id` + 上述 `user_id`/`username` + 过期时间),后续 H5 可用 **`session_id`** 或 **`token`(商城临时 token,见模式 B)** 调用资产/领取等接口。
|
||||||
@@ -86,9 +86,9 @@ flowchart LR
|
|||||||
用于开发、联调前自测、或 PlayX 接口未就绪时:
|
用于开发、联调前自测、或 PlayX 接口未就绪时:
|
||||||
|
|
||||||
1. 配置 **`playx.verify_token_local_only = true`**(环境变量 **`PLAYX_VERIFY_TOKEN_LOCAL_ONLY`**,默认可为开启,以项目 `config/playx.php` 为准)。
|
1. 配置 **`playx.verify_token_local_only = true`**(环境变量 **`PLAYX_VERIFY_TOKEN_LOCAL_ONLY`**,默认可为开启,以项目 `config/playx.php` 为准)。
|
||||||
2. 此时 **`/api/v1/playx/verify-token` 不会访问 PlayX**,仅在商城内校验 **商城临时 token**(token 表类型 **`muser`**,由下方 `temLogin` 签发)。
|
2. 此时 **`/api/v1/mall/verifyToken` 不会访问 PlayX**,仅在商城内校验 **商城临时 token**(token 表类型 **`muser`**,由下方 `temLogin` 签发)。
|
||||||
3. 调用 **`GET/POST /api/v1/temLogin?username=...`**(需 **`buildadmin.agent_auth.temp_login_enable = true`**):不存在则创建 **`mall_user`**,并保证存在 **`mall_playx_user_asset`**(含 `playx_user_id`,默认 **`mall_{id}`**),返回 **`userInfo.token`**、**`playx_user_id`**、**`expires_in`** 等。
|
3. 调用 **`GET/POST /api/v1/temLogin?username=...`**(需 **`buildadmin.agent_auth.temp_login_enable = true`**):不存在则创建 **`mall_user`**,并保证存在 **`mall_playx_user_asset`**(含 `playx_user_id`,默认 **`mall_{id}`**),返回 **`userInfo.token`**、**`playx_user_id`**、**`expires_in`** 等。
|
||||||
4. 再用该 token 调用 **`verify-token`** 可得到 **`session_id`**,与模式 A 一样供后续接口使用;或直接带 **`token` / `ba-token`** 调资产等接口(见《PlayX-接口文档》§3.1)。
|
4. 再用该 token 调用 **`verifyToken`** 可得到 **`session_id`**,与模式 A 一样供后续接口使用;或直接带 **`token` / `ba-token`** 调资产等接口(见《PlayX-接口文档》§3.1)。
|
||||||
|
|
||||||
#### 4.1.4 会话续期与前端约定
|
#### 4.1.4 会话续期与前端约定
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ flowchart LR
|
|||||||
|
|
||||||
- **目的**:推送昨日玩家数据,用于 T+1 计算入池与领取上限。
|
- **目的**:推送昨日玩家数据,用于 T+1 计算入池与领取上限。
|
||||||
- **幂等键**:`user_id + date`(date 建议为 PlayX 业务日)
|
- **幂等键**:`user_id + date`(date 建议为 PlayX 业务日)
|
||||||
- **Method/Path(建议)**:`POST /api/v1/playx/daily-push`
|
- **Method/Path(建议)**:`POST /api/v1/mall/dailyPush`
|
||||||
|
|
||||||
请求字段说明(最小集合,来自现有资料):
|
请求字段说明(最小集合,来自现有资料):
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ flowchart LR
|
|||||||
|
|
||||||
其中:
|
其中:
|
||||||
|
|
||||||
- `PATH` 不含域名与 querystring(例如 `/api/v1/playx/daily-push`)。
|
- `PATH` 不含域名与 querystring(例如 `/api/v1/mall/dailyPush`)。
|
||||||
- `REQUEST_BODY_JSON` 使用原始 request body(不做 key 排序时,需双方约定序列化方式;更推荐双方统一为“key 排序后的紧凑 JSON”)。
|
- `REQUEST_BODY_JSON` 使用原始 request body(不做 key 排序时,需双方约定序列化方式;更推荐双方统一为“key 排序后的紧凑 JSON”)。
|
||||||
|
|
||||||
## 8. 错误码与可观测(建议)
|
## 8. 错误码与可观测(建议)
|
||||||
|
|||||||
@@ -823,6 +823,64 @@ curl -G 'http://localhost:1818/api/v1/mall/orders' --data-urlencode 'token=上
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.11 同步额度(可选)
|
### 3.11 积分流水(Points Logs)
|
||||||
|
* 方法:`GET`
|
||||||
|
* 路径:`/api/v1/mall/pointsLogs`
|
||||||
|
|
||||||
|
#### 请求参数(鉴权)
|
||||||
|
同 **3.1**(`session_id` / `token` / `user_id`)。
|
||||||
|
|
||||||
|
#### Query 参数
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `limit` | int | 否 | 每页条数,默认 20,最大 100 |
|
||||||
|
| `cursor` | string | 否 | 游标(上一页返回 `next_cursor`) |
|
||||||
|
| `direction` | string | 否 | `IN` 仅入账 / `OUT` 仅扣减;不传返回全部 |
|
||||||
|
|
||||||
|
#### 返回(成功 data)
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `data.list` | array | 流水数组(时间倒序) |
|
||||||
|
| `data.next_cursor` | string\|null | 下一页游标(本页最后一条记录的游标) |
|
||||||
|
|
||||||
|
`list` 每一项字段:
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `biz_type` | string | `CLAIM`/`REDEEM_BONUS`/`REDEEM_PHYSICAL`/`REDEEM_WITHDRAW`/`REFUND` |
|
||||||
|
| `direction` | string | `IN`/`OUT` |
|
||||||
|
| `points` | int | 积分变动值(正数,方向由 `direction` 表示) |
|
||||||
|
| `ts` | int | Unix 秒 |
|
||||||
|
| `ref_id` | string | 领取为 `claim_request_id`;订单为 `external_transaction_id` |
|
||||||
|
| `order_no` | string | 订单号(非订单类为空) |
|
||||||
|
| `order_status` | string | 订单状态(非订单类为空) |
|
||||||
|
| `mallItem` | object\|null | 商品信息(非订单类为 null) |
|
||||||
|
| `item_id` | int | 兼容字段:商品ID(非订单类为 0) |
|
||||||
|
| `item_title` | string | 兼容字段:商品标题(非订单类为空) |
|
||||||
|
| `item_type` | int | 兼容字段:商品类型(非订单类为 0;`1=BONUS 2=PHYSICAL 3=WITHDRAW`) |
|
||||||
|
| `item_score` | int | 兼容字段:商品所需积分(非订单类为 0) |
|
||||||
|
| `cursor` | string | 当前记录游标 |
|
||||||
|
|
||||||
|
`mallItem` 字段(非隐私):
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `id` | int | `mall_item.id` |
|
||||||
|
| `title` | string | 商品名 |
|
||||||
|
| `type` | int | 商品类型 |
|
||||||
|
| `score` | int | 所需积分 |
|
||||||
|
| `amount` | number | 现金面值 |
|
||||||
|
| `multiplier` | int | 流水倍数 |
|
||||||
|
| `category` | string | 红利业务类别 |
|
||||||
|
| `category_title` | string | 类别展示名 |
|
||||||
|
|
||||||
|
#### 示例
|
||||||
|
```bash
|
||||||
|
curl -G 'http://localhost:1818/api/v1/mall/pointsLogs' \
|
||||||
|
--data-urlencode 'token=上一步temLogin返回的token' \
|
||||||
|
--data-urlencode 'limit=20'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.12 同步额度(可选)
|
||||||
当前代码未实现并未注册路由:`/api/v1/mall/syncLimit`。
|
当前代码未实现并未注册路由:`/api/v1/mall/syncLimit`。
|
||||||
|
|
||||||
|
|||||||
BIN
docs/import-angpow-api.pdf
Normal file
BIN
docs/import-angpow-api.pdf
Normal file
Binary file not shown.
@@ -270,7 +270,7 @@
|
|||||||
|
|
||||||
### 6.2 发放请求状态机(商城内部)
|
### 6.2 发放请求状态机(商城内部)
|
||||||
|
|
||||||
针对每个订单(BONUS/WITHDRAW),在商城内部维护发放子状态,例如:
|
针对每个订单(BONUS/WITHDRAW),在商城内部维护推送playx状态,例如:
|
||||||
|
|
||||||
- `NOT_SENT`:未发送给 PlayX。
|
- `NOT_SENT`:未发送给 PlayX。
|
||||||
- `SENT_PENDING`:已发送,等待 PlayX 响应。
|
- `SENT_PENDING`:已发送,等待 PlayX 响应。
|
||||||
@@ -282,7 +282,7 @@
|
|||||||
|
|
||||||
- 只有在 `NOT_SENT` 或 `FAILED_RETRYABLE` 状态下才允许“再次发送”。
|
- 只有在 `NOT_SENT` 或 `FAILED_RETRYABLE` 状态下才允许“再次发送”。
|
||||||
- 一旦进入 `ACCEPTED`,不得再发请求(自动或人工)。
|
- 一旦进入 `ACCEPTED`,不得再发请求(自动或人工)。
|
||||||
- 订单业务状态(PENDING/COMPLETED/REJECTED)与发放子状态之间要有清晰映射:
|
- 订单业务状态(PENDING/COMPLETED/REJECTED)与推送playx状态之间要有清晰映射:
|
||||||
- `ACCEPTED` + 对账确认成功 → `COMPLETED`。
|
- `ACCEPTED` + 对账确认成功 → `COMPLETED`。
|
||||||
- `FAILED_FINAL` → `REJECTED`(并退积分)。
|
- `FAILED_FINAL` → `REJECTED`(并退积分)。
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user