I am making an e-commerce website by Django and want to use Stripe Checkout Session for receiving online payments.
I followed https://stripe.com/docs/api/checkout/sessions for creating checkout sessions and https://stripe.com/docs/webhooks/build for creating the webhooks.
I could receive payments smoothly, but I want to change the 'order' to 'complete = True' right after payments are received. However, the request of view 'stripe_webhook' does not have attribute of user, so I can't call 'request.user' to get the corresponding 'order'. How could I solve this issue? Thanks so much.
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 import path
from .views import *
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/[email protected]/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 %}
question from:
https://stackoverflow.com/questions/65932993/how-to-change-make-changes-to-my-order-in-django-after-receiving-payment-by-st