From e57f7d4c2cd092fdd3e4237cc4d7e6717de216bb Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 09:49:13 +0800
Subject: [PATCH 01/17] 1
---
.../src/pages/AdminPaymentConfig.tsx | 22 +++++++
video-gen-api/app/api/v1/payments.py | 5 +-
video-gen-api/app/services/payment.py | 64 +++++++++++--------
3 files changed, 63 insertions(+), 28 deletions(-)
diff --git a/video-gen-admin/src/pages/AdminPaymentConfig.tsx b/video-gen-admin/src/pages/AdminPaymentConfig.tsx
index 22a33915..511ae365 100644
--- a/video-gen-admin/src/pages/AdminPaymentConfig.tsx
+++ b/video-gen-admin/src/pages/AdminPaymentConfig.tsx
@@ -27,6 +27,8 @@ const AdminPaymentConfig: React.FC = () => {
wechat_cert_serial_no: map['payment_wechat_cert_serial_no'] || '',
wechat_api_v3_key: map['payment_wechat_api_v3_key'] || '',
wechat_notify_url: map['payment_wechat_notify_url'] || '',
+ wechat_public_key: map['payment_wechat_public_key'] || '',
+ wechat_public_key_id: map['payment_wechat_public_key_id'] || '',
alipay_app_id: map['payment_alipay_app_id'] || '',
alipay_private_key: map['payment_alipay_private_key'] || '',
alipay_public_key: map['payment_alipay_public_key'] || '',
@@ -58,6 +60,8 @@ const AdminPaymentConfig: React.FC = () => {
payment_wechat_cert_serial_no: values.wechat_cert_serial_no || '',
payment_wechat_api_v3_key: values.wechat_api_v3_key || '',
payment_wechat_notify_url: values.wechat_notify_url || '',
+ payment_wechat_public_key: values.wechat_public_key || '',
+ payment_wechat_public_key_id: values.wechat_public_key_id || '',
payment_alipay_enabled: String(alipayEnabled),
payment_alipay_app_id: values.alipay_app_id || '',
payment_alipay_private_key: values.alipay_private_key || '',
@@ -188,6 +192,24 @@ const AdminPaymentConfig: React.FC = () => {
+
+
+
+
+
+
diff --git a/video-gen-api/app/api/v1/payments.py b/video-gen-api/app/api/v1/payments.py
index d85a6236..2a35cd01 100644
--- a/video-gen-api/app/api/v1/payments.py
+++ b/video-gen-api/app/api/v1/payments.py
@@ -112,8 +112,11 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
appid = db_configs.get("payment_wechat_appid", "")
+ public_key = db_configs.get("payment_wechat_public_key", "")
+ public_key_id = db_configs.get("payment_wechat_public_key_id", "")
+ notify_url = db_configs.get("payment_wechat_notify_url", "")
- client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid)
+ client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid, notify_url, public_key, public_key_id)
if not client:
logger.error("WeChat client not initialized for callback")
return {"code": "SUCCESS", "message": "OK"}
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 2568b0d2..79737a1b 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -357,7 +357,9 @@ def _get_wechat_client(
cert_serial_no: str,
api_v3_key: str,
appid: str,
- notify_url: str = ""
+ notify_url: str = "",
+ public_key: str = None,
+ public_key_id: str = None
):
"""Get or create a WeChat Pay client. Recreated if config changes."""
global _wechat_client, _wechat_mch_id
@@ -375,28 +377,25 @@ def _get_wechat_client(
return None
try:
- import os
- # 创建并确保微信支付证书目录存在
- wechat_cert_dir = os.path.abspath(os.path.join(
- os.path.dirname(os.path.dirname(__file__)),
- "..",
- "storage",
- "wechat_certs"
- ))
- os.makedirs(wechat_cert_dir, exist_ok=True)
- logger.info("WeChat Pay platform certificates will be stored in: %s", wechat_cert_dir)
- logger.info(f"mch_id={mch_id}, cert_serial_no={cert_serial_no}, appid={appid}, notify_url={notify_url}, api_v3_key={api_v3_key}, private_key={private_key}")
- # 初始化微信支付客户端,cert_dir=None,让 SDK 在线获取证书
- _wechat_client = WeChatPay(
- wechatpay_type=WeChatPayType.NATIVE,
- mchid=mch_id,
- private_key=private_key.strip(),
- cert_serial_no=cert_serial_no,
- appid=appid,
- apiv3_key=api_v3_key,
- notify_url=notify_url,
- cert_dir=wechat_cert_dir, # 不缓存证书,每次都从微信服务器获取
- )
+ # 初始化微信支付客户端
+ wechatpay_args = {
+ "wechatpay_type": WeChatPayType.NATIVE,
+ "mchid": mch_id,
+ "private_key": private_key.strip(),
+ "cert_serial_no": cert_serial_no,
+ "appid": appid,
+ "apiv3_key": api_v3_key,
+ "notify_url": notify_url,
+ }
+ # 如果配置了 public_key 和 public_key_id,就使用它们,否则不设置
+ if public_key and public_key_id:
+ wechatpay_args["public_key"] = public_key
+ wechatpay_args["public_key_id"] = public_key_id
+ logger.info("Using configured platform public key")
+ else:
+ logger.info("No platform public key configured, will try to download")
+
+ _wechat_client = WeChatPay(**wechatpay_args)
_wechat_mch_id = mch_id
logger.info("WeChat Pay client initialized successfully")
return _wechat_client
@@ -424,11 +423,13 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
appid = db_configs.get("payment_wechat_appid", "")
notify_url = db_configs.get("payment_wechat_notify_url", "")
+ public_key = db_configs.get("payment_wechat_public_key", "")
+ public_key_id = db_configs.get("payment_wechat_public_key_id", "")
if not all([mch_id, private_key, cert_serial_no, api_v3_key, appid]):
logger.warning("WeChat payment config missing in database")
return None
- client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid, notify_url)
+ client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid, notify_url, public_key, public_key_id)
if client is None:
return None
@@ -471,8 +472,11 @@ async def _close_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
appid = db_configs.get("payment_wechat_appid", "")
+ public_key = db_configs.get("payment_wechat_public_key", "")
+ public_key_id = db_configs.get("payment_wechat_public_key_id", "")
+ notify_url = db_configs.get("payment_wechat_notify_url", "")
- client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid)
+ client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid, notify_url, public_key, public_key_id)
if client is None:
return False
@@ -503,8 +507,11 @@ async def _query_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
appid = db_configs.get("payment_wechat_appid", "")
+ public_key = db_configs.get("payment_wechat_public_key", "")
+ public_key_id = db_configs.get("payment_wechat_public_key_id", "")
+ notify_url = db_configs.get("payment_wechat_notify_url", "")
- client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid)
+ client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid, notify_url, public_key, public_key_id)
if client is None:
return None
@@ -545,8 +552,11 @@ async def _refund_wechat_order(
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
appid = db_configs.get("payment_wechat_appid", "")
+ public_key = db_configs.get("payment_wechat_public_key", "")
+ public_key_id = db_configs.get("payment_wechat_public_key_id", "")
+ notify_url = db_configs.get("payment_wechat_notify_url", "")
- client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid)
+ client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, appid, notify_url, public_key, public_key_id)
if client is None:
return {"success": False, "message": "微信支付客户端初始化失败"}
From 591f0b897807a53fc497d793324ead5153cff752 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 09:55:37 +0800
Subject: [PATCH 02/17] 1
---
video-gen-api/app/services/payment.py | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 79737a1b..a2966afc 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -435,7 +435,7 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
try:
# 调用微信支付 Native 下单接口
- result = client.pay(
+ code, result = client.pay(
description=f"充值订单 {order.order_no}",
out_trade_no=order.order_no,
amount={
@@ -448,14 +448,14 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
}
)
- if result.get('code_url'):
+ if code == 200 and isinstance(result, dict) and result.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
logger.info(f"WeChat order created successfully: order_no={order.order_no}")
return result.get('code_url')
else:
logger.error(
f"WeChat pay failed: order_no={order.order_no}, "
- f"result={result}"
+ f"code={code}, result={result}"
)
return None
except Exception as e:
@@ -486,12 +486,12 @@ async def _close_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
return True
try:
- result = client.close(out_trade_no=order.order_no)
- if result:
+ code, result = client.close(out_trade_no=order.order_no)
+ if code == 200:
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}")
+ logger.error(f"WeChat close failed: order_no={order.order_no}, code={code}, result={result}")
return False
except Exception as e:
logger.exception(f"WeChat close exception: order_no={order.order_no}")
@@ -521,8 +521,8 @@ async def _query_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
return {"trade_state": "SUCCESS"}
try:
- result = client.query(out_trade_no=order.order_no)
- if result.get('trade_state'):
+ code, result = client.query(out_trade_no=order.order_no)
+ if code == 200 and isinstance(result, dict) and result.get('trade_state'):
logger.info(
f"WeChat query succeeded: order_no={order.order_no}, "
f"trade_state={result.get('trade_state')}"
@@ -531,7 +531,7 @@ async def _query_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
else:
logger.error(
f"WeChat query failed: order_no={order.order_no}, "
- f"result={result}"
+ f"code={code}, result={result}"
)
return None
except Exception as e:
@@ -567,7 +567,7 @@ async def _refund_wechat_order(
try:
out_refund_no = f"{order.order_no}_refund_{int(datetime.now().timestamp())}"
- result = client.refund(
+ code, result = client.refund(
out_trade_no=order.order_no,
out_refund_no=out_refund_no,
amount={
@@ -578,17 +578,17 @@ async def _refund_wechat_order(
reason=refund_reason
)
- if result.get('status') == 'SUCCESS':
+ if code == 200 and isinstance(result, dict) and result.get('status') == 'SUCCESS':
logger.info(f"WeChat refund succeeded: order_no={order.order_no}")
return {"success": True, "refund_id": result.get('refund_id')}
else:
logger.error(
f"WeChat refund failed: order_no={order.order_no}, "
- f"result={result}"
+ f"code={code}, result={result}"
)
return {
"success": False,
- "message": f"微信退款失败: {result.get('code', '')}"
+ "message": f"微信退款失败: code={code}, {result.get('code', '') if isinstance(result, dict) else ''}"
}
except Exception as e:
logger.exception(f"WeChat refund exception: order_no={order.order_no}")
From eeeb4f1cb1aa3192e124b2a10d6cd46c5178e86e Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:06:55 +0800
Subject: [PATCH 03/17] 1
---
video-gen-api/app/services/payment.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index a2966afc..362f6ff3 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -448,7 +448,7 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
}
)
- if code == 200 and isinstance(result, dict) and result.get('code_url'):
+ if code == 200 and hasattr(result, 'get') and result.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
logger.info(f"WeChat order created successfully: order_no={order.order_no}")
return result.get('code_url')
@@ -522,7 +522,7 @@ async def _query_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
try:
code, result = client.query(out_trade_no=order.order_no)
- if code == 200 and isinstance(result, dict) and result.get('trade_state'):
+ if code == 200 and hasattr(result, 'get') and result.get('trade_state'):
logger.info(
f"WeChat query succeeded: order_no={order.order_no}, "
f"trade_state={result.get('trade_state')}"
@@ -578,7 +578,7 @@ async def _refund_wechat_order(
reason=refund_reason
)
- if code == 200 and isinstance(result, dict) and result.get('status') == 'SUCCESS':
+ if code == 200 and hasattr(result, 'get') and result.get('status') == 'SUCCESS':
logger.info(f"WeChat refund succeeded: order_no={order.order_no}")
return {"success": True, "refund_id": result.get('refund_id')}
else:
@@ -588,7 +588,7 @@ async def _refund_wechat_order(
)
return {
"success": False,
- "message": f"微信退款失败: code={code}, {result.get('code', '') if isinstance(result, dict) else ''}"
+ "message": f"微信退款失败: code={code}, {result.get('code', '') if hasattr(result, 'get') else ''}"
}
except Exception as e:
logger.exception(f"WeChat refund exception: order_no={order.order_no}")
From adde56bf1d192f456974a8c49f6877d7813188c9 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:08:34 +0800
Subject: [PATCH 04/17] 1
---
video-gen-api/app/services/payment.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 362f6ff3..cecf6207 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -391,13 +391,11 @@ def _get_wechat_client(
if public_key and public_key_id:
wechatpay_args["public_key"] = public_key
wechatpay_args["public_key_id"] = public_key_id
- logger.info("Using configured platform public key")
else:
logger.info("No platform public key configured, will try to download")
_wechat_client = WeChatPay(**wechatpay_args)
_wechat_mch_id = mch_id
- logger.info("WeChat Pay client initialized successfully")
return _wechat_client
except Exception as e:
logger.exception(
@@ -450,7 +448,6 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
if code == 200 and hasattr(result, 'get') and result.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
- logger.info(f"WeChat order created successfully: order_no={order.order_no}")
return result.get('code_url')
else:
logger.error(
From ef2dc94c7188f2043fe6f3f78e33f4774cb0e95d Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:10:48 +0800
Subject: [PATCH 05/17] 1
---
video-gen-api/app/services/payment.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index cecf6207..becb8c15 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -446,7 +446,7 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
}
)
- if code == 200 and hasattr(result, 'get') and result.get('code_url'):
+ if code == 200 and result.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
return result.get('code_url')
else:
From 392507fa1e96a18b7a26566ecf33be6770567e88 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:13:32 +0800
Subject: [PATCH 06/17] 1
---
video-gen-api/app/services/payment.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index becb8c15..d722b2e5 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -445,8 +445,8 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
"payer_client_ip": "127.0.0.1",
}
)
-
- if code == 200 and result.get('code_url'):
+ logger.info(f"WeChat pay response: {code}, {result}")
+ if code == 200 and hasattr(result, 'get') and result.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
return result.get('code_url')
else:
From af3faeb655b7e0e8eb825a72d286f5b4da8ac1a8 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:15:58 +0800
Subject: [PATCH 07/17] 1
---
video-gen-api/app/services/payment.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index d722b2e5..fc7ae2fb 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -445,8 +445,7 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
"payer_client_ip": "127.0.0.1",
}
)
- logger.info(f"WeChat pay response: {code}, {result}")
- if code == 200 and hasattr(result, 'get') and result.get('code_url'):
+ if code == 200:
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
return result.get('code_url')
else:
From e699b110f813c878cb0c9fda86da70bdf4b0d781 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:20:27 +0800
Subject: [PATCH 08/17] 1
---
video-gen-api/app/services/payment.py | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index fc7ae2fb..19f6a96d 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -445,7 +445,8 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
"payer_client_ip": "127.0.0.1",
}
)
- if code == 200:
+ result = result or {}
+ if code == 200 and result.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
return result.get('code_url')
else:
@@ -518,7 +519,8 @@ async def _query_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
try:
code, result = client.query(out_trade_no=order.order_no)
- if code == 200 and hasattr(result, 'get') and result.get('trade_state'):
+ result = result or {}
+ if code == 200 and result.get('trade_state'):
logger.info(
f"WeChat query succeeded: order_no={order.order_no}, "
f"trade_state={result.get('trade_state')}"
@@ -573,8 +575,9 @@ async def _refund_wechat_order(
},
reason=refund_reason
)
+ result = result or {}
- if code == 200 and hasattr(result, 'get') and result.get('status') == 'SUCCESS':
+ if code == 200 and result.get('status') == 'SUCCESS':
logger.info(f"WeChat refund succeeded: order_no={order.order_no}")
return {"success": True, "refund_id": result.get('refund_id')}
else:
@@ -584,7 +587,7 @@ async def _refund_wechat_order(
)
return {
"success": False,
- "message": f"微信退款失败: code={code}, {result.get('code', '') if hasattr(result, 'get') else ''}"
+ "message": f"微信退款失败: code={code}, {result.get('code', '')}"
}
except Exception as e:
logger.exception(f"WeChat refund exception: order_no={order.order_no}")
From 41ed9d2352c4da4a63f64bc8ac259eb1c229ad18 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:24:12 +0800
Subject: [PATCH 09/17] 1
---
video-gen-api/app/services/payment.py | 44 ++++++++++++++++++++-------
1 file changed, 33 insertions(+), 11 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 19f6a96d..b38f5600 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -1,5 +1,6 @@
import logging
import os
+import json
from datetime import datetime, timedelta
# 尝试设置 SSL 证书路径
@@ -351,6 +352,23 @@ _wechat_client = None
_wechat_mch_id = None
+def _parse_wechat_result(result) -> dict:
+ """解析微信支付SDK返回的result为字典"""
+ data = {}
+ if isinstance(result, dict):
+ data = result
+ elif isinstance(result, str):
+ try:
+ data = json.loads(result)
+ except:
+ pass
+ elif hasattr(result, 'get'):
+ data = result
+ elif hasattr(result, '__dict__'):
+ data = result.__dict__
+ return data
+
+
def _get_wechat_client(
mch_id: str,
private_key: str,
@@ -445,10 +463,13 @@ def _create_wechat_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
"payer_client_ip": "127.0.0.1",
}
)
- result = result or {}
- if code == 200 and result.get('code_url'):
+
+ data = _parse_wechat_result(result)
+
+ if code == 200 and data.get('code_url'):
# 注意:微信返回的 code_url 可能需要进一步处理成二维码图片地址
- return result.get('code_url')
+ logger.info(f"WeChat order created successfully: order_no={order.order_no}")
+ return data.get('code_url')
else:
logger.error(
f"WeChat pay failed: order_no={order.order_no}, "
@@ -519,13 +540,13 @@ async def _query_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
try:
code, result = client.query(out_trade_no=order.order_no)
- result = result or {}
- if code == 200 and result.get('trade_state'):
+ data = _parse_wechat_result(result)
+ if code == 200 and data.get('trade_state'):
logger.info(
f"WeChat query succeeded: order_no={order.order_no}, "
- f"trade_state={result.get('trade_state')}"
+ f"trade_state={data.get('trade_state')}"
)
- return result
+ return data
else:
logger.error(
f"WeChat query failed: order_no={order.order_no}, "
@@ -575,11 +596,12 @@ async def _refund_wechat_order(
},
reason=refund_reason
)
- result = result or {}
- if code == 200 and result.get('status') == 'SUCCESS':
+ data = _parse_wechat_result(result)
+
+ if code == 200 and data.get('status') == 'SUCCESS':
logger.info(f"WeChat refund succeeded: order_no={order.order_no}")
- return {"success": True, "refund_id": result.get('refund_id')}
+ return {"success": True, "refund_id": data.get('refund_id')}
else:
logger.error(
f"WeChat refund failed: order_no={order.order_no}, "
@@ -587,7 +609,7 @@ async def _refund_wechat_order(
)
return {
"success": False,
- "message": f"微信退款失败: code={code}, {result.get('code', '')}"
+ "message": f"微信退款失败: code={code}, {data.get('code', '')}"
}
except Exception as e:
logger.exception(f"WeChat refund exception: order_no={order.order_no}")
From b9a2bd5befd8e6eb1fc53d96050214f9f8917f5c Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 10:35:14 +0800
Subject: [PATCH 10/17] 1
---
.../src/components/Layout/AppLayout.tsx | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/video-gen-app/src/components/Layout/AppLayout.tsx b/video-gen-app/src/components/Layout/AppLayout.tsx
index c19e1424..fffe327f 100644
--- a/video-gen-app/src/components/Layout/AppLayout.tsx
+++ b/video-gen-app/src/components/Layout/AppLayout.tsx
@@ -693,13 +693,15 @@ const AppLayout: React.FC = () => {
try {
setPaying(true);
const order = await createRechargeOrder(plan.id, paymentMethod);
- if (order.paymentMethod === 'alipay' && order.qrUrl) {
- // Alipay: show the real QR code URL from the backend
+ // 检查是否有二维码信息,支持支付宝和微信支付
+ const qrCode = order.qrUrl || order.codeUrl || order.qr_code || order.code_url;
+ if ((order.paymentMethod === 'alipay' || order.paymentMethod === 'wechat') && qrCode) {
+ // Alipay or WeChat Pay: show the QR code
const paymentInfo = {
price: plan.price,
credits: totalCredits,
- qrCode: order.qrUrl,
- method: 'alipay',
+ qrCode: qrCode,
+ method: order.paymentMethod,
};
setCurrentPaymentInfo(paymentInfo);
setRechargeModalOpen(false);
@@ -711,8 +713,8 @@ const AppLayout: React.FC = () => {
orderNo: order.orderNo,
price: plan.price,
credits: totalCredits,
- qrCode: order.qrUrl,
- method: 'alipay',
+ qrCode: qrCode,
+ method: order.paymentMethod,
createdAt: order.createdAt || new Date().toISOString(),
timeoutSeconds: 180,
}));
@@ -720,7 +722,7 @@ const AppLayout: React.FC = () => {
// Start polling for payment status
startPolling(order.orderNo);
} else {
- // WeChat or mock mode (mock auto-completes, no QR needed)
+ // Mock mode (auto-completes, no QR needed)
message.success('充值成功!积分已到账');
useAuthStore.getState().refreshUser();
setRechargeModalOpen(false);
From 20a0348743a4a9800316f885c8fd9eb0a858652d Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:08:47 +0800
Subject: [PATCH 11/17] 1
---
.../src/pages/AdminPaymentConfig.tsx | 20 ++++++++---
video-gen-api/app/services/payment.py | 35 ++++++++++++++++---
2 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/video-gen-admin/src/pages/AdminPaymentConfig.tsx b/video-gen-admin/src/pages/AdminPaymentConfig.tsx
index 511ae365..d8353f8f 100644
--- a/video-gen-admin/src/pages/AdminPaymentConfig.tsx
+++ b/video-gen-admin/src/pages/AdminPaymentConfig.tsx
@@ -235,11 +235,23 @@ const AdminPaymentConfig: React.FC = () => {
-
-
+
+
-
-
+
+
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index b38f5600..28bbb017 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -211,6 +211,28 @@ _alipay_client = None
_alipay_client_app_id = None
+def _format_alipay_key(key: str) -> str:
+ """
+ 格式化支付宝密钥,移除PEM头部和尾部,并清理所有空白字符。
+ """
+ if not key:
+ return ""
+ # 移除首尾空白
+ key = key.strip()
+ # 移除 PEM 头部和尾部
+ key = key.replace("-----BEGIN RSA PRIVATE KEY-----", "")
+ key = key.replace("-----BEGIN PRIVATE KEY-----", "")
+ key = key.replace("-----END RSA PRIVATE KEY-----", "")
+ key = key.replace("-----END PRIVATE KEY-----", "")
+ key = key.replace("-----BEGIN PUBLIC KEY-----", "")
+ key = key.replace("-----END PUBLIC KEY-----", "")
+ key = key.replace("-----BEGIN ALIPAY PUBLIC KEY-----", "")
+ key = key.replace("-----END ALIPAY PUBLIC KEY-----", "")
+ # 移除所有空白字符(换行、空格、制表符等)
+ key = "".join(key.split())
+ return key
+
+
def _get_alipay_client(app_id: str, private_key: str, public_key: str, gateway: str = ""):
"""Get or create an Alipay client. Recreated if app_id changes."""
global _alipay_client, _alipay_client_app_id
@@ -228,18 +250,23 @@ def _get_alipay_client(app_id: str, private_key: str, public_key: str, gateway:
)
return None
+ # 格式化私钥和公钥
+ formatted_private_key = _format_alipay_key(private_key)
+ formatted_public_key = _format_alipay_key(public_key)
+
config = AlipayClientConfig()
config.server_url = gateway or "https://openapi.alipay.com/gateway.do"
config.app_id = app_id
- config.app_private_key = private_key
- config.alipay_public_key = public_key
+ config.app_private_key = formatted_private_key
+ config.alipay_public_key = formatted_public_key
config.sign_type = "RSA2"
config.charset = "utf-8"
try:
_alipay_client = DefaultAlipayClient(config, logger)
_alipay_client_app_id = app_id
- except Exception:
+ logger.info("Alipay client initialized successfully")
+ except Exception as e:
logger.exception("Failed to initialize Alipay client")
_alipay_client = None
_alipay_client_app_id = None
@@ -505,7 +532,7 @@ async def _close_wechat_order(db: AsyncSession, order: PaymentOrder, db_configs:
try:
code, result = client.close(out_trade_no=order.order_no)
- if code == 200:
+ if code == 204:
logger.info(f"WeChat order closed: order_no={order.order_no}")
return True
else:
From 133e9eed5b8fc9af4938b6c8058ebd494f7b3476 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:31:25 +0800
Subject: [PATCH 12/17] 1
---
video-gen-api/app/services/payment.py | 33 +++------------------------
1 file changed, 3 insertions(+), 30 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 28bbb017..11dbca61 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -211,28 +211,6 @@ _alipay_client = None
_alipay_client_app_id = None
-def _format_alipay_key(key: str) -> str:
- """
- 格式化支付宝密钥,移除PEM头部和尾部,并清理所有空白字符。
- """
- if not key:
- return ""
- # 移除首尾空白
- key = key.strip()
- # 移除 PEM 头部和尾部
- key = key.replace("-----BEGIN RSA PRIVATE KEY-----", "")
- key = key.replace("-----BEGIN PRIVATE KEY-----", "")
- key = key.replace("-----END RSA PRIVATE KEY-----", "")
- key = key.replace("-----END PRIVATE KEY-----", "")
- key = key.replace("-----BEGIN PUBLIC KEY-----", "")
- key = key.replace("-----END PUBLIC KEY-----", "")
- key = key.replace("-----BEGIN ALIPAY PUBLIC KEY-----", "")
- key = key.replace("-----END ALIPAY PUBLIC KEY-----", "")
- # 移除所有空白字符(换行、空格、制表符等)
- key = "".join(key.split())
- return key
-
-
def _get_alipay_client(app_id: str, private_key: str, public_key: str, gateway: str = ""):
"""Get or create an Alipay client. Recreated if app_id changes."""
global _alipay_client, _alipay_client_app_id
@@ -250,23 +228,18 @@ def _get_alipay_client(app_id: str, private_key: str, public_key: str, gateway:
)
return None
- # 格式化私钥和公钥
- formatted_private_key = _format_alipay_key(private_key)
- formatted_public_key = _format_alipay_key(public_key)
-
config = AlipayClientConfig()
config.server_url = gateway or "https://openapi.alipay.com/gateway.do"
config.app_id = app_id
- config.app_private_key = formatted_private_key
- config.alipay_public_key = formatted_public_key
+ config.app_private_key = private_key
+ config.alipay_public_key = public_key
config.sign_type = "RSA2"
config.charset = "utf-8"
try:
_alipay_client = DefaultAlipayClient(config, logger)
_alipay_client_app_id = app_id
- logger.info("Alipay client initialized successfully")
- except Exception as e:
+ except Exception:
logger.exception("Failed to initialize Alipay client")
_alipay_client = None
_alipay_client_app_id = None
From f45528d2221826effaded2e79406863aed2f95de Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:39:34 +0800
Subject: [PATCH 13/17] 1
---
video-gen-api/app/services/payment.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 11dbca61..ae184869 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -404,6 +404,7 @@ def _get_wechat_client(
"appid": appid,
"apiv3_key": api_v3_key,
"notify_url": notify_url,
+ "logger": logger,
}
# 如果配置了 public_key 和 public_key_id,就使用它们,否则不设置
if public_key and public_key_id:
From e3d46bf2a3d9a767eee0944195352323e6e2d33f Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:47:17 +0800
Subject: [PATCH 14/17] 1
---
video-gen-api/app/services/payment.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index ae184869..3bc0cc56 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -412,7 +412,7 @@ def _get_wechat_client(
wechatpay_args["public_key_id"] = public_key_id
else:
logger.info("No platform public key configured, will try to download")
-
+ logger.info(f"Initializing WeChat Pay client with args: {wechatpay_args}")
_wechat_client = WeChatPay(**wechatpay_args)
_wechat_mch_id = mch_id
return _wechat_client
From 46b41447cbafec1bb22012b8c8f4dc3a449d1b6d Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:49:43 +0800
Subject: [PATCH 15/17] 1
---
video-gen-api/app/services/payment.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 3bc0cc56..6e8110cc 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -26,7 +26,7 @@ from app.utils.id_gen import generate_id, generate_order_no
import time as _time
logger = logging.getLogger("payment")
-logger.setLevel(logging.INFO)
+logger.setLevel(logging.DEBUG)
_log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "log", "payment")
os.makedirs(_log_dir, exist_ok=True)
@@ -412,7 +412,6 @@ def _get_wechat_client(
wechatpay_args["public_key_id"] = public_key_id
else:
logger.info("No platform public key configured, will try to download")
- logger.info(f"Initializing WeChat Pay client with args: {wechatpay_args}")
_wechat_client = WeChatPay(**wechatpay_args)
_wechat_mch_id = mch_id
return _wechat_client
From deb6d14d92beb1687f7e463e6208ff0461a6a0a3 Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:57:37 +0800
Subject: [PATCH 16/17] 1
---
video-gen-api/app/services/payment.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index 6e8110cc..fd20b416 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -1136,7 +1136,7 @@ async def process_payment_success_by_order_no(
db,
order.user_id,
order.credits,
- f"充值成功({order.credits}积分)",
+ f"充值成功({order.credits}积分), 订单号: {order_no}",
related_id=order.id,
)
await db.commit()
From e250401f45aadc72238afcb1b0fa2ceb8bcf0a6a Mon Sep 17 00:00:00 2001
From: wwwwwwwww <526125649@qq.com>
Date: Fri, 12 Jun 2026 11:59:33 +0800
Subject: [PATCH 17/17] 1
---
video-gen-api/app/services/payment.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/video-gen-api/app/services/payment.py b/video-gen-api/app/services/payment.py
index fd20b416..bc87720a 100644
--- a/video-gen-api/app/services/payment.py
+++ b/video-gen-api/app/services/payment.py
@@ -1136,7 +1136,7 @@ async def process_payment_success_by_order_no(
db,
order.user_id,
order.credits,
- f"充值成功({order.credits}积分), 订单号: {order_no}",
+ f"充值成功({order.credits}积分), 订单号: {order_no}, 金额: {order.amount}",
related_id=order.id,
)
await db.commit()