Co-authored-by: OuYingJun1024 <1034284404@qq.com> Reviewed-on: #11 Co-authored-by: ouzhou <ouzhou@wonderable.ai> Co-committed-by: ouzhou <ouzhou@wonderable.ai>
傻瓜比价 App 后端 — API 接口文档(索引)
Base URL:生产
https://app-api.shaguabijia.com;本地联调http://<开发机>:8770协议:HTTP / JSON,请求与响应体均application/json,字段统一 snake_case 鉴权:需鉴权的接口在请求头带Authorization: Bearer <access_token>最后更新:2026-05-31(+ 比价战绩里程碑 12d/12e) 架构: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 |
无 | 详情 |
| 9 | POST /api/v1/meituan/coupons |
无 | 详情 |
| 10 | POST /api/v1/meituan/feed |
无 | 详情 |
| 11 | POST /api/v1/meituan/referral-link |
无 | 详情 |
比价透传(前缀 /api/v1,外卖 MVP;与 coupon/step 同为透传 pricebot-backend) |
|||
| 12 | POST /api/v1/intent/recognize |
无 | 详情 |
| 13 | POST /api/v1/price/step |
无 | 详情 |
比价记录(前缀 /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 | 详情 |
比价战绩里程碑(前缀 /api/v1/compare;福利页「记录比价战绩」,按成功比价数解锁逐档发金币) |
|||
| 12d | GET /api/v1/compare/milestones |
Bearer | 详情 |
| 12e | POST /api/v1/compare/milestones/{milestone}/claim |
Bearer | 详情 |
钱包 / 我的资产(前缀 /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 | 详情 |
| 23 | GET /api/v1/wallet/withdraw/status |
Bearer | 详情 |
| 24 | GET /api/v1/wallet/withdraw-orders |
Bearer | 详情 |
签到(前缀 /api/v1/signin) |
|||
| 25 | GET /api/v1/signin/status |
Bearer | 详情 |
| 26 | POST /api/v1/signin |
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 | 详情 |
用户资料(前缀 /api/v1/user) |
|||
| 35 | PATCH /api/v1/user/profile |
Bearer | 详情 |
| 36 | POST /api/v1/user/avatar |
Bearer | 详情 |
| 37 | DELETE /api/v1/user |
Bearer | 详情 |
帮助与反馈(前缀 /api/v1/feedback) |
|||
| 38 | POST /api/v1/feedback |
Bearer | 详情 |
静态资源(StaticFiles 挂载,见下方 /media 静态服务) |
|||
| - | GET /media/avatars/<file> |
无 | 用户头像;返回二进制图片 |
| - | GET /media/feedback/<file> |
无 | 反馈截图;返回二进制图片 |
⚠️ 美团三个接口当前无鉴权,且
referral-link的sid允许客户端传值覆盖默认渠道——见各接口"备注"。coupon/step及外卖比价的intent/recognize/price/step都透传到 pricebot-backend,MVP 阶段均不鉴权(device_id 透传,待补 JWT——见各接口详情)。 福利相关业务接口(wallet/signin/tasks/savings、ad/reward-status)均需 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 | 头图 |
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必须为高熵随机串(生产严禁用默认值)。