diff --git a/video-gen-api/app/cmd/migrate_user_credits.py b/video-gen-api/app/cmd/migrate_user_credits.py index a436a78a..1a512560 100644 --- a/video-gen-api/app/cmd/migrate_user_credits.py +++ b/video-gen-api/app/cmd/migrate_user_credits.py @@ -61,7 +61,7 @@ async def amain(argv: list[str]) -> int: description="历史用户积分迁移", source_type=CreditBalanceSourceType.LEGACY_MIGRATION.value, valid_from=migration_time, - expires_at=add_natural_months(migration_time, 1), + expires_at=add_natural_months(migration_time, 12), credit_level=CreditLevel.GENERAL.value, source_id=user_id, related_id=user_id, diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py index c75eb6b4..f9aeadb8 100644 --- a/video-gen-api/app/services/payment.py +++ b/video-gen-api/app/services/payment.py @@ -625,9 +625,33 @@ async def _close_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs: if code == 204: logger.info(f"WeChat order closed: order_no={order.order_no}") return True - else: - logger.error(f"WeChat close failed: order_no={order.order_no}, code={code}, result={result}") - return False + + data = _parse_wechat_result(result) + error_code = str( + data.get("code") + or data.get("err_code") + or data.get("error_code") + or "" + ).upper() + raw_result = str(result).upper() + + # 微信明确返回“订单不存在”时,同样视为没有远端订单需要继续关闭。 + # 只兼容明确的订单不存在错误,不吞掉签名、网络、系统等其他异常。 + if error_code in {"ORDER_NOT_EXIST", "ORDERNOTEXIST"} or ( + code == 404 + and ("ORDER_NOT_EXIST" in raw_result or "ORDERNOTEXIST" in raw_result) + ): + logger.info( + f"WeChat order not exist, treat as closed for local expiry: " + f"order_no={order.order_no}, code={code}, error_code={error_code or 'unknown'}" + ) + return True + + logger.error( + f"WeChat close failed: order_no={order.order_no}, " + f"code={code}, result={result}" + ) + return False except Exception as e: logger.exception(f"WeChat close exception: order_no={order.order_no}") return False @@ -885,13 +909,24 @@ async def _close_alipay_order(db: AsyncSession, order: PaymentOrder, db_configs: if response.is_success(): logger.info(f"Alipay order closed: order_no={order.order_no}") return True - else: - logger.error( - f"Alipay close failed: code={response.code}, " - f"msg={response.msg}, sub_code={response.sub_code}, " - f"sub_msg={response.sub_msg}, order_no={order.order_no}" + + # 支付宝明确返回“交易不存在”时,远端没有可继续关闭的交易。 + # 对本地已经达到超时时间的 pending 订单,可视为关单目标已经满足, + # 避免 Celery 每分钟对同一订单无限重复调用 trade.close。 + if str(response.sub_code or "").upper() == "ACQ.TRADE_NOT_EXIST": + logger.info( + f"Alipay trade not exist, treat as closed for local expiry: " + f"order_no={order.order_no}, code={response.code}, " + f"sub_code={response.sub_code}" ) - return False + return True + + logger.error( + f"Alipay close failed: code={response.code}, " + f"msg={response.msg}, sub_code={response.sub_code}, " + f"sub_msg={response.sub_msg}, order_no={order.order_no}" + ) + return False except Exception as e: if "TypeError" in str(e) and ("bytes" in str(e) or "str" in str(e)):