pay is ok
This commit is contained in:
@@ -259,57 +259,116 @@ def payment_finish(request):
|
||||
}
|
||||
|
||||
body = request.body.decode('utf-8')
|
||||
print(f"收到回调 Body (长度: {len(body)})")
|
||||
print(f"收到回调 Body (长度: {len(body)}):")
|
||||
print(f"--- BODY START ---")
|
||||
print(body)
|
||||
print(f"--- BODY END ---")
|
||||
|
||||
# 打印所有微信支付相关的头信息
|
||||
print("收到回调 Headers:")
|
||||
for key, value in request.headers.items():
|
||||
if key.lower().startswith('wechatpay'):
|
||||
print(f" {key}: {value}")
|
||||
|
||||
try:
|
||||
# 2. 初始化微信支付客户端
|
||||
# 2. 获取支付配置并初始化
|
||||
wechat_config = WeChatPayConfig.objects.filter(is_active=True).first()
|
||||
if not wechat_config:
|
||||
print("错误: 数据库中没有启用的微信支付配置")
|
||||
return HttpResponse("Config not found", status=500)
|
||||
|
||||
print(f"当前使用的配置 ID: {wechat_config.id}, 商户号: {wechat_config.mch_id}")
|
||||
|
||||
wxpay, error_msg = get_wechat_pay_client()
|
||||
if not wxpay:
|
||||
print(f"错误: 无法初始化客户端: {error_msg}")
|
||||
return HttpResponse(error_msg, status=500)
|
||||
|
||||
# 3. 打印当前证书状态,帮助排查“平台证书”问题
|
||||
cert_count = len(wxpay._core._certificates)
|
||||
print(f"当前已加载平台证书数量: {cert_count}")
|
||||
|
||||
# 3. 解析并校验基础信息
|
||||
try:
|
||||
data = json.loads(body)
|
||||
print(f"解析后的回调数据概览: id={data.get('id')}, event_type={data.get('event_type')}, resource_type={data.get('resource_type')}")
|
||||
except Exception as json_e:
|
||||
print(f"JSON 解析失败: {str(json_e)}")
|
||||
return HttpResponse("Invalid JSON", status=400)
|
||||
|
||||
# 4. 使用 SDK 标准方法处理 (内部包含:验签 + 解密)
|
||||
# 只有当 验签通过 且 解密成功 时,result 才有值
|
||||
result = wxpay.callback(headers, body)
|
||||
# 4. 尝试解密
|
||||
apiv3_key = str(wechat_config.apiv3_key).strip()
|
||||
print(f"正在使用 Key[{apiv3_key[:3]}...{apiv3_key[-3:]}] (长度: {len(apiv3_key)}) 尝试解密...")
|
||||
|
||||
if result:
|
||||
print(f"验证身份与解密成功: {result}")
|
||||
# 处理订单逻辑...
|
||||
data = result
|
||||
if 'out_trade_no' not in data and 'resource' in data:
|
||||
data = data.get('resource', {})
|
||||
# 优先使用 SDK 的 callback 方法
|
||||
try:
|
||||
print("尝试使用 SDK callback 方法解密并验证签名...")
|
||||
# 调试:打印 headers 关键信息
|
||||
print(f"Headers: Timestamp={headers.get('Wechatpay-Timestamp')}, Serial={headers.get('Wechatpay-Serial')}")
|
||||
|
||||
out_trade_no = data.get('out_trade_no')
|
||||
transaction_id = data.get('transaction_id')
|
||||
trade_state = data.get('trade_state')
|
||||
result_str = wxpay.callback(headers, body)
|
||||
if result_str:
|
||||
result = json.loads(result_str)
|
||||
print(f"SDK 解密成功: {result.get('out_trade_no')}")
|
||||
else:
|
||||
print("SDK callback 返回空,可能是签名验证失败。")
|
||||
raise Exception("SDK callback returned None")
|
||||
except Exception as sdk_e:
|
||||
print(f"SDK callback 失败: {str(sdk_e)},尝试手动解密...")
|
||||
|
||||
if trade_state == 'SUCCESS':
|
||||
try:
|
||||
order = None
|
||||
if out_trade_no.startswith('PAY'):
|
||||
t_index = out_trade_no.find('T')
|
||||
order_id = int(out_trade_no[3:t_index])
|
||||
order = Order.objects.get(id=order_id)
|
||||
else:
|
||||
order = Order.objects.get(out_trade_no=out_trade_no)
|
||||
|
||||
if order and order.status != 'paid':
|
||||
order.status = 'paid'
|
||||
order.wechat_trade_no = transaction_id
|
||||
order.save()
|
||||
print(f"订单 {order.id} 状态已更新")
|
||||
except Exception as e:
|
||||
print(f"订单更新失败: {str(e)}")
|
||||
resource = data.get('resource', {})
|
||||
ciphertext = resource.get('ciphertext')
|
||||
nonce = resource.get('nonce')
|
||||
associated_data = resource.get('associated_data')
|
||||
|
||||
return HttpResponse(status=200)
|
||||
else:
|
||||
print("错误: 微信支付身份验证(验签)失败或解密失败。")
|
||||
print("请检查: 1. API V3 密钥是否正确; 2. 平台证书是否下载成功。")
|
||||
return HttpResponse("Signature verification failed", status=401)
|
||||
print(f"提取的解密参数: nonce={nonce}, associated_data={associated_data}, ciphertext_len={len(ciphertext) if ciphertext else 0}")
|
||||
|
||||
try:
|
||||
if not all([ciphertext, nonce, apiv3_key]):
|
||||
raise ValueError(f"缺少解密必要参数: ciphertext={bool(ciphertext)}, nonce={bool(nonce)}, key={bool(apiv3_key)}")
|
||||
|
||||
if len(apiv3_key) != 32:
|
||||
raise ValueError(f"APIV3 Key 长度错误: 预期 32 字节,实际 {len(apiv3_key)} 字节")
|
||||
|
||||
aesgcm = AESGCM(apiv3_key.encode('utf-8'))
|
||||
decrypted_data = aesgcm.decrypt(
|
||||
nonce.encode('utf-8'),
|
||||
base64.b64decode(ciphertext),
|
||||
associated_data.encode('utf-8') if associated_data else b""
|
||||
)
|
||||
result = json.loads(decrypted_data.decode('utf-8'))
|
||||
print(f"手动解密成功: {result.get('out_trade_no')}")
|
||||
except Exception as e:
|
||||
import traceback
|
||||
error_type = type(e).__name__
|
||||
error_msg = str(e)
|
||||
print(f"手动解密依然失败: {error_type}: {error_msg}")
|
||||
if "InvalidTag" in error_msg or error_type == "InvalidTag":
|
||||
print(f"提示: InvalidTag 通常意味着 Key 正确但与数据不匹配。")
|
||||
print(f"当前使用的 Key: {apiv3_key}")
|
||||
print(f"请确认该 Key 是否确实是商户号 {wechat_config.mch_id} 的 APIV3 密钥。")
|
||||
traceback.print_exc()
|
||||
return HttpResponse("Decryption failed", status=400)
|
||||
|
||||
# 5. 订单处理 (保持原有逻辑)
|
||||
out_trade_no = result.get('out_trade_no')
|
||||
transaction_id = result.get('transaction_id')
|
||||
trade_state = result.get('trade_state')
|
||||
|
||||
if trade_state == 'SUCCESS':
|
||||
try:
|
||||
order = None
|
||||
if out_trade_no.startswith('PAY'):
|
||||
t_index = out_trade_no.find('T')
|
||||
order_id = int(out_trade_no[3:t_index])
|
||||
order = Order.objects.get(id=order_id)
|
||||
else:
|
||||
order = Order.objects.get(out_trade_no=out_trade_no)
|
||||
|
||||
if order and order.status != 'paid':
|
||||
order.status = 'paid'
|
||||
order.wechat_trade_no = transaction_id
|
||||
order.save()
|
||||
print(f"订单 {order.id} 状态已更新")
|
||||
except Exception as e:
|
||||
print(f"订单更新失败: {str(e)}")
|
||||
|
||||
return HttpResponse(status=200)
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
Reference in New Issue
Block a user