Python LINE Pay SDK を試してみる


LINE Pay の先生である加川さん @sumihiro3 が作ってくれたSDKを理解して使えるようになるためのメモ書き。
https://github.com/sumihiro3/line-pay-sdk-python/tree/master/examples

単発の一般決済だけならスターターを作ったので[こちら](https://github.com/maztak/line-pay-v3-python-starter)を使ってくださいまし。

##前提知識
###SDKとは
>SDKは、少ない労力でアプリケーションを開発できるようにするために、プログラム、API、サンプルコードなどをパッケージにしたものだ。開発者はSDKを使えば、機能を実現する技術の詳しい仕組みを理解していなくても、アプリケーションに新機能を実装できる。

###LINE Pay API(v3)の決済フロー
![line_pay_api02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/340e63ff-123e-4471-16df-75a21f540d64.jpeg)
引用：https://dev.classmethod.jp/articles/devio-cafe-line/

![line_pay_v3_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/a8b43fad-4cd2-3cd7-3911-bd8243980ce5.png)
引用：https://dev.classmethod.jp/articles/line-pay-v3-lambda/


ちょっとややこしいですが、SPというのは Service Provider で我々事業者のことです。

①RequestAPIを使ってPayから決済URLを発行してもらい
②ユーザーにURLを投げてタップしてもらって例の決済画面で承認してもらう
③するとSPである我々事業者（のアプリやシステム）に承認された通知が来るのでConfirmAPIを使って決済を完了する

通常はこれで売上確定となり、僕らはCaptureAPIなるものを使用せずとも良い。しかし決済完了と売上確定までにワンステップ挟みたいケースがあるらしく、その場合は以下のようにCaptureAPIを使って自分で売上確定処理をしないといけないらしい。

> Request APIの"options.payment.capture"をfalseに設定するとオーソリと売上確定が分離された決済になり、決済を完了させても決済ステータスは売上確定待ち(オーソリ)状態のままとなります。売上を確定するには、Capture APIを呼び出して売上確定を行う必要があります。

```
request_options = {
// 省略
    "options": {
        "payment": {
            "capture": False
        }
    },
// 省略
response = api.request(request_options)
```

![ldgq20200720ハンズオン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/aea162c2-35fe-3769-1b0e-ba0a1c7a6974.png)


これが LINE Pay API v3 の基本的な決済の流れですが、ユーザー視点では「LINE Pay で支払う」→「決済画面に行く」→「決済ボタンを押す」の3工程しかないので、初心者エンジニアである我々には上記のような処理が裏側で行われていることがイメージしにくいと思う。ぶっちゃけSDKなのでこの辺は分かってなくても使えればいいと思う。

##事前準備

- 前提としてPCのPythonのバージョンは3.6以上にしておいてください
- LINE Pay の加盟店IDが無い方や実際の決済をしないためにSandbox環境の加盟店アカウントを取得しておいてください

ただしSandboxでやると実際のPayの挙動と違ってくるし、自動決済（サブスク）とかの表示も一般決済と変わらないようなのでややこしくなる。なんか挙動が同じテストできるアカウントをLINEさん作ってくれないかなぁ。

##Sandboxでの取引確認

Sandboxのアカウントで加盟店MyPageにログインしてもその画面には取引履歴は残らない。ログイン後に右上の`Sandbox`のリンクをクリックするとSandboxで決済した取引履歴が見れる（最初の画面は連動キーを取得する以外使いみちがないようだ‥）。

![スクリーンショット 2020-11-02 19.15.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/295033a9-9d74-0180-9a7d-3bbf5962f859.png)

![スクリーンショット 2020-11-02 19.17.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/f55c7aea-cef6-74a5-726f-890840bd504a.png)



##まずはSDKのクローンorダウンロード

まずはGitHubリポジトリをクローンもしくは[ダウンロード](https://github.com/sumihiro3/line-pay-sdk-python/archive/master.zip)して解凍する

ターミナルでこのディレクトリまで移動

```
$ cd ine-pay-sdk-python-master
```

pip install で必要なライブラリをインストール

```
$ pip install -r requirements.txt
```

`.env.sample`ファイルをコピーし`.env`ファイルを作成

```
$ cp ./.env.sample ./.env
```

ngrokでポート8000を外部URLでアクセスできるようにしておく

```
$ ngrok http 8000
```

VSCodeやAtom, vim, emacs など任意のエディタで`.env`ファイルを編集
ngrokで発行されたドメインと、LINE Pay 加盟店 MyPage の決済連動管理>連動キーから確認できるChannes_IDとChannel Secret Keyを入力する

```
HOST_NAME=xxxxx.ngrok.io
LINE_PAY_CHANNEL_ID=YOUR_LINE_PAY_CHANNEL_ID
LINE_PAY_CHANNEL_SECRET=YOUR_LINE_PAY_CHANNEL_SECRET
```

##一般決済

基本的にこのSDKは試したい決済流れの`.py`ファイルをRunさせて、`xxxxx.ngrok.io/request`にアクセスすることでその流れを試せる作りになっているようだ。

###一般決済→返金

```
$ python request-confirm-refund.py
```

この状態で`https://xxxxx.ngrok.io/request`にアクセスすると

<img width="375px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/838ab65f-cbaf-1e00-e745-0df4f6a40884.png">

`paymentUrl`を押すと（Sandboxなので）下記画面に行くのでLINEログインする（モバイルで上記URLにアクセスして試みたり、QRコードのスキャンで決済を試そうとするとなぜか失敗した‥）。

![スクリーンショット 2020-11-02 19.26.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/617c4fc8-e5c0-2fc9-e699-5620974cd3bb.png)

Sandboxの模擬決済画面が開くので`PAY NOW`を押す

![スクリーンショット 2020-11-02 19.27.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/e59d26be-7179-bb5b-5b64-84f5b6901f68.png)

決済完了すると決済結果を表示する画面にリダイレクトされる

![スクリーンショット 2020-11-02 19.27.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/5dc281ac-2dec-8140-c8ed-5a9d25f2e614.png)

今回は返金を試せるpyファイルなので、一番下に出ている`REFUND`リンクを押すと返金処理ができ、次の画面にリダイレクトされる。

<img width="375px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/1682ef15-83c9-6b82-3d20-929153c59135.png">

この時の加盟店MyPageのSandbox画面の取引内訳はこのようになっており、上段No.1が決済、下段No.2が決済キャンセルの処理として記録されている。

![スクリーンショット 2020-11-02 19.38.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/9974f2d0-6b82-f195-e2a4-3e3e34534431.png)

![スクリーンショット 2020-11-02 19.38.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/5a818ef0-550d-e3fb-0782-466d975b9056.png)




###一般決済→キャプチャ

request_optionsの中のoptions.payment.captureをFalseにすることで、決済後に敢えて売上確定待ち（オーソリ）状態とし、後ほどCaptureAPIを用いて売上確定（キャプチャー）を試すには`authorizations-capture.py`ファイルをRunする。

```authorizations-capture.py
        "options": {
            "payment": {
                "capture": False
            }
        },
```

```
$ python authorizations-capture.py
```

同じく`https://xxxxx.ngrok.io/request`にアクセスして決済すると、次はキャプチャ用のリンクが記載された画面にリダイレクトされる。

<img width="375px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/e3231a1f-5f4e-9839-1dea-3d15a7d05901.png">

なおこのときの加盟店MyPageの取引内訳は以下のようになっている。

決済後の取引内訳↓
![スクリーンショット 2020-11-02 20.02.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/dd4a9c5f-63fd-893f-10bd-82dee7a51135.png)

キャプチャ後の取引内訳↓
![スクリーンショット 2020-11-02 20.04.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/1addeb34-e11c-6e3c-c2a8-4e154e88e65e.png)

なお売上確定処理は本来この画面からも出来るはずなのだが、このSDKを用いてやったときはなぜか売上確定ボタンがでない。Sandboxだからか？

##Checkout

CheckoutはEC等での決済時に配送先住所や送料を含めてよしなに決済できるAPIだが、このAPIはSandbox環境では利用ができず、正式な加盟店でも利用に審査がいる。なので本SDKでは試すpyファイルが用意されていないようだ。

##自動決済

```
$ python request-confirm-pre_approved.py
```

これで同様に`https://xxxxx.ngrok.io/request`にアクセスして決済すると、決済後に以後の自動決済用のRegKeyが取得できる。LINE Pay の使用として初回決済とRegKeyの取得を同時に行うようだ（Sandboxでは本来の自動決済の流れにあるチェックが再現されていない…）。

<img width="375px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/fbc3c53a-5959-e227-13b2-8108fe03e03c.png">

下にあるリンクをクリックすることでRegKeyと Pay Preapproved API を使って自動決済ができる。が、加盟店MyPageの取引内訳には自動決済による取引が記録されない‥。これもSandboxだからだろうか。

正式な LINE Pay 自動決済 の流れは以下のようなものです。
https://youtu.be/KdQLm88nl2Q

##アクセスURLがすべて/requestなのはなぜ？

<img width="375px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/d8c9d79c-2edc-3065-8934-e5c315a7d69f.png">
これも素人意見かもしれないが、ファイル内にある各HTMLファイルにアクセスできないのはなぜだろうと思っていた。が、Python（もしくはFlask）の場合は以下のようにpyファイルでrouteのURLが決められているので、ここにしかアクセスできない。templates配下のHTMLファイルにはpyファイルの中で`return render_template("request.html", result=response)`のようにしてプログラムが呼び出す用のHTMLファイルなのだ。

```xxx.py
@app.route("/request", methods=['GET'])
def pay_request():
    # 省略
    return render_template("request.html", result=response)
```



##参考

- https://dev.classmethod.jp/articles/linepay-regkey/

- https://qiita.com/sotozaki/items/e178f5ec3c34aa7b1b17

> - RegKeyの有効期限は180日
> - RegKeyが有効かチェックするAPIはあるが有効期限を知る手段はない
> - ユーザーは設定画面からexpireできる
> - sandbox環境では有効期限が1日に設定されている

ユーザーのexpireは多分ここのこと

<img width="180px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/7653007b-2483-4be6-660a-657f492747ba.png">
LINEアプリのウォレットっからLINE Payを立ち上げる（LIFFアプリとして立ち上がる）

<img width="180px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/cb423cc3-f371-7016-e454-233724a41c10.png">
下の方の自動決済を押す

<img width="180px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/0abd40c2-e2ec-1f2a-8205-b68c26afe90f.png">
本番環境でサブスクしていればここで管理ができるようだ。なおSandboxでのRegKeyは何も表示されないよう。