DEV Community

fullStackMafia🀄
fullStackMafia🀄

Posted on

How to build a custom checkout page in minutes with Django and JavaScript.

When implementing payment options in an app, it's always a good idea to have a payment process that's as brief and straightforward as possible. In this article, we're going to build a checkout modal to process one time payments on web apps using Rave, Django and JavaScript. To solve the issue of using pip and virtualenv together, we'll use pipenv to create our development environment. If you need help setting up pipenv, please check out this guide.

Setting up a Project

The first thing we'll do is install Django. Then we'll start a new project which we'll name djangorave. In this project, we'll create our first app which we'll call payments. Navigate to your terminal and input the following commands:

   # install Django
   $ pipenv install django

   # activate the pipenv shell to start a new shell subprocess
   $ pipenv shell

   (rave-checkout-python) $ django-admin startproject djangorave
   (rave-checkout-python) $ python manage.py startapp payments

Enter fullscreen mode Exit fullscreen mode

Note that the virtual environment rave-checkout-python is just a part of my code directory, yours can be anything you choose. Let's add the newly installed app to the INSTALLED_APPS configuration in settings.py:

INSTALLED_APPS = [
    'django.contrib',
    'django.contrib.admin',
    'django.contrib .auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    #update the newly installed app
    'payments.apps.PaymentsConfig',
]

Enter fullscreen mode Exit fullscreen mode

Next, in the same folder we'll update the urls.py file to include the payments app:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('payments.urls')), 
]

Enter fullscreen mode Exit fullscreen mode

Our next step is to create a homepage for our application. In the djangorave parent folder, create a folder named templates and in it, your homepage:


(rave-checkout-python) $ mkdir templates
(rave-checkout-python) $ touch templates/homepage.html
Enter fullscreen mode Exit fullscreen mode

Then we'll update the settings.py file so Django can access the templates folder:


#djangorave/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'], # add this line
        'APP_DIRS': True,
     },
]
Enter fullscreen mode Exit fullscreen mode

We'll just fill the homepage with a basic message for now:


   # templates/homepage.html

   My First Django app
Enter fullscreen mode Exit fullscreen mode

Then in the payments folder, we'll create a views.py file where Django class-based and generic views will be used to render the homepage:


   # payments/views.py

   from django.views.generic.base import TemplateView

   class HomePageView(TemplateView):
       template_name = 'homepage.html'
Enter fullscreen mode Exit fullscreen mode

The view exists but it doesn't have a URL path yet. Let's change this by creating a urls.py in our payments app where we'll assign a path to our view:

    #payments/urls.py

    from django.urls import path
    from . import views

    urlpatterns = [
        path('', views.HomePageView.as_view(), name='homepage'),
    ]

Enter fullscreen mode Exit fullscreen mode

At this point, our app is good enough to be viewed on the browser. Let's synchronize the changes we've made so far to our database and start the app on our local server:


# use the migrate command to sync to your database
(rave-checkout-python) $ python manage.py migrate

# start a local webserver with the runserver command
(rave-checkout-python) $ python manage.py runserver
Enter fullscreen mode Exit fullscreen mode

This starts up your app on http://127.0.0.1:8000/. Navigate to this path on your browser and you should see your home page:

Alt Text

Integrate Rave

The second phase of building this app will be to integrate Rave into the app. Head on to Rave's website and sign up for an account. On your dashboard, first switch from live mode to test mode then navigate to Settings > API and get your API keys:

Alt Text

Copy your public and secret keys and paste them at the bottom of your settings.py file. Be sure to include the inverted commas:


    #settings.py

    RAVE_PUBLIC_KEY = 'YOUR PUBLIC KEY HERE'
    RAVE_SECRET_KEY = 'YOUR SECRET KEY HERE'

Enter fullscreen mode Exit fullscreen mode

Building the checkout form

Now we have our API keys, let's add Rave's inline script to our homepage.html file:


    <form>
      <script src="https://api.ravepay.co/flwv3-pug/getpaidx/api/flwpbf-inline.js"></script>
        <h3>SUPPORT NATURE WITH AS LOW AS $1</h3>
        <button type="button" onClick="payWithRave()">Donate Here</button>
    </form>
    <script>
        const publicKey = "{{ key }}";

        function payWithRave() {
            var x = getpaidSetup({
                PBFPubKey: publicKey,
                customer_email: "user@example.com",
                amount: 1,
                customer_phone: "234099940409",
                currency: "USD",
                txref: "rave-123456",
                custom_title: "Wildlife Park",
                onclose: function() {},
                callback: function(response) {
                    var txref = response.tx.txRef;
                    console.log("This is the response returned after a charge", response);
                    x.close();
                }
            });
        }
    </script>

Enter fullscreen mode Exit fullscreen mode

In the above template, you'll notice there's a {{ key }} attribute assigned to the publickey constant. It should hold the value of our Rave public key. Let's update its value in views.py:


# payments/views.py

from django.conf import settings
from django.views.generic.base import TemplateView

class HomePageView(TemplateView):
    template_name = 'homepage.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['key'] = settings.RAVE_PUBLIC_KEY
        return context
Enter fullscreen mode Exit fullscreen mode

Hit the refresh button and a basic HTML page that we can work with comes up:

Click on the Donate Here button and a modal customized by Rave opens up for you to make payment:

Alt Text

Make a test payment by using one of Rave's test cards here. Let's use 5531 8866 5214 2950, ensure that the expiry date and CVV number are correctly inputted as well. If prompted for an OTP or PIN, use the specified values in the list of cards:

Alt Text

To confirm that payment was successful, head on to your Rave dashboard and click on Transactions to access your transaction history:

Alt Text

Payment verification from the user's end

Sure our merchants can tell that payments are being made to their Rave account but how can a user tell that their payment was successful? Let's create a page that displays a success message to a user whenever they make a successful payment. In the templates folder, create a new file success.html:

# templates/success.html

<h3>Your payment was successful<h3/>
Enter fullscreen mode Exit fullscreen mode

Next, we'll create a view for success.html:


#payments/views.py

from django.shortcuts import render
from django.conf import settings
from django.views.generic.base import TemplateView
class HomePageView(TemplateView):
    template_name = 'home.html'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['key'] = settings.RAVE_PUBLIC_KEY
        context['logo'] = settings.WILDLIFE_LOGO
        return context

# create the view here
class Success(TemplateView):
    template_name = 'success.html'
Enter fullscreen mode Exit fullscreen mode

Then we'll create a URL Pattern for the view:


    #payments/urls.py

    from django.urls import path
    from . import views
    urlpatterns = [
        path('success.html', views.Success.as_view(), name='success') #add this line,
        path('', views.HomePageView.as_view(), name='home'),
    ]

Enter fullscreen mode Exit fullscreen mode

Lastly, we'll include success.html in the callback function in homepage.html:


    callback: function(response) {
        var txref = response.tx.txRef;
        console.log("This is the response returned after a charge", response);
        if (
            response.tx.chargeResponseCode == "00" ||
            response.tx.chargeResponseCode == "0"
        ) {
            document.location.href = "success.html"
                // redirect to a success page
        } else {
            // redirect to a failure page.
        }
        x.close();
    }

Enter fullscreen mode Exit fullscreen mode

Seems we're good to go. Let's make a test payment and see what the flow looks like:

Summary

In a more practical scenario, we would use a more secure connection and also be more careful with handling our API keys by storing them securely in environment variables. Should you need the source code of this demo, you can find it here.

Top comments (7)

Collapse
 
o3cloudng profile image
Olumide Oderinde

Nice work @fullstackmafia ,
I have something like this already with more security using Django decouple .env etc
I want to ask for an ideal way to generate unique txref for each transaction as opposed to the default txref: "rave-123456",?

Collapse
 
temmy_web profile image
Adesiyan Tope

I have an ecommercebapplication which i am building, I want to use DJANGORAVE to make payment. I have issues with how to pass the amount and email context to the JavaScript file, please help me.

Collapse
 
derekzyl profile image
derekzyl

How did you sort out this challenge??

Collapse
 
igweprince0 profile image
SkyData 🤖

This is nice, but is there anyway I can get and order id after transaction is successful? I want to update a model instance after payment. Please help.

Collapse
 
igweprince0 profile image
SkyData 🤖

Never mind, I figured it out.

Collapse
 
primestar_ace profile image
PRIME STAR ACE

How do i add this to sign up forms??

Collapse
 
trabelsi10chaima profile image
trabelsi10chaima

where does the money goes can't we configure an account where all the payment go there