请求指导Django集成Stripe自定义支付流程及用户信息处理
Django集成Stripe自定义支付流完整指南
1. 后端核心逻辑:创建支付意图与用户信息存储
首先需要在Django后端实现两个核心接口:生成Stripe Payment Intent的接口,以及接收Stripe支付状态通知的Webhook接口,同时要设计订单模型来存储用户信息和支付关联数据。
定义订单模型
先创建一个Order模型,用来保存用户信息、商品详情和支付状态:
# models.py from django.db import models class Order(models.Model): STATUS_CHOICES = ( ('pending', '待支付'), ('paid', '已支付'), ('failed', '支付失败'), ) customer_name = models.CharField(max_length=100) customer_email = models.EmailField() customer_phone = models.CharField(max_length=20) item_id = models.CharField(max_length=50) # 对应你商品的唯一标识,比如"xl-tshirt" amount = models.IntegerField() # 金额单位为分(Stripe要求) stripe_payment_intent_id = models.CharField(max_length=100, blank=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending') created_at = models.DateTimeField(auto_now_add=True)
实现Payment Intent创建接口
这个接口负责接收前端传来的用户信息和商品ID,创建订单记录,并生成Stripe支付意图:
# views.py import stripe from django.conf import settings from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .models import Order stripe.api_key = settings.STRIPE_SECRET_KEY @csrf_exempt def create_payment_intent(request): if request.method != 'POST': return JsonResponse({'error': '仅支持POST请求'}, status=405) # 提取前端提交的用户信息和商品ID data = request.POST customer_name = data.get('customer_name') customer_email = data.get('customer_email') customer_phone = data.get('customer_phone') item_id = data.get('item_id') # 根据商品ID获取对应金额(实际项目中建议从商品数据库读取) item_amount_map = { 'xl-tshirt': 2000, # 代表20美元 # 可添加更多商品配置 } amount = item_amount_map.get(item_id, 0) if amount == 0: return JsonResponse({'error': '无效的商品ID'}, status=400) # 创建订单记录,保存用户信息 order = Order.objects.create( customer_name=customer_name, customer_email=customer_email, customer_phone=customer_phone, item_id=item_id, amount=amount ) # 生成Stripe Payment Intent try: payment_intent = stripe.PaymentIntent.create( amount=amount, currency='usd', metadata={ 'order_id': order.id, # 关联订单ID,方便后续Webhook更新状态 'item_id': item_id } ) # 更新订单的支付意图ID order.stripe_payment_intent_id = payment_intent.id order.save() return JsonResponse({'clientSecret': payment_intent.client_secret}) except stripe.error.StripeError as e: return JsonResponse({'error': str(e)}, status=400)
配置接口路由
在urls.py中添加对应路由:
# urls.py from django.urls import path from . import views urlpatterns = [ path('create-payment-intent/', views.create_payment_intent, name='create_payment_intent'), # 其他路由... ]
2. 前端自定义结账页面实现
前端需要完成商品展示、用户信息收集、Stripe支付表单渲染,以及提交数据到后端的逻辑:
<!-- checkout.html 自定义结账页面 --> <!DOCTYPE html> <html> <head> <title>确认订单与支付</title> <script src="https://js.stripe.com/v3/"></script> </head> <body> <!-- 商品详情区域 --> <div class="product-card"> <h2>XL纯棉T恤</h2> <p>价格:$20.00</p> <input type="hidden" id="item-id" value="xl-tshirt"> </div> <!-- 用户信息收集表单 --> <form id="customer-form"> <div> <label>姓名:</label> <input type="text" id="customer-name" required> </div> <div> <label>邮箱:</label> <input type="email" id="customer-email" required> </div> <div> <label>电话:</label> <input type="tel" id="customer-phone" required> </div> </form> <!-- Stripe支付元素容器 --> <div id="payment-element"></div> <button id="pay-btn">完成支付</button> <div id="error-message"></div> <script> // 初始化Stripe,替换为你的公钥 const stripe = Stripe('pk_test_your_public_key'); const elements = stripe.elements(); // 渲染支付表单 const paymentElement = elements.create('payment'); paymentElement.mount('#payment-element'); const payBtn = document.getElementById('pay-btn'); const itemId = document.getElementById('item-id').value; payBtn.addEventListener('click', async (e) => { e.preventDefault(); payBtn.disabled = true; // 收集用户表单数据 const customerName = document.getElementById('customer-name').value; const customerEmail = document.getElementById('customer-email').value; const customerPhone = document.getElementById('customer-phone').value; // 向后端请求生成支付意图 const response = await fetch('/create-payment-intent/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ customer_name: customerName, customer_email: customerEmail, customer_phone: customerPhone, item_id: itemId }) }); const data = await response.json(); if (data.error) { document.getElementById('error-message').textContent = data.error; payBtn.disabled = false; return; } // 确认支付 const { error } = await stripe.confirmPayment({ elements, clientSecret: data.clientSecret, confirmParams: { return_url: 'https://your-domain.com/payment-success/', // 支付成功跳转页 }, }); if (error) { document.getElementById('error-message').textContent = error.message; payBtn.disabled = false; } }); </script> </body> </html>
3. 配置Stripe Webhook更新支付状态
为了确保支付状态的准确性,必须通过Stripe Webhook监听支付事件,更新本地订单状态:
实现Webhook接口
# views.py @csrf_exempt def stripe_webhook(request): payload = request.body sig_header = request.META.get('HTTP_STRIPE_SIGNATURE') event = None try: event = stripe.Webhook.construct_event( payload, sig_header, settings.STRIPE_WEBHOOK_SECRET ) except (ValueError, stripe.error.SignatureVerificationError): return JsonResponse({'error': '验证失败'}, status=400) # 处理支付成功事件 if event['type'] == 'payment_intent.succeeded': payment_intent = event['data']['object'] order_id = payment_intent['metadata']['order_id'] try: order = Order.objects.get(id=order_id) order.status = 'paid' order.save() # 这里可添加发送确认邮件、生成订单凭证等后续逻辑 except Order.DoesNotExist: pass # 处理支付失败事件 elif event['type'] == 'payment_intent.payment_failed': payment_intent = event['data']['object'] order_id = payment_intent['metadata']['order_id'] try: order = Order.objects.get(id=order_id) order.status = 'failed' order.save() except Order.DoesNotExist: pass return JsonResponse({'status': 'success'})
添加Webhook路由
# urls.py urlpatterns += [ path('stripe-webhook/', views.stripe_webhook, name='stripe_webhook'), ]
最后在Stripe后台配置Webhook端点,指向你的域名/stripe-webhook/,并监听payment_intent.succeeded和payment_intent.payment_failed事件,将生成的Webhook Secret配置到Django的settings.py中。
用户信息处理说明
- 收集:通过前端自定义表单收集用户姓名、邮箱、电话等信息,和商品ID一起提交到后端。
- 存储:后端接口接收数据后,直接写入
Order模型,完成用户信息与订单的绑定。 - 关联支付:创建Payment Intent时,通过
metadata字段将订单ID传递给Stripe,确保Webhook能准确关联到对应订单。 - 后续使用:支付成功后,可通过
Order记录中的用户信息发送确认通知、生成订单详情页等。
内容的提问来源于stack exchange,提问作者Paul Viorel
相关产品推荐
相关产品推荐

