Edited at

LINE Payを使ってみよう

More than 1 year has passed since last update.


はじめに

conpassでの連絡が漏れていて申し訳ないのですが、nodeの最新バージョン(8以上)をインストールしてください

当日作業するノートPCにNode.jsのLTS(最新安定版)をインストールしておいてください。

ダウンロード|Node.js



今日の勉強会の流れ


  1. おうむ返しbotを作る

  2. Flex Messageを返す

  3. LINE Pay APIを使ってみる



はじめに

ngrokを使います。

初めはLINEの設定をするので、インストールされていない方はあらかじめインストールをお願いします。

# macの場合

brew cask install ngrok
# linuxの場合
npm i -g ngrok



Messaging APIの利用

LINE Developersから新しいbotを作成します。

「今すぐ始めよう」 > 「プロバイダの選択」 > 「新規チャネル作成」 をします。

※チャンネル作成時に業種選択がありますが、特段の理由がない場合は「その他」を選択します。

image.png



初期設定画面

screencapture-developers-line-me-console-channel-1598664616-basic-2018-08-05-16_45_00.png



初期設定から変更すること


  1. メールアドレスの編集

  2. Webhook送信 > 編集 > 利用する

  3. アクセストークンの発行

    時間は0時間で大丈夫

  4. 自動応答メッセージ/友だち追加時あいさつ を利用しないに変更

  5. Channel Secret/アクセストークンをメモ



npmの設定

今回はnode v10.1.0を利用します。

作業用ディレクトリの作成/必要パッケージのインストールを行います。

また、botで使用するファイルも同時に作成します

 → node -v

v10.1.0
mkdir ~/workspace
cd ~/workspace
npm init -y
npm i -s @line/bot-sdk express dotenv
touch server.js .env



  • @line/bot-sdk: LINE botを扱うためのbot

  • express: サーバーを扱うためのパッケージ

  • dotenv: .envファイルから環境変数をロードするためのパッケージ




serverの中身


server.js

'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
require('dotenv').config();

const PORT = process.env.PORT || 3000;

const config = {
channelSecret: process.env.CHANNEL_SECRET,
channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN
};

const app = express();

app.post('/webhook', line.middleware(config), (req, res) => {
console.log(req.body.events);
Promise
.all(req.body.events.map(handleEvent))
.then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
if (event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
}

return client.replyMessage(event.replyToken, {
type: 'text',
text: event.message.text //実際に返信の言葉を入れる箇所
});
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);




環境変数の設定

先ほど初期設定画面でメモしたCHANNEL_SECRETとアクセストークンを.envファイルに設定ファイルを追記します。


.env

CHANNEL_SECRET=""

CHANNEL_ACCESS_TOKEN=""



ngrokでhttps通信を可能にします。

※サーバーとは別のターミナルで開く

$ ngrok http 3000

Session Status online
Session Expired Restart ngrok or upgrade: ngrok.com/upgrade
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://xxxxxx.ngrok.io -> localhost:3000
Forwarding https://xxxxxx.ngrok.io -> localhost:3000

Connections ttl opn rt1 rt5 p50 p90
105 0 0.00 0.00 0.87 4.76


webhookの設定

設定画面からwebhookのURLをhttps://xxxxxxxx.ngrok.io + /webhook に変更。


プロバイダーリスト > プロバイダー > bot名からアクセスできます


botを友達追加する

初期設定画面のQRコードから友達追加をします。

おうむ返ししてくれるbotが完成しました。



Flex Message

Flex Messageとは、ユーザーがJSON形式で作成できるテンプレートです。

非常に自由度が高いので様々なテンプレートを作成することができます。

また、それぞれからactionを呼び出すことが可能です。



actionでできることは...

actionからは様々な物を呼び出すことが可能です。

アクションオブジェクトでできることにまとめてあるので、ぜひ読んでみてください。(よかったらいいねお願いします。



Flex Meesageシミュレーター

シュミレーターを利用することにより、プログラムを書かずに簡単にリッチなメニューを作成することができます。

image.png



今回はMenuを使います。

Flex Message Simulatorから + => Menu を選択します。

image.png



jsonの作成

メッセージを返すjsonファイルを作ります。


messages/flex.js

module.exports = {

flex: {
"type": "flex",
"altText": "This is a Flex Message",
"contents":
// シミュレーターで出力されたJSON中身
}
}



server.jsからFlex Messageを呼び出します。


server.js

const flex = require('./messages/flex');

...

次にバーガーと入力された時にFlex Messageを返すようにします。


server.js

...

if (event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
}
if (event.message.text == 'バーガー'){
return client.replyMessage(event.replyToken, flex.flex);
}
return client.replyMessage(event.replyToken, {
type: 'text',
text: event.message.text
});
...



Flex Messageを送信

「バーガー」と入力するとFlex Messageを送信することができました!



LINE Pay

LINE Payではreserveとconfirmという2つのステップがあります。

流れ的には次の通りです


  1. reserveで商品・値段を確定

  2. LINEの画面でLINE Payにログイン

  3. confirm画面でLINE Payの決済を確定

1.から2.へのアクションはURLで2.に飛ばすことができれば良いので、

Webページから2.line botから2. へも飛ばすことが可能です。



LINE Payの登録

https://pay.line.me/jp/developers/techsupport/sandbox/creation?locale=ja_JP からsandbox、userの作成を行います。

アカウントを作成すると登録したメールアドレスにuser_idとpasswordが届きます。メールにログイン用のURLが指定されているのでそこからログインしてください



環境変数へ追加



コピーした変数を.envに記述します。

LINE_PAY_CHANNEL_ID=あなたのCHANNEL ID

LINE_PAY_CHANNEL_SECRET=あなたのCHANNEL SECRET
LINE_PAY_CONFIRM_URL=ngrokのURL/pay/confirm



LINE Payの準備

必要なパッケージのインストールとLINE Payの設定を書き込むファイルを作成します。

cd ~/workspace

npm i -s line-pay memory-cache uuid
touch pay.js



  • line-pay: LINE Pay APIのNode.js用SDK

  • memory-cache: インメモリーのキー・バリューストア

  • uuid: UUIDを生成するためのライブラリ。注文IDを生成するために利用




pay.jsに必要なファイルを読み込む


pay.js

const uuid = require("uuid/v4");

const cache = require("memory-cache");

// for line pay
const line_pay = require("line-pay");
const pay = new line_pay({
channelId: process.env.LINE_PAY_CHANNEL_ID,
channelSecret: process.env.LINE_PAY_CHANNEL_SECRET,
hostname: process.env.LINE_PAY_HOSTNAME,
isSandbox: true
})

// for line bot
const line = require('@line/bot-sdk');
const config = {
channelSecret: process.env.CHANNEL_SECRET,
channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN
};
const client = new line.Client(config);

module.exports = {
reserve: // これから書く
confirm: // これから書く
}




reserve

pay.jsにreverveの部分を追加します。


pay.js

  reserve: (event, item, amount) => {

let reservation = {
productName: item,
amount: amount,
currency: "JPY",
orderId: uuid(),
confirmUrl: process.env.LINE_PAY_CONFIRM_URL,
confirmUrlType: "SERVER"
}

pay.reserve(reservation).then((response) => {
reservation.transactionId = response.info.transactionId;
reservation.userId = event.source.userId;

// Save transaction information to cache
cache.put(response.info.transactionId, reservation);

const message = {
type: "template",
altText: `${item}を購入するには下記のボタンで決済に進んでください`,
template: {
type: "buttons",
text: `${item}を購入するには下記のボタンで決済に進んでください`,
actions: [
{type: "uri", label: "LINE Payで決済", uri: response.info.paymentUrl.web},
]
}
}
return client.replyMessage(event.replyToken, message);
});
},




confirm

pay.jsにconfirmの部分を追加します。


pay.js

  confirm: (transactionId) => {

console.log('called confirm')
// Restore data from cache
const reservation = cache.get(transactionId);
if (!reservation){
console.log("Reservation not found.");
return res.status(400).send("Reservation not found.")
}

console.log(`Restore data from cache.`);
console.log(reservation);

const confirmation = {
transactionId: transactionId,
amount: reservation.amount,
currency: reservation.currency
}

// Finished transaction
return pay.confirm(confirmation).then((response) => {
const messages = [{
type: "sticker",
packageId: 2,
stickerId: 516
},{
type: "text",
text: `ありがとうございます、${reservation.productName}の決済が完了しました。`
}]

return client.pushMessage(reservation.userId, messages);
});
}




flex messageからreserveを呼び出す

flex messageのボタンのactionをuriからpostbackに変更し、dataを追加します。


messages/flex.js


"action": {
"type": "postback",
"label": "Add to Cart",
"data": "action=buy&id=1&productName=バーガー&amount=500"
}



postbackからLINE Payの決済画面を呼び出す

postbackで返ってきたイベントをreserveに渡し、LINE Payの決済画面へ誘導します。


server.js

...

const queryString = require('querystring');
const pay = require('./pay');
...

function handleEvent(event) {
...
if (event.type === 'postback') {
const data = queryString.parse(event.postback.data);
console.log({data: data})
return pay.reserve(event, data.productName, data.amount);
}

if (event.type !== 'message' || event.message.type !== 'text') {
...
}




confirm画面へ

決済画面から返ってきたcallback urlからconfirm画面へ飛ばします


server.js

app.get("/pay/confirm", (req, res, next) => {

console.log('called confirm path')

if (!req.query.transactionId){
console.log("Transaction Id not found.");
return res.status(400).send("Transaction Id not found.");
}
pay.confirm(req.query.transactionId);
})




完成

もう一度「バーガー」と入力しカートを押すとLINE Payの決済画面に遷移し、決済可能できるbotが完成しました。



参考文献



gist

SDKを使わずにLINE Payも利用することが可能です。

Nodejs版を置いて置きます。直接httpリクエストを送っているため、多言語でも実装できると思います。