Django网站集成帕夏银行支付系统:流程疑问与SSL错误排查求助
Django集成帕夏银行支付系统问题解决指南
一、SSL错误原因及解决方法
你遇到的SSL错误,本质是银行服务器使用了自签名证书(或证书链包含自签名证书),而requests库默认会验证服务器证书的合法性,因此触发了验证失败。
银行提供的安全证书就是用来解决这个问题的,具体用法是在请求时指定该证书作为验证依据:
import requests def send_request(): url = 'https://ecomm.pashabank.az:18443/ecomm2/MerchantHandler/?command=v&amount=5¤cy=932&client_ip_addr=167.184.1.132&msg_type=SMS' # 替换为你存放银行证书的实际路径 bank_cert_path = '/path/to/your/django/project/certs/pasha_bank_cert.pem' # 通过verify参数指定证书,让requests用它验证服务器身份 response = requests.post(url, verify=bank_cert_path) print(response) send_request()
注意:绝对不要用
verify=False跳过验证,这会让请求暴露在中间人攻击风险下,不符合支付安全要求。
二、帕夏银行支付集成完整流程(Django后台)
1. 核心流程原理
- 用户在你的网站发起支付请求(点击付款按钮)
- Django后端生成银行要求的参数(金额、货币、用户IP等),向银行的
MerchantHandler接口发送初始化请求 - 银行返回支付会话ID或跳转URL
- 后端把跳转URL返回给前端,前端通过新窗口打开该URL让用户填写银行卡信息
- 用户完成支付后,银行通过回调接口主动通知你的后端支付结果
- 后端根据回调结果更新订单状态,并返回确认响应给银行
2. Django具体实现步骤
(1)编写支付初始化视图
在views.py中处理前端的支付请求:
from django.http import JsonResponse import requests import xml.etree.ElementTree as ET def initiate_payment(request): if request.method != 'POST': return JsonResponse({'status': 'error', 'msg': '仅支持POST请求'}) # 从前端或订单模型获取支付信息 amount = request.POST.get('amount', '5') # 获取用户真实IP(如果网站有反向代理,需要配置Django的X-Forwarded-For解析) client_ip = request.META.get('REMOTE_ADDR') currency = '932' # 阿塞拜疆马纳特的标准货币代码 bank_api_url = 'https://ecomm.pashabank.az:18443/ecomm2/MerchantHandler/' params = { 'command': 'v', # 按银行文档指定的初始化命令 'amount': amount, 'currency': currency, 'client_ip_addr': client_ip, 'msg_type': 'SMS', 'order_id': 'YOUR_ORDER_ID' # 传递你的系统订单ID,回调时用来关联订单 } bank_cert_path = '/path/to/your/certs/pasha_bank_cert.pem' try: response = requests.post(bank_api_url, params=params, verify=bank_cert_path) # 解析银行返回的XML响应(根据银行文档格式调整) root = ET.fromstring(response.content) session_id = root.find('session_id').text # 拼接用户支付页面URL payment_page_url = f'https://ecomm.pashabank.az:18443/ecomm2/PaymentPage?session_id={session_id}' return JsonResponse({'status': 'success', 'payment_url': payment_page_url}) except Exception as e: return JsonResponse({'status': 'error', 'msg': str(e)})
(2)编写支付回调视图
银行支付完成后会主动调用你的回调接口,用来通知支付结果:
from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt import xml.etree.ElementTree as ET @csrf_exempt # 银行回调不会携带CSRF令牌,需禁用验证 def payment_callback(request): if request.method != 'POST': return HttpResponse('无效请求') # 解析银行回调的XML内容 root = ET.fromstring(request.body) order_id = root.find('order_id').text payment_status = root.find('status').text amount = root.find('amount').text # 这里更新你的订单状态,比如: # from .models import Order # Order.objects.filter(id=order_id).update(payment_status=payment_status) # 必须返回银行要求的确认响应,示例为XML格式 confirm_xml = '<response><result>OK</result></response>' return HttpResponse(confirm_xml, content_type='application/xml')
(3)配置URL路由
在urls.py中添加对应路由:
from django.urls import path from . import views urlpatterns = [ path('payment/initiate/', views.initiate_payment, name='initiate_payment'), path('payment/callback/', views.payment_callback, name='payment_callback'), ]
(4)前端简单实现
前端点击付款按钮时,请求后端获取支付URL并打开新窗口:
document.getElementById('pay-button').addEventListener('click', async () => { const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; const response = await fetch('/payment/initiate/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrfToken }, body: 'amount=10' // 替换为实际订单金额 }); const data = await response.json(); if (data.status === 'success') { window.open(data.payment_url, '_blank', 'width=650,height=850'); } else { alert('支付初始化失败:' + data.msg); } });
三、关键注意事项
- 证书管理:银行证书要存放在Django项目的安全目录,不要提交到版本仓库
- IP准确性:必须传递用户真实IP,否则银行可能拒绝请求;若使用Nginx等反向代理,需配置Django的
USE_X_FORWARDED_HOST和SECURE_PROXY_SSL_HEADER - 回调安全:要验证回调请求的真实性,比如通过银行提供的IP白名单、请求签名验证(具体看银行文档)
- 异常处理:要处理请求超时、银行返回错误码等情况,避免订单状态不一致
内容的提问来源于stack exchange,提问作者HTML
相关产品推荐
相关产品推荐

