[PYTHON] Easy implementation of credit card payment function with PAY.JP [Django]

What is PAY.JP?

Official: https://pay.jp/

A service that makes it easy to introduce credit card payments. Implement using the provided API and SDK.

The card information input form provided by PAY.JP is an iframe.

PAYJP completely protects the high threshold around payment from the input part of the client. Therefore, it is not necessary for them to manage personal information such as the card number entered by the user, and it seems that it can be implemented by pasting at least one line of JavaScript. It's amazing.

It seems that data on payments and card information can be obtained from REST-based APIs. I think the documentation is easy for engineers to understand, so I think it's easy to implement. PAY.JP API Reference

What to implement

At the time of writing, Flask and Sinatra are the only official tutorials. Most of the other Qiita articles were implemented in Rails, so I will implement it in Django.

Introduce PAY.JP and implement the payment function.

Execution environment

MacOS Catalina version: 10.15.5
Python 3.8.3
Django 3.0.8
payjp  0.0.5

First run Django

Create a sample project folder and move it into the folder.

$ mkdir my-project; cd my-project

Install the required libraries (django, payjp).

$ pip install django payjp

Generate a Django project

$ django-admin startproject project .

Confirm that the development server is started with the following code in the directory where manage.py is generated.

$ python manage.py runserver

Check the API key for using PAYJP

You can check the API key from "API" on the left sidebar by accessing PAYJP settings screen. This time, I just want to run it in my environment, so I will use the test private key and test public key.

スクリーンショット 2020-07-06 11.11.31.png * The image is partially cropped.

Now that you're ready to work, let's create an application and work with PAYJP.

Generate a Django application that works with PAY.JP.

$ python manage.py startapp app

Edit Django config file

in settings.py Register the application created earlier and set the private key of PAY.JP.

project/settings.py


...

import payjp

...

...

...

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    #add to
    "app", 
]

...

...

...

# PAY.JP settings
payjp.api_key = "sk_test_xxxxxxxxxxxxxxxxxxxxx" #Test private key

Implement View

app/views.py


from django.shortcuts import render
from django.views.generic import View

import payjp


# Create your views here.
class PayView(View):
    """
    use PAY.JP API
    """

    def get(self, request):
        #Pass the public key
        return render(
            request, "index.html", {"public_key": "pk_test_xxxxxxxxxxxxxxxxxxxxxxxx"}
        )

    def post(self, request):
        amount = request.POST.get("amount")
        payjp_token = request.POST.get("payjp-token")

        #Generate customer information from tokens
        customer = payjp.Customer.create(email="[email protected]", card=payjp_token)
        #Make a payment
        charge = payjp.Charge.create(
            amount=amount,
            currency="jpy",
            customer=customer.id,
            description="Django example charge",
        )

        context = {"amount": amount, "customer": customer, "charge": charge}
        return render(request, "index.html", context)
* In this article, the key is written directly for the sake of clarity. Be careful not to expose the parts of ** pk_test_xxxxxxxxxxxxxxxxxx ** and ** sk_test_xxxxxxxxxxxxxxxxxxxxx ** to the outside, such as by reading them with environment variables.

Creating Template

app


$ mkdir templates; cd templates
$ touch index.html

app/templates/index.html


<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="x-ua-compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <title>Sample application</title>
</head>

<body>
  <h1>Payment</h1>

  {% if charge %}
    <p>{{ amount }}Yen payment is complete.</p>
    <br>
    <p>customer: {{ customer }}</p>
    <br>
    <p>Charge: {{ charge }}</p>
  {% else %}
    <form action="{% url 'app' %}" method="post">
      {% csrf_token %}
      <div>
        <label for="amount">Payment</label>
        <input type="number" name="amount" id="amount" required>
      </div>

      <script type="text/javascript" src="https://checkout.pay.jp" class="payjp-button" data-key="{{ public_key }}">
      </script>
    </form>
  {% endif %}
</body>
</html>


Routing settings

project/urls.py



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

from app import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", views.PayView.as_view(), name="app")
]

I think you've implemented it!

Final directory structure


my-project
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── payjp.py
│   ├── templates
│   │   └── index.html
│   ├── tests.py
│   └── views.py
├── manage.py
└── project
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Operation check

Run application

$ python manage.py runserver

http://127.0.0.1:8000/ When you access スクリーンショット 2020-07-06 15.25.19.png

Will be displayed, so let's enter the payment amount and card information.

スクリーンショット 2020-07-06 15.25.47.png

Press Pay with Card

スクリーンショット 2020-07-06 15.26.14.png

You can also check the payment details on PAY.JP, so make sure you have the information you entered earlier. "Sales" item in the sidebar スクリーンショット 2020-07-06 15.44.08.png

Finally

You could easily implement payment processing in Django! I used the default form design this time, but it seems that you can customize it by setting your own CSS. Also, although the model processing was omitted this time, it is possible to create a practical application by saving the response (payment information, etc.) returned from the PAYJP API in the DB together with the user information. That's right.

Reference link:

PAY.JP API User's Guide PAY.JP API Reference

Recommended Posts

Easy implementation of credit card payment function with PAY.JP [Django]
Implementation of login function in Django
Equipped with a card function using payjp
Implementation of CRUD using REST API with Python + Django Rest framework + igGrid
Crawling with Python and Twitter API 2-Implementation of user search function
Introduction and implementation of activation function
Implementation of Dijkstra's algorithm with python
Implementation of custom user model authentication in Django REST Framework with djoser
Easy introduction of speech recognition with Python
[Reinforcement learning] Easy high-speed implementation of Ape-X!