目的
仕事で海外とやりとりすることが多くなってきました。
海外に行ったときに現地通貨が日本円ではいくらなのかをすぐに調べることができるツールがあれば便利だと思って今回、自分で作ってみました。
実現方法
入力
入力についてはLINEを使用しました。
使用したAPI
Foreign exchange rates API
https://exchangeratesapi.io/
ロジック
LINEに入力する文字の形式は固定にしました。
入力として受け付ける文字
(国名):(現地金額)は日本でいくら?
例
中国:1000は日本でいくら?
LINEで入力した内容をもとにAPIを利用して日本円に換算しています。
1.LINEで入力した国名をもとに通貨名を取得します。
連想配列でkey:国名、value:通貨名として紐づけを持たせています。
2.1.で取得した通貨名からレートを求め、日本円を取得します。
今回使用したAPIについては1ユーロあたりのレートが返却される仕様となっていました。
そのため、まず、入力した現地金額を何ユーロか求めて、1ユーロあたりの日本円をかけて
求めています。
コード
'use strict';
// ########################################
// 初期設定など
// ########################################
// パッケージを使用します
const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');
// ローカル(自分のPC)でサーバーを公開するときのポート番号です
const PORT = process.env.PORT || 3000;
// Messaging APIで利用するクレデンシャル(秘匿情報)です。
const config = {
channelSecret: '作成したBotのチャネルシークレット',
channelAccessToken: '作成したBotのチャネルアクセストークン'
};
// 国名と通貨の紐づけをしています。
const currency = new Array();
currency["カナダ"] = "CAD:ドル";
currency["香港"] = "HKD:ドル";
currency["アイスランド"] = "ISK:クローナ";
currency["フィリピン"] = "PHP:ペソ";
currency["デンマーク"] = "DKK:クローネ";
currency["ハンガリー"] = "HUF:フォリント";
currency["チェコ"] = "CZK:コルナ";
currency["オーストラリア"] = "AUD:ドル";
currency["ルーマニア"] = "RON:レウ";
currency["スウェーデン"] = "SEK:クローネ";
currency["インドネシア"] = "IDR:ルピア";
currency["インド"] = "INR:ルピー";
currency["ブラジル"] = "BRL:レアル";
currency["ロシア"] = "RUB:ルーブル";
currency["クロアチア"] = "HRK:クナ";
currency["日本"] = "JPY:円";
currency["タイ"] = "THB:バーツ";
currency["スイス"] = "CHF:フラン";
currency["シンガポール"] = "SGD:ドル";
currency["ポーランド"] = "PLN:ズウォティ";
currency["ブルガリア"] = "BGN:レフ";
currency["トルコ"] = "TRY:リラ";
currency["中国"] = "CNY:人民元";
currency["ノルウェー"] = "NOK:クローネ";
currency["ニュージーランド"] = "NZD:ドル";
currency["南アフリカ共和国"] = "ZAR:ランド";
currency["アメリカ"] = "USD:ドル";
currency["メキシコ"] = "MXN:ポンド";
currency["イスラエル"] = "ILS:新シケル";
currency["イギリス"] = "GBP:ポンド";
currency["韓国"] = "KRW:ウォン";
currency["マレーシア"] = "MYR:リンギット";
// ########################################
// APIでデータを取得する部分
// ########################################
// APIを呼び出し日本円を求める
const rateFunction = async (event) => {
const userText = event.message.text;
// ユーザーメッセージが「日の出」か「日の入り」かどうか
if (userText.indexOf('日本でいくら?') === -1) {
return client.replyMessage(event.replyToken, {
type: 'text',
text: '「(国名):(金額)は日本でいくら?」と話しかけてね'
});
} else {
// 「リプライ」を使って先に返事しておきます
await client.replyMessage(event.replyToken, {
type: 'text',
text: '調べています……'
});
let pushText = '';
try {
const country_amt = userText.substring(0, userText.indexOf('は'));
// LINEに入力した国名
const country = country_amt.substring(0, userText.indexOf(':'));
// LINEに入力した金額
const amt = country_amt.substring(userText.indexOf(':')+1, userText.length);
// axiosでレート取得のAPIを叩きます(少し時間がかかる・ブロッキングする)
const res = await axios.get('https://api.exchangeratesapi.io/latest');
// LINEに入力した国名から通貨を取得する
const country_tmp = currency[`${country}`];
// 通貨(英語名)
const country_currency = country_tmp.substring(0, country_tmp.indexOf(':'));
// 通貨(日本語名)
const country_currency_jpn = country_tmp.substring(country_tmp.indexOf(':')+1, country_tmp.length);
// LINEに入力した国名の1ユーロあたりのレート
const country_rates = res.data.rates[`${country_currency}`];
// 1ユーロあたりの日本円
const jpy_rates = res.data.rates.JPY;
// LINEに入力した金額の日本円
const jpy_yen = Math.round((amt / country_rates) * jpy_rates);
pushText = `日本円で約${jpy_yen}円です!`;
} catch (error) {
pushText = '検索中にエラーが発生しました。ごめんね。';
// APIからエラーが返ってきたらターミナルに表示する
console.error(error);
}
// 「プッシュ」で後からユーザーに通知します
return client.pushMessage(event.source.userId, {
type: 'text',
text: pushText,
});
}
};
// ########################################
// LINEサーバーからのWebhookデータを処理する部分
// ########################################
// LINE SDKを初期化します
const client = new line.Client(config);
// LINEサーバーからWebhookがあると「サーバー部分」から以下の "handleEvent" という関数が呼び出されます
async function handleEvent(event) {
// 受信したWebhookが「テキストメッセージ以外」であればnullを返すことで無視します
if (event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
}
// 関数を実行します
return rateFunction(event);
}
// ########################################
// Expressによるサーバー部分
// ########################################
// expressを初期化します
const app = express();
// HTTP POSTによって '/webhook' のパスにアクセスがあったら、POSTされた内容に応じて様々な処理をします
app.post('/webhook', line.middleware(config), (req, res) => {
// Webhookの中身を確認用にターミナルに表示します
console.log(req.body.events);
// 検証ボタンをクリックしたときに飛んできたWebhookを受信したときのみ以下のif文内を実行
if (req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff') {
res.send('Hello LINE BOT! (HTTP POST)'); // LINEサーバーに返答します
console.log('検証イベントを受信しました!'); // ターミナルに表示します
return; // これより下は実行されません
}
// あらかじめ宣言しておいた "handleEvent" 関数にWebhookの中身を渡して処理してもらい、
// 関数から戻ってきたデータをそのままLINEサーバーに「レスポンス」として返します
Promise.all(req.body.events.map(handleEvent)).then((result) => res.json(result));
});
// 最初に決めたポート番号でサーバーをPC内だけに公開します
// (環境によってはローカルネットワーク内にも公開されます)
app.listen(PORT);
console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);
結果
LINEに
中国:1000は日本でいくら?
と入力することで
日本円で約15807円です!
と返信をもらうことができました。
考察
目的である現地通貨が日本円ではいくらなのかを調べるツールを作ることができました。
ただ、下記の課題があると思っているので、改善していければと思ってます。
1.国名と通貨名の紐づけを連想配列にしているが、もう少しスマートな書き方を検討する。
2.連想配列に存在しない国名がきたときの制御ができていない。
3.入力として受け付ける文字が(国名):(現地金額)は日本でいくら?と指定しづらい。
下記のように対話形式で実現させる。
国名を入力してね!
→中国
→何元?
→1000
→1000元は日本円で約15807円です!