爆速でLine Pay APIをNode.jsで使ってみる

今回は**本物のお金による決済は行わず**サンドボックスの中だけで処理をします。

## 使うツール

- ngrok
- line pay sandbox

## OS

- MacOS Catalina

## 準備

とりあえず必要なものをインストールします。

```
$ git clone -b web-only https://github.com/nkjm/line-pay-bootcamp.git
$ cd line-pay-bootcamp/
$ npm install
$ npm install -s dotenv line-pay memory-cache uuid 
```

## コード

`web.js`に以下のコードをコピペします。

`pay/reserve`と`pay/confirm`の２つのエンドポイントを用意します。
また、参考にした記事と違うところとして、uuidをインポートするときは、`require('uuid')`にして、`uuid.v4()`で呼び出すようにします。

```web.js
"use strict";

// Import packages.
const express = require("express");
const app = express();

// Launch server.
app.listen(process.env.PORT || 5000, () => {
    console.log(`server is listening to ${process.env.PORT || 5000}...`);
});

// Middleware configuration to serve static file.
app.use(express.static(__dirname + "/public"));

// Set ejs as template engine.
app.set("view engine", "ejs");

// Router configuration to serve web page containing pay button.
app.get("/", (req, res) => {
    res.render(__dirname + "/index");
})

// Import environment variables from .env file.
require("dotenv").config();

// Import packages.
const uuid = require("uuid");
const cache = require("memory-cache");

// Instanticate LINE Pay API SDK.
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
})

// Router configuration to start payment.
app.use("/pay/reserve", (req, res) => {
    let options = {
        productName: "チョコレート",
        amount: 1,
        currency: "JPY",
        orderId: uuid.v4(),
        confirmUrl: process.env.LINE_PAY_CONFIRM_URL
    }

    pay.reserve(options).then((response) => {
        let reservation = options;
        reservation.transactionId = response.info.transactionId;

        console.log(`Reservation was made. Detail is following.`);
        console.log(reservation);

        // Save order information
        cache.put(reservation.transactionId, reservation);

        res.redirect(response.info.paymentUrl.web);
    })
})

// Router configuration to receive notification when user approves payment.
app.use("/pay/confirm", (req, res) => {
    if (!req.query.transactionId){
        throw new Error("Transaction Id not found.");
    }

    // Retrieve the reservation from database.
    let reservation = cache.get(req.query.transactionId);
    if (!reservation){
        throw new Error("Reservation not found.");
    }

    console.log(`Retrieved following reservation.`);
    console.log(reservation);

    let confirmation = {
        transactionId: req.query.transactionId,
        amount: reservation.amount,
        currency: reservation.currency
    }

    console.log(`Going to confirm payment with following options.`);
    console.log(confirmation);

    pay.confirm(confirmation).then((response) => {
        res.send("決済が完了しました。");
    });
})
```

## 走らせる

ngrokでlocalhostを外部に公開します。
環境変数をセットした上でアプリを走らせないといけないので、ngrok => .env編集 => アプリスタート、という流れになります。

```
$ ngrok http 5000

ngrok by @inconshreveable                                       (Ctrl+C to quit)
                                                                                
Session Status                online                                            
Session Expires               1 hour, 26 minutes                                
Version                       2.3.40                                            
Region                        United States (us)                                
Web Interface                 http://127.0.0.1:4040                             
Forwarding                    http://xxxxxx.ngrok.io -> http://localhost:5
Forwarding                    https://xxxxxx.ngrok.io -> http://localhost:
                                                                                
Connections                   ttl     opn     rt1     rt5     p50     p90       
                              14      0       0.00    0.01    7.19    9.35 
```

表示された外部のURLを`.env`に記載します。

```.env
LINE_PAY_CHANNEL_ID=xxxxx
LINE_PAY_CHANNEL_SECRET=xxxxxxx
LINE_PAY_CONFIRM_URL=https://xxxxxx.ngrok.io/pay/confirm
```

これでnode.jsアプリも走らせます！

```
$ npm start
```

ngrokのリンクをlineで開くと、決済のシミュレーションができます。

## 参考

この記事を読まなくても、以下の記事で事足りると思います、、、

https://qiita.com/ufoo68/items/a6d036d143fe4950aea3

https://qiita.com/nkjm/items/b4f70b4daaf343a2bedc