From 5a86350829e86bec0d8660b99581a62345c3e7dc Mon Sep 17 00:00:00 2001 From: wwwwwwwww <526125649@qq.com> Date: Mon, 15 Jun 2026 09:30:25 +0800 Subject: [PATCH] 1 --- video-gen-api/app/api/v1/payments.py | 56 +++++++++++++++++----------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/video-gen-api/app/api/v1/payments.py b/video-gen-api/app/api/v1/payments.py index 17f5d95c..76ab7ced 100644 --- a/video-gen-api/app/api/v1/payments.py +++ b/video-gen-api/app/api/v1/payments.py @@ -105,17 +105,18 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)): logger.exception(f"Mock WeChat callback error: {e}") return {"code": "SUCCESS", "message": "OK"} # 微信要求即使处理失败也返回成功 - # 真实模式:使用 wechatpayv3 SDK 验证回调并解析数据 + # 真实模式:使用 wechatpayv3 SDK 工具验证回调并解析数据 try: - from wechatpayv3 import Sign, AesCrypto + from wechatpayv3.utils import ( + rsa_verify, load_public_key, sha256, b64decode, + AESGCM, InvalidTag + ) mch_id = db_configs.get("payment_wechat_mch_id", "") - private_key = db_configs.get("payment_wechat_private_key", "") - cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "") api_v3_key = db_configs.get("payment_wechat_api_v3_key", "") public_key = db_configs.get("payment_wechat_public_key", "") - if not all([mch_id, private_key, cert_serial_no, api_v3_key]): + if not all([mch_id, api_v3_key]): logger.error("WeChat payment config missing for callback") return {"code": "SUCCESS", "message": "OK"} @@ -124,25 +125,28 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)): timestamp = headers.get("Wechatpay-Timestamp", "") nonce = headers.get("Wechatpay-Nonce", "") signature = headers.get("Wechatpay-Signature", "") - serial_no = headers.get("Wechatpay-Serial", "") # 验证签名:使用平台公钥验证 - if not public_key: - logger.warning("WeChat platform public key not configured, skipping signature verification") - else: - is_verified = Sign.verify( - public_key=public_key, - timestamp=timestamp, - nonce=nonce, - body=body_str, - signature=signature - ) - if not is_verified: - logger.warning("WeChat callback signature verification failed") + if public_key: + try: + # 构造签名串 + sign_string = f"{timestamp}\n{nonce}\n{body_str}\n" + # 验证签名 + is_verified = rsa_verify( + public_key=load_public_key(public_key), + data=sign_string.encode('utf-8'), + signature=b64decode(signature) + ) + if not is_verified: + logger.warning("WeChat callback signature verification failed") + raise HTTPException(status_code=400, detail="签名验证失败") + except Exception as e: + logger.warning(f"WeChat signature verification error: {e}") raise HTTPException(status_code=400, detail="签名验证失败") + else: + logger.warning("WeChat platform public key not configured, skipping signature verification") # 解密回调数据:使用 API v3 key - crypto = AesCrypto(api_v3_key) import json body_data = json.loads(body_str) if body_str else {} resource = body_data.get("resource", {}) @@ -155,9 +159,19 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)): associated_data = resource.get("associated_data", "") nonce_str = resource.get("nonce", "") - decrypted_str = crypto.decrypt_gcm(ciphertext, associated_data, nonce_str) + # 使用 AES-GCM 解密 + try: + aesgcm = AESGCM(api_v3_key) + decrypted_str = aesgcm.decrypt(ciphertext, associated_data, nonce_str) + except InvalidTag: + logger.error("WeChat callback decryption failed: Invalid tag") + raise HTTPException(status_code=400, detail="数据解密失败") + except Exception as e: + logger.error(f"WeChat callback decryption failed: {e}") + raise HTTPException(status_code=400, detail="数据解密失败") + if not decrypted_str: - logger.error("WeChat callback decryption failed") + logger.error("WeChat callback decryption returned empty") raise HTTPException(status_code=400, detail="数据解密失败") decrypted_data = json.loads(decrypted_str)