合并 main 并解决 API 文档冲突
This commit is contained in:
+135
-121
@@ -3,7 +3,11 @@
|
||||
> Base URL:生产 `https://app-api.shaguabijia.com`;本地联调 `http://<开发机>:8770`
|
||||
> 协议:HTTP / JSON,请求与响应体均 `application/json`,字段统一 **snake_case**(⚠️ 例外:消息通知中心 `notifications` 族与厂商推送 `push` 族按 PRD 前端契约用 **camelCase**,见各自文档)
|
||||
> 鉴权:需鉴权的接口在请求头带 `Authorization: Bearer <access_token>`
|
||||
<<<<<<< HEAD
|
||||
> 最后更新:2026-07-14(新增 **消息通知中心** 3 端点(M1-M3,虚拟数据阶段)与 **厂商推送测试** 3 端点(P1-P3,荣耀/华为/小米/OPPO/vivo);上一次 2026-06-23 补全 device/internal/CPS 短链等整族端点)
|
||||
=======
|
||||
> 最后更新:2026-07-09(① 比价透传改「软鉴权 + trace_id 签发 + harvest 落库」(#112 尾声帧 `trace/epilogue` 一并补录);② 新端点:`user/onboarding/reset`(#114)、`GET /internal/launch-confirm-samples`(#91);③ 参数更新:提现族 `source` 分账(#82/#121)、`wallet/account` 邀请奖励金余额、美团 feed/top-sales 按城市过滤(#116)、admin 调现金 `account` 目标账户(#95);④ **Admin 索引补全到当前全量**:新家族 roles(#117/#126)/coupon-data(#99)/device-liveness(#80)/event-logs(#83)/price-reports(#94)/CPS 运营台/提现审核族,及 feedbacks 采纳拒绝(#94/#105)、marquee 模式与真实条浏览(#122/#123)等。上一次 2026-07-03)
|
||||
>>>>>>> origin/main
|
||||
> 架构:`app/api/v1/` 只放很轻的接口层;穿山甲/微信支付/极光/短信/美团等 SDK 集成的重逻辑在 `app/integrations/`,实现细节见 [docs/integrations/](../integrations/README.md)。
|
||||
|
||||
---
|
||||
@@ -12,90 +16,98 @@
|
||||
|
||||
| # | 方法 + 路径 | 鉴权 | 详情 |
|
||||
|---|---|---|---|
|
||||
| 1 | `GET /health` | 无 | [详情](./health.md) |
|
||||
| 2 | `POST /api/v1/auth/jverify-login` | 无 | [详情](./auth-jverify-login.md) |
|
||||
| 3 | `POST /api/v1/auth/sms/send` | 无 | [详情](./auth-sms-send.md) |
|
||||
| 4 | `POST /api/v1/auth/sms/login` | 无 | [详情](./auth-sms-login.md) |
|
||||
| 5 | `POST /api/v1/auth/refresh` | 无 | [详情](./auth-refresh.md) |
|
||||
| 6 | `GET /api/v1/auth/me` | Bearer | [详情](./auth-me.md) |
|
||||
| 7 | `POST /api/v1/auth/logout` | Bearer | [详情](./auth-logout.md) |
|
||||
| 8 | `POST /api/v1/coupon/step` | 无 | [详情](./coupon-step.md)(透传 pricebot + best-effort 写 `coupon_*` 三表) |
|
||||
| 8a | `POST /api/v1/coupon/prompt/shown` | 无 | 引导窗弹出即上报(按 device+package+日记 `shown`,今天这个 App 不再自动弹)(无单独文档) |
|
||||
| 8b | `POST /api/v1/coupon/prompt/dismiss` | 无 | 用户拒绝/关闭引导窗(透传链路看不到拒绝,客户端通知)(无单独文档) |
|
||||
| 8c | `GET /api/v1/coupon/prompt/should-show` | 无 | 切到外卖 App 时是否还应弹引导窗(`device_id`+`package`)(无单独文档) |
|
||||
| 8d | `POST /api/v1/coupon/prompt/reset` | 无 | 重置今日引导窗 engagement(开发测频控用)(无单独文档) |
|
||||
| 8e | `GET /api/v1/coupon/completed-today` | 无 | 这台设备今天是否已跑完整轮领券(首页「去领取」卡置灰源)(无单独文档) |
|
||||
| 8f | `POST /api/v1/coupon/completed-today/reset` | 无 | 重置今日已完成(开发用)(无单独文档) |
|
||||
| 8g | `GET /api/v1/coupon/stats` | Bearer | 累计领券数(「我的」页战绩卡;按 user_id 聚合,**鉴权**)(无单独文档) |
|
||||
| 9 | `POST /api/v1/meituan/coupons` | 无 | [详情](./meituan-coupons.md) |
|
||||
| 10 | `POST /api/v1/meituan/feed` | 无 | [详情](./meituan-feed.md) |
|
||||
| 11 | `POST /api/v1/meituan/referral-link` | 无 | [详情](./meituan-referral-link.md) |
|
||||
| 11a | `POST /api/v1/meituan/top-sales` | 无 | [详情](./meituan-top-sales.md)(销量榜:离线库 `meituan_coupon` 按销量降序 + 跨源去重,不实时打美团) |
|
||||
| **比价透传**(前缀 `/api/v1`,外卖 MVP;与 `coupon/step` 同为透传 pricebot-backend;下按 Phase 流程列,均不鉴权) |||
|
||||
| 12 | `POST /api/v1/intent/recognize` | 无 | [详情](./compare-intent-recognize.md)(Phase 1 意图识别,单次,多数源) |
|
||||
| 12a | `POST /api/v1/intent/precoupon/step` | 无 | Phase 0 意图识别前先用券,仅美团源(透传,无单独文档) |
|
||||
| 12b | `POST /api/v1/intent/step` | 无 | Phase 1 多帧意图识别,仅淘宝源,循环到 done(透传,无单独文档) |
|
||||
| 13 | `POST /api/v1/price/step` | 无 | [详情](./compare-price-step.md)(Phase 2 步进) |
|
||||
| 13a | `POST /api/v1/trace/finalize` | 无 | 比价 trace 收尾上云,终止/未识别拿 trace_url(透传,无单独文档) |
|
||||
| 1 | `GET /health` | 无 | [详情](./other/health.md) |
|
||||
| 2 | `POST /api/v1/auth/jverify-login` | 无 | [详情](./auth/auth-jverify-login.md) |
|
||||
| 3 | `POST /api/v1/auth/sms/send` | 无 | [详情](./auth/auth-sms-send.md) |
|
||||
| 4 | `POST /api/v1/auth/sms/login` | 无 | [详情](./auth/auth-sms-login.md) |
|
||||
| 5 | `POST /api/v1/auth/refresh` | 无 | [详情](./auth/auth-refresh.md) |
|
||||
| 6 | `GET /api/v1/auth/me` | Bearer | [详情](./auth/auth-me.md) |
|
||||
| 7 | `POST /api/v1/auth/logout` | Bearer | [详情](./auth/auth-logout.md) |
|
||||
| 8 | `POST /api/v1/coupon/step` | 无 | [详情](./coupon/coupon-step.md)(透传 pricebot + best-effort 写 `coupon_*` 三表) |
|
||||
| 8a | `POST /api/v1/coupon/prompt/shown` | 无 | [详情](./coupon/coupon-prompt.md)(引导窗弹出即上报) |
|
||||
| 8b | `POST /api/v1/coupon/prompt/dismiss` | 无 | [详情](./coupon/coupon-prompt.md)(用户拒绝/关闭引导窗) |
|
||||
| 8c | `GET /api/v1/coupon/prompt/should-show` | 无 | [详情](./coupon/coupon-prompt.md)(切到外卖 App 时是否还应弹引导窗) |
|
||||
| 8d | `POST /api/v1/coupon/prompt/reset` | 无 | [详情](./coupon/coupon-prompt.md)(重置今日引导窗 engagement,开发测频控用) |
|
||||
| 8e | `GET /api/v1/coupon/completed-today` | 无 | [详情](./coupon/coupon-completed-today.md)(这台设备今天是否已跑完整轮领券) |
|
||||
| 8f | `POST /api/v1/coupon/completed-today/reset` | 无 | [详情](./coupon/coupon-completed-today.md)(重置今日已完成,开发用) |
|
||||
| 8g | `GET /api/v1/coupon/stats` | Bearer | [详情](./coupon/coupon-stats.md)(累计领券数,「我的」页战绩卡) |
|
||||
| 8h | `POST /api/v1/coupon/session` | 无 | [详情](./coupon/coupon-session.md)(领券流水上报,admin 看板数据源) |
|
||||
| 9 | `POST /api/v1/meituan/coupons` | 无 | [详情](./meituan/meituan-coupons.md) |
|
||||
| 10 | `POST /api/v1/meituan/feed` | 无 | [详情](./meituan/meituan-feed.md)(`rec` tab 离线库 + **按城市过滤** #116) |
|
||||
| 11 | `POST /api/v1/meituan/referral-link` | 无 | [详情](./meituan/meituan-referral-link.md) |
|
||||
| 11a | `POST /api/v1/meituan/top-sales` | 无 | [详情](./meituan/meituan-top-sales.md)(同城销量榜:离线库按销量降序 + 跨源去重 + 城市过滤 #116,不实时打美团) |
|
||||
| **比价透传**(前缀 `/api/v1`,透传 pricebot-backend;**软鉴权 OptionalUser** + 首帧签发 trace_id + harvest 落 `comparison_record`,2026-07 起不再是纯透传) |||
|
||||
| 12 | `POST /api/v1/intent/recognize` | 软 | [详情](./intent/compare-intent-recognize.md)(Phase 1 意图识别,单次,多数源;mint 帧建 running 行) |
|
||||
| 12a | `POST /api/v1/intent/precoupon/step` | 软 | [详情](./intent/intent-step.md)(Phase 0 意图识别前先用券,仅美团源) |
|
||||
| 12b | `POST /api/v1/intent/step` | 软 | [详情](./intent/intent-step.md)(Phase 1 多帧意图识别,仅淘宝源,循环到 done) |
|
||||
| 13 | `POST /api/v1/price/step` | 软 | [详情](./intent/compare-price-step.md)(Phase 2 步进;done 帧 harvest 写终态) |
|
||||
| 13a | `POST /api/v1/trace/finalize` | 软 | [详情](./other/trace-finalize.md)(比价 trace 收尾上云 + 夭折落库,终止/未识别拿 trace_url) |
|
||||
| 13b | `POST /api/v1/trace/epilogue` | 软 | [详情](./other/trace-finalize.md)(结果页尾声帧:App 结果页截图入 trace,纯透传不落库,#112) |
|
||||
| **比价记录**(前缀 `/api/v1/compare`;按用户落库,**鉴权**,区别于上面不鉴权的透传) |||
|
||||
| 12a | `POST /api/v1/compare/record` | Bearer | [详情](./compare-record-report.md) |
|
||||
| 12b | `GET /api/v1/compare/records` | Bearer | [详情](./compare-records.md) |
|
||||
| 12c | `GET /api/v1/compare/records/{id}` | Bearer | [详情](./compare-record-detail.md) |
|
||||
| 12e | `GET /api/v1/compare/stats` | Bearer | [详情](./compare-stats.md)(「我的」页省钱战绩卡:完成比价数 + 累计发现可省) |
|
||||
| 12a | `POST /api/v1/compare/record` | Bearer | [详情](./compare/compare-record-report.md) |
|
||||
| 12b | `GET /api/v1/compare/records` | Bearer | [详情](./compare/compare-records.md) |
|
||||
| 12c | `GET /api/v1/compare/records/{id}` | Bearer | [详情](./compare/compare-record-detail.md) |
|
||||
| 12e | `GET /api/v1/compare/stats` | Bearer | [详情](./compare/compare-stats.md)(「我的」页省钱战绩卡:完成比价数 + 累计发现可省) |
|
||||
| **比价战绩里程碑**(前缀 `/api/v1/compare`;福利页「记录比价战绩」,按成功比价数解锁逐档发金币) |||
|
||||
| 12d | `GET /api/v1/compare/milestones` | Bearer | [详情](./compare-milestones.md) |
|
||||
| 12e | `POST /api/v1/compare/milestones/{milestone}/claim` | Bearer | [详情](./compare-milestone-claim.md) |
|
||||
| 12d | `GET /api/v1/compare/milestones` | Bearer | [详情](./compare/compare-milestones.md) |
|
||||
| 12e | `POST /api/v1/compare/milestones/{milestone}/claim` | Bearer | [详情](./compare/compare-milestone-claim.md) |
|
||||
| **设备 / 无障碍存活监控**(前缀 `/api/v1/device`;心跳超时检出 + 掉线召回,#65) |||
|
||||
| D1 | `POST /api/v1/device/register` | Bearer | [详情](./device-liveness.md)(注册设备/更新极光 push token) |
|
||||
| D2 | `POST /api/v1/device/heartbeat` | Bearer | [详情](./device-liveness.md)(无障碍服务存活心跳,心跳也能自注册) |
|
||||
| D3 | `GET /api/v1/device/liveness` | Bearer | [详情](./device-liveness.md)(进 App 查本机是否被判掉线过) |
|
||||
| D4 | `POST /api/v1/device/liveness/ack` | Bearer | [详情](./device-liveness.md)(确认已弹引导,清掉线告警) |
|
||||
| D1 | `POST /api/v1/device/register` | Bearer | [详情](./device/device-liveness.md)(注册设备/更新极光 push token) |
|
||||
| D2 | `POST /api/v1/device/heartbeat` | Bearer | [详情](./device/device-liveness.md)(无障碍服务存活心跳,心跳也能自注册) |
|
||||
| D3 | `GET /api/v1/device/liveness` | Bearer | [详情](./device/device-liveness.md)(进 App 查本机是否被判掉线过) |
|
||||
| D4 | `POST /api/v1/device/liveness/ack` | Bearer | [详情](./device/device-liveness.md)(确认已弹引导,清掉线告警) |
|
||||
| **上报更低价**(前缀 `/api/v1/report`;众包纠偏,人工审核发奖) |||
|
||||
| R1 | `POST /api/v1/report` | Bearer | 提交上报(multipart:`comparison_record_id`/`reported_platform_id`/`reported_price`(元) + 1~4 张截图;原最低价反查 `comparison_record.best_*` 校验须更低)(无单独文档) |
|
||||
| R2 | `GET /api/v1/report/records` | Bearer | 上报记录列表(`?status=` pending/approved/rejected 可选筛选)(无单独文档) |
|
||||
| **好友邀请**(前缀 `/api/v1/invite`;注册即生效,双方各发 1 万金币) |||
|
||||
| I1 | `GET /api/v1/invite/me` | Bearer | 我的邀请码 + 分享链接 + 已邀人数/已得金币(无单独文档) |
|
||||
| I2 | `GET /api/v1/invite/invitees` | Bearer | 我邀请的人列表(`limit`/`offset` 分页)(无单独文档) |
|
||||
| I3 | `POST /api/v1/invite/landing-track` | 无 | 落地页 `dl.html` 访问上报指纹(剪贴板归因兜底;浏览器无 token)(无单独文档) |
|
||||
| I4 | `POST /api/v1/invite/bind` | Bearer | 绑定邀请人;支持 clipboard/manual 邀请码 + fingerprint 指纹反查三种归因(无单独文档) |
|
||||
| R1 | `POST /api/v1/report` | Bearer | [详情](./other/report-submit.md)(提交上报更低价,multipart:比价记录ID+平台+价格+截图1-4张) |
|
||||
| R2 | `GET /api/v1/report/records` | Bearer | [详情](./other/report-records.md)(上报记录列表,?status=pending/approved/rejected 可选筛选) |
|
||||
| **好友邀请**(前缀 `/api/v1/invite`;绑定注册即生效但**不发奖**,#113 起好友「比价并下单」才给邀请人发**邀请奖励金**,经 `POST /order/report` 触发) |||
|
||||
| I1 | `GET /api/v1/invite/me` | Bearer | [详情](./invite/invite-me.md)(我的邀请码+分享链接+已邀人数/已得金币) |
|
||||
| I2 | `GET /api/v1/invite/invitees` | Bearer | [详情](./invite/invite-invitees.md)(我邀请的人列表,limit/offset 分页) |
|
||||
| I3 | `POST /api/v1/invite/landing-track` | 无 | [详情](./invite/invite-bind.md)(落地页 dl.html 访问上报指纹,剪贴板归因兜底;浏览器无 token) |
|
||||
| I4 | `POST /api/v1/invite/bind` | Bearer | [详情](./invite/invite-bind.md)(绑定邀请人;支持 clipboard/manual 邀请码+fingerprint 指纹反查三种归因) |
|
||||
| **钱包 / 我的资产**(前缀 `/api/v1/wallet`) |||
|
||||
| 14 | `GET /api/v1/wallet/account` | Bearer | [详情](./wallet-account.md) |
|
||||
| 15 | `GET /api/v1/wallet/coin-transactions` | Bearer | [详情](./wallet-coin-transactions.md) |
|
||||
| 16 | `GET /api/v1/wallet/cash-transactions` | Bearer | [详情](./wallet-cash-transactions.md) |
|
||||
| 17 | `GET /api/v1/wallet/exchange-info` | 无 | [详情](./wallet-exchange-info.md) |
|
||||
| 18 | `POST /api/v1/wallet/exchange` | Bearer | [详情](./wallet-exchange.md) |
|
||||
| 19 | `POST /api/v1/wallet/bind-wechat` | Bearer | [详情](./wallet-bind-wechat.md) |
|
||||
| 20 | `POST /api/v1/wallet/unbind-wechat` | Bearer | [详情](./wallet-unbind-wechat.md) |
|
||||
| 21 | `GET /api/v1/wallet/withdraw-info` | Bearer | [详情](./wallet-withdraw-info.md) |
|
||||
| 22 | `POST /api/v1/wallet/withdraw` | Bearer | [详情](./wallet-withdraw.md) |
|
||||
| 23 | `GET /api/v1/wallet/withdraw/status` | Bearer | [详情](./wallet-withdraw-status.md) |
|
||||
| 24 | `GET /api/v1/wallet/withdraw-orders` | Bearer | [详情](./wallet-withdraw-orders.md) |
|
||||
| 14 | `GET /api/v1/wallet/account` | Bearer | [详情](./wallet/wallet-account.md) |
|
||||
| 15 | `GET /api/v1/wallet/coin-transactions` | Bearer | [详情](./wallet/wallet-coin-transactions.md) |
|
||||
| 16 | `GET /api/v1/wallet/cash-transactions` | Bearer | [详情](./wallet/wallet-cash-transactions.md) |
|
||||
| 17 | `GET /api/v1/wallet/exchange-info` | 无 | [详情](./wallet/wallet-exchange-info.md) |
|
||||
| 18 | `POST /api/v1/wallet/exchange` | Bearer | [详情](./wallet/wallet-exchange.md) |
|
||||
| 19 | `POST /api/v1/wallet/bind-wechat` | Bearer | [详情](./wallet/wallet-bind-wechat.md) |
|
||||
| 20 | `POST /api/v1/wallet/unbind-wechat` | Bearer | [详情](./wallet/wallet-unbind-wechat.md) |
|
||||
| 21 | `GET /api/v1/wallet/withdraw-info` | Bearer | [详情](./wallet/wallet-withdraw-info.md) |
|
||||
| 22 | `POST /api/v1/wallet/withdraw` | Bearer | [详情](./wallet/wallet-withdraw.md)(`source` 分账:coin_cash / invite_cash,#121) |
|
||||
| 23 | `GET /api/v1/wallet/withdraw/status` | Bearer | [详情](./wallet/wallet-withdraw-status.md) |
|
||||
| 24 | `GET /api/v1/wallet/withdraw-orders` | Bearer | [详情](./wallet/wallet-withdraw-orders.md)(可按 `source` 过滤) |
|
||||
| 24a | `POST /api/v1/wallet/transfer-auth` | Bearer | [详情](./wallet/wallet-transfer-auth.md)(开启免确认到账,申请授权,返回拉起微信授权页的 package) |
|
||||
| 24b | `GET /api/v1/wallet/transfer-auth/status` | Bearer | [详情](./wallet/wallet-transfer-auth.md)(查免确认授权状态,从微信授权页返回后轮询) |
|
||||
| 24c | `POST /api/v1/wallet/transfer-auth/close` | Bearer | [详情](./wallet/wallet-transfer-auth.md)(关闭免确认到账,解除授权) |
|
||||
| **签到**(前缀 `/api/v1/signin`) |||
|
||||
| 25 | `GET /api/v1/signin/status` | Bearer | [详情](./signin-status.md) |
|
||||
| 26 | `POST /api/v1/signin` | Bearer | [详情](./signin-do.md) |
|
||||
| 26a | `POST /api/v1/signin/boost` | Bearer | [详情](./signin-boost.md) |
|
||||
| 25 | `GET /api/v1/signin/status` | Bearer | [详情](./signin/signin-status.md) |
|
||||
| 26 | `POST /api/v1/signin` | Bearer | [详情](./signin/signin-do.md) |
|
||||
| 26a | `POST /api/v1/signin/boost` | Bearer | [详情](./signin/signin-boost.md) |
|
||||
| **任务**(前缀 `/api/v1/tasks`) |||
|
||||
| 27 | `GET /api/v1/tasks` | Bearer | [详情](./tasks-list.md) |
|
||||
| 28 | `POST /api/v1/tasks/{task_key}/claim` | Bearer | [详情](./tasks-claim.md) |
|
||||
| 27 | `GET /api/v1/tasks` | Bearer | [详情](./tasks/tasks-list.md) |
|
||||
| 28 | `POST /api/v1/tasks/{task_key}/claim` | Bearer | [详情](./tasks/tasks-claim.md) |
|
||||
| **省钱**(前缀 `/api/v1/savings`) |||
|
||||
| 29 | `GET /api/v1/savings/summary` | Bearer | [详情](./savings-summary.md) |
|
||||
| 30 | `GET /api/v1/savings/battle` | Bearer | [详情](./savings-battle.md) |
|
||||
| 31 | `GET /api/v1/savings/records` | Bearer | [详情](./savings-records.md) |
|
||||
| 29 | `GET /api/v1/savings/summary` | Bearer | [详情](./savings/savings-summary.md) |
|
||||
| 30 | `GET /api/v1/savings/battle` | Bearer | [详情](./savings/savings-battle.md) |
|
||||
| 31 | `GET /api/v1/savings/records` | Bearer | [详情](./savings/savings-records.md) |
|
||||
| **看广告发奖**(前缀 `/api/v1/ad`) |||
|
||||
| 32 | `GET /api/v1/ad/pangle-callback` | 验签 | [详情](./ad-pangle-callback.md) |
|
||||
| 33 | `GET /api/v1/ad/reward-status` | Bearer | [详情](./ad-reward-status.md) |
|
||||
| 34 | `POST /api/v1/ad/test-grant` | Bearer | [详情](./ad-test-grant.md) |
|
||||
| 35 | `POST /api/v1/ad/ecpm-report` | Bearer | [详情](./ad-ecpm-report.md) |
|
||||
| 35a | `POST /api/v1/ad/feed-reward` | Bearer | [详情](./ad-feed-reward.md) |
|
||||
| 35b | `POST /api/v1/ad/reward-noshow` | Bearer | [详情](./ad-reward-noshow.md)(激励视频提前关闭/未发奖留痕,只记原因不发币) |
|
||||
| 35c | `GET /api/v1/ad/feed-reward/units` | Bearer | 信息流广告今日已发份数/上限(配合 `feed-reward` 看进度)(无单独文档) |
|
||||
| 32 | `GET /api/v1/ad/pangle-callback` | 验签 | [详情](./ad/ad-pangle-callback.md) |
|
||||
| 33 | `GET /api/v1/ad/reward-status` | Bearer | [详情](./ad/ad-reward-status.md) |
|
||||
| 34 | `POST /api/v1/ad/test-grant` | Bearer | [详情](./ad/ad-test-grant.md) |
|
||||
| 35 | `POST /api/v1/ad/ecpm-report` | Bearer | [详情](./ad/ad-ecpm-report.md) |
|
||||
| 35a | `POST /api/v1/ad/feed-reward` | Bearer | [详情](./ad/ad-feed-reward.md) |
|
||||
| 35b | `POST /api/v1/ad/reward-noshow` | Bearer | [详情](./ad/ad-reward-noshow.md)(激励视频提前关闭/未发奖留痕,只记原因不发币) |
|
||||
| 35c | `GET /api/v1/ad/feed-reward/units` | Bearer | [详情](./ad/ad-feed-reward.md)(信息流广告今日已发份数/上限,配合 feed-reward 看进度) |
|
||||
| 35d | `POST /api/v1/ad/watch-report` | Bearer | [详情](./ad/ad-watch-report.md)(上报激励视频观看时长,旧客户端兼容) |
|
||||
| **用户资料**(前缀 `/api/v1/user`) |||
|
||||
| 35 | `PATCH /api/v1/user/profile` | Bearer | [详情](./user-profile.md) |
|
||||
| 36 | `POST /api/v1/user/avatar` | Bearer | [详情](./user-avatar.md) |
|
||||
| 36a | `POST /api/v1/user/onboarding/complete` | Bearer | 标记新手引导完成(按 账号+device_id 幂等,跨卸载重装持久)(无单独文档) |
|
||||
| 36b | `GET /api/v1/user/onboarding/status` | Bearer | 查该 (账号,设备) 是否走过引导(运营在 admin 删记录即触发重走)(无单独文档) |
|
||||
| 37 | `DELETE /api/v1/user` | Bearer | [详情](./user-delete.md) |
|
||||
| 35 | `PATCH /api/v1/user/profile` | Bearer | [详情](./user/user-profile.md) |
|
||||
| 36 | `POST /api/v1/user/avatar` | Bearer | [详情](./user/user-avatar.md) |
|
||||
| 36a | `POST /api/v1/user/onboarding/complete` | Bearer | [详情](./user/user-onboarding.md)(标记新手引导完成,按 账号+device_id 幂等,跨卸载重装持久) |
|
||||
| 36b | `GET /api/v1/user/onboarding/status` | Bearer | [详情](./user/user-onboarding.md)(查该 账号+设备 是否走过引导,运营在 admin 删记录即触发重走) |
|
||||
| 36c | `POST /api/v1/user/onboarding/reset` | Bearer | [详情](./user/user-onboarding.md)(重置本设备引导标记,下次登录重走,#114) |
|
||||
| 37 | `DELETE /api/v1/user` | Bearer | [详情](./user/user-delete.md) |
|
||||
| **帮助与反馈**(前缀 `/api/v1/feedback`) |||
|
||||
<<<<<<< HEAD
|
||||
| 38 | `POST /api/v1/feedback` | Bearer | [详情](./feedback.md) |
|
||||
| 38a | `GET /api/v1/feedback/config` | Bearer | 反馈页「加群二维码」卡配置(开关 + 二维码图 + 三行文案)(无单独文档) |
|
||||
| 38b | `GET /api/v1/feedback/records` | Bearer | 我的反馈历史(pending/adopted/rejected)(无单独文档) |
|
||||
@@ -107,63 +119,65 @@
|
||||
| P1 | `GET /api/v1/push/vendors` | Bearer | [详情](./push-vendor-test.md)(5 厂商服务端凭据配置状态,缺哪些 .env 键一目了然) |
|
||||
| P2 | `GET /api/v1/push/templates` | Bearer | [详情](./push-vendor-test.md)(13 类通知的 push 标题/正文模板 + PRD 示例渲染效果) |
|
||||
| P3 | `POST /api/v1/push/test` | Bearer | [详情](./push-vendor-test.md)(测试发送:默认 mock 不真发;mock=false 真发;可联动插一条站内 mock 通知闭环验证已读) |
|
||||
=======
|
||||
| 38 | `POST /api/v1/feedback` | Bearer | [详情](./other/feedback.md) |
|
||||
| 38a | `GET /api/v1/feedback/config` | Bearer | [详情](./other/feedback-config.md)(反馈页「加群二维码」卡配置:开关+二维码图+三行文案) |
|
||||
| 38b | `GET /api/v1/feedback/records` | Bearer | [详情](./other/feedback-records.md)(我的反馈历史,pending/adopted/rejected) |
|
||||
| **埋点 & 订单上报**(前缀分散;全部 Bearer 除 analytics/events 不强制登录) |||
|
||||
| E1 | `POST /api/v1/analytics/events` | 无 | [详情](./other/analytics-events.md)(批量上报埋点事件,不强制登录,每批最多200条) |
|
||||
| E2 | `POST /api/v1/order/report` | Bearer | [详情](./other/order-report.md)(上报归因订单,比价后5分钟内点链接+支付金额与比价价相差≤1元) |
|
||||
>>>>>>> origin/main
|
||||
| **首页门面数据 / 客户端配置**(前缀 `/api/v1/platform`;全平台展示数字 + 运营开关,**全部不鉴权**,登录前可读) |||
|
||||
| 39 | `GET /api/v1/platform/stats` | 无 | [详情](./platform-stats.md) |
|
||||
| 40 | `GET /api/v1/platform/savings-feed` | 无 | [详情](./platform-savings-feed.md) |
|
||||
| 40a | `GET /api/v1/platform/flags` | 无 | 客户端运营 feature flag(比价/领券期广告开关等),拉取后缓存(无单独文档) |
|
||||
| 40b | `GET /api/v1/platform/ad-config` | 无 | 客户端拉广告配置(穿山甲 app_id + 各位 ID + 各场景开关;不含验签密钥)(无单独文档) |
|
||||
| 40c | `GET /api/v1/platform/app-version` | 无 | 最新 App 版本(OTA 检查更新;与本机 versionCode 比)(无单独文档) |
|
||||
| 39 | `GET /api/v1/platform/stats` | 无 | [详情](./platform/platform-stats.md) |
|
||||
| 40 | `GET /api/v1/platform/savings-feed` | 无 | [详情](./savings/platform-savings-feed.md) |
|
||||
| 40a | `GET /api/v1/platform/flags` | 无 | [详情](./platform/platform-flags.md)(客户端运营 feature flag,比价/领券期广告开关等,拉取后缓存) |
|
||||
| 40b | `GET /api/v1/platform/ad-config` | 无 | [详情](./platform/platform-ad-config.md)(客户端拉广告配置:穿山甲 app_id+各位ID+各场景开关;不含验签密钥) |
|
||||
| 40c | `GET /api/v1/platform/app-version` | 无 | [详情](./platform/platform-app-version.md)(最新 App 版本,OTA 检查更新;与本机 versionCode 比) |
|
||||
| **微信支付回调**(前缀 `/api/v1/wxpay`) |||
|
||||
| W1 | `POST /api/v1/wxpay/transfer-auth-notify` | 无 | 免确认收款授权结果通知(一期 stub:仅应答 200 不验签不改账,授权状态靠主动查询兜底)(无单独文档) |
|
||||
| **CPS 群发短链落地**(**无前缀**,挂域名根;公网不鉴权) |||
|
||||
| C1 | `GET /c/{code}` | 无 | [详情](./cps-redirect.md)(短链落地:微信授权拿 openid + 记点击 + 302 跳/淘宝 H5 落地页) |
|
||||
| C2 | `POST /c/{code}/copy` | 无 | [详情](./cps-redirect.md)(淘宝落地页点「复制口令」记 `copy`) |
|
||||
| C3 | `GET /wx/oauth/cb` | 无 | [详情](./cps-redirect.md)(微信网页授权回调;upsert `cps_wx_user` + 种 cookie,`include_in_schema=False`) |
|
||||
| C4 | `GET /MP_verify_*.txt` | 无 | [详情](./cps-redirect.md)(微信「网页授权域名」归属校验文件,`include_in_schema=False`) |
|
||||
| C1 | `GET /c/{code}` | 无 | [详情](./other/cps-redirect.md)(短链落地:微信授权拿 openid + 记点击 + 302 跳/淘宝 H5 落地页) |
|
||||
| C2 | `POST /c/{code}/copy` | 无 | [详情](./other/cps-redirect.md)(淘宝落地页点「复制口令」记 `copy`) |
|
||||
| C3 | `GET /wx/oauth/cb` | 无 | [详情](./other/cps-redirect.md)(微信网页授权回调;upsert `cps_wx_user` + 种 cookie,`include_in_schema=False`) |
|
||||
| C4 | `GET /MP_verify_*.txt` | 无 | [详情](./other/cps-redirect.md)(微信「网页授权域名」归属校验文件,`include_in_schema=False`) |
|
||||
| **内部回写端点**(前缀 `/internal`;pricebot/发布流程→app-server,**`X-Internal-Secret` 头**,非客户端接口) |||
|
||||
| N1 | `POST /internal/price-observation` | 内部密钥 | [详情](./internal.md)(比价价格事实批量落 `price_observation`) |
|
||||
| N2 | `GET /internal/store-mapping/lookup` | 内部密钥 | [详情](./internal.md)(按源平台店名反查目标平台已沉淀店铺 id/deeplink) |
|
||||
| N3 | `POST /internal/store-mapping` | 内部密钥 | [详情](./internal.md)(跨平台店铺身份映射落 `store_mapping`) |
|
||||
| N4 | `POST /internal/store-mapping/invalidate` | 内部密钥 | [详情](./internal.md)(标记某平台 shopId 缓存 deeplink 失效) |
|
||||
| N5 | `POST /internal/launch-confirm-sample` | 内部密钥 | [详情](./internal.md)(启动确认窗兜底样本落 `launch_confirm_sample`) |
|
||||
| N6 | `POST /internal/app-version` | 内部密钥 | [详情](./internal.md)(发布流程写最新 App 版本,落 `app_config`) |
|
||||
| N1 | `POST /internal/price-observation` | 内部密钥 | [详情](./internal/internal.md)(比价价格事实批量落 `price_observation`) |
|
||||
| N2 | `GET /internal/store-mapping/lookup` | 内部密钥 | [详情](./internal/internal.md)(按源平台店名反查目标平台已沉淀店铺 id/deeplink) |
|
||||
| N3 | `POST /internal/store-mapping` | 内部密钥 | [详情](./internal/internal.md)(跨平台店铺身份映射落 `store_mapping`) |
|
||||
| N4 | `POST /internal/store-mapping/invalidate` | 内部密钥 | [详情](./internal/internal.md)(标记某平台 shopId 缓存 deeplink 失效) |
|
||||
| N5 | `POST /internal/launch-confirm-sample` | 内部密钥 | [详情](./internal/internal.md)(启动确认窗兜底样本落 `launch_confirm_sample`) |
|
||||
| N6 | `POST /internal/app-version` | 内部密钥 | [详情](./internal/internal.md)(发布流程写最新 App 版本,落 `app_config`) |
|
||||
| N7 | `GET /internal/launch-confirm-samples` | 内部密钥 | [详情](./internal/internal.md)(样本列表,供 pricebot distill 脚本聚合沉淀回静态规则,#91) |
|
||||
| **静态资源**(StaticFiles 挂载,见下方 `/media` 静态服务) |||
|
||||
| - | `GET /media/avatars/<file>` | 无 | 用户头像;返回二进制图片 |
|
||||
| - | `GET /media/feedback/<file>` | 无 | 反馈截图;返回二进制图片 |
|
||||
| **运营后台 Admin**(独立子应用 `app/admin/`,前缀 `/admin/api`,独立进程 + 独立 admin JWT。鉴权列:`admin`=任意已登录管理员,`operator`/`finance`/`super_admin`=需对应角色(`super_admin` 恒通过)) |||
|
||||
| A1 | `POST /admin/api/auth/login` | 无 | [详情](./admin-auth-login.md) |
|
||||
| A2 | `GET /admin/api/auth/me` | admin | [详情](./admin-auth-me.md) |
|
||||
| A3 | `GET /admin/api/stats/overview` | admin | [详情](./admin-stats-overview.md) |
|
||||
| A4 | `GET /admin/api/users` | admin | [详情](./admin-users-list.md) |
|
||||
| A5 | `GET /admin/api/users/{user_id}` | admin | [详情](./admin-user-detail.md) |
|
||||
| A6 | `POST /admin/api/users/{user_id}/status` | operator | [详情](./admin-user-status.md) |
|
||||
| A7 | `POST /admin/api/users/{user_id}/coins` | finance | [详情](./admin-user-coins.md) |
|
||||
| A8 | `POST /admin/api/users/{user_id}/cash` | finance | [详情](./admin-user-cash.md) |
|
||||
| A9 | `GET /admin/api/wallet/coin-transactions` | admin | [详情](./admin-wallet-coin-transactions.md) |
|
||||
| A10 | `GET /admin/api/wallet/cash-transactions` | admin | [详情](./admin-wallet-cash-transactions.md) |
|
||||
| A11 | `GET /admin/api/withdraws` | admin | [详情](./admin-withdraws-list.md) |
|
||||
| A12 | `POST /admin/api/withdraws/reconcile` | finance | [详情](./admin-withdraw-reconcile.md) |
|
||||
| A13 | `POST /admin/api/withdraws/{out_bill_no}/refresh` | finance | [详情](./admin-withdraw-refresh.md) |
|
||||
| A14 | `GET /admin/api/feedbacks` | admin | [详情](./admin-feedbacks-list.md) |
|
||||
| A15 | `POST /admin/api/feedbacks/{feedback_id}/handle` | operator | [详情](./admin-feedback-handle.md) |
|
||||
| A16 | `GET /admin/api/admins` | super_admin | [详情](./admin-admins-list.md) |
|
||||
| A17 | `POST /admin/api/admins` | super_admin | [详情](./admin-admin-create.md) |
|
||||
| A18 | `PATCH /admin/api/admins/{admin_id}` | super_admin | [详情](./admin-admin-update.md) |
|
||||
| A19 | `GET /admin/api/audit-logs` | admin | [详情](./admin-audit-logs.md) |
|
||||
| A20 | `GET /admin/api/dashboard-display` | admin | [详情](./admin-dashboard-display.md) |
|
||||
| A21 | `PATCH /admin/api/dashboard-display/{metric}` | operator | [详情](./admin-dashboard-display.md) |
|
||||
| A22 | `GET /admin/api/marquee-seeds` | admin | [详情](./admin-marquee-seeds.md) |
|
||||
| A23 | `POST /admin/api/marquee-seeds` | operator | [详情](./admin-marquee-seeds.md) |
|
||||
| A24 | `PATCH /admin/api/marquee-seeds/{seed_id}` | operator | [详情](./admin-marquee-seeds.md) |
|
||||
| A25 | `DELETE /admin/api/marquee-seeds/{seed_id}` | operator | [详情](./admin-marquee-seeds.md) |
|
||||
| A26 | `POST /admin/api/marquee-seeds/bulk` | operator | [详情](./admin-marquee-seeds.md) |
|
||||
| A27 | `GET /admin/api/marquee-seeds/preview` | admin | [详情](./admin-marquee-seeds.md) |
|
||||
| A28 | `GET /admin/api/ad-coin-audit` | admin | [详情](./admin-ad-coin-audit.md)(看广告金币公式复算对账,只读) |
|
||||
| A29 | `GET /admin/api/ad-revenue-report` | admin | [详情](./admin-ad-revenue-report.md)(广告收益报表:按用户/日期/类型/应用/代码位 聚合 条数/收益/金币,只读) |
|
||||
| **运营后台 Admin**(独立子应用 `app/admin/`,前缀 `/admin/api`,独立进程 + 独立 admin JWT。鉴权列:`admin`=任意已登录管理员,`operator`/`finance`/`super_admin`=需对应角色;#117 起可见页由 [admin_role](../database/admin_role.md) 数据驱动,`super_admin` 恒通过) |||
|
||||
| A1 | `POST /admin/api/auth/login` · `GET /auth/me` | 无 / admin | [详情](./admin/auth/admin-auth-login.md) / [me](./admin/auth/admin-auth-me.md)(me 返回有效可见页 `pages`) |
|
||||
| A2 | `GET /admin/api/stats/overview` | admin | [详情](./admin/admin-stats-overview.md)(大盘核心指标;#103 按 trace 聚合 + 京东收益 #90 + feed_scene 口径 #125) |
|
||||
| A3 | `GET /admin/api/event-logs` | admin | [详情](./admin/admin-event-logs.md)(埋点日志检索,#83) |
|
||||
| **A·用户**:`GET /users`(筛选排序分页)、`GET /users/{id}`(360 详情)、`GET /{id}/reward-stats` + `GET /{id}/coin-records`(提现详情联查)、`POST /{id}/status`(封禁)、`POST /{id}/debug-trace`(调试链接权限)、`POST /{id}/coins`、`POST /{id}/cash`(#95 `account` 目标账户) ||| [列表](./admin/users/admin-users-list.md) / [详情](./admin/users/admin-user-detail.md) / [状态+debug-trace](./admin/users/admin-user-status.md) / [金币](./admin/users/admin-user-coins.md) / [现金](./admin/users/admin-user-cash.md) |
|
||||
| A4 | `GET /admin/api/wallet/coin-transactions` / `cash-transactions` | admin | [金币](./admin/wallet/admin-wallet-coin-transactions.md) / [现金](./admin/wallet/admin-wallet-cash-transactions.md) |
|
||||
| **A·提现审核台**:`GET /withdraws`(列表)、`/summary`、`/health-check`(finance)、`/ledger-check`(#121 分账对账)、`/{out_bill_no}`(详情)、`POST /reconcile`、单笔 `refresh`/`approve`/`reject`、批量 `bulk/refresh`/`bulk/approve`/`bulk/reject` ||| [列表](./admin/withdraws/admin-withdraws-list.md) / [审核族](./admin/withdraws/admin-withdraw-review.md) / [对账](./admin/withdraws/admin-withdraw-reconcile.md) / [查单](./admin/withdraws/admin-withdraw-refresh.md) |
|
||||
| **A·反馈**:`GET /feedbacks`、`/summary`、`POST /{id}/approve`(采纳发币 #94)、`/{id}/reject`、`/{id}/handle` ||| [列表](./admin/feedbacks/admin-feedbacks-list.md) / [审核族](./admin/feedbacks/admin-feedback-handle.md) |
|
||||
| A5 | `GET`/`PATCH` `/admin/api/feedback-config`,`POST`/`DELETE` `…/image` | operator | 反馈页「加群二维码」卡配置(admin 侧;C 端读见 38a)(无单独文档,见 `app/admin/routers/feedback_qr.py`) |
|
||||
| **A·上报更低价**:`GET /price-reports`、`/summary`、`POST /{id}/approve|reject`(#94) ||| [审核族](./admin/admin-price-reports.md) |
|
||||
| A6 | `GET /admin/api/comparison-records`(+`/{id}` 详情) | admin | 比价记录检索(按 user/phone/**店与商品名模糊搜** #117 筛;详情含 LLM 调用明细)(无单独文档,见 `app/admin/routers/comparison.py`) |
|
||||
| A7 | `GET /admin/api/coupon-data`(+`/user-records`) | admin | [详情](./admin/admin-coupon-data.md)(领券数据看板,#99) |
|
||||
| A8 | `GET /admin/api/device-liveness`(+`/stats`) | admin | [详情](./admin/admin-device-liveness.md)(设备存活监控,#80) |
|
||||
| A9 | `GET /onboarding/devices`、`POST /devices/{id}/reset`、`POST /reset-all` | operator | 新手引导记录管理(按设备聚合/重置)(无单独文档,见 `app/admin/routers/onboarding.py`) |
|
||||
| **A·轮播**:`GET /marquee-seeds`、`/preview`、`/real-records`(#123)、`GET`/`PATCH` `/mode`(#122,模式落 `app_config`)、`POST`(+`/bulk`、`/batch-delete`、`/batch-enable`)、`PATCH`/`DELETE` `/{seed_id}` ||| [详情](./admin/admin-marquee-seeds.md) |
|
||||
| A10 | `GET / PATCH /admin/api/dashboard-display` | admin / operator | [详情](./admin/admin-dashboard-display.md)(首页三统计配置) |
|
||||
| A11 | `GET /admin/api/ad-coin-audit` | admin | [详情](./admin/ad/admin-ad-coin-audit.md)(看广告金币公式复算对账,只读) |
|
||||
| A12 | `GET /admin/api/ad-revenue-report` | admin | [详情](./admin/ad/admin-ad-revenue-report.md)(广告收益报表:分页/场景/`app_env` 筛 + **DAU/ARPU** #120;真实收益侧接穿山甲日表 #92) |
|
||||
| A13 | `GET / PATCH /admin/api/ad-config` | operator/finance | 广告配置(穿山甲 ID/验签密钥/各场景开关;C 端只读版见 40b)(无单独文档,见 `app/admin/routers/ad_config.py`) |
|
||||
| A14 | `GET /admin/api/config`、`PATCH /config/{key}` | operator/finance | 运营可配置项([app_config](../database/app_config.md):奖励常量/提现地板价等;#117 修系统配置下发)(无单独文档,见 `app/admin/routers/config.py`) |
|
||||
| **A·管理员与角色**(super_admin):`GET`/`POST` `/admins`、`PATCH`/`DELETE` `/admins/{id}`(#126 删除+`pages_override`)、`GET`/`POST` `/roles`、`GET /roles/catalog`、`PATCH`/`DELETE` `/roles/{id}`(#117/#126 自定义角色) ||| [列表](./admin/admins/admin-admins-list.md) / [建](./admin/admins/admin-admin-create.md) / [改+删](./admin/admins/admin-admin-update.md) / [角色](./admin/admin-roles.md) |
|
||||
| A15 | `GET /admin/api/audit-logs` | admin | [详情](./admin/admin-audit-logs.md) |
|
||||
| **A·CPS 运营台**:群/活动 CRUD、`POST /referral-links`、`POST /orders/reconcile`(美团+京东 #90)、`GET /orders`、`/stats`、群 `timeseries`/`daily`/`wx-users`/`day-users`(#79) ||| [详情](./admin/admin-cps.md) |
|
||||
| - | `GET /admin/api/health` | 无 | admin 健康检查(无单独文档) |
|
||||
|
||||
> ⚠️ 美团三个接口当前**无鉴权**,且 `referral-link` 的 `sid` 允许客户端传值覆盖默认渠道——见各接口"备注"。
|
||||
> `coupon/step` 及外卖比价的 `intent/recognize`、`intent/precoupon/step`、`intent/step`、`price/step`、`trace/finalize` 都透传到 pricebot-backend,**MVP 阶段均不鉴权**(device_id 透传,待补 JWT——见 `app/api/v1/compare.py`)。
|
||||
> `coupon/step` 透传到 pricebot-backend,**仍不鉴权**(device_id 区分设备,待补 JWT)。外卖比价透传族(`intent/*`、`price/step`、`trace/finalize|epilogue`)2026-07 起改**软鉴权 OptionalUser**:带 Bearer 则比价记录绑 `user_id`,不带也放行;并由 app-server 首帧签发 `trace_id` + harvest 落 `comparison_record`(见 `app/api/v1/compare.py` 模块注释)。
|
||||
> 福利相关业务接口(wallet/signin/tasks/savings、`ad/reward-status`、`ad/feed-reward`)均需 **Bearer**;`wallet/exchange-info` 是静态规则无鉴权;`ad/pangle-callback` 不走 JWT、靠穿山甲**验签**;`ad/test-grant` **仅本地联调**(开关控制,生产 404)。
|
||||
> 金额字段一律以**分**为单位(`*_cents`)。
|
||||
|
||||
@@ -209,8 +223,8 @@
|
||||
|---|---|---|
|
||||
| `id` | int | 用户主键 |
|
||||
| `phone` | string | 手机号(注销账号后变 `deleted_<id>` 占位释放唯一约束) |
|
||||
| `nickname` | string \| null | 昵称,经 [`PATCH /api/v1/user/profile`](./user-profile.md) 修改 |
|
||||
| `avatar_url` | string \| null | 头像相对 URL(`/media/avatars/...`),经 [`POST /api/v1/user/avatar`](./user-avatar.md) 上传 |
|
||||
| `nickname` | string \| null | 昵称,经 [`PATCH /api/v1/user/profile`](./user/user-profile.md) 修改 |
|
||||
| `avatar_url` | string \| null | 头像相对 URL(`/media/avatars/...`),经 [`POST /api/v1/user/avatar`](./user/user-avatar.md) 上传 |
|
||||
| `register_channel` | string | 注册渠道:`jverify` / `sms` |
|
||||
| `status` | string | `active` / `disabled` / `deleted` |
|
||||
| `created_at` | datetime | 注册时间 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/ad/ecpm-report — 上报本次广告展示的 eCPM(内部收益统计)
|
||||
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
请求体:`EcpmReportIn`
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/ad/pangle-callback — 穿山甲 GroMore 激励视频发奖回调(S2S)
|
||||
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:**无 JWT,靠验签**(穿山甲 GroMore 服务器调用) | 限流:同 IP ≤300 次/分 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:**无 JWT,靠验签**(穿山甲 GroMore 服务器调用) | 限流:同 IP ≤300 次/分 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> ⚠️ 我们客户端用 `useMediation(true)`(GroMore 融合),回调走 **GroMore 广告位层级**(规范见 supportcenter/26240),**不是**联盟代码位层级(5416)。两者密钥、响应格式都不同,别混。后台配置入口:**GroMore 聚合管理 → 搜广告位ID → 编辑 → 勾选「服务端激励回调」**(广告位层级配了就别再在代码位层级重复配,会冲突)。
|
||||
>
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/ad/reward-status — 今日看广告发奖进度
|
||||
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/ad/test-grant — [仅本地联调]模拟穿山甲回调发奖
|
||||
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | 限流:同 IP ≤60 次/分 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | 限流:同 IP ≤60 次/分 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> ⚠️ **仅本地联调**,受 `AD_REWARD_TEST_GRANT_ENABLED` 开关控制,**生产必须关闭**(默认 False → 一律 404)。
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# POST /api/v1/ad/watch-report — 上报激励视频观看时长
|
||||
|
||||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | 限流:同 IP ≤120 次/分 | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端在激励视频关闭(onAdClose)后上报本次实际观看秒数,服务端累计到当日总时长。当前产品只保留每日 500 次上限,DAILY_AD_WATCH_SECONDS_LIMIT=0 表示时长闸不启用;该接口仍保留用于旧客户端兼容和排查观看时长。
|
||||
|
||||
## 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `seconds` | int | ✅ (≥0) | 本次观看秒数,服务端夹 [0, MAX_SINGLE_WATCH_SECONDS] |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"seconds": 28
|
||||
}
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`WatchReportOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `watched_seconds_today` | int | 今日累计观看秒数 |
|
||||
| `watch_seconds_limit` | int | 每日上限(秒);0 表示当前未启用时长闸 |
|
||||
| `watch_seconds_remaining` | int | 今日剩余可观看秒数 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"watched_seconds_today": 128,
|
||||
"watch_seconds_limit": 0,
|
||||
"watch_seconds_remaining": 0
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `401` 未鉴权 / token 失效
|
||||
- `422` `seconds` 缺或为负
|
||||
|
||||
## 说明
|
||||
- 鉴权靠 Bearer,`user_id` 取自 JWT(不信 body)
|
||||
- 后端只做累计 + 上限裁切,不据此发奖(发奖靠 S2S 回调)
|
||||
- `watch_seconds_limit=0` 时客户端不据此拦截,按每日 500 次上限走
|
||||
@@ -1,23 +0,0 @@
|
||||
# POST /admin/api/feedbacks/{feedback_id}/handle — 标记反馈已处理
|
||||
|
||||
> 所属:Admin·反馈 组(前缀 `/admin/api/feedbacks`) | 鉴权:Bearer admin_token(角色:`operator`,`super_admin` 恒通过,`require_role("operator")`) | [← 返回 API 索引](./README.md)
|
||||
|
||||
## 入参
|
||||
- 路径:`feedback_id`(int)
|
||||
- body:无
|
||||
|
||||
## 出参
|
||||
响应 `200`:`OkResponse` = `{ "ok": true }`
|
||||
|
||||
幂等说明:将该反馈 `status` 置为 `handled`(不校验原状态,重复调用结果一致)。
|
||||
|
||||
## 错误码
|
||||
- `401` 未带/无效/过期 admin token、管理员被禁用(头带 `WWW-Authenticate: Bearer`)
|
||||
- `403` 角色不足(需 `operator` 或 `super_admin`)
|
||||
- `404` 反馈不存在(`detail: "反馈不存在"`)
|
||||
- `422` `feedback_id` 非合法 int
|
||||
|
||||
## 说明
|
||||
- 写操作记审计 [admin_audit_log](../database/admin_audit_log.md):`action="feedback.handle"`、`target_type="feedback"`、`target_id=<feedback_id>`、`detail={"before": <原 status>, "after": "handled"}`、`ip=<客户端 IP>`。
|
||||
- 状态变更与审计写入在同一事务(`commit=False` 后统一 `db.commit()`)。
|
||||
- 关联表 [feedback](../database/feedback.md)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# Admin 看广告金币审计
|
||||
|
||||
> 所属:Admin 组(前缀 `/admin/api/ad-coin-audit`) | 鉴权:Admin Bearer(任意已登录 admin,只读) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin 组(前缀 `/admin/api/ad-coin-audit`) | 鉴权:Admin Bearer(任意已登录 admin,只读) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
把「看视频赚金币」(`ad_reward_record`)和「比价信息流广告」(`ad_feed_reward_record`)两类发奖记录,用与**正式发奖完全相同**的公式 [`app/core/rewards.py` `calculate_ad_reward_coin`](../../app/core/rewards.py) 复算一遍 `expected_coin`,与实际入账的 `actual_coin` 对比,核对金币公式是否生效。**纯只读对账**,不发币、不改任何数据。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Admin 广告收益报表
|
||||
|
||||
> 所属:Admin 组(前缀 `/admin/api/ad-revenue-report`) | 鉴权:Admin Bearer(任意已登录 admin,只读) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin 组(前缀 `/admin/api/ad-revenue-report`) | 鉴权:Admin Bearer(任意已登录 admin,只读) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
按 **用户 × 日期 × 广告类型 × 我们的应用 × 我们的代码位** 聚合,回答「每个用户某天、每类广告(激励视频 / 信息流 / 历史 Draw)分别**看了多少条**、**收益多少**、按现算法**发了多少金币**、广告来自**哪个应用的哪个代码位**」。**纯只读**,不发币、不改数据,也**不改发奖逻辑**。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/audit-logs — 审计日志(谁改了什么,游标分页)
|
||||
|
||||
> 所属:Admin·Audit 组(前缀 `/admin/api/audit-logs`) | 鉴权:Bearer admin_token(角色:任意已登录 admin) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·Audit 组(前缀 `/admin/api/audit-logs`) | 鉴权:Bearer admin_token(角色:任意已登录 admin) | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参(query)
|
||||
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
||||
@@ -0,0 +1,17 @@
|
||||
# /admin/api/coupon-data — 领券数据看板(#99)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api`) | 鉴权:admin(任意已登录管理员) | 表 [coupon_session](../../database/coupon_session.md) | [← 返回 API 索引](../README.md)
|
||||
|
||||
数据源是客户端两段上报的 `coupon_session`(一次领券任务一行:发起建行/收尾更新)。看板量化:发起数、完成率、**中途流失**(started 无终态)、平均/分位耗时、各平台耗时、机型/ROM 维度。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET /admin/api/coupon-data` | 看板聚合:发起/完成数 + 耗时分位 + 按天趋势 + 逐条明细(按 `started_date` 区间 + `app_env` 筛,默认只看 prod 防测试数据串台) |
|
||||
| `GET /admin/api/coupon-data/user-records` | 某用户全部领券记录(用户列表点手机号抽屉:领券次数 + 记录列表) |
|
||||
|
||||
## 说明
|
||||
- 明细行 LEFT JOIN `user` 出手机号/昵称(匿名领券行 user 列为空)。
|
||||
- 「发起平台」列按 `origin_package` 区分:空=App 内首页发起,包名=从对应外卖 App 弹券引导发起。
|
||||
- 耗时口径:`elapsed_ms` 客户端全程计时(只统计 completed)。
|
||||
@@ -0,0 +1,28 @@
|
||||
# /admin/api/cps — CPS 群发联盟运营台(群/活动/短链/对账)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api/cps`) | 鉴权:读=admin,写=operator/finance(对账) | 表 [cps_group](../../database/cps_group.md) / [cps_activity](../../database/cps_activity.md) / [cps_link](../../database/cps_link.md) / [cps_click](../../database/cps_click.md) / [cps_order](../../database/cps_order.md) / [cps_wx_user](../../database/cps_wx_user.md) | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 业务与授权流程详见 [guides/CPS发券分发与微信授权](../../guides/CPS发券分发与微信授权.md);C 端落地短链见 [cps-redirect](../other/cps-redirect.md)。
|
||||
|
||||
私域社群 CPS 的完整运营链:建群(拿 `sid`)→ 建活动(券/物料)→ 生成群发短链 `/c/{code}` → 用户点击/复制口令 → 联盟订单按 `sid` 归群对账,汇成「点击→下单→佣金」漏斗。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET / POST /admin/api/cps/groups`,`PATCH / DELETE /groups/{id}` | 推广群 CRUD;含美团平台的群自动分配 `sid` |
|
||||
| `GET / POST /admin/api/cps/activities`,`PATCH / DELETE /activities/{id}` | 可推广活动 CRUD(美团 actId / 淘宝淘口令 / 京东链接) |
|
||||
| `POST /admin/api/cps/upload-image`、`GET /activity-images` | 活动落地页图上传 / 已有图列表(新建复用) |
|
||||
| `POST /admin/api/cps/referral-links` | 批量生成群×活动短链(美团经 sid 转链) |
|
||||
| `POST /admin/api/cps/orders/reconcile` | 拉联盟订单对账(美团 `query_order` + 京东联盟 #90,`order_id` 幂等 upsert;finance) |
|
||||
| `GET /admin/api/cps/orders` | 订单明细(游标分页,可按 sid / 状态筛) |
|
||||
| `GET /admin/api/cps/stats` | 按群对账统计(点击/订单/GMV/预估与结算佣金) |
|
||||
| `GET /admin/api/cps/groups/{id}/timeseries` | 群点击时序(天/小时级 PV/UV/复制,折线图) |
|
||||
| `GET /admin/api/cps/groups/{id}/daily` | 群每天明细大表格(点击+订单按天合并;#79 起支持按天下钻) |
|
||||
| `GET /admin/api/cps/groups/{id}/wx-users` | 群内微信用户(领券画像:头像/昵称/领券次数) |
|
||||
| `GET /admin/api/cps/groups/{id}/day-users` | 某天该群按用户的领券/点击 + 每人点过的券(#79) |
|
||||
|
||||
## 说明
|
||||
- 订单与点击**只能在群(sid)维度汇合**,无法对到单笔(联盟只回传 sid)。
|
||||
- 京东单有效性按 `jd_valid_code`,美团按 `mt_status`(4 取消/5 风控不计佣,6 结算才到账);淘宝无对账 API,对账列显示 `-`。
|
||||
- #119 修美团 `pay_time` 入库为空导致大盘时间窗漏算。
|
||||
@@ -1,6 +1,6 @@
|
||||
# Admin 首页数据配置 — 三统计展示模式
|
||||
|
||||
> 所属:Admin 组(前缀 `/admin/api/dashboard-display`) | 鉴权:Admin Bearer(改需 operator/super) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin 组(前缀 `/admin/api/dashboard-display`) | 鉴权:Admin Bearer(改需 operator/super) | [← 返回 API 索引](../README.md)
|
||||
|
||||
配置客户端首页三个门面数字(帮助用户 / 完成比价 / 累计节省)的展示模式。每个指标可独立选 real/manual/random。用户侧读取见 [platform-stats](./platform-stats.md);表见 [ops_stat_config](../database/ops_stat_config.md)。
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# /admin/api/device-liveness — 设备存活监控(#80)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api`) | 鉴权:admin | 表 [device_liveness](../../database/device_liveness.md) | [← 返回 API 索引](../README.md)
|
||||
|
||||
无障碍保护存活的后台视角:哪些设备开过保护(`ever_protected`)、现在在线还是掉线(心跳超时,#107 起阈值 1 小时)、首次开启时间(`first_protected_at`)。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET /admin/api/device-liveness/stats` | 顶部卡片统计:设备总数 / 开过保护 / 当前在线 / 掉线数 |
|
||||
| `GET /admin/api/device-liveness` | 设备存活列表(游标分页):在线情况/设备 id/归属用户 筛选 + 排序,**默认掉线置顶**;行含最近心跳、首次开启、App 版本、push token 有无 |
|
||||
|
||||
## 说明
|
||||
- 「在线」= `last_heartbeat_at` 距今 < 超时阈值;掉线召回链路(worker 置 `kill_alert_pending` → 客户端 pull)见表文档。
|
||||
@@ -0,0 +1,15 @@
|
||||
# /admin/api/event-logs — 埋点日志(#83)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api`) | 鉴权:admin | 表 [analytics_event](../../database/analytics_event.md) | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端埋点(`POST /api/v1/analytics/events` 批量上报)的后台检索页。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET /admin/api/event-logs` | 埋点事件列表(游标分页):可按 `event` / `device_id` / `user_id` 筛;行含事件名、props、页面、机型/系统/网络、client_ts |
|
||||
|
||||
## 说明
|
||||
- 纯只读;无聚合报表(要分析导出后自己算)。
|
||||
- 时间轴用 `client_ts`(事件真实发生时刻),入库时间受客户端攒批影响。
|
||||
@@ -1,8 +1,8 @@
|
||||
# Admin 首页轮播种子管理
|
||||
|
||||
> 所属:Admin 组(前缀 `/admin/api/marquee-seeds`) | 鉴权:Admin Bearer(改需 operator/super) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin 组(前缀 `/admin/api/marquee-seeds`) | 鉴权:Admin Bearer(改需 operator/super) | [← 返回 API 索引](../README.md)
|
||||
|
||||
管理首页轮播「真实+种子混播」的兜底种子。种子是「生成规则」:`masked_user` 可空(空→feed 随机合成名)、金额是 `[min_cents, max_cents]` 区间(feed 每次随机取值)。用户侧 feed 见 [platform-savings-feed](./platform-savings-feed.md);表见 [ops_marquee_seed](../database/ops_marquee_seed.md)。金额单位:分(前端 ÷100 显示元)。
|
||||
管理首页轮播「真实+种子混播」的兜底种子。种子是「生成规则」:`masked_user` 可空(空→feed 随机合成名)、金额是 `[min_cents, max_cents]` 区间(feed 每次随机取值)。用户侧 feed 见 [platform-savings-feed](../savings/platform-savings-feed.md);表见 [ops_marquee_seed](../../database/ops_marquee_seed.md)。金额单位:分(前端 ÷100 显示元)。
|
||||
|
||||
## 复用结构 OpsMarqueeSeedOut
|
||||
| 字段 | 类型 | 说明 |
|
||||
@@ -19,9 +19,20 @@
|
||||
出参 `200`:`list[OpsMarqueeSeedOut]`(按 `sort_order,id`)。
|
||||
|
||||
## GET /admin/api/marquee-seeds/preview — 预览实际混播 feed
|
||||
预览客户端实际会看到的轮播(真实记录会插队、种子随机抽取 / 金额随机 / 名字合成),供运营对效果。**含随机,每次结果不同**。
|
||||
预览客户端实际会看到的轮播(真实记录会插队、种子随机抽取 / 金额随机 / 名字合成),供运营对效果。**含随机,每次结果不同**;#122 起按**当前数据源模式**实时预览(mixed/real/seed 各自的真实产出)。
|
||||
- 入参:`limit`(query,1~30,默认 8)
|
||||
- 出参 `200`:`{"items": [{masked_user, saved_amount_cents, time}]}`(条目同 [platform-savings-feed](./platform-savings-feed.md))
|
||||
- 出参 `200`:`{"items": [{masked_user, saved_amount_cents, time}]}`(条目同 [platform-savings-feed](../savings/platform-savings-feed.md))
|
||||
|
||||
## GET /admin/api/marquee-seeds/real-records — 分页浏览当前模式下可展示的真实记录(#123)
|
||||
审核用:看「真实条」到底会拿哪些 `comparison_record` 上轮播(真实条**不按用户去重**,打乱+去连簇后混播;默认昵称归「无昵称」脱敏档,#122)。
|
||||
- 入参:`limit` / `cursor`(游标分页)
|
||||
- 出参 `200`:`{"items": [...], "next_cursor": int|null}`
|
||||
|
||||
## GET /admin/api/marquee-seeds/mode — 首页轮播数据源模式
|
||||
出参:`{"mode": "mixed" | "real" | "seed"}`(混播 / 只真实 / 只种子)。
|
||||
|
||||
## PATCH /admin/api/marquee-seeds/mode — 改数据源模式(带审计)
|
||||
- 入参:`{"mode": "mixed" | "real" | "seed"}`;operator 起。改动客户端重拉 feed 生效。
|
||||
|
||||
## POST /admin/api/marquee-seeds — 新增(带审计)
|
||||
入参 `OpsMarqueeSeedCreate`:`masked_user`(可选,空 / 不传 → 随机合成)、`min_cents`(必填,≥0)、`max_cents`(必填,≥min,≤1000 元)、`enabled`(默认 true)、`sort_order`(默认 0)。出参:新建的 `OpsMarqueeSeedOut`。`400`=金额非法。
|
||||
@@ -0,0 +1,16 @@
|
||||
# /admin/api/price-reports — 上报更低价审核(#94)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api/price-reports`) | 鉴权:读=admin,审=operator | 表 [price_report](../../database/price_report.md) | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> C 端提交/查询见 [report-submit](../other/report-submit.md) / [report-records](../other/report-records.md)。
|
||||
|
||||
用户众包「上报更低价」的人工审核台:审截图与价格,通过发固定金币。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET /admin/api/price-reports` | 上报列表(状态筛选 + 游标分页,含截图、关联比价记录快照) |
|
||||
| `GET /admin/api/price-reports/summary` | 审核统计(pending/approved/rejected 计数) |
|
||||
| `POST /admin/api/price-reports/{report_id}/approve` | 通过 → 发固定金币(`grant_coins` 同事务)+ 带审计 |
|
||||
| `POST /admin/api/price-reports/{report_id}/reject` | 拒绝(填原因,用户端可见)+ 带审计 |
|
||||
@@ -0,0 +1,19 @@
|
||||
# /admin/api/roles — 角色与可见页管理(RBAC,#117/#126)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api`,独立 admin JWT) | 鉴权:**super_admin** | 表 [admin_role](../../database/admin_role.md) | [← 返回 API 索引](../README.md)
|
||||
|
||||
后台 RBAC 的数据驱动层:内建三角色(`super_admin`/`finance`/`operator`,`is_builtin=true` 不可删)+ **自定义角色**(勾任意页面组合)。管理员的有效可见页 = `admin_user.pages_override`(个人覆盖,非空优先)∪ 否则取其角色 `pages`;`super_admin` 恒全通。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET /admin/api/roles` | 角色列表:`[{id, name, label, pages, is_builtin, admin_count}]`(含每个角色的使用人数) |
|
||||
| `GET /admin/api/roles/catalog` | 页面权限目录(分组):全部可勾选的页面 key(来自 `app/admin/permissions.py` 常量,不落库),前端渲染勾选面板用 |
|
||||
| `POST /admin/api/roles` | 新增自定义角色 `{name, pages}`(**name(key)= label = 输入名称**;不能叫 `super_admin`,重名 `409`);带审计 |
|
||||
| `PATCH /admin/api/roles/{role_id}` | 改展示名/可见页(内建角色的 `pages` 也可调);带审计 |
|
||||
| `DELETE /admin/api/roles/{role_id}` | 删角色;**内建(`is_builtin`)与在用(有 `admin_user.role` 引用)不可删**(400);带审计 |
|
||||
|
||||
## 说明
|
||||
- 管理员个人覆盖在 [`PATCH /admin/api/admins/{id}`](./admins/admin-admin-update.md) 的 `pages_override` 字段改,不在本组。
|
||||
- 加新后台页面要同步登记 `permissions.py` 目录,表里只存勾选结果(目录变更无需迁移)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/stats/overview — 大盘核心指标
|
||||
|
||||
> 所属:Admin·数据大盘 组(前缀 `/admin/api/stats`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 require_role) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·数据大盘 组(前缀 `/admin/api/stats`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 require_role) | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/admins — 创建管理员
|
||||
|
||||
> 所属:Admin·Accounts 组(前缀 `/admin/api/admins`) | 鉴权:Bearer admin_token(角色:super_admin) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·Accounts 组(前缀 `/admin/api/admins`) | 鉴权:Bearer admin_token(角色:super_admin) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
**application/json**:
|
||||
@@ -1,6 +1,6 @@
|
||||
# PATCH /admin/api/admins/{admin_id} — 改角色/启停/重置密码
|
||||
|
||||
> 所属:Admin·Accounts 组(前缀 `/admin/api/admins`) | 鉴权:Bearer admin_token(角色:super_admin) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·Accounts 组(前缀 `/admin/api/admins`) | 鉴权:Bearer admin_token(角色:super_admin) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
**路径参数**:
|
||||
@@ -8,12 +8,13 @@
|
||||
|---|---|---|---|
|
||||
| `admin_id` | int | ✓ | 目标管理员 id |
|
||||
|
||||
**application/json**(三字段都可选,只改传了的;至少传一个):
|
||||
**application/json**(字段都可选,只改传了的;至少传一个):
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `role` | string | ✗ | 改角色,枚举:`super_admin` / `finance` / `operator` |
|
||||
| `role` | string | ✗ | 改角色:内建 `super_admin` / `finance` / `operator` **或自定义角色 name**(#117/#126,见 [admin-roles](../admin-roles.md)) |
|
||||
| `pages_override` | list[string] \| null | ✗ | 个人可见页覆盖(#126):非空优先于角色 pages;传 `null` 清覆盖回归角色 |
|
||||
| `status` | string | ✗ | 启停,枚举:`active`(启用)/ `disabled`(禁用) |
|
||||
| `password` | string | ✗ | 重置密码,8–72 字(传则覆盖原密码) |
|
||||
| `password` | string | ✗ | 重置密码,8–72 字(传则覆盖原密码,同时更新 `plain_password` 明文副本) |
|
||||
|
||||
## 出参
|
||||
响应 `200`:`AdminOut`(更新后的管理员)
|
||||
@@ -24,9 +25,15 @@
|
||||
| `username` | string | 账号 |
|
||||
| `role` | string | 角色 |
|
||||
| `status` | string | 状态 |
|
||||
| `pages` | list[string] | **有效可见页**(pages_override 优先,否则角色 pages;super_admin 全量) |
|
||||
| `created_at` | datetime | 创建时间(UTC) |
|
||||
| `last_login_at` | datetime \| null | 上次登录时间 |
|
||||
|
||||
---
|
||||
|
||||
## DELETE /admin/api/admins/{admin_id} — 删除管理员(#126)
|
||||
物理删除(区别于禁用);**不可删自己**(`400`);带审计(`action=admin.delete`)。鉴权同本组(super_admin)。出参 `{"deleted": true}`。
|
||||
|
||||
## 错误码
|
||||
- `400` 不能禁用自己(`admin_id == 当前 admin.id` 且 `status=disabled`) / 无任何变更字段(三字段全空)
|
||||
- `401` 未带 admin token / token 无效或过期 / 管理员被禁用
|
||||
@@ -35,5 +42,5 @@
|
||||
- `422` `role`/`status` 非法枚举 / `password` 长度不在 8–72
|
||||
|
||||
## 说明
|
||||
- 更新成功后写一条审计:`action=admin.update`、`target_type=admin`、`target_id=admin_id`、`detail` 为本次实际变更字段(如 `{"role": "...", "status": "...", "password": "reset"}`,密码只记 `reset` 不记明文)。见 [admin_audit_log](../database/admin_audit_log.md)。
|
||||
- 数据表见 [admin_user](../database/admin_user.md)。
|
||||
- 更新成功后写一条审计:`action=admin.update`、`target_type=admin`、`target_id=admin_id`、`detail` 为本次实际变更字段(如 `{"role": "...", "status": "...", "password": "reset"}`,密码只记 `reset` 不记明文)。见 [admin_audit_log](../../../database/admin_audit_log.md)。
|
||||
- 数据表见 [admin_user](../../../database/admin_user.md)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/admins — 管理员列表
|
||||
|
||||
> 所属:Admin·Accounts 组(前缀 `/admin/api/admins`) | 鉴权:Bearer admin_token(角色:super_admin) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·Accounts 组(前缀 `/admin/api/admins`) | 鉴权:Bearer admin_token(角色:super_admin) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
无(按 `id` 升序返回全部,无分页)
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/auth/login — 管理员登录
|
||||
|
||||
> 所属:Admin·Auth 组(前缀 `/admin/api/auth`) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·Auth 组(前缀 `/admin/api/auth`) | 鉴权:无 | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
**application/json**:
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/auth/me — 当前管理员
|
||||
|
||||
> 所属:Admin·Auth 组(前缀 `/admin/api/auth`) | 鉴权:Bearer admin_token(角色:任意已登录 admin) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·Auth 组(前缀 `/admin/api/auth`) | 鉴权:Bearer admin_token(角色:任意已登录 admin) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
无(身份取自 Header token)
|
||||
@@ -0,0 +1,41 @@
|
||||
# /admin/api/feedbacks — 反馈审核族(采纳/拒绝/标记处理/统计)
|
||||
|
||||
> 所属:Admin·反馈 组(前缀 `/admin/api/feedbacks`) | 鉴权:Bearer admin_token(角色:`operator`,`super_admin` 恒通过,`require_role("operator")`;summary 任意 admin) | [← 返回 API 索引](../../README.md)
|
||||
>
|
||||
> 列表见 [admin-feedbacks-list](./admin-feedbacks-list.md)。#94 引入 采纳(发金币)/拒绝 审核语义,#105 加运营回复 `admin_reply`;旧「标记已处理」保留。
|
||||
|
||||
## POST /admin/api/feedbacks/{feedback_id}/approve — 采纳并发金币(#94)
|
||||
- body:`{reward_coins?(int,可 0), admin_reply?(string,用户可见), review_note?(string,内部)}`
|
||||
- 行为:`status → adopted`;`reward_coins > 0` 时走 `grant_coins` 同事务发币(流水 `coin_transaction`);写审计(`detail.after="adopted"`)。已终态(非 pending/new)→ `400`。
|
||||
- 出参:更新后的 FeedbackOut。
|
||||
|
||||
## POST /admin/api/feedbacks/{feedback_id}/reject — 拒绝采纳(#94)
|
||||
- body:`{reject_reason(string,用户可见), admin_reply?, review_note?}`
|
||||
- 行为:`status → rejected`;写审计(`detail.after="rejected"`)。已终态 → `400`。
|
||||
|
||||
## GET /admin/api/feedbacks/summary — 审核统计
|
||||
- 出参:各状态计数(`pending` / `adopted` / `rejected` / `handled`),审核台顶部卡片用;任意 admin 可读。
|
||||
|
||||
---
|
||||
|
||||
## POST /admin/api/feedbacks/{feedback_id}/handle — 标记反馈已处理(旧口径)
|
||||
|
||||
## 入参
|
||||
- 路径:`feedback_id`(int)
|
||||
- body:无
|
||||
|
||||
## 出参
|
||||
响应 `200`:`OkResponse` = `{ "ok": true }`
|
||||
|
||||
幂等说明:将该反馈 `status` 置为 `handled`(不校验原状态,重复调用结果一致)。
|
||||
|
||||
## 错误码
|
||||
- `401` 未带/无效/过期 admin token、管理员被禁用(头带 `WWW-Authenticate: Bearer`)
|
||||
- `403` 角色不足(需 `operator` 或 `super_admin`)
|
||||
- `404` 反馈不存在(`detail: "反馈不存在"`)
|
||||
- `422` `feedback_id` 非合法 int
|
||||
|
||||
## 说明
|
||||
- 写操作记审计 [admin_audit_log](../../../database/admin_audit_log.md):`action="feedback.handle"`、`target_type="feedback"`、`target_id=<feedback_id>`、`detail={"before": <原 status>, "after": "handled"}`、`ip=<客户端 IP>`。
|
||||
- 状态变更与审计写入在同一事务(`commit=False` 后统一 `db.commit()`)。
|
||||
- 关联表 [feedback](../../../database/feedback.md)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/feedbacks — 反馈工单列表(offset 分页 + 筛选/排序)
|
||||
|
||||
> 所属:Admin·反馈 组(前缀 `/admin/api/feedbacks`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 `require_role`,仅 `get_current_admin`) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·反馈 组(前缀 `/admin/api/feedbacks`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 `require_role`,仅 `get_current_admin`) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参(query)
|
||||
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/users/{user_id}/cash — 手动增减/设值现金(带审计)
|
||||
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
主要用于给无现金用户直接发钱、好让其测试提现链路。
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `mode` | string | ✗ | `delta`(默认)=增减 / `set`=设为指定值 |
|
||||
| `account` | string | ✗ | 目标账户(#95):`coin_cash`(默认,金币兑换的现金)/ `invite_cash`(邀请奖励金)。两本账物理隔离、各调各 |
|
||||
| `amount_cents` | int | ✓ | `delta` 模式:现金变动(分,正=发放,负=扣减,不可为 0);`set` 模式:目标现金值(分,须 ≥ 0) |
|
||||
| `reason` | string | ✓ | 操作原因,1–128 字(必填,入审计与流水备注) |
|
||||
|
||||
@@ -28,7 +29,7 @@
|
||||
- 金额单位一律为**分**(`*_cents`);本接口只动现金余额,不涉及金币。
|
||||
- **set 模式**:读当前余额算出差值 `delta = target - 当前余额`,再复用同一套写入逻辑(故只写一笔差值流水)。目标值须 ≥ 0;差值为 0(已等于目标)直接拒绝。
|
||||
- 扣减保护:实际写入的 `delta < 0` 时若扣减后现金余额 < 0 直接拒绝(运营误操作保护);set 模式目标值 ≥ 0 天然不会扣成负。
|
||||
- 现金变动写流水 [cash_transaction](../database/cash_transaction.md):`biz_type` 实际差值为正记 `admin_grant`、为负记 `admin_deduct`(set 模式同理,不新增流水类型),`remark = admin:<reason>`(截断至 128 字)。
|
||||
- 写操作记审计 [admin_audit_log](../database/admin_audit_log.md):`action = user.cash.grant`,`target_type = user`,`target_id = user_id`,`detail = {amount_cents(=实际差值), balance_after_cents, reason}`;set 模式额外带 `{mode:"set", target_cents, before_cents}`。并记录操作 IP。
|
||||
- 现金变动按 `account` 写对应账本流水:`coin_cash` → [cash_transaction](../../../database/cash_transaction.md),`invite_cash` → [invite_cash_transaction](../../../database/invite_cash_transaction.md)(#95);`biz_type` 实际差值为正记 `admin_grant`、为负记 `admin_deduct`(set 模式同理,不新增流水类型),`remark = admin:<reason>`(截断至 128 字)。
|
||||
- 写操作记审计 [admin_audit_log](../../../database/admin_audit_log.md):`action = user.cash.grant`,`target_type = user`,`target_id = user_id`,`detail = {amount_cents(=实际差值), balance_after_cents, reason}`;set 模式额外带 `{mode:"set", target_cents, before_cents}`。并记录操作 IP。
|
||||
- 现金变动 + 审计在同一事务原子提交(改钱必留痕)。
|
||||
- 关联用户表 [user](../database/user.md);现金账户 [coin_account](../database/coin_account.md);现金流水 [cash_transaction](../database/cash_transaction.md)。
|
||||
- 关联用户表 [user](../../../database/user.md);现金账户 [coin_account](../../../database/coin_account.md);现金流水 [cash_transaction](../../../database/cash_transaction.md)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/users/{user_id}/coins — 手动增减/设值金币(带审计)
|
||||
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
- 路径:`user_id`(int)
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/users/{user_id} — 用户 360 详情
|
||||
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 require_role) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 require_role) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
- 路径:`user_id`(int)
|
||||
@@ -38,6 +38,15 @@
|
||||
- `422` `user_id` 非整数
|
||||
|
||||
## 说明
|
||||
- 金币三项(`coin_balance` / `cash_balance_cents` / `total_coin_earned`)读 [coin_account](../database/coin_account.md);从未发生金币动作(账户不存在)时统一返回 0。
|
||||
- 金币三项(`coin_balance` / `cash_balance_cents` / `total_coin_earned`)读 [coin_account](../../../database/coin_account.md);从未发生金币动作(账户不存在)时统一返回 0。
|
||||
- 各 count 为聚合数,明细历史走带 `user_id` 过滤的分页接口(金币流水 / 现金流水 / 提现 / 比价 / 反馈)。
|
||||
- 关联用户表 [user](../database/user.md);金币账户 [coin_account](../database/coin_account.md);提现单 [withdraw_order](../database/withdraw_order.md);比价记录 [comparison_record](../database/comparison_record.md);反馈 [feedback](../database/feedback.md)。
|
||||
- 关联用户表 [user](../../../database/user.md);金币账户 [coin_account](../../../database/coin_account.md);提现单 [withdraw_order](../../../database/withdraw_order.md);比价记录 [comparison_record](../../../database/comparison_record.md);反馈 [feedback](../../../database/feedback.md)。
|
||||
|
||||
---
|
||||
|
||||
## 族内配套端点(提现详情页联查用)
|
||||
|
||||
| 方法 + 路径 | 说明 |
|
||||
|---|---|
|
||||
| `GET /admin/api/users/{user_id}/reward-stats` | 用户提现/看广告统计(按时间窗口):提现审核时评估该用户金币来源是否健康 |
|
||||
| `GET /admin/api/users/{user_id}/coin-records` | 用户金币发放记录(按时间窗口分页):提现详情底部表,逐笔看发币来源 |
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/users/{user_id}/status — 封禁/解封用户
|
||||
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:`operator`,`super_admin` 恒通过) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:`operator`,`super_admin` 恒通过) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参
|
||||
- 路径:`user_id`(int)
|
||||
@@ -21,5 +21,11 @@
|
||||
|
||||
## 说明
|
||||
- 业务写(改用户状态)与审计写在同一事务原子提交:改了就有痕、有痕就真改了。
|
||||
- 写操作记审计 [admin_audit_log](../database/admin_audit_log.md):`action = user.status.set`,`target_type = user`,`target_id = user_id`,`detail = {before, after}`,并记录操作 IP。
|
||||
- 关联用户表 [user](../database/user.md)。
|
||||
- 写操作记审计 [admin_audit_log](../../../database/admin_audit_log.md):`action = user.status.set`,`target_type = user`,`target_id = user_id`,`detail = {before, after}`,并记录操作 IP。
|
||||
- 关联用户表 [user](../../../database/user.md)。
|
||||
|
||||
---
|
||||
|
||||
## POST /admin/api/users/{user_id}/debug-trace — 开关调试链接权限
|
||||
- body:`{"enabled": true|false}` → 写 `user.debug_trace_enabled`(带审计 `action=user.debug_trace.set`)。
|
||||
- 开了的用户在比价完成弹窗 + 比价记录页可见「复制调试链接」按钮(trace_url);运营按用户灰度排障用。鉴权同本组(operator)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/users — 用户列表(筛选+排序+分页)
|
||||
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 require_role) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·用户 组(前缀 `/admin/api/users`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,无 require_role) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
## 入参(query)
|
||||
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/wallet/cash-transactions — 现金流水(游标分页)
|
||||
|
||||
> 所属:Admin·钱包 组(前缀 `/admin/api/wallet`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,仅需 `get_current_admin`,无 `require_role`) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·钱包 组(前缀 `/admin/api/wallet`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,仅需 `get_current_admin`,无 `require_role`) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
跨用户查询全量现金流水,可按 `user_id` / `biz_type` 过滤。游标分页(`id` 倒序)。金额单位一律为**分**。
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/wallet/coin-transactions — 金币流水(游标分页)
|
||||
|
||||
> 所属:Admin·钱包 组(前缀 `/admin/api/wallet`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,仅需 `get_current_admin`,无 `require_role`) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·钱包 组(前缀 `/admin/api/wallet`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,仅需 `get_current_admin`,无 `require_role`) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
跨用户查询全量金币流水,可按 `user_id` / `biz_type` 过滤。游标分页(`id` 倒序)。
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/withdraws/reconcile — 批量对账(扫超时 pending 单)
|
||||
|
||||
> 所属:Admin·提现 组(前缀 `/admin/api/withdraws`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·提现 组(前缀 `/admin/api/withdraws`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
扫描创建时间超过 `older_than_minutes` 分钟、仍为 `pending` 的提现单,逐单调微信查单并归一化(成功落 `success`;失败/已撤销则退款落 `failed`;查到 `WAIT_USER_CONFIRM` 视为用户放弃,撤单+退款)。用于解开"扣了款但转账没发起/没确认"的孤儿单。单笔失败不影响其余(内部 rollback 后继续,下轮再试)。
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# POST /admin/api/withdraws/{out_bill_no}/refresh — 单笔提现重试查单
|
||||
|
||||
> 所属:Admin·提现 组(前缀 `/admin/api/withdraws`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·提现 组(前缀 `/admin/api/withdraws`) | 鉴权:Bearer admin_token(角色:`finance`,`super_admin` 恒通过) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
对单笔提现单调微信查单并归一化:`SUCCESS`→`success`;`FAIL`/`CANCELLED`/`CLOSED`→退款+`failed`;查到 `WAIT_USER_CONFIRM` 视为用户放弃(`cancel_if_unconfirmed=True`),撤单+退款;`ACCEPTED`/`PROCESSING` 等仍在途则保持 `pending`。已是终态的单直接返回、不再查。
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# /admin/api/withdraws — 提现审核台(审核/批量/对账族)
|
||||
|
||||
> 所属:Admin 子应用(前缀 `/admin/api/withdraws`) | 鉴权:读=admin,写=**finance** | 表 [withdraw_order](../../../database/withdraw_order.md) | [← 返回 API 索引](../../README.md)
|
||||
>
|
||||
> 列表见 [admin-withdraws-list](./admin-withdraws-list.md);单笔查单见 [admin-withdraw-refresh](./admin-withdraw-refresh.md);超时对账见 [admin-withdraw-reconcile](./admin-withdraw-reconcile.md)。本文覆盖其余审核台端点。
|
||||
|
||||
提现状态机:`reviewing`(发起即扣款待审)→ 通过 `pending`(微信转账在途)→ `success`/`failed`(失败退款);拒绝 `rejected`(退款)。**#121 起按 `withdraw_order.source` 分账**:退款/流水落 `cash_transaction`(coin_cash)或 `invite_cash_transaction`(invite_cash)。
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 + 路径 | 鉴权 | 说明 |
|
||||
|---|---|---|
|
||||
| `GET /admin/api/withdraws/summary` | admin | 审核台统计:各状态计数(待审/在途/成功/失败/拒绝) |
|
||||
| `GET /admin/api/withdraws/health-check` | finance | 提现配置健康检查(证书/密钥路径/商户配置就位与否;暴露路径故限 finance+super) |
|
||||
| `GET /admin/api/withdraws/ledger-check` | admin | **资金账本校验**(#121):按 `source` 分账核对「提现单 ↔ 流水」金额闭环,邀请奖励金提现纳入对账 |
|
||||
| `GET /admin/api/withdraws/{out_bill_no}` | admin | 提现单详情(审核台抽屉;用户维度联查另走 `users/{id}/reward-stats` + `coin-records`) |
|
||||
| `POST /admin/api/withdraws/{out_bill_no}/approve` | finance | 审核通过 → 发起微信打款(`reviewing`→`pending`→查单归一化);带审计 |
|
||||
| `POST /admin/api/withdraws/{out_bill_no}/reject` | finance | 审核拒绝 → 按 source 退款 + `rejected`;带审计 |
|
||||
| `POST /admin/api/withdraws/bulk/refresh` | finance | 批量刷新查单(勾选多笔) |
|
||||
| `POST /admin/api/withdraws/bulk/approve` | finance | 批量审核通过并打款 |
|
||||
| `POST /admin/api/withdraws/bulk/reject` | finance | 批量审核拒绝并退款 |
|
||||
|
||||
## 说明
|
||||
- 批量接口逐单处理、逐单落审计,单笔失败不中断整批(返回逐单结果)。
|
||||
- 结果不明时先查单再定夺、绝不盲目退款(防退款后又到账),同 C 端口径。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /admin/api/withdraws — 提现单列表(游标分页)
|
||||
|
||||
> 所属:Admin·提现 组(前缀 `/admin/api/withdraws`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,列表为只读,仅需 `get_current_admin`,无 `require_role`) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Admin·提现 组(前缀 `/admin/api/withdraws`) | 鉴权:Bearer admin_token(角色:任意已登录管理员,列表为只读,仅需 `get_current_admin`,无 `require_role`) | [← 返回 API 索引](../../README.md)
|
||||
|
||||
跨用户查询全量提现单,可按 `user_id` / `status` 过滤。游标分页(`id` 倒序)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/auth/jverify-login — 极光一键登录
|
||||
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/jiguang](../integrations/jiguang.md)(极光核验链路、RSA 解密策略、私钥配对踩坑)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/auth/logout — 登出
|
||||
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:Bearer access_token | [← 返回 API 索引](./README.md)
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:Bearer access_token | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/auth/me — 获取当前登录用户
|
||||
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:Bearer access_token | [← 返回 API 索引](./README.md)
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:Bearer access_token | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(身份取自 Header token)
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/auth/refresh — 刷新 token
|
||||
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无(凭 body 里的 refresh_token) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无(凭 body 里的 refresh_token) | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/auth/sms/login — 手机号 + 验证码登录
|
||||
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/sms](../integrations/sms.md)(验证码校验逻辑)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/auth/sms/send — 发送短信验证码
|
||||
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Auth 组(前缀 `/api/v1/auth`) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/sms](../integrations/sms.md)(mock 模式、频控、接真供应商 TODO)。
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# POST /api/v1/price/step — 外卖比价 Phase 2 步进(透传到 pricebot)
|
||||
|
||||
> 所属:Compare 组(前缀 `/api/v1`,外卖比价) | 鉴权:**无(MVP 阶段不鉴权)** | [← 返回 API 索引](./README.md)
|
||||
|
||||
## 入参
|
||||
任意 JSON body,**不做 schema 校验**,原样透传给上游。后端仅从中读 `device_id`、`trace_id`、`step` 用于日志。
|
||||
客户端逐帧上报 `screen_state` + 上一步 `action_result`;`step=0` 还带 `query` + `calibration`(来自 Phase 1)。
|
||||
|
||||
## 出参
|
||||
pricebot-backend 的响应**原样返回**(JSON object)。含 `action`(tap / set_text / launch / wait / done…)、`continue`、`status`;最终 `done` 帧带 `comparison_results`(源 + 各目标平台到手价,按价升序)。
|
||||
|
||||
## 错误码
|
||||
- `400` body 不是合法 JSON
|
||||
- `502` pricebot 上游不可达(网络错误)或返回 5xx
|
||||
|
||||
## 说明
|
||||
把请求体原样转发到 `PRICEBOT_BASE_URL` 的 `/api/price/step`(去掉 `/v1`,async httpx)。**多轮循环**:客户端按返回的 `action` 操作手机、再上报下一帧,直到 `continue=false`。真正的目标驱动比价逻辑(多目标平台串行复现订单、读到手价、聚合排序)在 **pricebot-backend**,本接口只是"透传壳"。
|
||||
|
||||
⚠️ **MVP 阶段不鉴权**(同 `coupon/step`)。
|
||||
|
||||
**相关配置**:
|
||||
- `PRICEBOT_BASE_URL`(默认 `http://localhost:8000`;生产部署应与 pricebot-backend 同内网——比价一单 30~80 步、逐帧多一跳,走公网延迟会累积)
|
||||
- `PRICEBOT_COMPARE_TIMEOUT_SEC`(默认 60s,price/step 每帧都是 LLM)
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/compare/milestones/{milestone}/claim — 领取比价战绩里程碑奖励
|
||||
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
领取某一档(第 `milestone` 次)。⚠️ **当前不真发金币**(产品定,后续整体删除该功能):仍写
|
||||
`comparison_milestone_claim`((user_id, milestone) 唯一)标记该档已领、**每档只能领一次**,但不调
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/compare/milestones — 比价战绩里程碑进度
|
||||
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
福利页「记录比价战绩」的数据源。返回各档(第 1~6 次)解锁/领取状态。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/compare/records/{record_id} — 比价记录详情
|
||||
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
单条比价记录详情,在列表项基础上额外带 `raw_payload`(客户端上报的原始全量),供未来 UI 展示任意细节。
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# POST /api/v1/compare/record — 上报一次比价结果(幂等)
|
||||
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
比价 `done` 帧后,客户端用**带 JWT 的通道**上报一条比价结果,落 `comparison_record` 表,作为「我的比价记录」数据源 + 用户级行为画像。
|
||||
比价 `done` 帧后上报一条比价结果,落 `comparison_record` 表,作为「我的比价记录」数据源 + 用户级行为画像。
|
||||
|
||||
> ⚠️ 与不鉴权的透传端点 [`/api/v1/price/step`](./compare-price-step.md) 不同:那是转发壳,本接口按用户维度落库,**必须鉴权**。
|
||||
> 本轮只做 server 端;客户端在 done 帧后调本接口的改动另起一轮(见 [待办与技术债.md](../guides/待办与技术债.md) P1)。
|
||||
> ⚠️ **灰度定位(2026-07)**:写 `comparison_record` 现以透传壳 `compare.py` 的**后端 harvest** 为主(帧0 建 `running` 行 → done/finalize 落终态,新客户端不再 POST)。本接口降级为**老客户端兼容**通道,与 harvest 按 `trace_id` reconcile(**success 不被降级**);新版覆盖够高后可下线本 POST。
|
||||
> 与软鉴权透传端点 [`/api/v1/price/step`](./compare-price-step.md) 不同:那是转发壳(顺带 harvest 落库),本接口按用户维度显式上报,**必须鉴权**。
|
||||
|
||||
## 入参(JSON body)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `trace_id` | string | ✅ | — | pricebot 侧 trace_id。**幂等键**:同用户同 trace_id 重复上报覆盖、返回同一 id |
|
||||
| `trace_id` | string | ✅ | — | 一次比价的唯一标识(app-server 帧0 签发)。**幂等键(trace_id 单列唯一)**:同 trace_id 重复上报覆盖、返回同一 id;与 harvest 行按它 reconcile |
|
||||
| `business_type` | string | ❌ | `food` | `food`(外卖,当前唯一接通) / `ecom`(电商) / `coupon`(领券) |
|
||||
| `device_id` | string \| null | ❌ | null | 设备号 |
|
||||
| `store_name` | string \| null | ❌ | null | 店铺名(外卖,来自 calibration.result) |
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/compare/records — 比价记录列表(游标分页)
|
||||
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
「我的比价记录」列表页数据源。按 `id` 倒序(最新在前)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/compare/stats — 比价口径战绩(「我的」页省钱战绩卡)
|
||||
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:比价记录组(前缀 `/api/v1/compare`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -0,0 +1,67 @@
|
||||
# 今日领券完成状态(completed-today 族)
|
||||
|
||||
> 所属:Coupon 组(前缀 `/api/v1/coupon`) | 鉴权:无(按 device_id 判断) | [← 返回 API 索引](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## GET /completed-today — 今天是否已完成整轮领券
|
||||
|
||||
判断这台设备今天是否跑到 done 帧。已完成 → 首页「去领取」卡置灰。
|
||||
|
||||
### 入参(query)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 设备 ID(需与领券循环上报的一致) |
|
||||
|
||||
Mock 请求:
|
||||
```
|
||||
GET /api/v1/coupon/completed-today?device_id=android_abc123def456
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
响应 `200`:`CouponCompletedTodayOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `completed` | bool | 今天是否已跑完整轮 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{"completed": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /completed-today/reset — 重置今日已完成
|
||||
|
||||
删这台设备今天的 completion → `has_completed_today` 变 false,首页「去领取」卡恢复可点。开发设置用。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 设备 ID |
|
||||
| `package` | string | ❌ | App 包名(默认 "") |
|
||||
| `user_id` | int \| null | ❌ | 登录用户 ID |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 说明
|
||||
- 判断维度 `device_id`(客户端两端都用 ANDROID_ID)
|
||||
- 用户决策 A 方案:到 done 即算完成,不管单券成败
|
||||
- MVP 不鉴权
|
||||
@@ -0,0 +1,128 @@
|
||||
# 领券引导窗频控(prompt 族)
|
||||
|
||||
> 所属:Coupon 组(前缀 `/api/v1/coupon`) | 鉴权:无(按 device_id 判断,MVP 阶段) | [← 返回 API 索引](../README.md)
|
||||
|
||||
领券引导窗频控:今天这台设备**这个 App** 已弹过/领过/拒过 → 不再弹。各 App 独立(美团弹过不压淘宝/京东)。
|
||||
|
||||
---
|
||||
|
||||
## GET /prompt/should-show — 是否还应弹引导窗
|
||||
|
||||
客户端切到外卖 App 时查。
|
||||
|
||||
### 入参(query)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 设备 ID |
|
||||
| `package` | string | ❌ | App 包名(默认 "",老客户端兼容全局态) |
|
||||
|
||||
Mock 请求:
|
||||
```
|
||||
GET /api/v1/coupon/prompt/should-show?device_id=android_abc&package=com.sankuai.meituan
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
响应 `200`:`CouponPromptShouldShowOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `should_show` | bool | 今天是否还应弹引导窗 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{"should_show": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /prompt/shown — 引导窗弹出即上报
|
||||
|
||||
客户端弹出引导窗那刻调 → 记一条今日 engagement(shown),今天这个 App 不再自动弹。频控主判据管跨重装。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 设备 ID |
|
||||
| `package` | string | ✅ | App 包名 |
|
||||
| `user_id` | int \| null | ❌ | 登录用户 ID |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456",
|
||||
"package": "com.sankuai.meituan",
|
||||
"user_id": 42
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /prompt/dismiss — 用户拒绝/关闭引导窗
|
||||
|
||||
客户端点关闭时调 → 记 dismissed,今天这个 App 不再弹。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 设备 ID |
|
||||
| `package` | string | ❌ | App 包名(默认 "") |
|
||||
| `user_id` | int \| null | ❌ | 登录用户 ID |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456",
|
||||
"package": "com.sankuai.meituan"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /prompt/reset — 重置今日引导窗状态
|
||||
|
||||
删这台设备今天的 engagement → 今天又能弹。开发测频控用。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 设备 ID |
|
||||
| `package` | string | ❌ | App 包名(默认 "") |
|
||||
| `user_id` | int \| null | ❌ | 登录用户 ID |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 说明
|
||||
- 频控按 `(device, package, 日)`,各 App 独立
|
||||
- 弹出即占用今天一次(管跨重装),后续领取/拒绝再升级 type
|
||||
- user_id 可选,登录态带上就一并记(资产留痕)
|
||||
- MVP 不鉴权
|
||||
@@ -0,0 +1,75 @@
|
||||
# POST /api/v1/coupon/session — 领券任务流水上报
|
||||
|
||||
> 所属:Coupon 组(前缀 `/api/v1/coupon`) | 鉴权:无(按 device_id/trace_id 区分) | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端两段上报一次领券流水(发起 / 收尾),按 `trace_id` upsert 到 `coupon_session`。供 admin「领券数据」看板算发起/完成数、耗时分位、机型维度。
|
||||
|
||||
## 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `trace_id` | string | ✅ | 领券 trace 标识(同领券循环 step 的 trace_id) |
|
||||
| `device_id` | string | ✅ | 设备 ID(与领券循环一致) |
|
||||
| `status` | string | ✅ | `started` / `completed` / `failed` / `abandoned` |
|
||||
| `started_at_ms` | int | ✅ | 发起墙钟毫秒(客户端 `System.currentTimeMillis`) |
|
||||
| `user_id` | int \| null | ❌ | 登录用户 ID(未登录可空) |
|
||||
| `platforms` | list[string] \| null | ❌ | 勾选的平台列表 |
|
||||
| `origin_package` | string \| null | ❌ | 发起领券的 App 包名 |
|
||||
| `device_model` | string \| null | ❌ | 机型(如 `24115RA8EC`) |
|
||||
| `rom` | string \| null | ❌ | ROM 信息(如 `MIUI 14.0.8`) |
|
||||
| `app_env` | string \| null | ❌ | 应用环境(`prod` / `test`) |
|
||||
| `elapsed_ms` | int \| null | ❌ | 全程耗时(ms),收尾帧必带 |
|
||||
| `platform_elapsed` | dict \| null | ❌ | 各平台耗时(如 `{"meituan": 3200, "jd": 2800}`),收尾帧带 |
|
||||
| `claimed_count` | int \| null | ❌ | 本场实际领到的券张数 |
|
||||
| `trace_url` | string \| null | ❌ | trace 云端 URL(done 帧带) |
|
||||
|
||||
Mock 入参(started):
|
||||
```json
|
||||
{
|
||||
"trace_id": "tr_20260703_a1b2c3d4",
|
||||
"device_id": "android_abc123def456",
|
||||
"status": "started",
|
||||
"started_at_ms": 1719993600000,
|
||||
"user_id": 42,
|
||||
"platforms": ["meituan", "jd"],
|
||||
"origin_package": "com.sankuai.meituan",
|
||||
"device_model": "24115RA8EC",
|
||||
"rom": "MIUI 14.0.8",
|
||||
"app_env": "prod"
|
||||
}
|
||||
```
|
||||
|
||||
Mock 入参(completed):
|
||||
```json
|
||||
{
|
||||
"trace_id": "tr_20260703_a1b2c3d4",
|
||||
"device_id": "android_abc123def456",
|
||||
"status": "completed",
|
||||
"started_at_ms": 1719993600000,
|
||||
"user_id": 42,
|
||||
"platforms": ["meituan", "jd"],
|
||||
"origin_package": "com.sankuai.meituan",
|
||||
"device_model": "24115RA8EC",
|
||||
"rom": "MIUI 14.0.8",
|
||||
"app_env": "prod",
|
||||
"elapsed_ms": 12500,
|
||||
"platform_elapsed": {"meituan": 5200, "jd": 4800},
|
||||
"claimed_count": 3,
|
||||
"trace_url": "https://trace.shaguabijia.com/tr_20260703_a1b2c3d4"
|
||||
}
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `422` 必填字段缺失或类型不符
|
||||
|
||||
## 说明
|
||||
- 不鉴权(同领券循环 MVP,按 `device_id`/`trace_id`)
|
||||
- 写库失败不连累客户端(fire-and-forget,吞掉返回 ok)
|
||||
- 一次领券两段上报:发起(started)→ 收尾(completed/failed/abandoned)
|
||||
@@ -0,0 +1,33 @@
|
||||
# GET /api/v1/coupon/stats — 累计领券数
|
||||
|
||||
> 所属:Coupon 组(前缀 `/api/v1/coupon`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
「我的」页战绩卡「领取优惠券 X 张」数据源。该登录用户累计领到的券数(`SUM(claimed_count)`,与领券完成时给用户看的「本次领了 N 张」同源)。
|
||||
|
||||
**鉴权(CurrentUser)** — 区别于同文件不鉴权的 `/step` 透传与 `/prompt` 频控:个人战绩按 `user_id` 聚合,必须有登录态。
|
||||
|
||||
## 入参
|
||||
|
||||
无(`user_id` 从 JWT 取)。
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`CouponStatsOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `coupon_count` | int | 累计领到的券张数 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"coupon_count": 42
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `401` 未鉴权 / token 失效
|
||||
|
||||
## 说明
|
||||
- 口径:`SUM(claimed_count)` — 各成功领券记录 pricebot 展示张数之和
|
||||
- 只算登录用户,按 `user_id` 聚合(非 device_id)
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/coupon/step — 一键领券任务步进(透传到 pricebot)
|
||||
|
||||
> 所属:Coupon 组(前缀 `/api/v1/coupon`) | 鉴权:Bearer access_token(客户端契约;Server MVP 阶段不强校验) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Coupon 组(前缀 `/api/v1/coupon`) | 鉴权:Bearer access_token(客户端契约;Server MVP 阶段不强校验) | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
任意 JSON body,**不做 schema 校验**,原样透传给上游。后端仅从中读 `device_id`、`trace_id`、`step` 用于日志。
|
||||
@@ -1,6 +1,6 @@
|
||||
# 设备 / 无障碍存活监控(device 族)
|
||||
|
||||
> 所属:device 组(前缀 `/api/v1/device`,源 `app/api/v1/device.py`) | 鉴权:**全部 Bearer**(设备绑登录用户) | [← 返回 API 索引](./README.md)
|
||||
> 所属:device 组(前缀 `/api/v1/device`,源 `app/api/v1/device.py`) | 鉴权:**全部 Bearer**(设备绑登录用户) | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 落库:[`device_liveness`](../database/device_liveness.md) 表;后台 `heartbeat_monitor_worker` 据此检出心跳超时的设备并召回。设计见 spec `accessibility-liveness-push.md`(推送版)+ `accessibility-liveness-pull-prompt.md`(后置 pull 提醒版)。#65 新增。
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# POST /api/v1/intent/recognize — 外卖比价 Phase 1 意图识别(透传到 pricebot)
|
||||
# POST /api/v1/intent/recognize — 外卖比价 Phase 1 意图识别(透传 + 首帧 harvest 建行)
|
||||
|
||||
> 所属:Compare 组(前缀 `/api/v1`,外卖比价) | 鉴权:**无(MVP 阶段不鉴权)** | [← 返回 API 索引](./README.md)
|
||||
> 所属:Compare 组(前缀 `/api/v1`,外卖比价) | 鉴权:**软鉴权 OptionalUser**(带 JWT 则绑 `user_id`,不带也放行) | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
任意 JSON body,**不做 schema 校验**,原样透传给上游。后端仅从中读 `device_id`、`trace_id`、`step` 用于日志。
|
||||
任意 JSON body,**不做 schema 校验**,原样透传给上游。后端从中读 `device_id`、`trace_id`、`step`、`device_info` 用于日志与落库。
|
||||
客户端实际传源平台购物车页的无障碍树采集结果(pricebot 协议里的 `screens`:`cart_page_1` / `cart_page_2`)。
|
||||
|
||||
## 出参
|
||||
pricebot-backend 的响应**原样返回**(JSON object)。典型含 `result`(店名)、`calibration`(含 `source_platform_id` / `items` / `price`),客户端在 `step=0` 把它透传进 `/price/step`。
|
||||
pricebot-backend 的响应**原样返回**(JSON object),并在顶层补 `trace_id`。典型含 `result`(店名)、`calibration`(含 `source_platform_id` / `items` / `price`),客户端在 `step=0` 把它透传进 `/price/step`。
|
||||
|
||||
## 错误码
|
||||
- `400` body 不是合法 JSON
|
||||
@@ -18,7 +18,7 @@ pricebot-backend 的响应**原样返回**(JSON object)。典型含 `result`
|
||||
|
||||
外卖比价由客户端无障碍引擎在源平台(淘宝闪购 / 美团 / 京东外卖)购物车页点悬浮球触发 → 调本接口拿 `query` + `calibration` → 进入 `/price/step` 循环。
|
||||
|
||||
⚠️ **MVP 阶段不鉴权**(同 `coupon/step`):`device_id` 透传给 pricebot 区分设备,后端拿不到 `user_id` → 行为暂绑不到登录用户。待补 JWT,见 [待办与技术债.md](../guides/待办与技术债.md) P1。
|
||||
**trace_id 签发 + harvest 建行(2026-07 起,`compare.py`)**:客户端首帧可不带 `trace_id`——app-server 用 uuid 签发、注入转发 body、回填响应顶层;**仅签发那帧**按 `trace_id` 建 [comparison_record](../../database/comparison_record.md) 的 `running` 行(幂等,best-effort),done / finalize 帧再补终态。**软鉴权**:带 Bearer 则记录绑 `user_id`,匿名行 `user_id` 暂空、由后续 `/compare/record` 上报补。
|
||||
|
||||
**相关配置**:
|
||||
- `PRICEBOT_BASE_URL`(默认 `http://localhost:8000`)
|
||||
@@ -0,0 +1,27 @@
|
||||
# POST /api/v1/price/step — 外卖比价 Phase 2 步进(透传 + done 帧 harvest 落库)
|
||||
|
||||
> 所属:Compare 组(前缀 `/api/v1`,外卖比价) | 鉴权:**软鉴权 OptionalUser**(带 JWT 则绑 `user_id`,不带也放行) | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
任意 JSON body,**不做 schema 校验**,原样透传给上游。后端从中读 `device_id`、`trace_id`、`step`、`device_info` 用于日志与落库。
|
||||
客户端逐帧上报 `screen_state` + 上一步 `action_result`;`step=0` 还带 `query` + `calibration`(来自 Phase 1)。
|
||||
|
||||
## 出参
|
||||
pricebot-backend 的响应**原样返回**(JSON object),并在顶层补 `trace_id`(见下「trace_id 签发」)。含 `action`(tap / set_text / launch / wait / done…)、`continue`、`status`、每帧顶层 `trace_url`;最终 `done` 帧带 `comparison_results`(源 + 各目标平台到手价,按价升序)。
|
||||
|
||||
## 错误码
|
||||
- `400` body 不是合法 JSON
|
||||
- `502` pricebot 上游不可达(网络错误)或返回 5xx
|
||||
|
||||
## 说明
|
||||
把请求体原样转发到 `PRICEBOT_BASE_URL` 的 `/api/price/step`(去掉 `/v1`,共享 httpx 单例)。**多轮循环**:客户端按返回的 `action` 操作手机、再上报下一帧,直到 `continue=false`。真正的目标驱动比价逻辑(多目标平台串行复现订单、读到手价、聚合排序)在 **pricebot-backend**。
|
||||
|
||||
**不再是纯透传壳(2026-07 起,`compare.py`)**:
|
||||
- **trace_id 签发**:客户端首帧可不带 `trace_id`——app-server 用 uuid 签发、注入转发 body、回填进响应顶层 `trace_id`,客户端后续帧都带它(老客户端自带则原样用)。
|
||||
- **harvest 落库**([comparison_record](../../database/comparison_record.md)):首帧(mint 时)建 `running` 行 → **done 帧** `harvest_done` 写 `success`/`failed` + 派生 `best_*`/`saved_amount_cents`。写库 best-effort(threadpool 独立 session),失败不连累透传。
|
||||
- **软鉴权**:新客户端带 Bearer → 记录绑 `user_id`;老客户端/匿名 → `user_id` 暂空,由其后续 `POST /compare/record` 上报补(灰度期两条写路径按 `trace_id` reconcile,success 不降级)。
|
||||
- 邀请发奖**不在这里**:#113 起口径为好友「比价并下单」,发放在 `POST /order/report`。
|
||||
|
||||
**相关配置**:
|
||||
- `PRICEBOT_BASE_URL`(默认 `http://localhost:8000`;生产部署应与 pricebot-backend 同内网——比价一单 30~80 步、逐帧多一跳,走公网延迟会累积)
|
||||
- `PRICEBOT_COMPARE_TIMEOUT_SEC`(默认 60s,price/step 每帧都是 LLM)
|
||||
@@ -0,0 +1,113 @@
|
||||
# 比价意图多帧步进(intent/step + intent/precoupon/step)
|
||||
|
||||
> 所属:Intent 组(前缀 `/api/v1`,外卖比价透传) | 鉴权:无(MVP 阶段不鉴权) | [← 返回 API 索引](../README.md)
|
||||
|
||||
透传到 pricebot-backend。请求体原样转发、不做 schema 校验。
|
||||
|
||||
---
|
||||
|
||||
## POST /intent/step — Phase 1 多帧意图识别(淘宝源)
|
||||
|
||||
淘宝源走多帧版意图识别(展开+滚动采集→提取):循环调用直到 done(done 帧顶层带 `result` + `calibration`)。其它源走单次 `/intent/recognize`。
|
||||
|
||||
### 入参
|
||||
|
||||
透传 pricebot,客户端按 pricebot 协议组装。关键字段:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `device_id` | string | 设备 ID |
|
||||
| `trace_id` | string | 比价 trace 标识 |
|
||||
| `frame` | int | 帧序号(0 起始) |
|
||||
| `continue` | bool | 是否继续(pricebot 回传,客户端 next 调用时带上帧) |
|
||||
| `image` | string | 当前帧截图 base64 |
|
||||
| `platform` | string | 源平台 |
|
||||
| `package` | string | 目标平台包名 |
|
||||
| *(透传)* | | 其余字段由 pricebot 定义,本端点不做校验 |
|
||||
|
||||
Mock 入参(首帧):
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456",
|
||||
"trace_id": "tr_20260703_e5f6g7h8",
|
||||
"frame": 0,
|
||||
"continue": true,
|
||||
"image": "/9j/4AAQSkZJRgABAQEAYABgAAD/...(base64)",
|
||||
"platform": "taobao",
|
||||
"package": "com.sankuai.meituan"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
透传 pricebot 原始响应。通常包含 `action.command`(`continue` / `done`)、`action.params` 等。
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"trace_id": "tr_20260703_e5f6g7h8",
|
||||
"frame": 0,
|
||||
"continue": true,
|
||||
"action": {
|
||||
"command": "continue",
|
||||
"params": {
|
||||
"next_frame": 1,
|
||||
"scroll_distance": 300
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /intent/precoupon/step — Phase 0 意图识别前先用券(美团源)
|
||||
|
||||
美团源平台「意图识别前先用券」多帧循环:客户端在调 `/intent/recognize` 之前先循环调本端点到 done(`continue=false`)。订单页底部有「点击使用X红包」就自动选最大免费券用上,已用券/无券则首帧秒过。与 `/intent/step` 同属 intent 域,复用同一透传壳。
|
||||
|
||||
### 入参
|
||||
|
||||
同 `/intent/step`,透传 pricebot。
|
||||
|
||||
Mock 入参(首帧):
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456",
|
||||
"trace_id": "tr_20260703_i9j0k1l2",
|
||||
"frame": 0,
|
||||
"continue": true,
|
||||
"image": "/9j/4AAQSkZJRgABAQEAYABgAAD/...(base64)",
|
||||
"platform": "meituan",
|
||||
"package": "com.sankuai.meituan"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
透传 pricebot 原始响应。
|
||||
|
||||
Mock 出参(无券首帧秒过):
|
||||
```json
|
||||
{
|
||||
"trace_id": "tr_20260703_i9j0k1l2",
|
||||
"frame": 0,
|
||||
"continue": false,
|
||||
"action": {
|
||||
"command": "done",
|
||||
"params": {
|
||||
"coupon_used": false,
|
||||
"reason": "no_coupon_available"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 错误码
|
||||
- `502` pricebot 不可达或返回 5xx
|
||||
- `400` 请求体不是合法 JSON
|
||||
|
||||
## 说明
|
||||
- 两个端点是同域透传,区别是 pricebot 后端路由不同(`/api/intent/step` vs `/api/intent/precoupon/step`)
|
||||
- 一致性 hash 按 `trace_id` 路由到同一 pricebot 实例
|
||||
- MVP 阶段不鉴权(待补 JWT)
|
||||
@@ -1,6 +1,6 @@
|
||||
# 内部回写端点(internal 族,pricebot / 发布流程 → app-server)
|
||||
|
||||
> 所属:internal 组(前缀 `/internal`,源 `app/api/internal/`) | 鉴权:**`X-Internal-Secret` 头**(== `settings.INTERNAL_API_SECRET`) | [← 返回 API 索引](./README.md)
|
||||
> 所属:internal 组(前缀 `/internal`,源 `app/api/internal/`) | 鉴权:**`X-Internal-Secret` 头**(== `settings.INTERNAL_API_SECRET`) | [← 返回 API 索引](../README.md)
|
||||
|
||||
**不是给客户端的接口**:不走用户 JWT。`§6` 是 app-server 透传给 pricebot,这里反过来——pricebot(及发布流程)把少量数据 server→server 回写 app-server 落库。
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
| 方法 + 路径 | 落库 | 说明 |
|
||||
|---|---|---|
|
||||
| `POST /internal/price-observation` | [`price_observation`](../database/price_observation.md) | 比价 done 帧整批价格事实上报;`(trace_id, platform, scope)` 幂等,返回 `{inserted, skipped}` |
|
||||
| `GET /internal/store-mapping/lookup` | (只读 [`store_mapping`](../database/store_mapping.md)) | 比价前按 `source_platform`+`name`(+`lat`/`lng`)反查各目标平台已沉淀的店铺 id/deeplink;命中→pricebot 直接 deeplink 省现场搜店 |
|
||||
| `POST /internal/price-observation` | [`price_observation`](../../database/price_observation.md) | 比价 done 帧整批价格事实上报;`(trace_id, platform, scope)` 幂等,返回 `{inserted, skipped}` |
|
||||
| `GET /internal/store-mapping/lookup` | (只读 [`store_mapping`](../../database/store_mapping.md)) | 比价前按 `source_platform`+`name`(+`lat`/`lng`)反查各目标平台已沉淀的店铺 id/deeplink;命中→pricebot 直接 deeplink 省现场搜店 |
|
||||
| `POST /internal/store-mapping` | `store_mapping` | 跨平台「同一家店」身份映射上报;`trace_id` 幂等、填空合并,返回 `{inserted, row_id}` |
|
||||
| `POST /internal/store-mapping/invalidate` | `store_mapping` | 标记某平台 `shop_id` 的缓存 deeplink 失效(pricebot 撞错误页回退时报);当前支持 `taobao`/`jd`,其它平台 no-op,返回 `{ok, affected}` |
|
||||
| `POST /internal/launch-confirm-sample` | [`launch_confirm_sample`](../database/launch_confirm_sample.md) | 启动确认窗 LLM 兜底放行后回写样本(host 包 + 弹窗树 + plan + locale);**都上报、不去重**,返回 `{id}` |
|
||||
| `POST /internal/app-version` | [`app_config`](../database/app_config.md)(key=`latest_app_version`) | **发布流程**(非 pricebot)出 APK 后写最新版本号/下载链接/sha256;客户端再 `GET /api/v1/platform/app-version` 读做 OTA。也是应急改版本信息(紧急下线/改 `apk_url`)入口 |
|
||||
| `POST /internal/launch-confirm-sample` | [`launch_confirm_sample`](../../database/launch_confirm_sample.md) | 启动确认窗 LLM 兜底放行后回写样本(host 包 + 弹窗树 + plan + locale);**都上报、不去重**,返回 `{id}` |
|
||||
| `GET /internal/launch-confirm-samples` | (只读 `launch_confirm_sample`) | 样本列表(#91,供 pricebot `distill_launch_confirm.py` 聚合沉淀回静态规则);可选筛 `exec_success` / `host_package` / `since_days`,`limit` 默认 1000 |
|
||||
| `POST /internal/app-version` | [`app_config`](../../database/app_config.md)(key=`latest_app_version`) | **发布流程**(非 pricebot)出 APK 后写最新版本号/下载链接/sha256;客户端再 `GET /api/v1/platform/app-version` 读做 OTA。也是应急改版本信息(紧急下线/改 `apk_url`)入口 |
|
||||
|
||||
## 错误
|
||||
- `401` 密钥不匹配 / 缺失。
|
||||
@@ -0,0 +1,100 @@
|
||||
# 邀请绑定(bind + landing-track)
|
||||
|
||||
> 所属:Invite 组(前缀 `/api/v1/invite`) | 鉴权:bind 需 Bearer / landing-track 无需鉴权 | [← 返回 API 索引](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## POST /bind — 绑定邀请人
|
||||
|
||||
把当前登录用户(被邀请人)绑定到某邀请码。支持三种归因路径:clipboard(首启读剪贴板)、manual(手动输入邀请码)、fingerprint(指纹兜底反查)。**#113 起绑定只建关系、不发奖**——发奖后置到被邀请人「比价并实际下单」(`POST /order/report` 触发,给邀请人发**邀请奖励金**,`compare_reward_granted` 幂等闸一人一次)。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `invite_code` | string \| null | ❌ | 邀请码;走指纹兜底时为空 |
|
||||
| `channel` | string | ✅ | 归因来源:`clipboard` / `manual` / `fingerprint` |
|
||||
| `fingerprint` | object \| null | ❌ | 指纹兜底时必传 |
|
||||
| `fingerprint.screen` | string | - | 屏幕分辨率(如 `1080x2400`) |
|
||||
| `fingerprint.device_model` | string | - | 设备型号(如 `24115RA8EC`) |
|
||||
|
||||
Mock 入参(clipboard 归因):
|
||||
```json
|
||||
{
|
||||
"invite_code": "A3F8K2",
|
||||
"channel": "clipboard",
|
||||
"fingerprint": null
|
||||
}
|
||||
```
|
||||
|
||||
Mock 入参(指纹兜底):
|
||||
```json
|
||||
{
|
||||
"invite_code": null,
|
||||
"channel": "fingerprint",
|
||||
"fingerprint": {
|
||||
"screen": "1080x2400",
|
||||
"device_model": "24115RA8EC"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
响应 `200`:`BindInviteOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `status` | string | `success` / `already_bound` / `invalid_code` / `self_invite` / `not_eligible` / `fp_not_found` |
|
||||
| `coins_awarded` | int | 兼容保留字段(#113 前"绑定即发金币"口径)。**#113 起新绑定恒 0**,前端不应再据此展示发奖 |
|
||||
| `message` | string | 给前端直接展示的文案 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"coins_awarded": 0,
|
||||
"message": "邀请绑定成功"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /landing-track — 落地页指纹采集
|
||||
|
||||
B 浏览器打开 `dl.html?ref=xxx` 时上报指纹(剪贴板归因失败时兜底)。**无需鉴权**(浏览器没 token)。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `ref` | string | ✅(4-16 位) | 邀请码(落地页 `?ref=`) |
|
||||
| `screen` | string | ❌ | 屏幕分辨率(如 `1080x2400`) |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"ref": "A3F8K2",
|
||||
"screen": "1080x2400"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
响应 `200`:`LandingTrackOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `status` | string | `ok` / `invalid_code` / `no_ip` |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{"status": "ok"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 说明
|
||||
- `bind`: 绑定只在注册后首次有效(`not_eligible` = 已过新人期),自邀屏蔽
|
||||
- `landing-track`: IP/UA 服务端从 HTTP 头自动拿,JS 无需上报
|
||||
- 指纹反查窗口期由 `INVITE_FP_WINDOW_DAYS` 控制
|
||||
@@ -0,0 +1,63 @@
|
||||
# GET /api/v1/invite/invitees — 我邀请的人列表
|
||||
|
||||
> 所属:Invite 组(前缀 `/api/v1/invite`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
分页查询当前用户成功邀请的人列表。邀请页小窗(取前几条)+ 完整列表页(分页加载)共用。
|
||||
|
||||
## 入参(query)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `limit` | int | ❌ | 每页条数(1–50,默认 20) |
|
||||
| `offset` | int | ❌ | 偏移量(≥0,默认 0) |
|
||||
|
||||
Mock 请求:
|
||||
```
|
||||
GET /api/v1/invite/invitees?limit=5&offset=0
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`InviteeListOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `items` | list[InviteeItem] | 被邀请人列表 |
|
||||
| `items[].display_name` | string | 显示名(昵称 → 微信昵称 → 脱敏手机号,后端已兜底) |
|
||||
| `items[].avatar_url` | string \| null | 头像 URL;null = 前端画默认色块 |
|
||||
| `items[].coins` | int | 这次邀请给邀请人发的金币(**历史留痕**:#113 前旧口径的发放额;新绑定恒 0) |
|
||||
| `items[].is_compared` | bool | 该好友是否已完成过一次比价(#113:好友列表据此分「邀请成功 / 去提醒」,在途列表只取 `false` 的) |
|
||||
| `items[].invited_at` | datetime | 邀请绑定时间(ISO 8601 UTC) |
|
||||
| `total` | int | 我邀请的总人数 |
|
||||
| `has_more` | bool | 还有下一页吗 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"display_name": "省钱小王",
|
||||
"avatar_url": "/media/avatars/u2_f1e2d3c4b5a60708.jpg",
|
||||
"coins": 0,
|
||||
"is_compared": true,
|
||||
"invited_at": "2026-06-28T14:30:00Z"
|
||||
},
|
||||
{
|
||||
"display_name": "138****1234",
|
||||
"avatar_url": null,
|
||||
"coins": 0,
|
||||
"is_compared": false,
|
||||
"invited_at": "2026-07-01T09:15:00Z"
|
||||
}
|
||||
],
|
||||
"total": 5,
|
||||
"has_more": false
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `401` 未鉴权 / token 失效
|
||||
|
||||
## 说明
|
||||
- 名字/头像降级兜底在后端算好:昵称 → 微信昵称 → 脱敏手机号
|
||||
- `limit` 钳到 [1, 50],`offset` 钳到 ≥0
|
||||
@@ -0,0 +1,48 @@
|
||||
# GET /api/v1/invite/me — 我的邀请信息
|
||||
|
||||
> 所属:Invite 组(前缀 `/api/v1/invite`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
获取当前用户的邀请码、分享链接、已邀人数、累计获得金币/奖励金,以及 7 天一轮的倒计时信息。
|
||||
|
||||
## 入参
|
||||
|
||||
无(`user_id` 从 JWT 取)。
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`InviteInfoOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `invite_code` | string | 我的邀请码(6-8 位) |
|
||||
| `share_url` | string | 落地页链接(含 `?ref=`),前端据此生成二维码 + 复制分享 |
|
||||
| `invited_count` | int | 已成功邀请人数 |
|
||||
| `coins_earned` | int | 累计从邀请获得的金币(v1 口径) |
|
||||
| `reward_balance_cents` | int | v2 可提现邀请奖励金(分) |
|
||||
| `reward_withdrawn_cents` | int | v2 累计提现成功的邀请奖励金(分) |
|
||||
| `countdown_days_left` | int | v2 本轮剩余天数(7 天 1 轮) |
|
||||
| `countdown_is_fresh_round` | bool | 是否刚进入新一轮(非首轮第 1 天) |
|
||||
| `countdown_text` | string | 倒计时展示文案(前端直接显示,新轮含换行) |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"invite_code": "A3F8K2",
|
||||
"share_url": "https://app.shaguabijia.com/dl.html?ref=A3F8K2",
|
||||
"invited_count": 5,
|
||||
"coins_earned": 50000,
|
||||
"reward_balance_cents": 3200,
|
||||
"reward_withdrawn_cents": 1800,
|
||||
"countdown_days_left": 4,
|
||||
"countdown_is_fresh_round": false,
|
||||
"countdown_text": "还剩 4 天"
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `401` 未鉴权 / token 失效
|
||||
|
||||
## 说明
|
||||
- 首次调用自动生成邀请码(幂等)
|
||||
- v2 奖励金与现金隔离(`reward_balance_cents` 独立于 `cash_balance_cents`)
|
||||
- 7 天 1 轮倒计时:新用户从注册日起算
|
||||
@@ -1,23 +0,0 @@
|
||||
# POST /api/v1/meituan/top-sales — 销量最高(离线库)
|
||||
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
>
|
||||
> 数据来自离线库 [database/meituan_coupon](../database/meituan_coupon.md);**不实时打美团**(美团搜索对销量排序支持差、且有 402 限流)。
|
||||
|
||||
## 入参
|
||||
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `page` | int | ❌ | 1 | ≥1 |
|
||||
| `page_size` | int | ❌ | 20 | 1–50 |
|
||||
| `platform` | int \| null | ❌ | null | 1 只外卖 / 2 只到店 / 不填=全部(全城销量) |
|
||||
|
||||
## 出参
|
||||
响应 `200`:`{ items: CouponCard[], has_next: bool, search_id: null, status: "ok"|"empty"|"degraded" }`。`CouponCard` 见 [API 索引](./README.md#复用数据结构);`status` 语义见 [feed 接口](./meituan-feed.md#status-字段前端据此显示占位)。
|
||||
|
||||
## 说明
|
||||
- 从 `meituan_coupon` 取 `sale_volume_num` 非空的券,`DISTINCT ON(dedup_key)` 跨源去重(每个「品牌|名|价」只留销量最高一条,同销量再按佣金),按销量降序分页;每页只对当前 ~20 条做 `from_raw` 解析(翻页快,不全表拉取)。
|
||||
- **不依赖 MT 凭证**(纯库查询)。库为空(prod 刚部署 / ETL 未跑完)→ `status=empty`;库查询异常 → `status=degraded`。均返 `200`、不抛 5xx。
|
||||
- **仅 PostgreSQL**(`DISTINCT ON` 为 PG 专用)。
|
||||
|
||||
## 错误码
|
||||
无业务级错误码:库空 / 异常都返 `200` + 空 `items` + 对应 `status`。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/meituan/coupons — 券列表 / 搜索
|
||||
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/meituan](../integrations/meituan.md)(CPS S-Ca 签名、入参换算坑)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/meituan/feed — 首页推荐流(多 tab)
|
||||
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/meituan](../integrations/meituan.md)(CPS S-Ca 签名、入参换算坑);离线库见 [database/meituan_coupon](../database/meituan_coupon.md)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/meituan/referral-link — 换取推广链接
|
||||
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/meituan](../integrations/meituan.md)(CPS S-Ca 签名、入参换算坑)。
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# POST /api/v1/meituan/top-sales — 销量最高(离线库)
|
||||
|
||||
> 所属:美团 CPS 组(前缀 `/api/v1/meituan`,**全部无鉴权**) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 数据来自离线库 [database/meituan_coupon](../../database/meituan_coupon.md);**不实时打美团**(美团搜索对销量排序支持差、且有 402 限流)。
|
||||
|
||||
## 入参
|
||||
| 字段 | 类型 | 必填 | 默认 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `page` | int | ❌ | 1 | ≥1 |
|
||||
| `page_size` | int | ❌ | 20 | 1–50 |
|
||||
| `platform` | int \| null | ❌ | null | 1 只外卖 / 2 只到店 / 不填=全部 |
|
||||
| `longitude` / `latitude` | float \| null | ❌(实际必带) | null | 设备坐标(#116):服务端离线反查城市(`utils/geo` + `meituan_city`)→ **只返回同城券**;老客户端不带坐标 → 返空 + `status=degraded`(不 422、不误返全城) |
|
||||
|
||||
## 出参
|
||||
响应 `200`:`{ items: CouponCard[], has_next: bool, search_id: null, status: "ok"|"empty"|"degraded" }`。`CouponCard` 见 [API 索引](../README.md#复用数据结构);`status` 语义见 [feed 接口](./meituan-feed.md#status-字段前端据此显示占位)。
|
||||
|
||||
## 说明
|
||||
- 从 `meituan_coupon` 取 `sale_volume_num` 非空 **且 `city_id` = 反查城市** 的券(#116,同城销量榜),`DISTINCT ON(dedup_key)` 跨源去重(每个「品牌|名|价」只留销量最高一条,同销量再按佣金),按销量降序分页;每页只对当前 ~20 条做 `from_raw` 解析(翻页快,不全表拉取)。
|
||||
- **不依赖 MT 凭证**(纯库查询)。库为空(prod 刚部署 / ETL 未跑完)→ `status=empty`;库查询异常 → `status=degraded`。均返 `200`、不抛 5xx。
|
||||
- **仅 PostgreSQL**(`DISTINCT ON` 为 PG 专用)。
|
||||
|
||||
## 错误码
|
||||
无业务级错误码:库空 / 异常都返 `200` + 空 `items` + 对应 `status`。
|
||||
@@ -0,0 +1,82 @@
|
||||
# POST /api/v1/analytics/events — 批量上报埋点事件
|
||||
|
||||
> 所属:Analytics 组(前缀 `/api/v1/analytics`) | 鉴权:无(不强制登录,未登录态也要采集行为) | [← 返回 API 索引](../README.md)
|
||||
|
||||
批量接收新手引导(及后续)埋点,append 落 `analytics_event` 表。`user_id` 由客户端在 body 可选带上,不靠 Bearer。服务端补 `client_ip`(X-Forwarded-For)与 `server_at`(接收时间)。
|
||||
|
||||
## 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅(≤64) | 设备 ID |
|
||||
| `user_id` | int \| null | ❌ | 登录用户 ID(未登录可空) |
|
||||
| `sent_at` | int \| null | ❌ | 批次发送时间(epoch ms) |
|
||||
| `oem` | string \| null | ❌ | 厂商(如 `Xiaomi`) |
|
||||
| `os` | string \| null | ❌ | 操作系统(如 `Android 14`) |
|
||||
| `model` | string \| null | ❌ | 机型(如 `24115RA8EC`) |
|
||||
| `app_ver` | string \| null | ❌ | App 版本 |
|
||||
| `channel` | string \| null | ❌ | 渠道 |
|
||||
| `events` | list[object] | ✅(1-200 条) | 事件数组 |
|
||||
| `events[].event` | string | ✅(≤64) | 事件名(如 `onboarding_start`) |
|
||||
| `events[].client_ts` | int | ✅ | 端事件发生时间(epoch ms) |
|
||||
| `events[].session_id` | string \| null | ❌ | 会话 ID |
|
||||
| `events[].page` | string \| null | ❌ | 页面标识 |
|
||||
| `events[].network` | string \| null | ❌ | 网络类型(如 `wifi`) |
|
||||
| `events[].props` | dict | ❌ | 事件属性(key-value) |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456",
|
||||
"user_id": 42,
|
||||
"sent_at": 1719993700000,
|
||||
"oem": "Xiaomi",
|
||||
"os": "Android 14",
|
||||
"model": "24115RA8EC",
|
||||
"app_ver": "0.1.5",
|
||||
"channel": "official",
|
||||
"events": [
|
||||
{
|
||||
"event": "onboarding_start",
|
||||
"client_ts": 1719993600000,
|
||||
"session_id": "sess_a1b2c3",
|
||||
"page": "onboarding",
|
||||
"network": "wifi",
|
||||
"props": {"step": "1", "source": "fresh_install"}
|
||||
},
|
||||
{
|
||||
"event": "onboarding_step_complete",
|
||||
"client_ts": 1719993615000,
|
||||
"session_id": "sess_a1b2c3",
|
||||
"page": "onboarding",
|
||||
"network": "wifi",
|
||||
"props": {"step": "1", "duration_ms": "15000"}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`AnalyticsIngestOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `ok` | bool | 固定 `true` |
|
||||
| `received` | int | 成功写入的条数 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"received": 2
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `422` `events` 为空或超过 200 条 / 字段类型不符
|
||||
|
||||
## 说明
|
||||
- `user_id` 不靠 JWT:未登录态也要采集行为(新手引导可能在登录前)
|
||||
- 每批最多 200 条,建议客户端攒到一定量再批量上报
|
||||
- `client_ts` 是端侧时间(客户端时钟),`server_at` 由服务端补(可靠时间轴)
|
||||
@@ -1,6 +1,6 @@
|
||||
# CPS 群发短链落地(cps-redirect 族)
|
||||
|
||||
> 所属:cps-redirect 组(**无前缀**,挂域名根;源 `app/api/v1/cps_redirect.py`) | 鉴权:**公网无鉴权**(群里任何人点都要能跳/能领) | [← 返回 API 索引](./README.md)
|
||||
> 所属:cps-redirect 组(**无前缀**,挂域名根;源 `app/api/v1/cps_redirect.py`) | 鉴权:**公网无鉴权**(群里任何人点都要能跳/能领) | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 落库:点击落 [`cps_click`](../database/cps_click.md)、微信落地页用户落 [`cps_wx_user`](../database/cps_wx_user.md);短链由 [`cps_link`](../database/cps_link.md) 解析。
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# GET /api/v1/feedback/config — 反馈页二维码卡配置
|
||||
|
||||
> 所属:Feedback 组(前缀 `/api/v1/feedback`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
运营后台配的反馈页「加群二维码」卡配置(开关 + 二维码图 + 三行文案)。客户端进反馈页时拉取,据此渲染整张「加群二维码」卡。
|
||||
|
||||
## 入参
|
||||
|
||||
无(`user_id` 从 JWT 取)。
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`FeedbackQrConfigOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `enabled` | bool | 是否展示加群二维码卡 |
|
||||
| `image_url` | string \| null | 二维码图片 URL(相对 `/media` 路径);空 → 客户端走本地兜底 |
|
||||
| `title` | string | 卡片标题(如 `加入用户反馈群`) |
|
||||
| `group_name` | string | 群名称(如 `傻瓜比价用户群`) |
|
||||
| `subtitle` | string | 副标题/说明文案(如 `扫码加入,你的声音我们听得见`) |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"image_url": "/media/feedback_qr/qr_default.png",
|
||||
"title": "加入用户反馈群",
|
||||
"group_name": "傻瓜比价用户群",
|
||||
"subtitle": "扫码加入,你的声音我们听得见"
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `401` 未鉴权 / token 失效
|
||||
|
||||
## 说明
|
||||
- `image_url` 是相对路径,客户端按自己的 `BASE_URL` 拼绝对地址
|
||||
- `enabled=false` 时客户端隐藏整张卡
|
||||
- 配置在 admin 后台 `feedback_qr` 表维护
|
||||
@@ -0,0 +1,71 @@
|
||||
# GET /api/v1/feedback/records — 我的反馈历史
|
||||
|
||||
> 所属:Feedback 组(前缀 `/api/v1/feedback`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
查询当前用户提交的反馈历史,支持按状态筛选。
|
||||
|
||||
## 入参(query)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `status` | string \| null | ❌ | 筛选状态:`pending` / `adopted` / `rejected`;不传 = 全部 |
|
||||
|
||||
Mock 请求:
|
||||
```
|
||||
GET /api/v1/feedback/records?status=adopted
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`FeedbackRecordsOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `records` | list[FeedbackRecordOut] | 反馈记录列表 |
|
||||
| `records[].id` | int | 反馈 ID |
|
||||
| `records[].content` | string | 反馈正文 |
|
||||
| `records[].scene` | string \| null | 问题场景(比价结果页反馈时带,如 `找错商品`) |
|
||||
| `records[].images` | list[string] | 截图 URL 列表 |
|
||||
| `records[].status` | string | `pending` / `adopted` / `rejected` |
|
||||
| `records[].reject_reason` | string \| null | 驳回原因 |
|
||||
| `records[].reward_coins` | int \| null | 采纳后发的金币数 |
|
||||
| `records[].admin_reply` | string \| null | 管理员回复 |
|
||||
| `records[].created_at` | datetime | 提交时间 |
|
||||
| `counts` | object | 三态计数(不受 status 筛选影响) |
|
||||
| `counts.all` | int | 总数 |
|
||||
| `counts.pending` | int | 待处理 |
|
||||
| `counts.adopted` | int | 已采纳 |
|
||||
| `counts.rejected` | int | 已驳回 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"records": [
|
||||
{
|
||||
"id": 56,
|
||||
"content": "比价结果显示美团 28.5 元,但实际下单时涨到了 32 元",
|
||||
"scene": "价格不一致",
|
||||
"images": ["/media/feedback/u42_f1e2d3c4b5a60708.jpg"],
|
||||
"status": "adopted",
|
||||
"reject_reason": null,
|
||||
"reward_coins": 500,
|
||||
"admin_reply": "感谢反馈,已核实并修复",
|
||||
"created_at": "2026-07-02T15:20:00Z"
|
||||
}
|
||||
],
|
||||
"counts": {
|
||||
"all": 3,
|
||||
"pending": 1,
|
||||
"adopted": 2,
|
||||
"rejected": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `400` 无效的 `status` 值(仅 `pending`/`adopted`/`rejected` 合法)
|
||||
- `401` 未鉴权
|
||||
|
||||
## 说明
|
||||
- `counts` 始终基于全量(不受 `status` 筛选影响),供前端筛选 chip
|
||||
- `scene` 仅比价结果页反馈时带(区分普通反馈 vs 比价场景反馈)
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/feedback — 提交反馈
|
||||
|
||||
> 所属:Feedback 组(前缀 `/api/v1/feedback`) | 鉴权:Bearer access_token | [← 返回 API 索引](./README.md)
|
||||
> 所属:Feedback 组(前缀 `/api/v1/feedback`) | 鉴权:Bearer access_token | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
**multipart/form-data**:
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /health — 健康检查
|
||||
|
||||
> 所属:Meta | 鉴权:无 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Meta | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无
|
||||
@@ -0,0 +1,74 @@
|
||||
# POST /api/v1/order/report — 上报归因订单
|
||||
|
||||
> 所属:Order 组(前缀 `/api/v1/order`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
比价后 5 分钟内点链接下单、支付金额与比价价相差 ≤1 元时,客户端上报归因订单。落 `savings_record`(`source='compare'`),客户端幂等键防重。
|
||||
|
||||
## 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `client_event_id` | string | ✅(≤64) | 客户端幂等键(UUID) |
|
||||
| `platform` | string | ✅(≤32) | 平台展示名(如 `美团`) |
|
||||
| `platform_package` | string \| null | ❌ | 平台包名 |
|
||||
| `pay_channel` | string | ✅(≤16) | 支付渠道(`wechat` / `alipay`) |
|
||||
| `compared_price_cents` | int | ✅(≥0) | 我们给出的比价价(分) |
|
||||
| `paid_amount_cents` | int | ✅(≥0) | 实际支付金额(分) |
|
||||
| `device_id` | string \| null | ❌ | 设备 ID |
|
||||
| `shop_name` | string \| null | ❌ | 门店名(如 `肯德基宅急送(天北路店)`) |
|
||||
| `dishes` | list[string] | ❌ | 菜品名列表 |
|
||||
| `original_price_cents` | int \| null | ❌ | 源平台原价(分),省额 = 原价 − 实付 |
|
||||
| `source_platform_name` | string \| null | ❌ | 源平台展示名(如 `美团`) |
|
||||
| `source_deeplink` | string \| null | ❌ | 源平台重进链接(预留,本期只存不展示) |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"client_event_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"platform": "美团",
|
||||
"platform_package": "com.sankuai.meituan",
|
||||
"pay_channel": "wechat",
|
||||
"compared_price_cents": 2850,
|
||||
"paid_amount_cents": 2800,
|
||||
"device_id": "android_abc123def456",
|
||||
"shop_name": "肯德基宅急送(天北路店)",
|
||||
"dishes": ["香辣鸡腿堡套餐", "可口可乐(中)"],
|
||||
"original_price_cents": 4200,
|
||||
"source_platform_name": "美团",
|
||||
"source_deeplink": null
|
||||
}
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`OrderReportOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `id` | int | 省钱记录 ID |
|
||||
| `platform` | string | 平台 |
|
||||
| `pay_channel` | string | 支付渠道 |
|
||||
| `compared_price_cents` | int | 比价价(分) |
|
||||
| `paid_amount_cents` | int | 实付金额(分) |
|
||||
| `duplicated` | bool | 是否为重复上报(幂等命中) |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"id": 1234,
|
||||
"platform": "美团",
|
||||
"pay_channel": "wechat",
|
||||
"compared_price_cents": 2850,
|
||||
"paid_amount_cents": 2800,
|
||||
"duplicated": false
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `401` 未鉴权 / token 失效
|
||||
- `422` 必填字段缺失或类型不符
|
||||
|
||||
## 说明
|
||||
- 记账唯一真相表是 `savings_record`(`source='compare'`)
|
||||
- `client_event_id` 幂等防重(网络重试不重复记)
|
||||
- 省额 = `original_price_cents − paid_amount_cents`(若原价可用)
|
||||
@@ -0,0 +1,81 @@
|
||||
# GET /api/v1/report/records — 上报更低价记录列表
|
||||
|
||||
> 所属:Report 组(前缀 `/api/v1/report`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
当前用户的上报更低价记录列表,支持按状态筛选。
|
||||
|
||||
## 入参(query)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `status` | string \| null | ❌ | 筛选状态:`pending` / `approved` / `rejected`;不传 = 全部 |
|
||||
|
||||
Mock 请求:
|
||||
```
|
||||
GET /api/v1/report/records?status=pending
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`ReportRecordsOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `records` | list[ReportRecordOut] | 上报记录列表 |
|
||||
| `records[].id` | int | 记录 ID |
|
||||
| `records[].store_name` | string \| null | 门店名 |
|
||||
| `records[].dish_summary` | string \| null | 菜品摘要(如 `香辣鸡腿堡套餐、可口可乐`) |
|
||||
| `records[].original_platform_id` | string \| null | 原最低价来源平台 ID |
|
||||
| `records[].original_platform_name` | string \| null | 原最低价来源平台名 |
|
||||
| `records[].original_price_cents` | int \| null | 原最低价(分) |
|
||||
| `records[].reported_platform_id` | string | 上报平台标识 |
|
||||
| `records[].reported_platform_name` | string | 上报平台名(如 `京东外卖`) |
|
||||
| `records[].reported_price_cents` | int | 上报更低价(分) |
|
||||
| `records[].images` | list[string] | 截图 URL 列表 |
|
||||
| `records[].status` | string | `pending` / `approved` / `rejected` |
|
||||
| `records[].reject_reason` | string \| null | 驳回原因(rejected 时) |
|
||||
| `records[].reward_coins` | int \| null | 通过后发的金币数 |
|
||||
| `records[].created_at` | datetime | 提交时间 |
|
||||
| `counts` | object | 四态计数(不受 status 筛选影响,供前端 chip 展示) |
|
||||
| `counts.all` | int | 总数 |
|
||||
| `counts.pending` | int | 审核中 |
|
||||
| `counts.approved` | int | 已通过 |
|
||||
| `counts.rejected` | int | 未通过 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"records": [
|
||||
{
|
||||
"id": 89,
|
||||
"store_name": "肯德基宅急送(天北路店)",
|
||||
"dish_summary": "香辣鸡腿堡套餐、可口可乐(中)",
|
||||
"original_platform_id": "meituan-waimai",
|
||||
"original_platform_name": "美团外卖",
|
||||
"original_price_cents": 2850,
|
||||
"reported_platform_id": "jd-waimai",
|
||||
"reported_platform_name": "京东外卖",
|
||||
"reported_price_cents": 1880,
|
||||
"images": ["/media/price_report/u42_a1b2c3d4e5f6g7h8.jpg"],
|
||||
"status": "pending",
|
||||
"reject_reason": null,
|
||||
"reward_coins": null,
|
||||
"created_at": "2026-07-03T10:30:00Z"
|
||||
}
|
||||
],
|
||||
"counts": {
|
||||
"all": 3,
|
||||
"pending": 1,
|
||||
"approved": 1,
|
||||
"rejected": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `400` 无效的 `status` 值(仅 `pending`/`approved`/`rejected` 合法)
|
||||
- `401` 未鉴权
|
||||
|
||||
## 说明
|
||||
- `counts` 始终基于全量(不受 `status` 筛选影响),供前端筛选 chip 显示各状态数量
|
||||
- 价格单位均为分(`*_cents`),客户端 ÷100 显示元
|
||||
@@ -0,0 +1,57 @@
|
||||
# POST /api/v1/report — 提交上报更低价
|
||||
|
||||
> 所属:Report 组(前缀 `/api/v1/report`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
众包纠偏:用户发现比价记录中某平台有更低价格时提交上报。需附截图证明,原最低价由 `comparison_record_id` 反查(不信任客户端传的快照),提交价必须 < 原最低价。提交后 `status=pending`,人工审核通过后发奖。
|
||||
|
||||
## 入参
|
||||
|
||||
**multipart/form-data**:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `comparison_record_id` | int | ✅ | 比价记录 ID |
|
||||
| `reported_platform_id` | string | ✅ | 上报平台标识:`meituan-waimai` / `jd-waimai` / `taobao-shanguang` |
|
||||
| `reported_price` | string | ✅ | 用户填的更低价(元,如 `23.5`) |
|
||||
| `images` | file[] | ✅(1–4 张) | 截图证明 |
|
||||
|
||||
Mock 入参(curl 示例):
|
||||
```bash
|
||||
curl -X POST https://app-api.shaguabijia.com/api/v1/report \
|
||||
-H "Authorization: Bearer <access_token>" \
|
||||
-F "comparison_record_id=5678" \
|
||||
-F "reported_platform_id=jd-waimai" \
|
||||
-F "reported_price=18.8" \
|
||||
-F "images=@screenshot1.png" \
|
||||
-F "images=@screenshot2.png"
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`ReportSubmitOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `id` | int | 上报记录 ID |
|
||||
| `status` | string | 固定 `pending`(待审核) |
|
||||
| `created_at` | datetime | 提交时间(ISO 8601 UTC) |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"id": 89,
|
||||
"status": "pending",
|
||||
"created_at": "2026-07-03T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `400` 价格不合法(≤0 / 格式错)/ 上报价 ≥ 原最低价 / 图片问题(空/超 4 张/格式不对)/ 不支持的上报平台
|
||||
- `401` 未鉴权
|
||||
- `404` 比价记录不存在或不属于当前用户
|
||||
|
||||
## 说明
|
||||
- 原最低价由 `comparison_record_id` → `ComparisonRecord.best_price_cents` 反查
|
||||
- 校验(D):`reported_price_cents < original_price_cents`,否则 400
|
||||
- 截图落盘 `MEDIA_ROOT/price_report/`,文件名随机防覆盖
|
||||
- 发奖走人工审核(admin 后台操作),不在此端点
|
||||
@@ -0,0 +1,59 @@
|
||||
# POST /api/v1/trace/finalize + /trace/epilogue — 比价 trace 收尾族
|
||||
|
||||
> 所属:透传端点(前缀 `/api/v1`,外卖比价) | 鉴权:软鉴权 OptionalUser | [← 返回 API 索引](../README.md)
|
||||
|
||||
## POST /api/v1/trace/finalize — 收尾上云(+夭折落库)
|
||||
|
||||
透传到 pricebot-backend。用户终止 / Phase 1 未识别没走到 done 帧时,pricebot 没上云也没回传 `trace_url`。客户端收尾时打这个,pricebot 按 `trace_id` 一致性 hash 落到处理这条 trace 的同一进程(dir_cache 在那才能算对 trace 目录),打包上云返回 `{trace_url}`。
|
||||
|
||||
**顺手夭折落库(2026-07 起)**:app-server 把该 trace 的 [comparison_record](../../database/comparison_record.md) `running` 行更新成夭折终态(`harvest_abort`,**不降级已 success**)。body 可带 `status`(`cancelled`/`failed`)+ `reason`;老客户端只带 `trace_id` → 默认 `cancelled`,其后续 `/compare/record` 上报再补精确态。
|
||||
|
||||
## 入参
|
||||
|
||||
透传 pricebot,客户端按 pricebot 协议组装。关键字段:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `device_id` | string | 设备 ID |
|
||||
| `trace_id` | string | 比价 trace 标识 |
|
||||
| *(透传)* | | 其余字段由 pricebot 定义,本端点不做校验 |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456",
|
||||
"trace_id": "tr_20260703_m3n4o5p6",
|
||||
"reason": "user_cancelled"
|
||||
}
|
||||
```
|
||||
|
||||
## 出参
|
||||
|
||||
透传 pricebot 原始响应,通常包含 `trace_url`。
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"trace_url": "https://trace.shaguabijia.com/tr_20260703_m3n4o5p6",
|
||||
"ok": true
|
||||
}
|
||||
```
|
||||
|
||||
## 错误码
|
||||
- `502` pricebot 不可达或返回 5xx
|
||||
- `400` 请求体不是合法 JSON
|
||||
|
||||
## 说明
|
||||
- 一致性 hash 按 `trace_id` 路由到同一 pricebot 实例(确保 dir_cache 命中)
|
||||
- 软鉴权(OptionalUser,同比价透传族)
|
||||
- 与 `/intent/recognize`、`/price/step` 等同属外卖比价透传族
|
||||
|
||||
---
|
||||
|
||||
## POST /api/v1/trace/epilogue — 结果页尾声帧(#112)
|
||||
|
||||
App 收到 done、渲染完**结果页**后,把自己页面的截图(base64,body ~几百 KB)传给 pricebot 存进 trace 目录并触发重传——trace 里补上「用户实际看到的汇总页」(步骤帧只有目标 App 画面)。
|
||||
|
||||
- **纯透传壳**:不建行、不落库(该 trace 的比价记录已由 done / finalize 落终态)。
|
||||
- 入参:`{device_id, trace_id, screenshot(base64), ...}`(pricebot 协议);出参:pricebot 原样响应。
|
||||
- 错误码同 finalize(`400` / `502`)。
|
||||
@@ -0,0 +1,43 @@
|
||||
# GET /api/v1/platform/ad-config — 客户端广告配置
|
||||
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端启动 / 每场广告前拉取,缓存后用:穿山甲 `app_id` + 各位 ID + 各场景开关。不含验签密钥(密钥只在后端验 S2S 回调用)。
|
||||
|
||||
## 入参
|
||||
|
||||
无。
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`AdConfigPublicOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `app_id` | string | 穿山甲应用 ID(改了需冷启才生效,SDK init 一次性读) |
|
||||
| `reward_code_id` | string | 福利页激励视频位 |
|
||||
| `compare_draw_code_id` | string | 比价 Draw 代码位 |
|
||||
| `coupon_draw_code_id` | string | 领券 Draw 代码位(与比价共用同一位,靠 `feed_scene` 区分收益) |
|
||||
| `reward_enabled` | bool | 福利激励视频开关 |
|
||||
| `compare_ad_enabled` | bool | 比价广告开关 |
|
||||
| `coupon_ad_enabled` | bool | 领券广告开关 |
|
||||
| `withdrawal_ad_enabled` | bool | 提现激励视频开关(关 = 客户端直接放行提现) |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"app_id": "5123456",
|
||||
"reward_code_id": "104001",
|
||||
"compare_draw_code_id": "104002",
|
||||
"coupon_draw_code_id": "104002",
|
||||
"reward_enabled": true,
|
||||
"compare_ad_enabled": true,
|
||||
"coupon_ad_enabled": true,
|
||||
"withdrawal_ad_enabled": false
|
||||
}
|
||||
```
|
||||
|
||||
## 说明
|
||||
- 空库回退默认值(= 客户端内置值,维持现状)
|
||||
- 不含验签密钥(`m-key`),安全边界
|
||||
- `coupon_draw_code_id` 与 `compare_draw_code_id` 通常同值,客户端按场景调不同端点区分
|
||||
@@ -0,0 +1,39 @@
|
||||
# GET /api/v1/platform/app-version — 最新 App 版本
|
||||
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端启动 / 手动检查更新时拉取。用 `latest_version_code` 与本机 `versionCode` 比;未配置(返回默认 0)时客户端视为已是最新。
|
||||
|
||||
## 入参
|
||||
|
||||
无。
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`AppVersionOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `latest_version_code` | int | 最新版 versionCode;0 = 未配置(无更新) |
|
||||
| `latest_version_name` | string | 展示用版本号(如 `0.1.4`) |
|
||||
| `apk_url` | string | 下载链接(发车产出的永久版本化链接) |
|
||||
| `update_note` | string | 更新说明,弹窗展示(如「修复了部分机型闪退问题」) |
|
||||
| `min_supported_version_code` | int | 本机低于此版本 = 强制更新;0 = 不强更(全可选) |
|
||||
| `apk_size_bytes` | int | 包大小(字节),展示「约 x MB」 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"latest_version_code": 42,
|
||||
"latest_version_name": "0.1.5",
|
||||
"apk_url": "https://cdn.shaguabijia.com/releases/app-v0.1.5.apk",
|
||||
"update_note": "1. 修复了部分机型闪退问题\n2. 优化了比价速度\n3. 新增省钱大作战功能",
|
||||
"min_supported_version_code": 35,
|
||||
"apk_size_bytes": 18350080
|
||||
}
|
||||
```
|
||||
|
||||
## 说明
|
||||
- 不鉴权(版本信息非敏感,检查更新可能在登录前)
|
||||
- `latest_version_code = 0` → 无更新,客户端无需提示
|
||||
- `min_supported_version_code > 本机 versionCode` → 强制更新弹窗(不可跳过)
|
||||
@@ -0,0 +1,28 @@
|
||||
# GET /api/v1/platform/flags — 客户端 Feature Flags
|
||||
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:无 | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端拉取运营开关并缓存(app 启动 / 每场比价开始时刷新)。不鉴权:开关非敏感,且比价无障碍服务取值时未必有登录态。值来自 `app_config`(admin 可改),空库回退默认。
|
||||
|
||||
## 入参
|
||||
|
||||
无。
|
||||
|
||||
## 出参
|
||||
|
||||
响应 `200`:`AppFlagsOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `comparing_ad_enabled` | bool | 比价/领券期是否展示信息流广告(远程 kill-switch) |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{
|
||||
"comparing_ad_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
## 说明
|
||||
- 客户端拉取后本地缓存,避免每次请求
|
||||
- 空库回退默认值(false)
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/platform/stats — 首页三统计(全平台门面数字)
|
||||
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:**无**(登录前首页也要展示) | [← 返回 API 索引](./README.md)
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:**无**(登录前首页也要展示) | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端首页顶部「帮助用户 / 完成比价 / 累计节省」三个平台级数字。每个指标的展示模式由运营后台配(见 [admin-dashboard-display](./admin-dashboard-display.md)),本接口只返回算好的结果值。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/platform/savings-feed — 首页轮播 feed(真实+种子混播)
|
||||
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:**无** | [← 返回 API 索引](./README.md)
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:**无** | [← 返回 API 索引](../README.md)
|
||||
|
||||
客户端首页顶部「某用户 比价后节省 xx 元」滚动条数据源。全平台真实比价记录优先;不足时用运营配的种子([ops_marquee_seed](../database/ops_marquee_seed.md))补齐到 `limit` 条「混播」,保证轮播不空。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/savings/battle — 省钱战绩
|
||||
|
||||
> 所属:Savings 组(前缀 `/api/v1/savings`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Savings 组(前缀 `/api/v1/savings`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/savings/records — 省钱明细(游标分页)
|
||||
|
||||
> 所属:Savings 组(前缀 `/api/v1/savings`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Savings 组(前缀 `/api/v1/savings`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参(query)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/savings/summary — 累计帮你省了
|
||||
|
||||
> 所属:Savings 组(前缀 `/api/v1/savings`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Savings 组(前缀 `/api/v1/savings`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/signin — 执行今日签到
|
||||
|
||||
> 所属:Signin 组(前缀 `/api/v1/signin`,本接口 POST 到前缀本身) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Signin 组(前缀 `/api/v1/signin`,本接口 POST 到前缀本身) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/signin/status — 今日签到状态 + 14 天档位
|
||||
|
||||
> 所属:Signin 组(前缀 `/api/v1/signin`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Signin 组(前缀 `/api/v1/signin`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/tasks/{task_key}/claim — 领取任务奖励
|
||||
|
||||
> 所属:Tasks 组(前缀 `/api/v1/tasks`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Tasks 组(前缀 `/api/v1/tasks`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参(path)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/tasks — 任务及领取状态
|
||||
|
||||
> 所属:Tasks 组(前缀 `/api/v1/tasks`,本接口 GET 前缀本身) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Tasks 组(前缀 `/api/v1/tasks`,本接口 GET 前缀本身) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/user/avatar — 上传头像
|
||||
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:Bearer access_token | [← 返回 API 索引](./README.md)
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:Bearer access_token | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
**multipart/form-data**:
|
||||
@@ -1,6 +1,6 @@
|
||||
# DELETE /api/v1/user — 注销账号
|
||||
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:Bearer access_token | [← 返回 API 索引](./README.md)
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:Bearer access_token | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(身份取自 Header token)
|
||||
@@ -0,0 +1,84 @@
|
||||
# 新手引导状态(onboarding 族)
|
||||
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:全部 Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
按(账号, 设备)维度跟踪新手引导完成状态,跨卸载重装持久。运营可在 admin 删记录触发重走。
|
||||
|
||||
---
|
||||
|
||||
## GET /onboarding/status — 查新手引导是否已完成
|
||||
|
||||
已登录用户启动时查:该(账号, 设备)走过引导没。`false` → 客户端应重走。
|
||||
|
||||
### 入参(query)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ❌(≤64 位) | 硬件级 ANDROID_ID;空 = 按未完成处理(不误跳过) |
|
||||
|
||||
Mock 请求:
|
||||
```
|
||||
GET /api/v1/user/onboarding/status?device_id=android_abc123def456
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
响应 `200`:`OnboardingStatusResponse`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `completed` | bool | 该(设备+账号)是否已走过新手引导 |
|
||||
|
||||
Mock 出参:
|
||||
```json
|
||||
{"completed": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /onboarding/complete — 标记新手引导完成
|
||||
|
||||
走完新手引导时调一次。按(当前账号, device_id)落一条完成标记,幂等(重复调用不报错)。
|
||||
|
||||
### 入参
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 硬件级 ANDROID_ID(与登录请求一致) |
|
||||
|
||||
Mock 入参:
|
||||
```json
|
||||
{
|
||||
"device_id": "android_abc123def456"
|
||||
}
|
||||
```
|
||||
|
||||
### 出参
|
||||
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/v1/user/onboarding/reset — 重置新手引导(#114)
|
||||
|
||||
删除(当前账号, `device_id`)的完成标记 → 该设备下次登录/进 App 重走引导。给客户端「设置 → 重看新手引导」入口用(此前只能运营在 admin 删记录)。
|
||||
|
||||
### 入参
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `device_id` | string | ✅ | 硬件级 ANDROID_ID(与 complete 一致) |
|
||||
|
||||
### 出参
|
||||
```json
|
||||
{"ok": true}
|
||||
```
|
||||
幂等:无标记时也返回 ok。
|
||||
|
||||
---
|
||||
|
||||
## 说明
|
||||
- 替代原 `force_onboarding`(按用户)→ 改设备维度后,运营删记录(或用户自己 reset)即触发重走
|
||||
- 幂等:重复标记 / 重复重置都不报错
|
||||
- `device_id` 为空时 `status` 一律返回未完成
|
||||
@@ -1,6 +1,6 @@
|
||||
# PATCH /api/v1/user/profile — 修改昵称
|
||||
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:Bearer access_token | [← 返回 API 索引](./README.md)
|
||||
> 所属:User 组(前缀 `/api/v1/user`) | 鉴权:Bearer access_token | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
请求体 JSON:
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/wallet/account — 金币 + 现金余额(我的资产)
|
||||
|
||||
> 所属:Wallet 组(前缀 `/api/v1/wallet`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Wallet 组(前缀 `/api/v1/wallet`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参
|
||||
无(用户由 token 确定)。
|
||||
@@ -11,8 +11,9 @@
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `coin_balance` | int | 当前金币余额 |
|
||||
| `cash_balance_cents` | int | 当前现金余额(分) |
|
||||
| `cash_balance_cents` | int | 当前现金余额(分,金币兑换账) |
|
||||
| `invite_cash_balance_cents` | int | 邀请奖励金余额(分,与现金**物理隔离**的第二本账,#82;好友比价并下单发奖入账,提现走 `source=invite_cash`) |
|
||||
| `total_coin_earned` | int | 累计赚取金币 |
|
||||
|
||||
## 说明
|
||||
账户不存在时自动创建(零余额)。福利页「我的资产」卡的数据源。
|
||||
账户不存在时自动创建(零余额)。福利页「我的资产」卡的数据源;邀请页「奖励金」余额也读它。
|
||||
@@ -1,6 +1,6 @@
|
||||
# POST /api/v1/wallet/bind-wechat — 微信授权 code 换 openid 并绑定
|
||||
|
||||
> 所属:Wallet 组(前缀 `/api/v1/wallet`) | 鉴权:Bearer | 限流:同 IP ≤10 次/分 | [← 返回 API 索引](./README.md)
|
||||
> 所属:Wallet 组(前缀 `/api/v1/wallet`) | 鉴权:Bearer | 限流:同 IP ≤10 次/分 | [← 返回 API 索引](../README.md)
|
||||
>
|
||||
> 集成实现:见 [integrations/wxpay](../integrations/wxpay.md)(code 换 openid / userinfo)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GET /api/v1/wallet/cash-transactions — 现金流水(游标分页)
|
||||
|
||||
> 所属:Wallet 组(前缀 `/api/v1/wallet`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||||
> 所属:Wallet 组(前缀 `/api/v1/wallet`) | 鉴权:Bearer | [← 返回 API 索引](../README.md)
|
||||
|
||||
## 入参(query)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user