こんにちは、こちらは国産Web API Advent Calendar 2018の1日目の記事です (※誰がなんと言おうと1日目の記事です、依頼日は12/4、投稿日は12/17でも1日目の記事です) 。普段はLINE株式会社でClovaのSoftware engineerをしています。本日はLINE Pay API (Clova APIじゃない!?) をPythonから叩いてみたというお題目で記事を書きたいと思います。
はじめに
本記事はLINE株式会社の許諾を得て投稿していますが、本記事で紹介するソースコードはLINE公式ではありません。ご利用の際は自己責任でお願い致します。
本記事は「LINE Pay APIを使ってアプリに決済を組み込む方法」をPythonで書いてみたものになります。LINE Payを使うまでの下準備 (アカウント登録、Sandbox環境の準備、など) はこちらが大変分かりやすいのでそちらを参照してください。
前置きが長くなりましたが、LINE Pay APIは誰でも無償で申請でき、簡単に利用できます。組み込み実装も簡単でした。なぜかネット上でLINE Pay API使ってみた系の情報があまり見つからず、唯一こちらのNode.js版の非公式SDKだけが有用な情報だったので、今回はPythonでSDK的な何かを作ってLINE Pay APIを使ってみたいと思います。
必要なもの
- LINE Pay Sandbox環境
- 固定IPがあるサーバー
- Python 3.6
ソースコード
下準備 (LINE Pay Sandbox環境の準備)
こちらを参考にしてください。
LINE Pay APIをPythonから叩いてみる
今回のデモの決済の流れは、ざっくりと以下になります。
支払い予約 (Server) → ユーザーの認可 (Client) → 支払いの実行 (Server)
とにかく一旦デモを動かしてみましょう。
$ git clone https://github.com/keigohtr/line-pay-python-example.git
$ cd line-pay-python-example
app.py
というのがデモの本体です。LINE Pay Sandbox環境のパラメータを設定してください。
LINE_PAY_CHANNEL_ID = 'your channel'
LINE_PAY_CHANNEL_SECRET = 'your secret'
下記コマンドでデモを起動します。デモを起動すると http://localhost:5000/
に「LINE Pay」ボタンがあります。押すとLINE認証の要求画面が出て、認証後に「チョコレート」を「1円」で決済できます。これはデモなので安心して決済してください。Sandbox環境では実際にお金を支払うことはありません。
$ pip install -r requirements.txt
$ python app.py
$ open http://localhost:5000/
デモの構成
line-pay-python-example
|- app.py Flask Webサービス
|- line_pay.py 自家製LINE Pay SDK的な何か
|- models/ sqliteでtransaction IDを管理
|- static/ 今回はLINE Payのiconを格納
|- templates/ Flask + Jinja2のテンプレート
WebフレームワークとしてFlaskを使いました。SQLAlchemyでsqliteのDBを立て、transactionの管理をしています。非常にシンプルな構成です。line_pay.py
というLINE Pay SDK的な何かを作りましてLINE Pay APIの全てを網羅しましたが、動作確認できているのは今回のデモで使用した「支払い予約 POST: /v2/payments/request
」と「支払い実行 POST: /v2/payments/{transaction_id}/confirm
」だけですのでご注意ください。
デモの実装を追ってみる
設定項目は以下の4つです。
LINE_PAY_URL = 'https://sandbox-api-pay.line.me'
LINE_PAY_CHANNEL_ID = 'your channel'
LINE_PAY_CHANNEL_SECRET = 'your secret'
LINE_PAY_CONFIRM_URL = 'http://localhost:5000/pay/confirm'
pay = LinePay(channel_id=LINE_PAY_CHANNEL_ID, channel_secret=LINE_PAY_CHANNEL_SECRET,
line_pay_url=LINE_PAY_URL, confirm_url=LINE_PAY_CONFIRM_URL)
今回のデモではLINE_PAY_URL
がsandbox環境に向いています。Productionで利用する場合はProduction用のURLを使いますが、その前にLINE Pay APIの利用審査があります。LINE_PAY_CONFIRM_URL
は「支払い予約」をしてユーザーが支払いOKと決めたとき、LINE Pay側からデモサーバーにcallbackするURLになります。デモではlocalhost
を向いていますが、Productionで利用する場合はLINE Pay Developersに設定したとおり「固定IP」を持つ「https」のエンドポイントである必要があります。以上の4つの設定項目がLinePay
classの最低限必要な引数となります。
続いて、支払い予約の部分を解説します。
@app.route("/pay/reserve", methods=['POST'])
def pay_reserve():
product_name = "チョコレート"
amount = 1
currency = "JPY"
(order_id, response) = pay.request_payments(product_name=product_name, amount=amount, currency=currency)
transaction_id = response["info"]["transactionId"]
obj = Transactions(transaction_id=transaction_id, order_id=order_id,
product_name=product_name, amount=amount, currency=currency)
db.session.add(obj)
db.session.commit()
db.session.close()
redirect_url = response["info"]["paymentUrl"]["web"]
return redirect(redirect_url)
今回のデモではproduct_name
とamount
、currency
を決め打ちにしました。支払い予約をするためには、product_name
とamount
、currency
、order_id
をLINE Pay APIにPOST: /v2/payments/request
する必要があります。order_id
はorder毎に振られるユニークな値でユーザーが自由に定義することができます。デモではpay.request_payments()
の中でorder_id
を自動生成し、APIリクエストを行っています。
APIレスポンスには色々と含まれているのですが、支払い予約が成功しているならばresponse["info"]["transactionId"]
にtransaction_id
が含まれています。transaction_id
はLINE Pay側から吐き出されたユニークな値です。自分たちのサービスで吐き出されたtransactionであることをちゃんと管理したいので、transaction_id
はDBに保存しておきます。最後に、response["info"]["paymentUrl"]["web"]
に「ユーザーの認可」用のredirect_url
が含まれていますので、ClientをredirectしてユーザーにLINE Payで認可してもらいます。
続いて、支払い実行部分を解説します。
@app.route("/pay/confirm", methods=['GET'])
def pay_confirm():
transaction_id = request.args.get('transactionId')
obj = Transactions.query.filter_by(transaction_id=transaction_id).one_or_none()
if obj is None:
raise Exception("Error: transaction_id not found.")
response = pay.confirm_payments(transaction_id=transaction_id, amount=obj.amount, currency=obj.currency)
db.session.query(Transactions).filter(Transactions.transaction_id == transaction_id).delete()
db.session.commit()
db.session.close()
return "Payment successfully finished."
ユーザーがLINE Payで認可していれば、callbackに指定したURLにGETでcallbackが返ってきます。Query parameterにtransaction_id
が含まれているので、先程DBに保存した値と一致するかチェックします。自分たちのサービスで吐き出されたtransactionであることが確認できたら、実際に支払い実行を行います。支払い実行をするためには、amount
、currency
をLINE Pay APIにPOST: /v2/payments/{transaction_id}/confirm
する必要があります。デモではpay.confirm_payments()
の中で適切なURLにAPIリクエストを行っています。
APIリクエストに成功したら、DBから当該transaction_id
のエントリを削除します。ただ、実際にProduction環境で利用する場合は、DBエントリを削除するのではなく"支払い済み"statusでもつけてください。transaction_id
かorder_id
は過去に実行したTransactionの参照や管理にも使いますので。
おわりに
今回はLINE Pay APIをPythonから叩いてみました。APIドキュメントは非常に読みやすく、構成もシンプルです。今回のデモを作るにあたって詰まった場所はありませんでしたし、組み込み難易度は非常に低いと思います。まだまだLINE Pay APIを使ってみた系の有用な情報が少ないと感じましたので、今回の記事が参考になれば幸いです。
参考情報
筆者について
LINE株式会社でSoftware engineerをしています、服部 (keigohtr) です。担当プロダクトはClovaで、担当領域はNLU (Natural Language Understanding) および機械学習まわりです。Kubernetes上で機械学習モジュールの配信基盤を作っていて、一連のソフトウェアをRekcurdと名付けてOSSとして公開しています。スターください(迫真)。また個人的に情報科学技術をWebAPIで売り買いできるWebAPIのマーケットプレイス Apitore を運営しています。世の中のあらゆる技術を簡単にデプロイでき、かつ誰でも簡単に利用できる、そんな世界を夢見ています。