傻瓜比价 App 后端 — API 接口文档
Base URL:生产 https://app-api.shaguabijia.com;本地联调 http://<开发机>:8770
协议:HTTP / JSON,请求与响应体均 application/json,字段统一 snake_case
鉴权:需鉴权的接口在请求头带 Authorization: Bearer <access_token>
最后更新:2026-05-27
通用约定
- 时间格式: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;生产环境关闭。
接口总览
| # |
方法 + 路径 |
鉴权 |
说明 |
| 1 |
GET /health |
无 |
健康检查 |
| 2 |
POST /api/v1/auth/jverify-login |
无 |
极光一键登录 |
| 3 |
POST /api/v1/auth/sms/send |
无 |
发送短信验证码(mock) |
| 4 |
POST /api/v1/auth/sms/login |
无 |
手机号 + 验证码登录 |
| 5 |
POST /api/v1/auth/refresh |
无 |
刷新 token |
| 6 |
GET /api/v1/auth/me |
Bearer |
获取当前登录用户 |
| 7 |
POST /api/v1/auth/logout |
Bearer |
登出(服务端占位) |
| 8 |
POST /api/v1/meituan/coupons |
无 |
券列表 / 搜索 |
| 9 |
POST /api/v1/meituan/feed |
无 |
首页混合推荐流 |
| 10 |
POST /api/v1/meituan/referral-link |
无 |
换取推广链接(点"抢"时调) |
⚠️ 美团三个接口当前无鉴权,且 referral-link 的 sid 允许客户端传值覆盖默认渠道——见各接口"备注"。
复用数据结构
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 |
手机号 |
nickname |
string | null |
昵称(当前无接口可改,恒为 null) |
avatar_url |
string | null |
头像(同上) |
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分" |
1. Meta
GET /health
- 鉴权:无
- 入参:无
- 响应
200:{ "status": "ok" }
2. Auth 组(前缀 /api/v1/auth)
2.1 POST /jverify-login — 极光一键登录
| 字段 |
类型 |
必填 |
说明 |
login_token |
string |
✅(非空) |
客户端极光 loginAuth 拿到的 loginToken |
operator |
string |
❌(默认 "") |
运营商标识 CM/CU/CT,仅用于后端日志 |
- 响应
200:TokenWithUser(user.register_channel 为 "jverify")
- 错误:
502 极光验证或 RSA 解密失败;403 账号被禁用
- 说明:后端拿
login_token 调极光 loginTokenVerify 验真 → 取回 RSA 加密的手机号 → 用私钥解密 → 注册即登录(手机号不存在则建号)→ 签发 JWT。
2.2 POST /sms/send — 发送短信验证码
| 字段 |
类型 |
必填 |
说明 |
phone |
string |
✅ |
手机号,正则 ^1\d{10}$ |
| 字段 |
类型 |
说明 |
sent |
bool |
是否已发送 |
mock |
bool |
是否 mock 模式(true 时不真发,任意 6 位通过) |
cooldown_sec |
int |
多少秒后才能再次发送 |
- 错误:
429 发送过频(默认 60s 冷却内重复发)
- 说明:mock 模式(
SMS_MOCK=true)下不真发短信,仅记录冷却时间。
2.3 POST /sms/login — 手机号 + 验证码登录
| 字段 |
类型 |
必填 |
说明 |
phone |
string |
✅ |
手机号 ^1\d{10}$ |
code |
string |
✅ |
验证码,长度 4–8 |
- 响应
200:TokenWithUser(user.register_channel 为 "sms")
- 错误:
400 验证码错误;403 账号被禁用
- 说明:mock 模式下任意 6 位数字均通过校验。注册即登录。
2.4 POST /refresh — 刷新 token
- 鉴权:无(凭 body 里的 refresh_token)
- 入参:
| 字段 |
类型 |
必填 |
说明 |
refresh_token |
string |
✅ |
有效的 refresh token |
- 响应
200:TokenPair(注意:不含 user 字段)
- 错误:
401 refresh token 无效/过期/类型不对,或用户不存在/被禁用
- 说明:服务端校验 refresh token(验签 + 验过期 + 验类型为 refresh)并查库确认用户仍 active,然后签发全新的 access+refresh 对。客户端在请求收到 401 时由 OkHttp
Authenticator 自动调用。
2.5 GET /me — 获取当前登录用户
- 鉴权:✅ Bearer access_token
- 入参:无(身份取自 Header token)
- 响应
200:UserOut
- 错误:
401 未带 token / token 无效或过期 / 用户被禁用
2.6 POST /logout — 登出
- 鉴权:✅ Bearer access_token
- 入参:无
- 响应
200:{ "ok": true }
- 说明:服务端无状态、不吊销 token(占位实现),真正失效靠客户端删除本地 token。后续若加 jti 黑名单可在此写入。
3. 美团 CPS 组(前缀 /api/v1/meituan,全部无鉴权)
3.1 POST /coupons — 券列表 / 搜索
| 字段 |
类型 |
必填 |
默认 |
说明 |
longitude |
float |
✅ |
— |
经度 |
latitude |
float |
✅ |
— |
纬度 |
platform |
int |
❌ |
1 |
1=外卖/到家, 2=到店 |
biz_line |
int |
❌ |
null |
到店子类:1到餐 2到综 3酒店 4门票 |
list_topic_id |
int |
❌ |
3 |
榜单:1精选 2今日必推 3爆款筛选 5限时筛选 |
keyword |
string |
❌ |
null |
搜索词(填了则忽略 list_topic_id,走搜索) |
sort_field |
int |
❌ |
null |
1价格 2销量 6离我最近(搜索时默认 6) |
search_id |
string |
❌ |
null |
翻页 token,首页不填 |
page |
int |
❌ |
1 |
≥1 |
page_size |
int |
❌ |
20 |
1–20 |
- 响应
200:{ items: CouponCard[], has_next: bool, search_id: string|null }
- 错误:
502 美团接口失败
- 备注:当前 Android 客户端未调用此接口(搜索功能尚未实现),仅后端实现完整。
3.2 POST /feed — 首页混合推荐流
| 字段 |
类型 |
必填 |
默认 |
说明 |
longitude |
float |
✅ |
— |
经度 |
latitude |
float |
✅ |
— |
纬度 |
page |
int |
❌ |
1 |
≥1 |
page_size |
int |
❌ |
20 |
1–20 |
- 响应
200:{ items: CouponCard[], has_next: bool, page: int }
- 备注:后端在
coupons 之上封装的"伪推荐"——每页并发拉一次外卖、一次到店(到餐)榜单,按 2 外卖 + 1 到店 交叉去重。榜单组合写死 3 页(第1页爆款、第2页今日必推、第3页外卖精选+到店限时),第 3 页起 has_next=false、第 4 页返空。
⚠️ 可观测性盲区:feed 内部对美团调用异常是静默吞掉返回空列表(不报 502、不打日志)。若 items 为空但无错误,优先用 coupons 接口逼出真实错误(它会以 502 暴露,如"MT_CPS_APP_KEY not configured")。
3.3 POST /referral-link — 换取推广链接
| 字段 |
类型 |
必填 |
默认 |
说明 |
product_view_sign |
string |
✅ |
— |
券的换链主键(来自 CouponCard) |
platform |
int |
❌ |
1 |
1=外卖/到家, 2=到店 |
biz_line |
int |
❌ |
null |
到店子类 |
sid |
string |
❌ |
服务端默认 sgbjia |
渠道追踪标识 |
link_type_list |
int[] |
❌ |
[1, 3] |
1=H5长链 2=H5短链 3=deeplink |
| 字段 |
类型 |
说明 |
link |
string |
默认推广链接(按 data > H5(1) > deeplink(3) > 任意 兜底) |
link_map |
object |
各类型链接 { "linkType": "url" },如 {"1": "<H5>", "3": "<deeplink>"} |
- 错误:
502 美团接口失败
- 备注:客户端实际优先用
link_map["3"](deeplink)拉起美团 App,失败降级 link_map["1"](H5)。
⚠️ 安全:sid 允许客户端传值覆盖服务端默认渠道,理论上他人可借本接口刷自己渠道的分佣;建议服务端锁定 sid、忽略客户端传值。
附:鉴权与刷新机制
- 签发:登录成功后签发 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 必须为高熵随机串(生产严禁用默认值)。