feat: 阶段 2 - /usage/consume、pending 授权惰性激活

- usage.py: POST /usage/consume,事务内校验会话(严格 device_id)、
  激活 pending、按 time/points 分支扣减;失败返回 ok:false + reason
- 积分扣减用条件 UPDATE 原子完成,status 赋值写在自减之前
  (MySQL SET 从左到右求值,否则 IF 读到已减 1 的值,判空差 1)
- 时间授权 usage_logs 按 (user_id, device_id) 60 秒节流;积分每次必写
- auth.py: 新增 activate_pending_authorization(),失效 active 后
  FIFO 激活 pending,时间授权按原时长从当前时刻重新锚定
- get_status/handle_scan 接入惰性激活;get_status 改事务包裹
- _get_active_authorization/_serialize_authorization 改公开供 usage 复用
- config/.env.example: 新增 USAGE_LOG_THROTTLE_SECONDS
This commit is contained in:
gjm committed 2026-09-27 15:00:02 +08:00
1 parent a798fbad60
commit cfb2a36c87
5 files changed
+255 -23

No files matched your search

+4 -2
View File
@@ -4,7 +4,7 @@
GET /wechat - 微信服务器验证(签名校验 + 返回 echostr)
POST /wechat - 接收微信推送的消息和事件(subscribe / SCAN 触发扫码授权)
授权接口在 auth.py 中定义,通过 include_router 挂载。
授权接口在 auth.py、使用扣减接口在 usage.py 中定义,通过 include_router 挂载。
"""
import hashlib
@@ -18,6 +18,7 @@ from fastapi.responses import PlainTextResponse
import auth
import db
import usage
from config import WECHAT_TOKEN
logging.basicConfig(
@@ -37,8 +38,9 @@ async def lifespan(app: FastAPI):
logger.info("MySQL 连接池已关闭")
app = FastAPI(title="WeChat API", version="0.2.0", lifespan=lifespan)
app = FastAPI(title="WeChat API", version="0.3.0", lifespan=lifespan)
app.include_router(auth.router)
app.include_router(usage.router)
def verify_signature(signature: str, timestamp: str, nonce: str) -> bool: