From a798fbad60ad951543132853dfd5a84cef515b47 Mon Sep 17 00:00:00 2001 From: LittleGuo Date: Sat, 26 Sep 2026 23:58:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20need=5Fpurchase=20=E6=97=B6=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=9B=9E=E5=A4=8D=E6=96=87=E6=A1=88=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E8=AF=AF=E6=8A=A5"=E6=8E=88=E6=9D=83=E6=88=90=E5=8A=9F"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit handle_scan() 原先只返回场景是否绑定成功,导致无可用授权的用户扫码后 微信里收到"授权成功"、而 MFC 轮询拿到 need_purchase,提示不一致。 改为返回 authorized / need_purchase / invalid 三种结果,与 /auth/status 的 status 取值保持一致,wechat.py 据此选择回复文案。 --- auth.py | 22 ++++++++++++++-------- wechat.py | 12 ++++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/auth.py b/auth.py index 12a7daf..be7c1f8 100644 --- a/auth.py +++ b/auth.py @@ -107,11 +107,14 @@ async def get_status(scene: str = Query(..., description="create_scene 返回的 # 业务逻辑 # --------------------------------------------------------------------------- -async def handle_scan(scene_str: str, openid: str) -> bool: +async def handle_scan(scene_str: str, openid: str) -> str: """ - 处理扫码事件。 + 处理扫码事件,返回结果(取值与 /auth/status 的 status 一致): + + - "authorized" 场景绑定成功,且用户有可用授权 + - "need_purchase" 场景绑定成功,但用户没有可用授权(需充值) + - "invalid" 场景不存在、已过期,或已被处理过(重复扫码) - 返回 True 表示本次扫码完成授权,False 表示场景无效、已过期或已被处理。 整个流程在事务内完成,并对 scene 行加排他锁,保证同一 scene 只被处理一次。 """ async with db.acquire() as conn: @@ -127,12 +130,12 @@ async def handle_scan(scene_str: str, openid: str) -> bool: if scene_row is None: await conn.rollback() - return False + return "invalid" if scene_row["status"] == "authorized": # 重复扫码:只处理第一次,后续忽略 await conn.rollback() - return False + return "invalid" if not scene_row["not_expired"]: await cur.execute( @@ -141,10 +144,12 @@ async def handle_scan(scene_str: str, openid: str) -> bool: (scene_row["id"],), ) await conn.commit() - return False + return "invalid" user_id = await _find_or_create_user(cur, openid) await _grant_free_authorization(cur, user_id) + # 免费授权发完后仍无可用授权 → 需要充值(阶段 3) + has_auth = await _get_active_authorization(cur, user_id) is not None await cur.execute( "UPDATE auth_scenes SET status = 'authorized', user_id = %s, authorized_at = NOW() " @@ -160,8 +165,9 @@ async def handle_scan(scene_str: str, openid: str) -> bool: ) await conn.commit() - logger.info("扫码授权成功 scene_str=%s openid=%s", scene_str, openid) - return True + result = "authorized" if has_auth else "need_purchase" + logger.info("扫码完成 scene_str=%s openid=%s 结果=%s", scene_str, openid, result) + return result except Exception: await conn.rollback() raise diff --git a/wechat.py b/wechat.py index ce01646..e775762 100644 --- a/wechat.py +++ b/wechat.py @@ -126,10 +126,14 @@ async def _handle_scan_event( # 无场景值的普通关注 return _reply_text(from_user, to_user, "欢迎关注!") - authorized = await auth.handle_scan(scene_str, from_user) - if authorized: - return _reply_text(from_user, to_user, "授权成功,请返回电脑端继续操作。") - return _reply_text(from_user, to_user, "二维码已失效或已被使用,请在电脑端刷新后重新扫码。") + result = await auth.handle_scan(scene_str, from_user) + if result == "authorized": + reply = "授权成功,请返回电脑端继续操作。" + elif result == "need_purchase": + reply = "当前无可用授权,请返回电脑端按提示操作。" + else: + reply = "二维码已失效或已被使用,请在电脑端刷新后重新扫码。" + return _reply_text(from_user, to_user, reply) def _parse_scene_key(event_key: str, is_subscribe: bool) -> str: