Reviewed-on: #128
27 KiB
傻瓜比价 App 后端 — API 接口文档(索引)
Base URL:生产
https://app-api.shaguabijia.com;本地联调http://<开发机>:8770协议:HTTP / JSON,请求与响应体均application/json,字段统一 snake_case 鉴权:需鉴权的接口在请求头带Authorization: Bearer <access_token>最后更新: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) 架构:app/api/v1/只放很轻的接口层;穿山甲/微信支付/极光/短信/美团等 SDK 集成的重逻辑在app/integrations/,实现细节见 docs/integrations/。
接口总览
| # | 方法 + 路径 | 鉴权 | 详情 |
|---|---|---|---|
| 1 | GET /health |
无 | 详情 |
| 2 | POST /api/v1/auth/jverify-login |
无 | 详情 |
| 3 | POST /api/v1/auth/sms/send |
无 | 详情 |
| 4 | POST /api/v1/auth/sms/login |
无 | 详情 |
| 5 | POST /api/v1/auth/refresh |
无 | 详情 |
| 6 | GET /api/v1/auth/me |
Bearer | 详情 |
| 7 | POST /api/v1/auth/logout |
Bearer | 详情 |
| 8 | POST /api/v1/coupon/step |
无 | 详情(透传 pricebot + best-effort 写 coupon_* 三表) |
| 8a | POST /api/v1/coupon/prompt/shown |
无 | 详情(引导窗弹出即上报) |
| 8b | POST /api/v1/coupon/prompt/dismiss |
无 | 详情(用户拒绝/关闭引导窗) |
| 8c | GET /api/v1/coupon/prompt/should-show |
无 | 详情(切到外卖 App 时是否还应弹引导窗) |
| 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 | 详情(累计领券数,「我的」页战绩卡) |
| 8h | POST /api/v1/coupon/session |
无 | 详情(领券流水上报,admin 看板数据源) |
| 9 | POST /api/v1/meituan/coupons |
无 | 详情 |
| 10 | POST /api/v1/meituan/feed |
无 | 详情(rec tab 离线库 + 按城市过滤 #116) |
| 11 | POST /api/v1/meituan/referral-link |
无 | 详情 |
| 11a | POST /api/v1/meituan/top-sales |
无 | 详情(同城销量榜:离线库按销量降序 + 跨源去重 + 城市过滤 #116,不实时打美团) |
比价透传(前缀 /api/v1,透传 pricebot-backend;软鉴权 OptionalUser + 首帧签发 trace_id + harvest 落 comparison_record,2026-07 起不再是纯透传) |
|||
| 12 | POST /api/v1/intent/recognize |
软 | 详情(Phase 1 意图识别,单次,多数源;mint 帧建 running 行) |
| 12a | POST /api/v1/intent/precoupon/step |
软 | 详情(Phase 0 意图识别前先用券,仅美团源) |
| 12b | POST /api/v1/intent/step |
软 | 详情(Phase 1 多帧意图识别,仅淘宝源,循环到 done) |
| 13 | POST /api/v1/price/step |
软 | 详情(Phase 2 步进;done 帧 harvest 写终态) |
| 13a | POST /api/v1/trace/finalize |
软 | 详情(比价 trace 收尾上云 + 夭折落库,终止/未识别拿 trace_url) |
| 13b | POST /api/v1/trace/epilogue |
软 | 详情(结果页尾声帧:App 结果页截图入 trace,纯透传不落库,#112) |
比价记录(前缀 /api/v1/compare;按用户落库,鉴权,区别于上面不鉴权的透传) |
|||
| 12a | POST /api/v1/compare/record |
Bearer | 详情 |
| 12b | GET /api/v1/compare/records |
Bearer | 详情 |
| 12c | GET /api/v1/compare/records/{id} |
Bearer | 详情 |
| 12e | GET /api/v1/compare/stats |
Bearer | 详情(「我的」页省钱战绩卡:完成比价数 + 累计发现可省) |
比价战绩里程碑(前缀 /api/v1/compare;福利页「记录比价战绩」,按成功比价数解锁逐档发金币) |
|||
| 12d | GET /api/v1/compare/milestones |
Bearer | 详情 |
| 12e | POST /api/v1/compare/milestones/{milestone}/claim |
Bearer | 详情 |
设备 / 无障碍存活监控(前缀 /api/v1/device;心跳超时检出 + 掉线召回,#65) |
|||
| D1 | POST /api/v1/device/register |
Bearer | 详情(注册设备/更新极光 push token) |
| D2 | POST /api/v1/device/heartbeat |
Bearer | 详情(无障碍服务存活心跳,心跳也能自注册) |
| D3 | GET /api/v1/device/liveness |
Bearer | 详情(进 App 查本机是否被判掉线过) |
| D4 | POST /api/v1/device/liveness/ack |
Bearer | 详情(确认已弹引导,清掉线告警) |
上报更低价(前缀 /api/v1/report;众包纠偏,人工审核发奖) |
|||
| R1 | POST /api/v1/report |
Bearer | 详情(提交上报更低价,multipart:比价记录ID+平台+价格+截图1-4张) |
| R2 | GET /api/v1/report/records |
Bearer | 详情(上报记录列表,?status=pending/approved/rejected 可选筛选) |
好友邀请(前缀 /api/v1/invite;绑定注册即生效但不发奖,#113 起好友「比价并下单」才给邀请人发邀请奖励金,经 POST /order/report 触发) |
|||
| 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 指纹反查三种归因) |
钱包 / 我的资产(前缀 /api/v1/wallet) |
|||
| 14 | GET /api/v1/wallet/account |
Bearer | 详情 |
| 15 | GET /api/v1/wallet/coin-transactions |
Bearer | 详情 |
| 16 | GET /api/v1/wallet/cash-transactions |
Bearer | 详情 |
| 17 | GET /api/v1/wallet/exchange-info |
无 | 详情 |
| 18 | POST /api/v1/wallet/exchange |
Bearer | 详情 |
| 19 | POST /api/v1/wallet/bind-wechat |
Bearer | 详情 |
| 20 | POST /api/v1/wallet/unbind-wechat |
Bearer | 详情 |
| 21 | GET /api/v1/wallet/withdraw-info |
Bearer | 详情 |
| 22 | POST /api/v1/wallet/withdraw |
Bearer | 详情(source 分账:coin_cash / invite_cash,#121) |
| 23 | GET /api/v1/wallet/withdraw/status |
Bearer | 详情 |
| 24 | GET /api/v1/wallet/withdraw-orders |
Bearer | 详情(可按 source 过滤) |
| 24a | POST /api/v1/wallet/transfer-auth |
Bearer | 详情(开启免确认到账,申请授权,返回拉起微信授权页的 package) |
| 24b | GET /api/v1/wallet/transfer-auth/status |
Bearer | 详情(查免确认授权状态,从微信授权页返回后轮询) |
| 24c | POST /api/v1/wallet/transfer-auth/close |
Bearer | 详情(关闭免确认到账,解除授权) |
签到(前缀 /api/v1/signin) |
|||
| 25 | GET /api/v1/signin/status |
Bearer | 详情 |
| 26 | POST /api/v1/signin |
Bearer | 详情 |
| 26a | POST /api/v1/signin/boost |
Bearer | 详情 |
任务(前缀 /api/v1/tasks) |
|||
| 27 | GET /api/v1/tasks |
Bearer | 详情 |
| 28 | POST /api/v1/tasks/{task_key}/claim |
Bearer | 详情 |
省钱(前缀 /api/v1/savings) |
|||
| 29 | GET /api/v1/savings/summary |
Bearer | 详情 |
| 30 | GET /api/v1/savings/battle |
Bearer | 详情 |
| 31 | GET /api/v1/savings/records |
Bearer | 详情 |
看广告发奖(前缀 /api/v1/ad) |
|||
| 32 | GET /api/v1/ad/pangle-callback |
验签 | 详情 |
| 33 | GET /api/v1/ad/reward-status |
Bearer | 详情 |
| 34 | POST /api/v1/ad/test-grant |
Bearer | 详情 |
| 35 | POST /api/v1/ad/ecpm-report |
Bearer | 详情 |
| 35a | POST /api/v1/ad/feed-reward |
Bearer | 详情 |
| 35b | POST /api/v1/ad/reward-noshow |
Bearer | 详情(激励视频提前关闭/未发奖留痕,只记原因不发币) |
| 35c | GET /api/v1/ad/feed-reward/units |
Bearer | 详情(信息流广告今日已发份数/上限,配合 feed-reward 看进度) |
| 35d | POST /api/v1/ad/watch-report |
Bearer | 详情(上报激励视频观看时长,旧客户端兼容) |
用户资料(前缀 /api/v1/user) |
|||
| 35 | PATCH /api/v1/user/profile |
Bearer | 详情 |
| 36 | POST /api/v1/user/avatar |
Bearer | 详情 |
| 36a | POST /api/v1/user/onboarding/complete |
Bearer | 详情(标记新手引导完成,按 账号+device_id 幂等,跨卸载重装持久) |
| 36b | GET /api/v1/user/onboarding/status |
Bearer | 详情(查该 账号+设备 是否走过引导,运营在 admin 删记录即触发重走) |
| 36c | POST /api/v1/user/onboarding/reset |
Bearer | 详情(重置本设备引导标记,下次登录重走,#114) |
| 37 | DELETE /api/v1/user |
Bearer | 详情 |
帮助与反馈(前缀 /api/v1/feedback) |
|||
| 38 | POST /api/v1/feedback |
Bearer | 详情 |
| 38a | GET /api/v1/feedback/config |
Bearer | 详情(反馈页「加群二维码」卡配置:开关+二维码图+三行文案) |
| 38b | GET /api/v1/feedback/records |
Bearer | 详情(我的反馈历史,pending/adopted/rejected) |
| 埋点 & 订单上报(前缀分散;全部 Bearer 除 analytics/events 不强制登录) | |||
| E1 | POST /api/v1/analytics/events |
无 | 详情(批量上报埋点事件,不强制登录,每批最多200条) |
| E2 | POST /api/v1/order/report |
Bearer | 详情(上报归因订单,比价后5分钟内点链接+支付金额与比价价相差≤1元) |
首页门面数据 / 客户端配置(前缀 /api/v1/platform;全平台展示数字 + 运营开关,全部不鉴权,登录前可读) |
|||
| 39 | GET /api/v1/platform/stats |
无 | 详情 |
| 40 | GET /api/v1/platform/savings-feed |
无 | 详情 |
| 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 比) |
微信支付回调(前缀 /api/v1/wxpay) |
|||
| W1 | POST /api/v1/wxpay/transfer-auth-notify |
无 | 免确认收款授权结果通知(一期 stub:仅应答 200 不验签不改账,授权状态靠主动查询兜底)(无单独文档) |
| CPS 群发短链落地(无前缀,挂域名根;公网不鉴权) | |||
| C1 | GET /c/{code} |
无 | 详情(短链落地:微信授权拿 openid + 记点击 + 302 跳/淘宝 H5 落地页) |
| C2 | POST /c/{code}/copy |
无 | 详情(淘宝落地页点「复制口令」记 copy) |
| C3 | GET /wx/oauth/cb |
无 | 详情(微信网页授权回调;upsert cps_wx_user + 种 cookie,include_in_schema=False) |
| C4 | GET /MP_verify_*.txt |
无 | 详情(微信「网页授权域名」归属校验文件,include_in_schema=False) |
内部回写端点(前缀 /internal;pricebot/发布流程→app-server,X-Internal-Secret 头,非客户端接口) |
|||
| N1 | POST /internal/price-observation |
内部密钥 | 详情(比价价格事实批量落 price_observation) |
| N2 | GET /internal/store-mapping/lookup |
内部密钥 | 详情(按源平台店名反查目标平台已沉淀店铺 id/deeplink) |
| N3 | POST /internal/store-mapping |
内部密钥 | 详情(跨平台店铺身份映射落 store_mapping) |
| N4 | POST /internal/store-mapping/invalidate |
内部密钥 | 详情(标记某平台 shopId 缓存 deeplink 失效) |
| N5 | POST /internal/launch-confirm-sample |
内部密钥 | 详情(启动确认窗兜底样本落 launch_confirm_sample) |
| N6 | POST /internal/app-version |
内部密钥 | 详情(发布流程写最新 App 版本,落 app_config) |
| N7 | GET /internal/launch-confirm-samples |
内部密钥 | 详情(样本列表,供 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=需对应角色;#117 起可见页由 admin_role 数据驱动,super_admin 恒通过) |
|||
| A1 | POST /admin/api/auth/login · GET /auth/me |
无 / admin | 详情 / me(me 返回有效可见页 pages) |
| A2 | GET /admin/api/stats/overview |
admin | 详情(大盘核心指标;#103 按 trace 聚合 + 京东收益 #90 + feed_scene 口径 #125) |
| A3 | GET /admin/api/event-logs |
admin | 详情(埋点日志检索,#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 目标账户) |
列表 / 详情 / 状态+debug-trace / 金币 / 现金 | ||
| A4 | GET /admin/api/wallet/coin-transactions / cash-transactions |
admin | 金币 / 现金 |
A·提现审核台:GET /withdraws(列表)、/summary、/health-check(finance)、/ledger-check(#121 分账对账)、/{out_bill_no}(详情)、POST /reconcile、单笔 refresh/approve/reject、批量 bulk/refresh/bulk/approve/bulk/reject |
列表 / 审核族 / 对账 / 查单 | ||
A·反馈:GET /feedbacks、/summary、POST /{id}/approve(采纳发币 #94)、/{id}/reject、/{id}/handle |
列表 / 审核族 | ||
| 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) | ||
| 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 | 详情(领券数据看板,#99) |
| A8 | GET /admin/api/device-liveness(+/stats) |
admin | 详情(设备存活监控,#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} |
详情 | ||
| A10 | GET / PATCH /admin/api/dashboard-display |
admin / operator | 详情(首页三统计配置) |
| A11 | GET /admin/api/ad-coin-audit |
admin | 详情(看广告金币公式复算对账,只读) |
| A12 | GET /admin/api/ad-revenue-report |
admin | 详情(广告收益报表:分页/场景/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:奖励常量/提现地板价等;#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 自定义角色) |
列表 / 建 / 改+删 / 角色 | ||
| A15 | GET /admin/api/audit-logs |
admin | 详情 |
A·CPS 运营台:群/活动 CRUD、POST /referral-links、POST /orders/reconcile(美团+京东 #90)、GET /orders、/stats、群 timeseries/daily/wx-users/day-users(#79) |
详情 | ||
| - | GET /admin/api/health |
无 | admin 健康检查(无单独文档) |
⚠️ 美团三个接口当前无鉴权,且
referral-link的sid允许客户端传值覆盖默认渠道——见各接口"备注"。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)。
通用约定
- 时间格式:ISO 8601 UTC(如
2026-05-27T12:34:56Z) - 错误响应:FastAPI 标准结构
{"detail": "<错误信息>"},配合语义化 HTTP 状态码:400业务参数错(如验证码不对)401未认证 / token 无效或过期 / 用户被禁(响应头带WWW-Authenticate: Bearer)403账号被禁用422请求体字段校验失败(FastAPI 自动校验,如手机号格式)429触发限流(短信发送过频)502上游调用失败(极光验证/解密失败、美团接口失败)
- 接口文档(交互式):
APP_ENV非 prod 时开放GET /docs(Swagger UI)、GET /redoc;生产环境关闭。
游标分页约定
钱包流水 / 提现单 / 省钱明细等列表接口统一用游标分页:
- 请求 query:
limit(每页条数,1–100,默认 20)、cursor(上一页返回的next_cursor,首页不传)。 - 响应:
{ "items": [...], "next_cursor": <int|null> }。next_cursor为末条记录的 id;为null表示已到底,无更多数据。 items按id倒序(最新在前)。
复用数据结构
TokenPair
| 字段 | 类型 | 说明 |
|---|---|---|
access_token |
string | 访问令牌,之后每个鉴权请求带 Authorization: Bearer <它> |
refresh_token |
string | 刷新令牌 |
token_type |
string | 固定 "Bearer" |
expires_in |
int | access 剩余秒数(默认 7200 = 2h) |
refresh_expires_in |
int | refresh 剩余秒数(默认 2592000 = 30d) |
TokenWithUser
继承 TokenPair 全部字段,额外多一个 user(UserOut)。登录类接口成功时返回此结构。
UserOut
| 字段 | 类型 | 说明 |
|---|---|---|
id |
int | 用户主键 |
phone |
string | 手机号(注销账号后变 deleted_<id> 占位释放唯一约束) |
nickname |
string | null | 昵称,经 PATCH /api/v1/user/profile 修改 |
avatar_url |
string | null | 头像相对 URL(/media/avatars/...),经 POST /api/v1/user/avatar 上传 |
register_channel |
string | 注册渠道:jverify / sms |
status |
string | active / disabled / deleted |
created_at |
datetime | 注册时间 |
last_login_at |
datetime | 最近登录时间 |
CouponCard(券卡片,coupons 与 feed 的 items 元素)
| 字段 | 类型 | 说明 |
|---|---|---|
product_view_sign |
string | 换链主键(传给 referral-link) |
platform |
int | 1=外卖/到家, 2=到店 |
biz_line |
int | null | 到店子类:1到餐 2到综 3酒店 4门票 |
name |
string | 商品名 |
head_image_url |
string | 头图;后端已统一拼缩放参数 @375w_375h_1e_1c.webp(美团 CDN 服务端缩到 124dp + 转 WebP,实测省 76–99%),客户端直接用 |
brand_name |
string | null | 品牌名 |
brand_logo_url |
string | null | 品牌 logo |
sell_price |
string | 现价 |
original_price |
string | 原价 |
discount_amount |
string | 优惠额 = 原价 − 现价 |
commission_rate |
string | 佣金比例,如 "1.4%" |
commission_amount |
string | null | 预估佣金(元) |
sale_volume |
string | null | 销量 |
poi_name |
string | null | 最近门店名 |
distance_text |
string | null | 格式化距离,如 "600m" / "1.5km" |
distance_meters |
float | null | 原始距离(米) |
available_poi_num |
int | null | 可用门店数 |
coupon_num |
int | null | 券张数 |
valid_days |
int | null | 券有效天数 |
price_label |
string | null | 如 "15天低价" |
rank_label |
string | null | 如 "2小时北京外卖销量榜第1名" |
rating_label |
string | null | 如 "4.6分" |
/media 静态服务
用户上传文件(头像/反馈截图)落盘到 settings.MEDIA_ROOT(默认 ./data/media/),由 FastAPI 的 StaticFiles 挂在 settings.MEDIA_URL_PREFIX(默认 /media)对外暴露:
GET /media/avatars/<file>— 用户头像(JPEG/PNG/WebP)GET /media/feedback/<file>— 反馈截图(同上)
生产建议:由 nginx 直接 serve MEDIA_ROOT 目录,绕过应用进程减少压力。
URL 格式:服务端返回相对路径(如 /media/avatars/u1_a4f2b3c8e9d2e0a1.jpg),客户端按自己的 BASE_URL 拼绝对地址——dev 下可能是 10.0.2.2/LAN IP/127.0.0.1,服务端不知道客户端怎么访问到自己。
文件名服务端随机生成 u<user_id>_<16 位 hex>.<ext>,杜绝路径穿越与覆盖。
附:鉴权与刷新机制
- 签发:登录成功后签发 access(HS256,2h) + refresh(30d),payload 含
sub(user_id)、typ(access/refresh)、iat、exp。 - 携带:客户端对需鉴权接口自动加
Authorization: Bearer <access>(登录类接口跳过)。 - 校验(
/me、/logout):验签 → 验过期 → 验typ=access→ 查库确认用户存在且status=active,任一不过 → 401。 - 续期:access 过期触发 401 → 客户端用 refresh 调
/refresh换新 token 对并重放原请求;refresh 也失效 → 清本地、跳登录。 - 无状态:token 不落库,服务端无法主动吊销(logout 为占位),靠短 access 有效期限制泄露风险。JWT 密钥
JWT_SECRET_KEY必须为高熵随机串(生产严禁用默认值)。