Node-REDでLINE Payを使ったデジタルお賽銭botを作ってみた
LINE DCAdvent Calendarもついに最終日です!
最終日は2本立てで書きました。
もう一本はアップデートしたLIFFのSDKでQRコードリーダーを紹介しているので、そちらもよかったらぜひご覧ください。
先日、LINE DCの忘年会LTにてNode-REDでLINE Payを使えるようにするオリジナルノードを公開した話をしました。
その時のスライドはこちら
このスライドでの予告通り、今回はNode-REDでLINE Payを使って決済機能をLINE botに実装する方法を紹介します。
クリスマス真っ只中ですが、メターバース(?)な初詣をテーマにスマホでお賽銭をする仕組みをLINEでやってみたらというテーマで作ってみたいと思いますw
事前準備
今回はIBM CloudでNode-REDの実行環境を構築する例を紹介します。
Node-REDが動けばお好みの環境で構築してもらってOKです。
IBM Cloudのアカウントを以下のURLから作成します(アカウント作成にはクレジットカードを使用した本人確認が必要です)。
環境構築(IBM Cloudの例)
Node-REDのセットアップ
IBM Cloudのアカウントにログインしたら、画面上部のリソース検索画面からNode-RED
と検索して表示される「Node-RED App」を選択します。
アプリの作成画面が表示されるので、作成
タブをクリックします。
作成画面ではアプリ名を必要に応じて好きな名前に設定します。アプリ名はそのままURLに使われるのでユニークな名前に設定する必要があります(ユニークじゃないときは作成時にエラーになります)。
他の設定はデフォルトのままでOKです。
最後に作成
ボタンをクリックします。
しばらくするとCloudant(Node-REDで使うデータベース)のプロビジョニングが行われるので完了するまで待ちます。
プロビジョニングが完了したらデプロイメントの自動化の項目にあるアプリのデプロイ
をクリックします。
以下の画面が表示されますので、デプロイメントの自動化無料枠でも使えるCloud Foundry
を選択します。
IBM Cloud API 鍵
は新規
をクリックして作成します。
API鍵の作成のときに以下のダイアログが表示されたら特に何も設定せずにOK
をクリックします。
画面の下部にある次へ
ボタンをクリックします。
DevOpsツールチェーンの詳細設定がありますが、ここも特に設定はなしで作成
ボタンをクリックします。
作成完了してデプロイメントのパイプラインが実行されます。ci-pipeline
をクリックすると別タブでデプロイの進行状況を確認できます。実行が完了すると左上のアプリURLが表示されたら環境構築が完了です。
Node-REDの設定
最初にアプリURLを開くと以下のようにWelcome画面が表示されるので、Next
をクリックします。
Node-REDのログイン情報を登録します。登録しないという選択肢もありますが、何も設定しないと誰でもフローが編集される上、今回のようにAPIを扱うノードだと簡単にアクセストークンがバレてしまうので、必ず登録しておきましょう。
またAllow anyonw to view the editor, but not make any changes
はフローは誰でも閲覧できますが、編集をするためにはログインするというオプションです。
拡張ノードのインストール方法に関する説明が書かれています。この後の手順でも解説しますのでここではNext
をクリックします。
最後にNode-REDの環境変数の設定について説明があるので、確認してFinish
をクリックします。
完了後にNode-REDにログインして以下のようなフローエディタが表示されたらNode-REDの設定は完了です。
ノードのインストール
Node-REDの実行環境を構築したところで、今回使用するノードをインストールします。
Node-REDのフローエディタから右上のハンバーガメニューから パレットの管理
を選択します。
ノードを追加
タブから以下のノードを検索、インストールします。
- node-red-contrib-line-pay
- node-red-contrib-line-messaging-api
フローのコピー
インストールしたところで、今回使用するフローを用意します。
以下のJSONをコピーして、Node-REDのフローエディタの右上のハンバーガーメニューから 読み込み
を選択します。
[{"id":"c9ac6da.8acb79","type":"tab","label":"お賽銭ボット","disabled":false,"info":""},{"id":"58111ba3.325234","type":"http in","z":"c9ac6da.8acb79","name":"","url":"callback","method":"post","upload":false,"swaggerDoc":"","x":120,"y":100,"wires":[["c8c6a378.8cccb","b9005e4b.5e7dd"]]},{"id":"20a15ce9.34b624","type":"http response","z":"c9ac6da.8acb79","name":"","statusCode":"","headers":{},"x":520,"y":80,"wires":[]},{"id":"544d0c5a.a6a174","type":"ReplyMessage","z":"c9ac6da.8acb79","name":"","replyMessage":"","x":1020,"y":180,"wires":[]},{"id":"c8c6a378.8cccb","type":"switch","z":"c9ac6da.8acb79","name":"","property":"payload.events","propertyType":"msg","rules":[{"t":"empty"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":310,"y":100,"wires":[["20a15ce9.34b624"],["fd958718.a8f038"]]},{"id":"b9005e4b.5e7dd","type":"debug","z":"c9ac6da.8acb79","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":194,"y":160,"wires":[]},{"id":"fd958718.a8f038","type":"switch","z":"c9ac6da.8acb79","name":"","property":"payload.events.0.message.text","propertyType":"msg","rules":[{"t":"eq","v":"支払い","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":160,"wires":[["9ef5ffb5.21132"],["544d0c5a.a6a174"]]},{"id":"9ef5ffb5.21132","type":"change","z":"c9ac6da.8acb79","name":"","rules":[{"t":"set","p":"payload.events.0.message.type","pt":"msg","to":"flex","tot":"str"},{"t":"set","p":"payload.events.0.message.altText","pt":"msg","to":"奉納お願いします","tot":"str"},{"t":"set","p":"payload.events.0.message.text","pt":"msg","to":"{\"type\":\"bubble\",\"direction\":\"ltr\",\"header\":{\"type\":\"box\",\"layout\":\"vertical\",\"contents\":[{\"type\":\"spacer\"}]},\"hero\":{\"type\":\"image\",\"url\":\"https://1.bp.blogspot.com/-lahlkRgDJn4/Wjnwx_ibCxI/AAAAAAABI1s/uOO0UrjRAqYdRj79P6gC0WezeLFsw388ACLcBGAs/s180-c/saisenbako_denshi_smartphone.png\",\"size\":\"full\",\"aspectRatio\":\"1.51:1\",\"aspectMode\":\"fit\"},\"body\":{\"type\":\"box\",\"layout\":\"vertical\",\"contents\":[{\"type\":\"text\",\"text\":\"奉納お願いします\",\"align\":\"center\",\"contents\":[]}]},\"footer\":{\"type\":\"box\",\"layout\":\"horizontal\",\"contents\":[{\"type\":\"button\",\"action\":{\"type\":\"uri\",\"label\":\"LINE Payでお支払い\",\"uri\":\"https://linecorp.com\"},\"color\":\"#1FF036FF\",\"style\":\"primary\"}]}}","tot":"json"},{"t":"set","p":"hookEvent","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{\"amount\":100,\"currency\":\"JPY\",\"orderId\":\"\",\"packages\":[{\"id\":\"package-999\",\"amount\":100,\"name\":\"LINE神社\",\"products\":[{\"id\":\"product-001\",\"name\":\"お賽銭\",\"imageUrl\":\"https://www.linefriends.jp/m/img/ic-brown_00_v03.7d3c4e0d.png\",\"quantity\":1,\"price\":100}]}],\"redirectUrls\":{\"confirmUrl\":\"\",\"cancelUrl\":\"\"},\"options\":{\"payment\":{\"payType\":\"PREAPPROVED\"}}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":120,"wires":[["4029fe47.5344f"]]},{"id":"4029fe47.5344f","type":"function","z":"c9ac6da.8acb79","name":"リクエストパラメータの用意","func":"// Node-REDのURL(自分のものに書き換える)\nvar appUrl = \"\";\nvar userId = msg.hookEvent.events[0].source.userId;\nmsg.payload.redirectUrls.confirmUrl = `${appUrl}/confirm_offering/${userId}`;\nmsg.payload.redirectUrls.cancelUrl = `${appUrl}/cancel`;\n\n// orderIdの定義(ユニークな値である必要があるためここで設定する)\nmsg.payload.orderId = `LS_${new Date().getTime()}`;\nreturn msg;","outputs":1,"noerr":0,"x":760,"y":120,"wires":[["68b01b1.a8536e4"]]},{"id":"68b01b1.a8536e4","type":"Request","z":"c9ac6da.8acb79","name":"","linepayConfig":"","x":980,"y":120,"wires":[["5773410a.e7014"]]},{"id":"f0228d6d.1081","type":"http in","z":"c9ac6da.8acb79","name":"","url":"confirm_offering/:userId","method":"get","upload":false,"swaggerDoc":"","x":160,"y":280,"wires":[["c440e6df.5d3f48"]]},{"id":"2aef75b9.62149a","type":"http response","z":"c9ac6da.8acb79","name":"","statusCode":"","headers":{},"x":870,"y":280,"wires":[]},{"id":"813f06b8.63e708","type":"template","z":"c9ac6da.8acb79","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<head>\n <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC\" crossorigin=\"anonymous\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n<body>\n <h1>奉納完了</h1>\n <p>orderId: {{ payload.info.transactionId }}</p>\n <img width=200 src=\"https://1.bp.blogspot.com/-rNHLEYba6no/Wj4InHuNzUI/AAAAAAABJN4/_VlYonboxTMLc6rCg4IA6R0m_OvdvVwRgCLcBGAs/s800/omairi_family_kimono.png\">\n</body>\n","output":"str","x":720,"y":280,"wires":[["2aef75b9.62149a"]]},{"id":"c440e6df.5d3f48","type":"change","z":"c9ac6da.8acb79","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"amount\":100,\"currency\":\"JPY\"}","tot":"json"},{"t":"set","p":"transactionId","pt":"msg","to":"req.query.transactionId","tot":"msg"},{"t":"set","p":"userId","pt":"msg","to":"req.params.userId","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":280,"wires":[["162cf4a7.903f8b"]]},{"id":"162cf4a7.903f8b","type":"Confirm","z":"c9ac6da.8acb79","name":"","linepayConfig":"","x":560,"y":280,"wires":[["813f06b8.63e708","b3d7495.ba858b8"]]},{"id":"5773410a.e7014","type":"function","z":"c9ac6da.8acb79","name":"返信用メッセージの作成","func":"var resBody = msg.payload;\nmsg.payload = msg.hookEvent;\nmsg.payload.events[0].message.text.footer.contents[0].action.uri = resBody.info.paymentUrl.web; \nreturn msg;","outputs":1,"noerr":0,"x":1190,"y":120,"wires":[["544d0c5a.a6a174"]]},{"id":"b3d7495.ba858b8","type":"function","z":"c9ac6da.8acb79","name":"支払い完了メッセージの作成","func":"var accessToken = \"YOUR_ACCESS_TOKEN\"\n// ヘッダーを設定\nmsg.headers = {};\nmsg.headers[\"Content-Type\"] = \"application/json\";\nmsg.headers[\"Authorization\"] = `Bearer ${accessToken}`;\n\n// 送信するメッセージを定義\nmsg.payload = {\n \"to\": msg.userId,\n \"messages\":[\n {\n \"type\":\"text\",\n \"text\":\"ようこそお参りくださいました\"\n },\n {\n \"type\": \"sticker\",\n \"packageId\": \"6136\",\n \"stickerId\": \"10551380\"\n }\n ]\n}\nreturn msg;","outputs":1,"noerr":0,"x":560,"y":340,"wires":[["4e9a4026.5a1cf"]]},{"id":"4e9a4026.5a1cf","type":"http request","z":"c9ac6da.8acb79","name":"","method":"POST","ret":"obj","paytoqs":false,"url":"https://api.line.me/v2/bot/message/push","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":340,"wires":[["592b7839.bfb118"]]},{"id":"592b7839.bfb118","type":"debug","z":"c9ac6da.8acb79","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":970,"y":340,"wires":[]}]
各認証情報の設定
これでフローは用意できましたが、必要なAPIキーがまだ設定されてないので、それぞれ設定していきます。
LINE Payの設定
まずはLINE Payの設定を行います。
Requestノードをダブルクリックすると、以下のようにノードの設定画面が開きます。
Config
の項目の右端にある鉛筆マークをクリックします。
以下の画面が出るので、それぞれ設定していきます。
設定項目に書く内容はドキュメントを参照してください。
LINE bot(Messaging API)の設定
それではMessaging APIの設定を行います。
LINE Developerコンソールにログインして、Messaging APIのチャネルを作成します。
その後チャネルシークレットとアクセストークンを取得します。
ReplyMessageノード
ReplyMessageノードをダブルクリックして設定画面を開いたら先程メモしたチャネルシークレットとアクセストークンを設定します。
Functionノード
続いてFunctionノードの中で支払い完了メッセージの作成
と書かれたノードをダブルクリックしてコードの編集画面を開きます。
コードの1行目のアクセストークンをご自分のものに書き換えます。
var accessToken = "YOUR_ACCESS_TOKEN";
なぜPushMessageノードがあるのにわざわざFunctionノードを使用しているかというと、PushMessageノードでは送信先のUserIDを予め決め打ちでやる必要があるため特定のユーザーにしかメッセージが送れないので不採用となりました(いつか修正してPR出そうと思います)。
動かしてみる
それでは一通り準備出来たところで動作確認です。動作確認の前にフローエディタの右上のデプロイボタンがグレーじゃなかった場合は、デプロイボタンを押して変更を適用しておきます。
その後ボットを友だち追加して、「支払い」というテキストを送信してみます。
すると、以下のように支払いするようにFlexメッセージが表示されるのでボタンを押して決済を始めます。
ボタンをタップすると、自動ログインして以下の決済画面が表示されます。
PAY NOW
ボタンをクリックして、決済を完了させます。
決済が完了するとこんな感じでメッセージとスタンプが表示されます。
一通り動かすとこんな感じで動きます
おわりに
今回はNode-REDとLINE Payを使ってお賽銭ボットを作成しました。
いらすとやでなんとなく徘徊していたらいい感じのイラストを見つけて今回のネタを思いつきましたw。
改めてNode-REDで実装してみると「LINE Payってこんな簡単に使えてしまうんだ」と感心しました。
今回は超簡単にLINE botにLINE Payを組み込むサンプルとして紹介しましたが、応用すればモバイルオーダーも実装できると思うので、ぜひ色々作ってみましょう。
それではよいお年を!
Discussion