Django Oscar - Stripe Integration - Part 20

This post comes in the sequence of:

 

Content:

  1. Stripe Configurations
  2. Redirect View
  3. Success View

 

 

 

1. Stripe Configurations

 

pip install stripe

 

  1. Create an account in Stripe
  2. Switch to the Test mode
  3. From the left bottom click Developers
  4. Copy the Publishable Key and the Secret Key as a string to your settings.py
     
STRIPE_PUBLISHABLE_KEY = "*****"   
STRIPE_SECRET_KEY = "*****"       

 

 

 

2. Redirect View

 

import stripe
from django.conf import settings
from django.urls import reverse

class GatewayRedirect(CheckoutSessionMixin, RedirectView):

    def get_redirect_url(self, **kwargs):

        basket = self.build_submission()['basket']

        if basket.is_empty:
            messages.error(self.request, "Your basket is empty")
            return reverse('basket:summary')

        else: basket.freeze()


        shipping_address = self.get_shipping_address(basket)
        shipping_method = self.get_shipping_method(basket, shipping_address=shipping_address)
        shipping_charge = shipping_method.calculate(basket)

        stripe.api_key = settings.STRIPE_SECRET_KEY
        session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            line_items=[{
                'price_data': {
                    'currency': 'eur',
                    'product_data': {'name': f"Basket #{basket.id}"},
                    'unit_amount': int((basket.total_incl_tax + shipping_charge.incl_tax) * 100),
                },
                'quantity': 1,
            }],
            mode='payment',
            success_url=self.request.build_absolute_uri(reverse('gateway_success', args=[basket.id]) )+"?session_id={CHECKOUT_SESSION_ID}",
            cancel_url=self.request.build_absolute_uri(reverse('gateway_cancel', args=[basket.id]) ),
            metadata={'basket_id': basket.id, 'method': "Stripe"},
        )


        return session.url   

 

 

 

3. Success View

 

class GatewaySuccess(PaymentDetailsView, OrderPlacementMixin):

    ...
    
    def get(self, request, *args, **kwargs):
        basket_id = kwargs.get('basket_id') 
        basket = Basket.objects.get(id=basket_id, status=Basket.FROZEN)
        if Selector: basket.strategy = Selector().strategy(self.request)
        Applicator().apply(basket, self.request.user, request=self.request)

        
        session_id = request.GET.get("session_id")
        if not session_id:
            messages.error(request, "Session not valid")
            basket.thaw()
            return redirect('basket:summary')

        try:
            session = stripe.checkout.Session.retrieve(session_id)
        except stripe.error.StripeError as e:
            messages.error(request, f"Error verifying the payment: {str(e)}")
            basket.thaw()
            return redirect('basket:summary')

        if session.payment_status != "paid":
            messages.error(request, "Payment not finished")
            basket.thaw()
            return redirect('basket:summary')
    
        
        return self.submit(**self.build_submission(basket=basket))