This commit is contained in:
2026-06-15 10:26:13 +08:00
parent 20d4b8d422
commit 013e99cd24
+20 -5
View File
@@ -153,6 +153,7 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
logger.warning("Wechatpay-Serial header missing, skipping signature verification")
# 解密回调数据:使用 API v3 key
# 官方文档:https://pay.weixin.qq.com/doc/v3/merchant/4012071382
import json
body_data = json.loads(body_str) if body_str else {}
resource = body_data.get("resource", {})
@@ -161,18 +162,32 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
logger.error("WeChat callback resource not found")
raise HTTPException(status_code=400, detail="数据格式错误")
# 验证加密算法(官方文档要求固定为 AEAD_AES_256_GCM
algorithm = resource.get("algorithm", "")
if algorithm != "AEAD_AES_256_GCM":
logger.error(f"WeChat callback unsupported algorithm: {algorithm}")
raise HTTPException(status_code=400, detail="不支持的加密算法")
ciphertext = resource.get("ciphertext", "")
associated_data = resource.get("associated_data", "")
nonce_str = resource.get("nonce", "")
# 使用 AES-GCM 解密
# 参数验证
if not ciphertext:
logger.error("WeChat callback ciphertext is empty")
raise HTTPException(status_code=400, detail="密文为空")
if not nonce_str:
logger.error("WeChat callback nonce is empty")
raise HTTPException(status_code=400, detail="随机数为空")
# 使用 AES-GCM 解密(符合官方文档规范)
try:
# API v3 key 需要转换为字节串
api_v3_key_bytes = api_v3_key.encode('utf-8')
# ciphertext 和 nonce 是 Base64 编码的,需要解码
ciphertext_bytes = b64decode(ciphertext) if ciphertext else b''
nonce_bytes = b64decode(nonce_str) if nonce_str else b''
ciphertext_bytes = b64decode(ciphertext)
nonce_bytes = b64decode(nonce_str)
# associated_data 是字符串,直接编码
associated_data_bytes = associated_data.encode('utf-8') if associated_data else b''
@@ -180,8 +195,8 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
aesgcm = AESGCM(api_v3_key_bytes)
decrypted_str = aesgcm.decrypt(ciphertext_bytes, associated_data_bytes, nonce_bytes)
except InvalidTag:
logger.error("WeChat callback decryption failed: Invalid tag")
raise HTTPException(status_code=400, detail="数据解密失败")
logger.error("WeChat callback decryption failed: Invalid tag (key or data mismatch)")
raise HTTPException(status_code=400, detail="数据解密失败(密钥或数据不匹配)")
except Exception as e:
logger.error(f"WeChat callback decryption failed: {e}")
raise HTTPException(status_code=400, detail="数据解密失败")