1、缺少支付幂等性保障

2、增加事务
3、增加金额一致性判断
4、增加后台退款功能
This commit is contained in:
2026-06-11 15:47:10 +08:00
parent 0f56ceedf7
commit 47a231d558
6 changed files with 249 additions and 39 deletions
+17 -2
View File
@@ -43,6 +43,7 @@ from app.services.notification import create_notification
from app.services.auth import hash_password, verify_password
from app.services.operation_log import log_operation
from app.services.resource_signed_url_service import build_resource_signed_url
from app.services.payment import sync_pending_orders, process_refund
from app.services.generation_billing_service import (
OWNER_GENERATION_RECORD,
@@ -457,6 +458,7 @@ async def get_payment_stats(
"pending": {"count": 0, "amount": 0.0},
"paid": {"count": 0, "amount": 0.0},
"cancelled": {"count": 0, "amount": 0.0},
"refunded": {"count": 0, "amount": 0.0},
}
# Parse dates and build base query filters
@@ -570,7 +572,7 @@ async def get_payment_stats(
"amount": round(o.amount, 2),
"credits": round(o.credits, 2),
"payment_method": o.payment_method,
"status": o.status if o.status in ("pending", "paid", "cancelled") else "cancelled",
"status": o.status if o.status in ("pending", "paid", "cancelled", "refunded") else "cancelled",
"trade_no": o.trade_no,
"paid_at": _iso(o.paid_at),
"created_at": _iso(o.created_at),
@@ -622,7 +624,7 @@ async def get_admin_payment_orders(
"amount": round(o.amount, 2),
"credits": round(o.credits, 2),
"payment_method": o.payment_method,
"status": o.status if o.status in ("pending", "paid", "cancelled") else "cancelled",
"status": o.status if o.status in ("pending", "paid", "cancelled", "refunded") else "cancelled",
"trade_no": o.trade_no,
"paid_at": _iso(o.paid_at),
"created_at": _iso(o.created_at),
@@ -660,6 +662,19 @@ async def update_payment_config(
}
@router.post("/payment-orders/{order_no}/refund")
async def refund_payment_order(
order_no: str,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
"""Refund a paid payment order."""
result = await process_refund(db, order_no)
if not result.get("success"):
raise HTTPException(status_code=400, detail=result.get("message", "退款失败"))
return result
# ── Industry Config ──────────────────────────────────────
def _serialize_industry(ind: IndustryConfig) -> dict: