JPYC QR 決済アプリのコードのご紹介①
JPYC QR 決済アプリのコードのご紹介①
サマリー
- JPYC QR Pay を実現するために書いたコードを紹介します
- すべてのソースコードは github で公開していますので、pull-request を送ったり、ご自身でさらに素晴らしいアプリ開発のお役に立てると嬉しいです
はじめに
先日、JPYC を店頭などで簡単に決済できるよう JPYC QR Pay というウェブアプリを公開しました。この記事ではこのアプリを作製するにあたり、書いたコードや調べた内容について紹介したいと思います。
JPYC をはじめとした暗号通貨が広く日本で広まるためには、多くの便利なアプリケーションが登場し、利便性が向上したり、多くのユースケースが出てくることが重要であると考えております。
ソースコードはすべて github で公開してはおりますが、これから暗号通貨のアプリケーションを開発したいと思っている方に、少しでもご参考になればという思いで、少しブレイクダウンしてご紹介致します。
QR コードへ決済情報の埋め込み
リアル店舗で MetaMask を使って JPYC を送金する場合、従来であれば、支払者(お客さん)による決済情報の入力(Network の選択、通貨の選択、送金額の入力、送金先の入力)が必要でした。これは今後 JPYC の店舗決済が広まるうえで非常に大きなハードルとなると考えたので、QR コードにこれらすべての内容を埋め込むことにより、QR コードをスキャンしてタップするだけで送金できるようにしました。
こちらの記事でも少し書いています。
支払い用の URL
Ethereum と ERC20 トークンの支払い情報を URL で記載する方法は Ethereum Improvement Propos (EIP)-681 で定義されています。
Polygon や Binance Smart Chain 上の ERC20 コインを送る場合は次のようなフォーマットになります。
ethereum:pay-[コントラクトアドレス]@[チェイン ID]/transfer?address=[送付先]&uint256=[送る金額]
なお、送金額は atomic unit (wei)で記載します。3e18 とは 3 x 1018 を意味します。(ガス代の指定などもできますが、ここでは省略します。)
例えば、3 JPYC on Polygon を私の投げ銭アドレスに送る場合は下記のようになります。
title | variable | example |
---|---|---|
JPYC コントラクトアドレス | jpyc_contract_addr | 0x6ae7dfc73e0dde2aa99ac063dcf7e8a63265108c |
Polygon Chain ID | polygon_chain_id | 137 |
送付先アドレス | dest_addr | 0xafd382aCC893127D6fbb197b87453070Fc14D43d |
送付額 | amount | 3e18 |
ethereum:pay-0x6ae7dfc73e0dde2aa99ac063dcf7e8a63265108c@137/transfer?address=0x330668C9EF59dD4F3b9b32EE978719Ee756D4b44&uint256=3e18
具体的なコードは次のようになります(不要かと思いますが。。。)。
let code =
"ethereum:pay-" +
jpyc_contract_addr +
"@" +
polygon_chain_id +
"/transfer?address=" +
dest_addr +
"&uint256=" +
amount +
"e18";
QR コードを描画する方法
次に、前のセクションを QR コードに埋め込む方法についてご紹介します。
QR コードを JavaScirpt で描画するためのライブラリはいくつか出ていますが、私は html の canvas に描画できるQRCode.jsを使いました。またこれを fork して、支払いコードを簡易的に生成できるライブラリにしました(QRCodePay.js)。
実際のコード
QRCode.js を使う場合
HTML
<head>
<script type="text/javascript" src="qrcodepay.min.js"></script>
</head>
~~~
<div id="qrcode"></div>
JavaScript
var qrcode = new QRCode(document.getElementById("qrcode"), {
width: 300,
height: 300,
});
let code =
"ethereum:pay-" +
jpyc_contract_addr +
"@" +
polygon_chain_id +
"/transfer?address=" +
dest_addr +
"&uint256=" +
amount +
"e18";
qrcode.makeCode(code);
QRCodePay.js を使う場合
QRCodePay.js では前のセクションで記載したトランザクションの URL 生成を組み込んでいますので、JPYC on Polygon の送付の場合は、送付額とアドレスだけ引数に指定するだけでQRコードを生成できます。
HTML
<head>
<script type="text/javascript" src="qrcodepay.min.js"></script>
</head>
~~
<div id="qrcode2"></div>
JavaScript
new QRCodePay( document.getElementById("qrcode2"), amount, dest_addr );
MetaMask 等のブラウザ拡張ウォレットと連携してアドレスを取得する
web3対応のブラウザ拡張ウォレットを導入しているとethereumオブジェクトがインジェクトされています。
アドレスをとるだけの最小コードは次のようになります。accountsにアドレスの配列が入ります。通常はaccounts[0]を使えばよいと思います。
window.web3 = new Web3(ethereum);
await ethereum.enable();
accounts = await web3.eth.getAccounts();
redditかどこかで紹介されていたコードは次のようになっています。
/** web3 */
window.addEventListener("load", async () => {
let accounts = [];
if (window.ethereum) {
window.web3 = new Web3(ethereum);
try {
await ethereum.enable();
accounts = await web3.eth.getAccounts();
} catch (error) {
// User denied account access...
}
}
~~~
if (accounts.length > 0) {
set_dest_addr(accounts[0]);
}
get_dest_addr();
});
スマートフォンの Metamask ブラウザで QR Pay を開く
リアル店舗ではスマートフォンでQRコードを生成すると思いますが、Safari等のスマートフォンのデフォルトブラウザはMetaMask等のブラウザ拡張ウォレットに対応していません。そのため、スマートフォンでMetaMask連携をさせようとすると、MetaMaskのウェブブラウザでJPYC QR Payを表示する必要があります。
MetaMaskのブラウザで表示するという手順が面倒だと考えましたので、iPhoneのSafari等で開いた場合に、MetaMask内のブラウザに飛ばすようにしました。
実はMetaMaskのオフィシャルページにdeep link generatorがあり、MetaMask内のブラウザに飛ばしてくれる機能があります。
今回は、前セクションのウォレットアドレスをとってくるコードの部分で、ethereumオブジェクトがなかった場合に、ポップアップ表示をしてMetaMaskで開くかどうかのリンクを表示しています。
具体的には次のコードです。
/** web3 */
window.addEventListener("load", async () => {
let accounts = [];
if (window.ethereum) {
window.web3 = new Web3(ethereum);
try {
await ethereum.enable();
accounts = await web3.eth.getAccounts();
} catch (error) {
// User denied account access...
}
}
// Legacy dapp browsers...
else if (window.web3) {
window.web3 = new Web3(web3.currentProvider);
accounts = await web3.eth.getAccounts();
}
// ↓ ここで、ポップアップを表示している
else {
$("#modal").modal("show");
}
ポップアップのボタンを押したときにdeep linkに飛ばすのは次のコードです。
$("#openMetamask").on("click", () => {
window.location.href =
"https://metamask.app.link/dapp/nuko973663.github.io/jpycpayqr/";
});
その他
長くなったので、①と②に分けました。②では苦労した着金確認の方法について記載します。