优化斗鱼充值

This commit is contained in:
yml2213
2026-08-13 21:43:27 +08:00
parent 902e669614
commit 0bf69c1240
19 changed files with 450 additions and 266 deletions
+76 -1
View File
@@ -6,7 +6,8 @@ import asyncio
import threading
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, Query, WebSocket, WebSocketDisconnect
from fastapi import APIRouter, Depends, HTTPException, Query, Request, WebSocket, WebSocketDisconnect
from loguru import logger
from sqlalchemy import or_
from sqlalchemy.orm import Session, joinedload
@@ -37,11 +38,85 @@ from ..services.douyu_service import (
douyu_task_payload,
ensure_douyu_config,
)
from core.douyu import FishFinRechargeClient, FishFinRechargeConfig, FishFinRechargeConfigError
router = APIRouter(prefix="/api/douyu", tags=["斗鱼活动"])
def _supplier_response_value(payload: dict, *keys: str):
"""兼容供应商把订单字段放在根节点、data 或 result 中。"""
data = payload.get("data") if isinstance(payload.get("data"), dict) else {}
result = payload.get("result") if isinstance(payload.get("result"), dict) else {}
for source in (payload, data, result):
for key in keys:
if source.get(key) is not None:
return source[key]
return None
@router.post("/supplier-recharge/callback")
async def supplier_recharge_callback(request: Request, db: Session = Depends(get_db)):
"""接收供应商直充终态通知,验签后按 out_order_id 幂等更新任务。"""
try:
payload = await request.json()
except ValueError as exc:
raise HTTPException(status_code=400, detail="供应商回调不是 JSON") from exc
if not isinstance(payload, dict):
raise HTTPException(status_code=400, detail="供应商回调格式无效")
try:
client = FishFinRechargeClient(FishFinRechargeConfig.from_env())
except FishFinRechargeConfigError as exc:
logger.error("[douyu] 供应商直充回调配置无效: {}", exc)
raise HTTPException(status_code=503, detail="供应商直充回调未配置") from exc
if not client.verify_response_sign(payload, "POST"):
logger.warning("[douyu] 供应商直充回调验签失败: keys={}", sorted(payload))
raise HTTPException(status_code=401, detail="供应商回调签名无效")
out_order_id = str(_supplier_response_value(payload, "out_order_id") or "").strip()
if not out_order_id:
raise HTTPException(status_code=400, detail="供应商回调缺少 out_order_id")
task = (
db.query(DouyuTask)
.filter(DouyuTask.supplier_out_order_id == out_order_id, DouyuTask.task_type == "create_gold_qr")
.first()
)
if not task:
raise HTTPException(status_code=404, detail="供应商回调订单不存在")
status = DouyuBatchRunner._to_int(_supplier_response_value(payload, "order_status", "orderStatus"))
result = dict(task.result) if isinstance(task.result, dict) else {}
result.update({
"out_order_id": out_order_id,
"order_id": _supplier_response_value(payload, "order_id", "orderId") or result.get("order_id"),
"supplier_order_status": status,
"supplier_order": DouyuBatchRunner._supplier_result(payload),
"supplier_callback_received": True,
})
if task.status not in {"success", "failed", "stopped"}:
if status == 2:
task.status = "success"
task.message = "供应商直充成功(异步通知)"
task.finished_at = datetime.now(timezone.utc)
if task.account:
task.account.bind_status = "gold_recharged"
task.account.updated_at = datetime.now(timezone.utc)
elif status in {3, 4}:
reason = str(_supplier_response_value(payload, "fail_reason", "message", "msg") or "供应商直充失败")
task.status = "failed"
task.message = reason[:512]
task.finished_at = datetime.now(timezone.utc)
else:
task.status = "running"
task.message = f"供应商直充订单处理中(状态 {status if status is not None else '-'}"
task.result = result
db.commit()
logger.info("[douyu] 供应商直充回调已处理: out_order_id={} status={}", out_order_id, status)
acknowledgement = {"code": 200, "message": "success"}
acknowledgement["sign"] = client.sign(acknowledgement, "POST")
return acknowledgement
def _can_view_all(user: User) -> bool:
return user_has_permission(user, "account:view_all")