PAY.JPでクレジットカード決済機能を簡単に実装【Django】

# PAY.JPとは

公式: https://pay.jp/

クレジットカード決済を簡単に導入できるサービス。提供されるAPIやSDKを使って実装する。

PAY.JPから提供されるカード情報入力フォームはiframeになっていて

* 決済の仕組みがよくわからない、怖い
* プロダクトに決済機能を導入したいが、個人情報の管理が大変そう

といった、決済周りの敷居の高い部分をクライアントの入力部分からまるっとPAYJPが保護してくれる。
なのでユーザが入力したカード番号などの個人情報を自分達が管理しなくて良く、最低一行のJavaScriptを貼るだけで実装できるらしい。すごい。

支払いやカード情報に関するデータはRESTベースのAPIから取得できるようで、
ドキュメントもエンジニアにはわかりやすいものだと思うので、実装はやりやすいのかなと思います。
[PAY.JP API リファレンス](https://pay.jp/docs/started "PAY.JP API リファレンス")



# 実装するもの

記事作成時点で公式のチュートリアルがFlaskとSinatraしかない。他Qiitaの記事だとRailsで実装された記事がほとんどだったので、Djangoで実装してみます。

PAY.JPを導入して、支払い機能を実装します。
※ PAY.JPには本番用とテスト用という概念があり、本番は実際にお金のやり取りをするための申請が必要なので今回は使いません、テスト用だと気軽に手元の環境で試せます。

## 実行環境
```
MacOS Catalina version: 10.15.5
Python 3.8.3
Django 3.0.8
payjp  0.0.5
```

# まずはDjangoを動かす
サンプルプロジェクト用フォルダを作成してフォルダ内に移動。

```
$ mkdir my-project; cd my-project
```

必要なライブラリ（django、payjp)をインストールする。

```bash
$ pip install django payjp
```

Djangoのプロジェクトを生成する

```bash
$ django-admin startproject project .
```

manage.pyが生成されたディレクトリで下記コードで開発用サーバが立ち上がることを確認します。

```bash
$ python manage.py runserver
```

# PAYJPを利用するためのAPIキーを確認する
[PAYJPの設定画面](https://pay.jp/d/settings)　にアクセスして左のサイドバーの「API」からAPIキーの確認ができます。
今回は手元の環境で動かしたいだけなのでテスト秘密鍵、テスト公開鍵を使用します。

<img width="1165" alt="スクリーンショット 2020-07-06 11.11.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299151/e9b16e97-4f46-8536-093a-6849d3ea3aac.png">

<font color="Red">
※ 画像は一部切り抜きにしてます。
</font>

作業に取り掛かる準備ができたので、アプリケーションを作ってPAYJPと連携しましょう。


# PAY.JPと連携するDjangoアプリケーションを生成。


```bash
$ python manage.py startapp app
```

## Djangoの設定ファイルの編集

settings.pyに
先程作成したアプリケーションを登録、またPAY.JPの秘密鍵を設定します。

```python: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",
    # 追加
    "app", 
]

...

...

...

# PAY.JP設定
payjp.api_key = "sk_test_xxxxxxxxxxxxxxxxxxxxx" # テスト用秘密鍵
```


## Viewを実装する

```python: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):
        # 公開鍵を渡す
        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")

        # トークンから顧客情報を生成
        customer = payjp.Customer.create(email="example@pay.jp", card=payjp_token)
        # 支払いを行う
        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)
```

<font color="Red">
※ 本記事ではわかりやすくするためにキーを直接書いてますが
**pk_test_xxxxxxxxxxxxxxxxx**や**sk_test_xxxxxxxxxxxxxxxxxxxxx**の部分は環境変数で読み込むようにするなど外部公開しないよう注意しましょう。
</font>


## Templateの作成

```bash:app
$ mkdir templates; cd templates
$ touch index.html
```

```django: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>サンプルアプリケーション</title>
</head>

<body>
  <h1>お支払い</h1>

  {% if charge %}
    <p>{{ amount }}円のお支払いが完了しました。</p>
    <br>
    <p>customer: {{ customer }}</p>
    <br>
    <p>Charge: {{ charge }}</p>
  {% else %}
    <form action="{% url 'app' %}" method="post">
      {% csrf_token %}
      <div>
        <label for="amount">お支払い</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>


```

## ルーティングの設定

```python: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")
]
```

これで実装はできたと思います！

# 最終的なディレクトリ構成

```bash

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
```

# 動作確認

アプリケーションの実行

```bash
$ python manage.py runserver
```

http://127.0.0.1:8000/
へアクセスすると
<img width="386" alt="スクリーンショット 2020-07-06 15.25.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299151/a2e5915f-668c-7303-adf6-30f5b64a643f.png">

が表示されるので、支払い金額とカード情報を入力してみましょう。

<img width="506" alt="スクリーンショット 2020-07-06 15.25.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299151/3a1ce217-a375-da74-2cf0-75ffe9a98e19.png">

カードで支払うを押下

<img width="283" alt="スクリーンショット 2020-07-06 15.26.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299151/a8197323-fa89-8d75-6960-63b93e69d0ff.png">


また、PAY.JPでも支払内容の確認ができますので先程入力した情報があることを確認してみましょう。
[サイドバーの「売上」の項目](https://pay.jp/d/charges)
<img width="1102" alt="スクリーンショット 2020-07-06 15.44.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299151/7b7167ae-8783-bfe6-d407-0b6760b08028.png">



# 最後に
Djangoでも簡単に支払いの処理が実装できました！
今回はデフォルトのフォームデザインを使いましたが、独自にCSSを設定したりしてカスタマイズできるようです。
また、今回はmodelの処理を省きましたが、PAYJP APIから返ってきたレスポンス（支払情報など）をユーザ情報と一緒にDBに保存しておくことで実用的なアプリケーションを作っていくことができそうです。


参考リンク：

[PAY.JP API 利用ガイド](https://pay.jp/docs/started "PAY.JP API 利用ガイド")
[PAY.JP API リファレンス](https://pay.jp/docs/api/)