Build a payment system with Django 3.1 and Stripe from scratch. Part 2
By: Alberto Naranjo
Tags: Python3, E Commerce Solution, Tech Entrepreneurs, Stripe, Django Rest Framework

Build the products page

The products page is the front store of your business, where you users will choose one or more products or digital services to buy before actually paying for them in a checkout page. For our tutorial we are going to suppose the user will pay for only one item at a time like a micro transaction to unlock some features from your web app. The options available for users to buy will be: Regular, Pro or Platinum. Right now we don’t care about how to enable this features for the user or what exactly happens after a payment is done. We will focus on this section on showing the items and starting a secure session.

Like a regular tech entrepreneur with full-stack coding skills we will need to change our hat at this point and go from backend development to frontend development. We will need to work with a basic html template to show our app interface and implement some functions in javascript to handle the secure Stripe session creation. But don’t worry! We will be back soon to the fun land of the backend and database development.

The page template and URL path

Django needs templates to render a view in HTML. So first create a /templates folder inside our /stripe_shop app folder. Django will search for templates by default in this folder for all the installed apps. Next we will create a basic template file called shop.html with some Bootstrap components in order to create our interface. Usually when working with templates you setup a modular system where the common components as the navigation or the header are included as blocks in a base template you just can render with your current page content. But this time since we only handling one page we are not going to create anything fancy, but at least it won’t look like a 1999 website and it won’t hurt your eyes while you are testing it. All advantages as you can see!

Copy this gist content into stripe_shop/templates/shop.html

Now we need to add the path to the view to render our shop template. Since we are not processing or passing any context to the template we can render directly without adding a view function using Django’s TemplateView.as_view directly in the url paths. Go to your main app’s url path settings myshop/urls.py and add the following lines:

...

from django.views.generic import TemplateView urlpatterns = [

...

path('', TemplateView.as_view(template_name='shop.html')),

]

First we import TemplateView class to render the template as a view, then we call the template directly in the default path. Now if you run the server and open http://127.0.0.1:8000 you should see our splendid new product page as a default page in our project.

Yay! our front store ready to sell some things and stuff

Adding javascript functionality

Our product page looks nice but the buttons don’t have any functionality. We need to add some vanilla javascript to handle the Stripe secure session creation. We still don’t have this endpoint ready in our app but we will add later right after. For now add these lines at the end of the <head> tag in our template shop.html :

<script src="https://js.stripe.com/v3/"></script>

This will call the the javascript library to handle secure transactions with Stripe. Then add this function at the end of the <body> tag in our shop.html template:

<script type="text/javascript">

// Create an instance of the Stripe object with your publishable API key

var stripe = Stripe('...');



// Gets all buy buttons

var buttons = document.getElementsByClassName('buy-button');

for (i = 0; i < buttons.length; i++) {



// for every button we will add a Stripe POST request action

buttons[i].addEventListener('click', function(event) {

var targetElement = event.target || event.srcElement;

var productName = targetElement.value;

console.log('Buying: ' + productName);



// Our endpoint with the chosen product name

var url = '/create-checkout-session/' + productName



// Create a new Checkout Session

fetch(url, {

method: 'POST',

})

.then(function(response) {

return response.json();

})

.then(function(session) {

return stripe.redirectToCheckout({ sessionId: session.id });

})

.then(function(result) {

// If `redirectToCheckout` fails due to a browser or network

// error, you should display the localized error message to your

// customer using `error.message`.

if (result.error) {

alert(result.error.message);

}

})

.catch(function(error) {

console.error('Error:', error);

});



});



}

</script>

First you will need to fill your Stripe public key in the Stripe instance constructor, double check you are using indeed the public key and not the private one. Since we are not passing any variable context to the template we can edit the key directly in the html code, however for a more advance system I highly recommend you to render the public key we already have in settings.py and you can pass to the template. Next functionality is pretty straight forward: we create an array with the button objects and we add them an event listener for the click events on them. Then we use the value property on each button to identify the product the user is selecting to buy. Using an asynchronous POST action we fetch a future endpoint (we haven’t implement it yet) in our project to start a secure checkout session. This endpoint will receive a productName from the buttons as a parameter in the url. If you would have more parameters to pass to the endpoint it should be good to handle them inside the body parameter of the javascript's fetch function.