如何将PayPal前端支付信息存入Django数据库?
问题描述
我在Django Web应用的前端使用PayPal标准IPN支付方案,前端代码如下:
<body> <!-- Set up a container element for the button --> <div id="paypal-button-container"></div> <!-- Include the PayPal JavaScript SDK --> <script src="https://www.paypal.com/sdk/js?client-id=test¤cy=USD"></script> <script> // Render the PayPal button into #paypal-button-container paypal.Buttons({ // Set up the transaction createOrder: function(data, actions) { return actions.order.create({ purchase_units: [{ amount: { value: '88.44' } }] }); }, // Finalize the transaction onApprove: function(data, actions) { return actions.order.capture().then(function(orderData) { // Successful capture! For demo purposes: console.log('Capture result', orderData, JSON.stringify(orderData, null, 2)); }); } }).render('#paypal-button-container'); </script> </body>
目前前端可以正常获取支付详情orderData,但尝试多种方法都无法将这些详情存入Django数据库(希望用简单模型实现,无需复杂API)。另外我不想使用django-paypal包,因为了解到它只支持“立即购买”按钮,没有智能按钮,无法支持信用卡/借记卡支付。请问:
django-paypal包是否支持智能按钮?- 如何手动实现将支付详情存入Django数据库?
解答
1. django-paypal是否支持智能按钮?
django-paypal主要针对传统的PayPal IPN和旧版Express Checkout方案,不支持当前PayPal JS SDK提供的智能按钮。它的按钮方案仅适配老式的“立即购买”按钮,无法支持信用卡/借记卡直接支付,你的顾虑是正确的,不使用该包是合理选择。
2. 手动实现支付详情存入Django数据库的步骤
步骤1:创建支付记录模型
在Django app的models.py中定义存储支付信息的模型,根据需求调整字段:
from django.db import models class PaymentRecord(models.Model): paypal_order_id = models.CharField(max_length=100, unique=True, verbose_name="PayPal订单ID") amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="支付金额") currency = models.CharField(max_length=10, verbose_name="货币类型") status = models.CharField(max_length=50, verbose_name="支付状态") buyer_email = models.EmailField(verbose_name="买家邮箱") created_at = models.DateTimeField(auto_now_add=True, verbose_name="记录创建时间") def __str__(self): return f"订单 {self.paypal_order_id} - {self.status}"
执行迁移命令创建表:
python manage.py makemigrations python manage.py migrate
步骤2:编写后端接收视图
在views.py中编写处理前端请求的视图,解析并保存支付数据:
from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST from .models import PaymentRecord import json @require_POST @csrf_exempt # 开发环境临时使用,生产环境请替换为CSRF令牌验证 def save_payment_record(request): try: # 解析前端传来的JSON数据 order_data = json.loads(request.body) # 提取核心支付信息(根据PayPal返回的orderData结构调整) paypal_order_id = order_data.get("id") amount = order_data["purchase_units"][0]["amount"]["value"] currency = order_data["purchase_units"][0]["amount"]["currency_code"] status = order_data["status"] buyer_email = order_data["payer"]["email_address"] # 创建并保存记录 PaymentRecord.objects.create( paypal_order_id=paypal_order_id, amount=amount, currency=currency, status=status, buyer_email=buyer_email ) return JsonResponse({"success": True, "message": "支付记录保存成功"}) except Exception as e: return JsonResponse({"success": False, "error": str(e)}, status=400)
步骤3:配置URL路由
在app的urls.py中添加视图路由:
from django.urls import path from . import views urlpatterns = [ # 其他路由... path("save-payment/", views.save_payment_record, name="save_payment"), ]
步骤4:修改前端代码发送数据
在PayPal按钮的onApprove回调中,添加发送数据到后端的逻辑,同时处理CSRF令牌(生产环境必需):
<script> paypal.Buttons({ createOrder: function(data, actions) { return actions.order.create({ purchase_units: [{ amount: { value: '88.44' } }] }); }, onApprove: function(data, actions) { return actions.order.capture().then(function(orderData) { console.log('Capture result', orderData, JSON.stringify(orderData, null, 2)); // 发送支付数据到Django后端 fetch("/save-payment/", { method: "POST", headers: { "Content-Type": "application/json", // 生产环境添加CSRF令牌头 "X-CSRFToken": getCookie("csrftoken") }, body: JSON.stringify(orderData) }) .then(response => response.json()) .then(result => { if (result.success) { console.log("支付记录已存入数据库"); // 可在此处添加跳转感谢页等逻辑 } else { console.error("保存支付记录失败:", result.error); } }) .catch(error => { console.error("发送数据到服务器出错:", error); }); }); } }).render('#paypal-button-container'); // 获取CSRF令牌的辅助函数 function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } </script>
注意事项
- CSRF保护:生产环境必须移除
@csrf_exempt,依赖前端传递X-CSRFToken头,上面的getCookie函数可以正确获取Django设置的CSRF令牌。 - 数据验证:前端传来的数据可能被篡改,最佳实践是后端调用PayPal的订单查询API,验证
orderData的真实性后再保存(即使你说无需API,也建议补充这一步保障安全)。 - 字段调整:根据PayPal返回的
orderData实际结构,调整后端提取字段的逻辑,确保数据准确。
内容的提问来源于stack exchange,提问作者webmar
相关产品推荐
相关产品推荐

