Django集成Paynow支付报错无法跳转支付结账页解决方案
错误原因
- 核心报错原因:Django视图函数要求必须返回Django内置的
HttpResponse类型(或其子类,如重定向响应、模板渲染响应)对象,但你在代码中直接返回了requests库请求第三方接口生成的Response对象。Django处理响应时会读取对象的streaming属性,而requests的Response类没有这个属性,因此抛出AttributeError: 'Response' object has no attribute 'streaming'错误。 - 附带逻辑错误:GET请求分支下错误传入了
request.POST初始化表单,GET请求无POST表单数据,会导致表单初始化异常;调用支付网关初始化接口后未解析响应内容、未提取支付跳转地址,无法实现跳转到支付页的需求。
修复方案
- 移除直接返回requests响应的错误逻辑,请求支付网关接口后先解析接口返回的JSON数据
- 修正GET分支的表单初始化逻辑,GET请求下直接实例化空表单
- 从支付网关的成功响应中提取收银台页面的跳转地址,使用Django内置的
redirect()方法返回重定向响应,引导用户跳转到支付页 - 补充接口请求异常、接口返回业务错误的处理逻辑,避免请求失败时直接抛出500错误
- 清理代码中重复赋值、定义后未使用的冗余变量
修复后代码示例
import datetime import requests from django.shortcuts import render, redirect from .forms import PaymentForm def process_paynow_payment(request, comment = None): if request.method == 'POST': form = PaymentForm(request.POST) if form.is_valid(): payment = form.save() user = request.user amount = payment.amount ref = payment.ref headers = { "authorization": f"Bearer XXXXXXXXX", "MerchantId": "XXXXXXX", "Content-Type": 'application/json' } data = { "reference": ref, "mchShortName": user.first_name, "productName": "Balance Deposit", "productDesc": "simply deposit now", "userPhone": "+123456789", "userRequestIp": "123.123.123.123", "amount": amount, "currency": "USD", "payTypes": ["BalancePayment", "BonusPayment", "OWealth"], "payMethods": ["account", "qrcode", "bankCard", "bankAccount", "bankTransfer", "bankUSSD"], "callbackUrl": "https://callbackurl.com/callbackUrl", "returnUrl": "https://myreturnurl.com/returnUrl", "expireAt": "10" } url = 'https://cashierapi.paynow.com/api/v3/cashier/initialize' try: pay_resp = requests.post(url, json=data, headers=headers, timeout=10) pay_resp.raise_for_status() # 接口返回4xx/5xx状态码时直接抛出异常 resp_data = pay_resp.json() # 注意:此处跳转地址字段名请根据Paynow实际接口文档调整,常见字段名如cashier_url、pay_url、redirect_url if resp_data.get('code') == 0 and resp_data.get('data', {}).get('cashier_url'): # 跳转到支付网关收银台页面 return redirect(resp_data['data']['cashier_url']) else: # 接口返回业务错误,把错误信息传给前端展示 form.add_error(None, f"支付初始化失败:{resp_data.get('msg', '未知错误')}") except Exception as e: form.add_error(None, f"支付请求失败,请稍后重试:{str(e)}") else: # GET请求初始化空表单,不要传入request.POST form = PaymentForm() return render(request, 'paynow/paynow_initiate_payment.html', {'form': form})
注意:代码中提取跳转地址的字段
cashier_url需要和Paynow支付网关实际返回的字段名保持一致,请对照官方接口文档调整对应字段。
内容的提问来源于stack exchange,提问作者Echiye Forcde
相关产品推荐
相关产品推荐

