You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django后端使用Stripe实现含多参会人信息的活动预订支付关联问题

Django+Stripe活动预订支付关联方案

核心结论

不需要将所有参会人信息传入Stripe请求,完全可以沿用标准场景下「预创建本地订单+传递唯一标识回调关联」的逻辑,适配复杂参会人场景即可。

具体实现步骤

  • 第一步:本地预存预订与参会人全量数据
    用户提交所有参会人信息后,先在本地数据库创建预订主记录,状态设为待支付,同时将所有参会人信息关联到该预订记录存入数据库,生成唯一的预订编号。参考Django模型定义如下:
from django.db import models
from django.utils.translation import gettext_lazy as _

class EventBooking(models.Model):
    class BookingStatus(models.TextChoices):
        PENDING = "pending", _("待支付")
        PAID = "paid", _("已支付")
        CANCELLED = "cancelled", _("已取消")
    booking_no = models.CharField(max_length=32, unique=True, verbose_name="预订编号")
    total_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="总金额")
    status = models.CharField(max_length=16, choices=BookingStatus.choices, default=BookingStatus.PENDING, verbose_name="预订状态")
    created_at = models.DateTimeField(auto_now_add=True)
    # 可补充其他业务字段:活动ID、下单用户ID等

class EventAttendee(models.Model):
    booking = models.ForeignKey(EventBooking, on_delete=models.CASCADE, related_name="attendees", verbose_name="所属预订")
    name = models.CharField(max_length=64, verbose_name="参会人姓名")
    phone = models.CharField(max_length=16, verbose_name="手机号")
    # 可补充其他参会人专属字段:身份证号、特殊需求等
  • 第二步:创建Stripe支付会话时仅传递唯一预订标识
    创建Stripe支付会话时,仅需将本地生成的唯一预订编号存入Stripe的metadata字段即可,不需要传递任何参会人相关信息。参考代码如下:
import stripe
from django.conf import settings

stripe.api_key = settings.STRIPE_SECRET_KEY

def create_stripe_checkout_session(booking):
    session = stripe.checkout.Session.create(
        payment_method_types=['card'],
        line_items=[{
            'price_data': {
                'currency': 'cny',
                'product_data': {
                    'name': f'活动预订 {booking.booking_no}',
                },
                'unit_amount': int(booking.total_amount * 100),
            },
            'quantity': 1,
        }],
        mode='payment',
        success_url=settings.STRIPE_SUCCESS_URL,
        cancel_url=settings.STRIPE_CANCEL_URL,
        # 仅传递本地唯一预订编号,无需传入参会人信息
        metadata={
            'booking_no': booking.booking_no,
        }
    )
    return session
  • 第三步:Webhook回调时关联本地数据完成订单履约
    接收Stripe支付成功的Webhook回调时,从返回的session数据的metadata中取出预订编号,查询本地数据库即可直接获取对应的预订记录和全量参会人信息,更新预订状态为已支付后即可完成后续履约逻辑。参考代码如下:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
import stripe

@csrf_exempt
def stripe_webhook(request):
    payload = request.body
    sig_header = request.META['HTTP_STRIPE_SIGNATURE']
    event = None

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
        )
    except ValueError:
        return HttpResponse(status=400)
    except stripe.error.SignatureVerificationError:
        return HttpResponse(status=400)

    # 处理支付成功事件
    if event['type'] == 'checkout.session.completed':
        session = event['data']['object']
        # 从metadata获取本地预订编号
        booking_no = session.get('metadata', {}).get('booking_no')
        if not booking_no:
            return HttpResponse(status=400)
        try:
            booking = EventBooking.objects.get(booking_no=booking_no, status=EventBooking.BookingStatus.PENDING)
        except EventBooking.DoesNotExist:
            return HttpResponse(status=404)
        # 更新预订状态
        booking.status = EventBooking.BookingStatus.PAID
        booking.save()
        # 直接通过 booking.attendees.all() 即可获取全量参会人信息,执行后续履约逻辑
        # 如发送参会通知、生成核销凭证等

    return HttpResponse(status=200)

方案优势

  • 所有业务敏感数据(参会人个人信息等)均存储在本地,避免跨境数据传输的合规风险,也不会受Stripe接口字段限制
  • 逻辑与标准商品支付流程对齐,开发成本低,问题排查路径清晰
  • 待支付状态的预订数据已完整存储,用户支付失败后再次发起支付无需重复填写参会人信息,用户体验更好

内容的提问来源于stack exchange,提问作者bodger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:45:04