From 4d1c3448d21d3c6b505783582363bb25b50334c5 Mon Sep 17 00:00:00 2001 From: eric Date: Mon, 16 Mar 2026 20:25:57 -0500 Subject: [PATCH] 's' --- app/routers/salon_meetup.py | 120 +++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 50 deletions(-) diff --git a/app/routers/salon_meetup.py b/app/routers/salon_meetup.py index d0e4619..d17e4b8 100644 --- a/app/routers/salon_meetup.py +++ b/app/routers/salon_meetup.py @@ -287,7 +287,7 @@ def _update_solan_red_on_payment(token: str, user_id: str, order_id: str, amount f"{base}/api/collections/solanRed/records", params={"filter": f'user_id = "{user_id}"', "sort": "-created", "perPage": 1}, headers={"Authorization": f"Bearer {token}"}, - timeout=10, + timeout=(8, 20), ) if r.status_code != 200: return @@ -303,9 +303,11 @@ def _update_solan_red_on_payment(token: str, user_id: str, order_id: str, amount f"{base}/api/collections/solanRed/records/{rec_id}", json=patch, headers={"Content-Type": "application/json", "Authorization": f"Bearer {token}"}, - timeout=10, + timeout=(8, 20), ) logging.info(f"salon complete-order 兜底更新 solanRed - user_id: {user_id}, amount: {amount_cents}") + except requests.exceptions.RequestException as e: + logging.warning(f"salon complete-order 兜底更新 solanRed 请求超时/失败: {e}") except Exception as e: logging.warning(f"salon complete-order 兜底更新 solanRed 失败: {e}") @@ -329,21 +331,24 @@ async def complete_order(item: dict): def _query_solan_red_paid() -> dict | None: """查 solanRed 是否已有 vip 和 amount,有则说明已支付成功,可快速返回""" - esc = user_id.replace("\\", "\\\\").replace('"', '\\"') - r = requests.get( - f"{base}/api/collections/solanRed/records", - params={"filter": f'user_id = "{esc}"', "sort": "-created", "perPage": 1}, - headers={"Authorization": f"Bearer {token}"}, - timeout=5, - ) - if r.status_code != 200: - return None - items = r.json().get("items") or [] - if not items: - return None - rec = items[0] - if rec.get("vip") and (rec.get("amount") or 0) > 0: - return {"wechatId": rec.get("wechatId"), "nickname": rec.get("nickname"), "media": rec.get("media")} + try: + esc = user_id.replace("\\", "\\\\").replace('"', '\\"') + r = requests.get( + f"{base}/api/collections/solanRed/records", + params={"filter": f'user_id = "{esc}"', "sort": "-created", "perPage": 1}, + headers={"Authorization": f"Bearer {token}"}, + timeout=(6, 12), + ) + if r.status_code != 200: + return None + items = r.json().get("items") or [] + if not items: + return None + rec = items[0] + if rec.get("vip") and (rec.get("amount") or 0) > 0: + return {"wechatId": rec.get("wechatId"), "nickname": rec.get("nickname"), "media": rec.get("media")} + except requests.exceptions.RequestException as e: + logging.warning(f"salon complete-order PocketBase solanRed 请求超时/失败: {e}") return None paid_record = await asyncio.to_thread(_query_solan_red_paid) @@ -353,14 +358,18 @@ async def complete_order(item: dict): if not email: raise HTTPException(status_code=400, detail="订单格式无效") def _login_pending() -> dict | None: - login_r = requests.post( - f"{base}/api/collections/users/auth-with-password", - json={"identity": email, "password": DEFAULT_PASSWORD}, - timeout=10, - ) - if login_r.status_code != 200: + try: + login_r = requests.post( + f"{base}/api/collections/users/auth-with-password", + json={"identity": email, "password": DEFAULT_PASSWORD}, + timeout=(6, 15), + ) + if login_r.status_code != 200: + return None + return login_r.json() + except requests.exceptions.RequestException as e: + logging.warning(f"salon complete-order PocketBase login 请求超时/失败: {e}") return None - return login_r.json() auth_data = await asyncio.to_thread(_login_pending) if not auth_data: raise HTTPException(status_code=500, detail="登录失败,请稍后重试") @@ -371,13 +380,17 @@ async def complete_order(item: dict): return {"ok": True, "token": None, "record": paid_record, "is_new": False} def _query_site_vip_count() -> int: - r = requests.get( - f"{base}/api/collections/site_vip/records", - params={"filter": f'order_id = "{order_id}" && site_id = "{SITE_ID}"', "perPage": 1}, - headers={"Authorization": f"Bearer {token}"}, - timeout=10, - ) - return (r.json().get("totalItems") or 0) if r.status_code == 200 else 0 + try: + r = requests.get( + f"{base}/api/collections/site_vip/records", + params={"filter": f'order_id = "{order_id}" && site_id = "{SITE_ID}"', "perPage": 1}, + headers={"Authorization": f"Bearer {token}"}, + timeout=(8, 20), + ) + return (r.json().get("totalItems") or 0) if r.status_code == 200 else 0 + except requests.exceptions.RequestException as e: + logging.warning(f"salon complete-order PocketBase site_vip 请求超时/失败: {e}") + return 0 cached_amount_cents: int | None = None # 从 poll 路径获取时缓存,避免兜底重复查 ZPAY max_retries = 4 @@ -439,14 +452,18 @@ async def complete_order(item: dict): raise HTTPException(status_code=400, detail="订单格式无效") def _login_pending() -> dict | None: - login_r = requests.post( - f"{base}/api/collections/users/auth-with-password", - json={"identity": email, "password": DEFAULT_PASSWORD}, - timeout=10, - ) - if login_r.status_code != 200: + try: + login_r = requests.post( + f"{base}/api/collections/users/auth-with-password", + json={"identity": email, "password": DEFAULT_PASSWORD}, + timeout=(6, 15), + ) + if login_r.status_code != 200: + return None + return login_r.json() + except requests.exceptions.RequestException as e: + logging.warning(f"salon complete-order PocketBase login 请求超时/失败: {e}") return None - return login_r.json() auth_data = await asyncio.to_thread(_login_pending) if not auth_data: @@ -460,18 +477,21 @@ async def complete_order(item: dict): # 非 pending 用户:返回 solanRed 记录供前端显示微信号 def _fetch_solan_record() -> dict | None: - esc = lookup_user_id.replace("\\", "\\\\").replace('"', '\\"') - r = requests.get( - f"{base}/api/collections/solanRed/records", - params={"filter": f'user_id = "{esc}"', "sort": "-created", "perPage": 1}, - headers={"Authorization": f"Bearer {token}"}, - timeout=5, - ) - if r.status_code == 200: - items = r.json().get("items") or [] - if items: - rec = items[0] - return {"wechatId": rec.get("wechatId"), "nickname": rec.get("nickname"), "media": rec.get("media")} + try: + esc = lookup_user_id.replace("\\", "\\\\").replace('"', '\\"') + r = requests.get( + f"{base}/api/collections/solanRed/records", + params={"filter": f'user_id = "{esc}"', "sort": "-created", "perPage": 1}, + headers={"Authorization": f"Bearer {token}"}, + timeout=(6, 12), + ) + if r.status_code == 200: + items = r.json().get("items") or [] + if items: + rec = items[0] + return {"wechatId": rec.get("wechatId"), "nickname": rec.get("nickname"), "media": rec.get("media")} + except requests.exceptions.RequestException as e: + logging.warning(f"salon complete-order PocketBase fetch_solan_record 请求超时/失败: {e}") return None record = await asyncio.to_thread(_fetch_solan_record)