【问题标题】:How to change make changes to my 'Order' in Django after receiving payment by Stripe Checkout Session?收到 Stripe Checkout Session 付款后,如何在 Django 中更改我的“订单”?
【发布时间】:2021-05-02 02:31:12
【问题描述】:

我正在通过 Django 制作一个电子商务网站,并希望使用 Stripe Checkout Session 来接收在线付款。

我关注 https://stripe.com/docs/api/checkout/sessions 创建结帐会话,关注 https://stripe.com/docs/webhooks/build 创建 webhook。

我可以顺利收到付款,但我想在收到付款后立即将“订单”更改为“完成 = True”。但是,视图“stripe_webhook”的请求没有用户属性,所以我不能调用“request.user”来获取相应的“订单”。我该如何解决这个问题?非常感谢。

models.py

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date_created = models.DateTimeField(auto_now_add=True, null = True, blank = True)
    date_completed = models.DateTimeField(null = True, blank = True)
    complete = models.BooleanField(default=False)
    transaction_id = models.CharField(max_length=100, null=True)

    def __str__(self):
        return f'{self.user.username} {self.date_created}'

views.py

@login_required
def stripe_payment(request):
    return render(request, 'stripe_payment.html', {})


@csrf_exempt
def stripe_config(request):
    if request.method == 'GET':
        stripe_config = {'publicKey': settings.STRIPE_PUBLISHABLE_KEY}
        return JsonResponse(stripe_config, safe=False)


@csrf_exempt
def stripe_create_checkout_session(request):
    if request.method == 'GET':
        domain_url = 'http://localhost:8000/'
        stripe.api_key = settings.STRIPE_SECRET_KEY
        order = Order.objects.get(user = request.user, complete = False)
        total = int(order.get_cart_items_total) * 100

        try:
            checkout_session = stripe.checkout.Session.create(
                success_url = domain_url + 'success?session_id={CHECKOUT_SESSION_ID}',
                cancel_url = domain_url + 'cancelled/',
                payment_method_types = ['card'],
                mode = 'payment',
                line_items = [
                    {
                        'name': ' ',
                        'quantity': 1,
                        'currency': 'usd',
                        'amount': total,
                    }
                ]
            )
            return JsonResponse({'sessionId': checkout_session['id']})

        except Exception as e:
            return JsonResponse({'error': str(e)})


@csrf_exempt
def stripe_webhook(request):
    stripe.api_key = settings.STRIPE_SECRET_KEY
    endpoint_secret = settings.STRIPE_ENDPOINT_SECRET
    payload = request.body
    sig_header = request.META['HTTP_STRIPE_SIGNATURE']
    event = None

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, endpoint_secret
        )
    except ValueError as e:
        # Invalid payload
        return HttpResponse(status=400)
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return HttpResponse(status=400)

    # Handle the checkout.session.completed event
    if event['type'] == 'checkout.session.completed':
        print("Payment was successful.")

        #request of this view does not have any user attribute
        order = Order.objects.get(user = request.user, complete = False)
        transaction_id = datetime.now().timestamp()
        order.complete = True
        order.transaction_id = transaction_id
        order.date_completed = datetime.now()
        order.save()
        print("Order was successfully updated and saved.")

    return HttpResponse(status=200)


def payment_success(request):
    return render(request, 'success.html', {})


def payment_cancel(request):
    return render(request, 'cancelled.html', {})

stripe.js

fetch("/stripe_config/")
.then((result) => { return result.json(); })
.then((data) => {
    // Initialize Stripe.js
    const stripe = Stripe(data.publicKey);

    // Event handler
    document.querySelector("#submitBtn").addEventListener("click", () => {
    // Get Checkout Session ID
    fetch("/stripe_create_checkout_session/")
    .then((result) => { return result.json(); })
    .then((data) => {
        console.log(data);
        // Redirect to Stripe Checkout
        return stripe.redirectToCheckout({sessionId: data.sessionId})
    })
    .then((res) => {
        console.log(res);
    });
    });
});

urls.py from django.urls 导入路径 从 .views 导入 *

urlpatterns = [  
    path('stripe_payment/', stripe_payment, name = 'stripe_payment'),
    path('stripe_config/', stripe_config, name = 'stripe_config'),
    path('stripe_create_checkout_session/', stripe_create_checkout_session, name = 'stripe_create_checkout_session'),
    path('webhook/', stripe_webhook),
    path('success/', payment_success, name = 'payment_success'),
    path('cancelled/', payment_cancel, name = 'payment_cancel'),

]

stripe_payment.html

{% extends 'base.html' %}
{% load static %}

{% block head_title %}Django + Stripe Checkout{% endblock %}


{% block extra_head %}
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.2/css/bulma.min.css">
    <script src="https://js.stripe.com/v3/"></script>
    <script src="{% static 'js/stripe.js' %}"></script>
    <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
{% endblock %}


{% block content %}
<!--Main layout-->
    <main>
        <section class="section">
        <div class="container">
            <button class="button is-primary" id="submitBtn">Purchase!</button>
        </div>
        </section>
    </main>
<!--Main layout-->
{% endblock content %}

【问题讨论】:

    标签: django stripe-payments


    【解决方案1】:

    Stripe webhook 事件有一个 data.object 属性,它表示事件所涉及的对象。

    checkout.session.completed 事件的情况下,data.object 将描述一个 Checkout Session 对象,其中包含对创建的 customer 的 ID 的引用。

    webhook 事件不会有 request.user 属性,因为调用来自 Stripe 而不是来自您的客户端。您可能希望收集 Stripe 客户 ID 或 Checkout Session ID 并将其映射到您自己数据库中的用户。

    【讨论】:

    • 如何收集结帐会话 ID 并将其映射到我数据库中的用户?确认付款后(发生在“stripe_webhook”视图中),我已经不能打电话给“用户”了。我应该如何将结帐会话 ID 映射到用户?谢谢。
    猜你喜欢
    • 1970-01-01
    • 2023-04-11
    • 2021-12-09
    • 2022-07-28
    • 2021-06-10
    • 2020-03-15
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    相关资源
    最近更新 更多