From 64f8be96b530f2fe8433c0eb1a23060e0f6591fd Mon Sep 17 00:00:00 2001 From: wwwwwwwww <526125649@qq.com> Date: Thu, 11 Jun 2026 10:04:18 +0800 Subject: [PATCH] 1 --- video-gen-api/app/api/v1/payments.py | 5 ++- video-gen-api/app/services/payment.py | 61 +++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/video-gen-api/app/api/v1/payments.py b/video-gen-api/app/api/v1/payments.py index 8939d2a0..122f5109 100644 --- a/video-gen-api/app/api/v1/payments.py +++ b/video-gen-api/app/api/v1/payments.py @@ -16,6 +16,9 @@ from app.services.payment import ( verify_wechat_callback, verify_alipay_callback, process_payment_success_by_order_no, + _get_payment_configs, + _is_mock_mode, + _check_and_expire_order, ) router = APIRouter(prefix="/payments", tags=["payments"]) @@ -42,7 +45,6 @@ async def recharge( raise HTTPException(status_code=400, detail="不支持的支付方式") # Check if the selected payment method is enabled in admin config - from app.services.payment import _get_payment_configs, _is_mock_mode configs = await _get_payment_configs(db) if not _is_mock_mode(configs): enabled_key = f"payment_{req.method}_enabled" @@ -118,7 +120,6 @@ async def list_orders( db: AsyncSession = Depends(get_db), ): # Auto-expire stale pending orders before returning - from app.services.payment import _check_and_expire_order result = await db.execute( select(PaymentOrder) .where(PaymentOrder.user_id == current_user.id) diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py index eb863b96..869f5be7 100644 --- a/video-gen-api/app/services/payment.py +++ b/video-gen-api/app/services/payment.py @@ -23,6 +23,19 @@ from app.models.system_config import SystemConfig from app.services.credits import add_credits from app.utils.id_gen import generate_id, generate_order_no +__all__ = [ + "create_recharge_order", + "verify_alipay_callback", + "verify_wechat_callback", + "process_payment_success_by_order_no", + "get_order", + "get_user_orders", + "expire_all_pending_orders", + "_get_payment_configs", + "_is_mock_mode", + "_check_and_expire_order", +] + # --------------------------------------------------------------------------- # Payment logger → log/payment/YYYY-MM-DD.log (one file per day, no cleanup) # --------------------------------------------------------------------------- @@ -135,6 +148,10 @@ async def _get_payment_configs(db: AsyncSession) -> dict[str, str]: return {c.key: c.value for c in result.scalars().all()} +def _is_mock_mode(configs: dict[str, str]) -> bool: + return configs.get("payment_mock", "false").lower() == "true" + + async def _check_and_expire_order(db: AsyncSession, order: PaymentOrder) -> bool: """If a pending order has passed its expiry, mark it cancelled. Returns True if the order was expired. @@ -237,24 +254,27 @@ def _get_alipay_client(app_id: str, private_key: str, public_key: str, gateway: async def create_recharge_order( db: AsyncSession, user_id: str, - amount: float, credits: float, - payment_method: str, + price: float, + label: str, + bonus_credits: float = 0, + method: str = "alipay", ) -> PaymentOrder: """Create a new pending payment order and call the payment gateway. If mock mode is enabled, auto-approves. Returns the PaymentOrder with qr_code (or None if mock). """ configs = await _get_payment_configs(db) - is_mock = configs.get("payment_mock", "false").lower() == "true" + is_mock = _is_mock_mode(configs) + total_credits = credits + bonus_credits order = PaymentOrder( id=generate_id(), user_id=user_id, order_no=generate_order_no(), - amount=amount, - credits=credits, - payment_method=payment_method, + amount=price, + credits=total_credits, + payment_method=method, status="pending" if not is_mock else "paid", qr_url=None, ) @@ -263,7 +283,7 @@ async def create_recharge_order( logger.info( f"ORDER_CREATED order_no={order.order_no} user={user_id} " - f"amount={amount} credits={credits} method={payment_method} mock={is_mock}" + f"amount={price} credits={total_credits} method={method} mock={is_mock}" ) if is_mock: @@ -273,12 +293,12 @@ async def create_recharge_order( return order # Real payment - if payment_method == "alipay": + if method == "alipay": qr_url = _create_alipay_order(order, configs) if qr_url: order.qr_url = qr_url await db.flush() - elif payment_method == "wechat": + elif method == "wechat": _create_wechat_order(order, configs) # Wechat would get a qr_url too, but stubbed for now @@ -286,6 +306,29 @@ async def create_recharge_order( return order +async def verify_wechat_callback(data: dict, db: AsyncSession) -> bool: + """Verify Wechat Pay callback signature. + Note: This is a stub implementation. + """ + configs = await _get_payment_configs(db) + wechat_api_key = configs.get("payment_wechat_api_key", "") + + if not wechat_api_key: + logger.warning("Wechat API key not configured, skipping signature verify") + return True + + try: + # TODO: Implement proper Wechat Pay signature verification + logger.info( + f"WECHAT_CALLBACK order_no={data.get('out_trade_no')} " + f"transaction_id={data.get('transaction_id')}" + ) + return True + except Exception: + logger.exception("Error verifying Wechat callback") + return False + + # --------------------------------------------------------------------------- # Wechat – stub for now # ---------------------------------------------------------------------------