marco aa34ad7d0b feat(compare): 外卖比价 2 端点透传到 pricebot-backend (food MVP)
仿 coupon_step 在 app/api/v1/compare.py 加纯 body 透传 2 端点(MVP 不鉴权,只读
device_id/trace_id/step 打日志,不做 schema 校验)。client /api/v1/{intent/recognize,
price/step} → backend 去掉 /v1 转发到 PRICEBOT_BASE_URL,接通外卖比价
client→server→pricebot-backend 链路。

- compare.py: _passthrough helper + intent/recognize + price/step
- config.py: PRICEBOT_COMPARE_TIMEOUT_SEC=60(意图识别大上下文 LLM、price/step
  每帧 LLM,比领券 30s 长;对齐客户端 agent ApiClient 的 60s 读超时)
- main.py: 注册 compare_router
- tests/test_compare_proxy.py: 2 端点参数化测试(透传/5xx→502/不可达→502/坏 JSON→400)
- docs/api/{compare-intent-recognize,compare-price-step}.md + 更新 README 索引
- 待办与技术债.md P2 外卖 2 端点标 (2026-05-27);电商 2 个待接(compare.py
  加两行即可)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:29:20 +08:00

shaguabijia-app-server

傻瓜比价正式 App 后端 — FastAPI + SQLAlchemy + JWT。

占坑期已有的试验后台 shaguabijia-server 是无状态 mock,本项目是正式版, 引入账号体系、JWT 登录态、Alembic 迁移、SQLite 起步可平滑切 PostgreSQL。

详细技术说明见 docs/后端技术实现.md(登录链路、极光 RSA、部署 checklist)。


技术栈

维度 选型 说明
语言 Python 3.11+
Web FastAPI 0.115+
ASGI uvicorn[standard]
ORM SQLAlchemy 2.0 Mapped/DeclarativeBase 新风格
迁移 Alembic render_as_batch 兼容 SQLite
DB SQLite 后续切 PostgreSQL 只改 DATABASE_URL
Auth JWT (PyJWT) access(2h) + refresh(30d)
极光一键登录 httpx + cryptography RSA 解密,逻辑参考试验后台
配置 pydantic-settings .env 加载
测试 pytest + TestClient

目录结构

shaguabijia-app-server/
├── app/
│   ├── main.py                FastAPI 入口 + /health + CORS
│   ├── core/
│   │   ├── config.py          Settings (pydantic-settings)
│   │   ├── logging.py         统一日志配置
│   │   ├── security.py        JWT 签发 / 校验 / token 对
│   │   ├── jiguang.py         极光 REST 调用 + RSA 解密
│   │   └── sms.py             短信验证码 (mock 实现)
│   ├── db/
│   │   ├── base.py            DeclarativeBase
│   │   └── session.py         engine + SessionLocal + get_db
│   ├── models/
│   │   └── user.py            User 表
│   ├── schemas/
│   │   └── auth.py            登录/Token 相关 Pydantic
│   ├── crud/
│   │   └── user.py            upsert_user_for_login 等
│   └── api/
│       ├── deps.py            get_current_user (Bearer 校验)
│       └── v1/
│           └── auth.py        /api/v1/auth/* 路由
│
├── alembic/                   迁移脚本
│   ├── env.py
│   ├── script.py.mako
│   └── versions/              (空,第一次跑 alembic revision 生成)
├── alembic.ini
│
├── deploy/
│   ├── shaguabijia-app-server.service   systemd unit
│   └── nginx/
│       └── app-api.shaguabijia.com.conf
│
├── secrets/                   不入 git。放 jverify_rsa_private.pem
├── data/                      不入 git。SQLite 文件默认在这里
├── tests/                     冒烟 + auth 流程
│
├── pyproject.toml
├── .env.example
└── README.md

API 接口

方法 路径 说明 鉴权
GET /health 健康检查
POST /api/v1/auth/jverify-login 极光一键登录(loginToken → 注册即登录 → 签发 token 对)
POST /api/v1/auth/sms/send 发短信验证码(mock 阶段任意 6 位通过)
POST /api/v1/auth/sms/login 手机号+验证码登录
POST /api/v1/auth/refresh refresh_token 换新的 token 对
GET /api/v1/auth/me 获取当前登录用户 Bearer access_token
POST /api/v1/auth/logout 登出(占位,客户端清 token) Bearer access_token

登录类接口的响应统一格式:

{
  "access_token": "eyJxxx...",
  "refresh_token": "eyJxxx...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "refresh_expires_in": 2592000,
  "user": {
    "id": 1,
    "phone": "13800138000",
    "nickname": null,
    "avatar_url": null,
    "register_channel": "jverify",
    "status": "active",
    "created_at": "2026-05-23T04:30:00Z",
    "last_login_at": "2026-05-23T04:30:00Z"
  }
}

文档启动后看 http://localhost:8770/docs (Swagger UI)。


本地开发

1. 装依赖

cd shaguabijia-app-server
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

2. 准备配置

cp .env.example .env
# 编辑 .env,生产部署务必改 JWT_SECRET_KEY

如果要测极光一键登录,把 RSA 私钥放到 ./secrets/jverify_rsa_private.pem。 没放也不影响其他接口(sms//health 等),只是 jverify-login 会 502。

3. 建表(首次)

# 生成首版 migration(已有 User model,会自动生成 create_table)
alembic revision --autogenerate -m "init user table"
# 应用 migration
alembic upgrade head

后续改 model 后:

alembic revision --autogenerate -m "add nickname index"
alembic upgrade head

4. 跑起来

uvicorn app.main:app --reload --port 8770

冒烟:

curl http://localhost:8770/health
# {"status":"ok"}

# mock 走通登录闭环
curl -X POST http://localhost:8770/api/v1/auth/sms/send -H 'Content-Type: application/json' -d '{"phone":"13800138000"}'

curl -X POST http://localhost:8770/api/v1/auth/sms/login -H 'Content-Type: application/json' -d '{"phone":"13800138000","code":"123456"}'
# 拿到 access_token 后:
curl http://localhost:8770/api/v1/auth/me -H "Authorization: Bearer <access_token>"

5. 测试

pytest -q

部署(生产)

参考 deploy/,部署到 app-api.shaguabijia.com:

# 一次性
ssh server "apt-get install -y python3.11-venv python3-pip"

# 后续更新
rsync -avz --exclude='__pycache__' --exclude='.venv' --exclude='data' --exclude='secrets/jverify_rsa_private.pem' \
    ./ server:/opt/shaguabijia-app-server/

# 私钥单独同步(只首次 / 私钥更换时)
scp secrets/jverify_rsa_private.pem server:/opt/shaguabijia-app-server/secrets/

ssh server "
    cd /opt/shaguabijia-app-server &&
    .venv/bin/pip install --quiet -e . &&
    .venv/bin/alembic upgrade head &&
    systemctl restart shaguabijia-app-server
"

详见 deploy/shaguabijia-app-server.servicedeploy/nginx/app-api.shaguabijia.com.conf


与试验后台的差异(为什么不直接复用 shaguabijia-server)

维度 试验后台 (shaguabijia-server) 本项目 (shaguabijia-app-server)
数据库 stdlib sqlite3,无 ORM SQLAlchemy 2.0 + Alembic
业务 mock parse(无账号体系) 完整账号体系 + JWT
登录态 无,客户端发 phone 当 ID JWT access+refresh
配置 硬编码 pydantic-settings + .env
短信登录 有(mock 实现,留扩展点)
域名 api.shaguabijia.com (试验) app-api.shaguabijia.com (正式)

极光一键登录的具体实现(REST 调用、RSA padding 试错顺序)直接参考自试验后台, 逻辑等价。

S
Description
傻瓜比价正式 app后端
Readme 73 MiB
Languages
Python 82.7%
HTML 16.5%
JavaScript 0.4%
Shell 0.3%