OuYingJun1024 0722d7b0d5 feat: 福利钱包+签到+省钱战绩+激励广告发奖+微信提现 后端
- 福利钱包: 金币/现金余额、流水、兑换 (api/v1/wallet.py, crud/wallet.py, models/wallet.py, schemas/welfare.py)
- 每日签到: 连续天数 + 档位奖励 (api/v1/signin.py, crud/signin.py, models/signin.py)
- 任务系统: "打开消息提醒"等任务领奖 (api/v1/tasks.py, crud/task.py, models/task.py)
- 省钱战绩: 省钱汇总/战绩/店铺菜品 (api/v1/savings.py, crud/savings.py, models/savings.py)
- 激励广告发奖: 穿山甲服务端回调 + 发奖规则 + 限流 (api/v1/ad.py, core/pangle.py, core/rewards.py, core/ratelimit.py, crud/ad_reward.py, schemas/ad.py, docs/ad_reward_golive_checklist.md)
- 微信提现: 商家转账到零钱 V3 (core/wxpay.py); user 表加微信 openid/nickname/avatar
- DB 迁移: 8 个 alembic (welfare 表/cash_transaction/openid 唯一约束/savings 店铺菜品/savings_record/ad_reward/withdraw_order+openid/user 微信字段)
- 运维脚本: reconcile_withdraws(对账) + reset_signin/reset_welfare + sim_pangle_callback(模拟穿山甲回调)
- 测试: test_welfare / test_withdraw / test_ad_reward
- 配置: .env.example + config.py 新增福利/广告/微信支付项; main.py 挂 5 个新路由

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 17:38:08 +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%