【PHP】世界の主要通貨を日本円に変換する

さてさて、以前私はカナダのバンクーバーに留学してたことがあるのですが、日本に帰ってきてからもこちらでは売っていない「ハンバーガー」や「ローストしたひまわりの種」「ホットチョコレート」がたまに食べたくなったりしています。

そして、そんなときによく思うのが、

そういえば、現地の通貨を日本円にするのってめんどくさかったなー😅

というものです。

長く生活しているとだいたい高い安いは分かるようになってきますが、行ってすぐだといちいち頭の中で計算しないといけないですし、なにより英語でしゃべらないといけないから頭はぐちゃぐちゃになるということがよくありました💦

というこで、今回はそんな経験も踏まえてPHPを使って世界の主要通貨を日本円に計算する方法を紹介します。

そして最後に、Laravelで通貨の自動計算するLINEボットをつくる方法も紹介してみたいと思います。

ぜひ皆さんのお役に立てると嬉しいです。

開発環境: PHP 7.2, Laravel 5.8

為替レートの情報をどこからとるか

もちろん為替レートは変動しているので、常に新しい情報を取得する必要があります。本格的にやろうと思えば、取引所から発行されるデータを自前で取得する必要がありますが、今回はテストなので以下のAPIを使って実装します。(とはいっても、このAPIも元は欧州中央銀行からデータを取得しているとのことです)

Foreign exchange rates API

世界の主要通貨を別の通貨に変換する関数

では、Foreign exchange rates APIを使った通貨変換の関数です。

function convert_currency($amount, $from_symbol, $to_symbol, $decimal_point = 2) {

    $converted_amount = null;
    $url = 'https://api.exchangeratesapi.io/latest?base='. $from_symbol;
    $data = json_decode(file_get_contents($url), true);

    if(isset($data['rates'][$to_symbol])) {

        $converted_amount = round($data['rates'][$to_symbol] * $amount, $decimal_point);

    }

    return $converted_amount;

}

使い方は、次のとおりです。(この例では、100米ドルを日本円に変換し、少数第2位まで求めます)

$amount = 100;          // 金額
$from_symbol = 'USD';   // この通貨を
$to_symbol = 'JPY';     // この通貨に変換
$decimal_point = 2;     // 小数点第2位で四捨五入
echo convert_currency($amount, $from_symbol, $to_symbol, $decimal_point);

なお、このAPIで利用できる通貨は以下のとおりです。(2019.09.02現在)

USD: アメリカ合衆国ドル
EUR: ユーロ
CNY: 人民元
KRW: ウォン
CAD: カナダ・ドル
AUD: オーストラリア・ドル
NZD: ニュージーランド・ドル
HKD: 香港ドル
SGD: シンガポール・ドル
GBP: UKポンド
ISK: アイスランド・クローナ
PHP: フィリピン・ペソ
DKK: デンマーク・クローネ
HUF: フォリント
CZK: チェコ・コルナ
RON: ルーマニア・レウ
SEK: スウェーデン・クローナ
IDR: ルピア
INR: インド・ルピー
BRL: レアル
RUB: ロシア・ルーブル
HRK: クーナ
THB: バーツ
CHF: スイス・フラン
MYR: リンギット
BGN: レフ
TRY: トルコリラ
NOK: ノルウェー・クローネ
ZAR: ランド
MXN: メキシコ・ペソ
ILS: シェケル
PLN: ズウォティ

世界の主要通貨を日本円に変換するLINEボットをつくる

では、ここからLaravelのお話になります。
先ほどの通貨を変換する方法を応用して実装していきます。

先に試してみる場合はこちらのQRコードを読み取ってください。

【LINE:日本円だといくら??】

LINE側の作業

LaravelでLINEにチャットボットをつくる(QRコード作成)「LINE Messaging APIを使えるようにする」「パッケージをインストールする」を参考にして実行しておいてください。

基本的には同じ作業になります。

ルートをつくる

まずはルートを作成します。
routes/web.phpを開いて以下を追加してください。

Route::post('currency-bot', 'CurrencyBotController@webhook');

そして、LINEからの送信はCSRFのミドルウェアが適用されないようにapp/Http/Middleware/VerifyCsrfToken.phpを開いて上で指定したURLを$exceptに登録しておきましょう。

    protected $except = [
        'currency-bot',
    ];

コントローラーをつくる

続いて、コントローラーをつくります。
以下のコマンドを実行してください。

php artisan make:controller CurrencyBotController

すると、app/Http/Controllers/CurrencyBotController.phpが作成されるので中身を以下のように変更してください。

<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Http\Request;
use LINE\LINEBot;
use LINE\LINEBot\Event\MessageEvent;
use LINE\LINEBot\Event\MessageEvent\TextMessage;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;

class CurrencyBotController extends Controller
{
    private $_currency_symbols = [
        'USD' => 'アメリカ合衆国ドル',
        'EUR' => 'ユーロ',
        'CNY' => '人民元',
        'KRW' => 'ウォン',
        'CAD' => 'カナダ・ドル',
        'AUD' => 'オーストラリア・ドル',
        'NZD' => 'ニュージーランド・ドル',
        'HKD' => '香港ドル',
        'SGD' => 'シンガポール・ドル',
        'GBP' => 'UKポンド',
        'ISK' => 'アイスランド・クローナ',
        'PHP' => 'フィリピン・ペソ',
        'DKK' => 'デンマーク・クローネ',
        'HUF' => 'フォリント',
        'CZK' => 'チェコ・コルナ',
        'RON' => 'ルーマニア・レウ',
        'SEK' => 'スウェーデン・クローナ',
        'IDR' => 'ルピア',
        'INR' => 'インド・ルピー',
        'BRL' => 'レアル',
        'RUB' => 'ロシア・ルーブル',
        'HRK' => 'クーナ',
        'THB' => 'バーツ',
        'CHF' => 'スイス・フラン',
        'MYR' => 'リンギット',
        'BGN' => 'レフ',
        'TRY' => 'トルコリラ',
        'NOK' => 'ノルウェー・クローネ',
        'ZAR' => 'ランド',
        'MXN' => 'メキシコ・ペソ',
        'ILS' => 'シェケル',
        'PLN' => 'ズウォティ'
    ];

    public function webhook(Request $request) {

        $channel_secret = '(ここにLINEのシークレット鍵)';
        $access_token = '(ここにLINEのアクセストークン)';
        $request_body = $request->getContent();
        $hash = hash_hmac('sha256', $request_body, $channel_secret, true);
        $signature = base64_encode($hash);

        if($signature === $request->header('X-Line-Signature')) {   // LINEからの送信を検証

            $client = new CurlHTTPClient($access_token);
            $bot = new LINEBot($client, ['channelSecret' => $channel_secret]);

            try {

                $events = $bot->parseEventRequest($request_body, $signature);

                foreach ($events as $event) {

                    if($event instanceof MessageEvent && $event instanceof TextMessage) {   // テキストメッセージの場合

                        $text = mb_convert_kana($event->getText(), 'a');    // LINEで送信されたテキスト
                        $reply_token = $event->getReplyToken();     // 返信用トークン
                        $pattern = '|([0-9\.]+) ?([a-zA-Z]{3})|';

                        if(preg_match($pattern, $text, $matches)) {

                            $amount = $matches[1];
                            $symbol = strtoupper($matches[2]);

                            if (isset($this->_currency_symbols[$symbol])) {

                                $currency_name = $this->_currency_symbols[$symbol];
                                $jpy_content = $this->jpyContent($amount, $symbol);

                                if(!empty($jpy_content)) {

                                    $replying_text = number_format($amount) .' '. $currency_name ."は、\n\n".
                                        $jpy_content;

                                }

                            }

                        }

                        if(empty($replying_text)) {

                            $replying_text = "金額の形式が正しくありません。".
                                $this->emoji('100094') .
                                $this->emoji('100029') ."\n\n".
                                "【例】100usd\n(100ドル → 日本円でいくら?)\n\n".
                                "なお、利用できる通貨は以下のとおりです(大文字小文字はどちらでもOK)". $this->emoji('10002D') ."\n\n".
                                $this->currencySymbolContent();

                        }

                        $bot->replyText($reply_token, $replying_text);    // 返信
                        break;

                    }

                }

            } catch (\Exception $e) {}

        }

    }

    private function jpyContent($amount, $symbol) {

        $content = '';
        $url = 'https://api.exchangeratesapi.io/latest?base='. $symbol;
        $data = json_decode(file_get_contents($url), true);

        if(isset($data['rates'], $data['rates']['JPY'])) {

            $dt = Carbon::parse($data['date']);
            $converted_amount = round($data['rates']['JPY'] * $amount);
            $content = "【約 ". number_format($converted_amount) ." 円】です".
                $this->emoji('10002D') ."\n\n".
                "(". $dt->format('Y年m月d日') ."現在)\n\n".
                $this->emoji('100077') ."タイミングによって多少の誤差はあります。また、この情報は自己責任で利用してください。";

        }

        return $content;

    }

    private function currencySymbolContent() {

        $content = '';

        foreach ($this->_currency_symbols as $symbol => $currency_name) {

            $content .= $currency_name .": ". $symbol ."\n";

        }

        return $content;

    }

    private function emoji($emoji_id) {

        $bin = hex2bin(str_pad($emoji_id, 8, '0', STR_PAD_LEFT));
        return mb_convert_encoding($bin, 'UTF-8', 'UTF-32BE');

    }
}

このコード通貨変換をしているのは、jpyContent()メソッドです。
ただし、今回変換するのは日本円で固定なので、引数は金額と変換元の通貨のみになっています。

また、LINEとの通信で必要な情報は以下のとおりです。
適宜内容を変更して実行してください。

  • LINEの秘密鍵 ・・・ $channel_secret
  • LINEのアクセストークン ・・・ $access_token

なお、Foreign exchange rates APIの通貨シンボル(例:USD)は大文字でないといけませんので、strtoupper()で変換しています。

テストしてみる

では、コードをサーバーにアップして通貨変換LINEボットをテストしてみましょう!

まず、100カナダドルから。

そして、85ユーロ。

はい!
どちらも成功です。

お疲れ様でした😊✨

ちなみに

今回作った通貨変換ボットは今後も公開し続けますので、ぜひ海外旅行の際にでも使ってください。(もちろん、現地でスマホがインターネットに繋がらないとだめですが・・・)

【LINE:日本円だといくら??】

おわりに

ということで、今回は世界の主要通貨を変換するという話題をお届けしました。

日本に住んでいると、あまり他国の通貨には馴染みはないかもしれませんが、これからよりグローバル化もすすむでしょうし、海外旅行も一般的になりましたので、テクニックとして覚えておいて損はないと思います。

ただし、やはり1つ心配なのは今回紹介したAPIがどこまで存続するかですね。調べたところ2018年あたりから提供されていてGitHubのスターも700近い人気のものなのですぐ終了することはないでしょうが、ひとつの不確定要素ではあります。

そのため、また時間ができたら日本の取引所などからデータを引っ張ってくるなどができないかを調査してみたいと思います。(詳しい方がいらっしゃったらぜひ教えてください😊)

ではでは〜!

「せめてA&Wハンバーガーだけでも近くに来ないかなー(沖縄にはあるそうです・・・)」

この記事が役立ちましたらシェアお願いします😊✨