1
This commit is contained in:
@@ -107,18 +107,16 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
|
|||||||
|
|
||||||
# 真实模式:使用 wechatpayv3 SDK 验证回调并解析数据
|
# 真实模式:使用 wechatpayv3 SDK 验证回调并解析数据
|
||||||
try:
|
try:
|
||||||
|
from wechatpayv3 import Sign, AesCrypto
|
||||||
|
|
||||||
mch_id = db_configs.get("payment_wechat_mch_id", "")
|
mch_id = db_configs.get("payment_wechat_mch_id", "")
|
||||||
private_key = db_configs.get("payment_wechat_private_key", "")
|
private_key = db_configs.get("payment_wechat_private_key", "")
|
||||||
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
|
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
|
||||||
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
|
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 = 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, notify_url, public_key, public_key_id)
|
if not all([mch_id, private_key, cert_serial_no, api_v3_key]):
|
||||||
if not client:
|
logger.error("WeChat payment config missing for callback")
|
||||||
logger.error("WeChat client not initialized for callback")
|
|
||||||
return {"code": "SUCCESS", "message": "OK"}
|
return {"code": "SUCCESS", "message": "OK"}
|
||||||
|
|
||||||
# 从请求头获取必要信息
|
# 从请求头获取必要信息
|
||||||
@@ -128,31 +126,47 @@ async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
|
|||||||
signature = headers.get("Wechatpay-Signature", "")
|
signature = headers.get("Wechatpay-Signature", "")
|
||||||
serial_no = headers.get("Wechatpay-Serial", "")
|
serial_no = headers.get("Wechatpay-Serial", "")
|
||||||
|
|
||||||
# 验证签名
|
# 验证签名:使用平台公钥验证
|
||||||
is_verified = client.verify(
|
if not public_key:
|
||||||
timestamp=timestamp,
|
logger.warning("WeChat platform public key not configured, skipping signature verification")
|
||||||
nonce=nonce,
|
else:
|
||||||
body=body_str,
|
is_verified = Sign.verify(
|
||||||
signature=signature,
|
public_key=public_key,
|
||||||
serial_no=serial_no
|
timestamp=timestamp,
|
||||||
)
|
nonce=nonce,
|
||||||
|
body=body_str,
|
||||||
|
signature=signature
|
||||||
|
)
|
||||||
|
if not is_verified:
|
||||||
|
logger.warning("WeChat callback signature verification failed")
|
||||||
|
raise HTTPException(status_code=400, detail="签名验证失败")
|
||||||
|
|
||||||
if not is_verified:
|
# 解密回调数据:使用 API v3 key
|
||||||
logger.warning("WeChat callback signature verification failed")
|
crypto = AesCrypto(api_v3_key)
|
||||||
raise HTTPException(status_code=400, detail="签名验证失败")
|
import json
|
||||||
|
body_data = json.loads(body_str) if body_str else {}
|
||||||
|
resource = body_data.get("resource", {})
|
||||||
|
|
||||||
# 解密回调数据
|
if not resource:
|
||||||
decrypted_data = client.decrypt(body_str)
|
logger.error("WeChat callback resource not found")
|
||||||
if not decrypted_data:
|
raise HTTPException(status_code=400, detail="数据格式错误")
|
||||||
|
|
||||||
|
ciphertext = resource.get("ciphertext", "")
|
||||||
|
associated_data = resource.get("associated_data", "")
|
||||||
|
nonce_str = resource.get("nonce", "")
|
||||||
|
|
||||||
|
decrypted_str = crypto.decrypt_gcm(ciphertext, associated_data, nonce_str)
|
||||||
|
if not decrypted_str:
|
||||||
logger.error("WeChat callback decryption failed")
|
logger.error("WeChat callback decryption failed")
|
||||||
raise HTTPException(status_code=400, detail="数据解密失败")
|
raise HTTPException(status_code=400, detail="数据解密失败")
|
||||||
|
|
||||||
|
decrypted_data = json.loads(decrypted_str)
|
||||||
|
|
||||||
# 处理支付成功回调
|
# 处理支付成功回调
|
||||||
if decrypted_data.get("event_type") == "TRANSACTION.SUCCESS":
|
if body_data.get("event_type") == "TRANSACTION.SUCCESS":
|
||||||
resource = decrypted_data.get("resource", {})
|
order_no = decrypted_data.get("out_trade_no", "")
|
||||||
order_no = resource.get("out_trade_no", "")
|
transaction_id = decrypted_data.get("transaction_id", "")
|
||||||
transaction_id = resource.get("transaction_id", "")
|
amount_info = decrypted_data.get("amount", {})
|
||||||
amount_info = resource.get("amount", {})
|
|
||||||
total_amount = amount_info.get("total", 0) / 100 # 转换为元
|
total_amount = amount_info.get("total", 0) / 100 # 转换为元
|
||||||
|
|
||||||
if order_no:
|
if order_no:
|
||||||
|
|||||||
Reference in New Issue
Block a user