Squareでは従来POSレジを提供してきましたが、今年から各種Web APIも提供しています。このWeb APIを使うことでオンライン決済なども可能になります。そのEコマースAPIは、サービス提供事業者はサービス利用者のカード番号を知らないままに決済が提供できるのが利点です。しかもよくある決済ASPのように別画面にいったりすることもなく、デザインの自由度も非常に高いものになっています。
今回はそんなEコマースAPIをNode.jsで実装する方法を紹介します。
フローについて
最初に処理フローについて紹介します。
- SquareのJavaScriptライブラリがフォームを生成する
- 入力されたカード番号などをSquareのサーバに送信する
- Squareのサーバから一時的に利用できるトークン(nonce)が返される
- 入力された顧客情報(名前、住所など)とトークンを自社サーバに送信する
- nonceと決済額をSquareに送信し、決済処理を行う
このようにカード番号などの情報をnonceに置き換えて決済を行うことで、サービス事業者はカード番号を知らずに決済処理が実現できます。
Webフォームを生成する
まずHTMLに次のように記述します。
<label>Card Number</label>
<div id="sq-card-number"></div>
<label>CVV</label>
<div id="sq-cvv"></div>
<label>Expiration Date</label>
<div id="sq-expiration-date"></div>
<label>Postal Code</label>
<div id="sq-postal-code"></div>
さらにJavaScriptタグとして下記を指定します。
<script type="text/javascript" src="https://js.squareup.com/v2/paymentform"></script>
さらにJavaScriptでidとカード情報の紐付けを行います。
var paymentForm = new SqPaymentForm({
applicationId: applicationId,
inputClass: 'sq-input',
inputStyles: [
{
fontSize: '15px'
}
],
cardNumber: {
elementId: 'sq-card-number',
placeholder: '•••• •••• •••• ••••'
},
cvv: {
elementId: 'sq-cvv',
placeholder: 'CVV'
},
expirationDate: {
elementId: 'sq-expiration-date',
placeholder: 'MM/YY'
},
postalCode: {
elementId: 'sq-postal-code'
},
callbacks: {
// 後ほど記述
}
});
そうするとページが表示された際に下記のようにフォームが生成されます。
<label>Card Number</label>
<iframe id="sq-card-number" name="sq-card-number-iframe" class="sq-input" frameborder="0" width="100%" scrolling="no" height="20" src="https://connect.squareup.com/v2/iframe?type=cardNumber"></iframe>
<label>CVV</label>
<iframe id="sq-cvv" name="sq-cvv-iframe" class="sq-input" frameborder="0" width="100%" scrolling="no" height="20" src="https://connect.squareup.com/v2/iframe?type=cvv"></iframe>
<label>Expiration Date</label>
<iframe id="sq-expiration-date" name="sq-expiration-date-iframe" class="sq-input" frameborder="0" width="100%" scrolling="no" height="20" src="https://connect.squareup.com/v2/iframe?type=expirationDate"></iframe>
<label>Postal Code</label>
<iframe id="sq-postal-code" name="sq-postal-code-iframe" class="sq-input" frameborder="0" width="100%" scrolling="no" height="20" src="https://connect.squareup.com/v2/iframe?type=postalCode"></iframe>
これで準備は完了です。
フォーム送信処理の変更
決済処理を開始するフォーム送信処理を変更します。例えばボタンを次のようにします。
<button type="submit" class="btn btn-primary"
onclick="requestCardNonce(event)">注文する</button>
そしてJavaScriptを次のように書きます。
function requestCardNonce(event) {
event.preventDefault();
paymentForm.requestCardNonce();
}
paymentForm.requestCardNonce()
にて前述のnonceを取得する処理が実行されます。その結果は cardNonceResponseReceived
に呼び出されます。
cardNonceResponseReceived: function(errors, nonce, cardData) {
if (errors) {
// エラーの場合
console.log("Encountered errors:");
errors.forEach(function(error) {
console.log(' ' + error.message);
});
} else {
// 処理成功の場合
document.getElementsByName('nonce')[0].value = nonce;
for (var key in cardData) {
document.getElementsByName(key)[0].value = cardData[key];
}
document.getElementById('commerceForm').submit();
}
},
上記のように記述した場合、HTMLのフォーム側にあらかじめhiddenを使って情報を書き込めるようにしておきます。
<!-- カードのnonceが入ります -->
<input type="hidden" name="nonce">
<!-- カードのブランドが入ります -->
<input type="hidden" name="card_brand">
<!-- カードの最後の4桁が入ります -->
<input type="hidden" name="last_4">
<!-- カードの有効期限(月)が入ります -->
<input type="hidden" name="exp_month">
<!-- カードの有効期限(年)が入ります -->
<input type="hidden" name="exp_year">
<!-- 郵便番号が入ります -->
<input type="hidden" name="billing_postal_code">
そして実際のフォームをサーバに送信します。
document.getElementById('commerceForm').submit();
サーバでの処理について
ではここからNode.jsの処理になります。Squareでは2017年09月現在、Node.js向けにフレームワークを提供していません。そこで unirest という汎用的なRESTクライアントライブラリを使います。npm を使ってインストール可能です。
$ npm install unirest -S
まずアクセストークンを用意しておきます。
let access_token = 'REPLACE_ME';
次に先のJavaScriptの処理で手に入れたnonce(テンポラリトークン)を得ます。ない場合はエラーです。
// データを取得します
const params = req.body;
const nonce = params.nonce;
if (typeof nonce === 'undefined') {
res.status(422).render();
return;
}
決済を行う店舗についてはあらかじめ分かっていることとします。
let location_id = 'AAA...BBB';
ではリクエスト情報を生成します。 idempotency_key はユニークなIDです。今回は uuid/v1
というライブラリを使ってUUIDを生成します。sendメソッドで決済額を指定し、決済処理を実行します。
// REST APIをコールします
unirest
// POSTメソッドを指定します
.post(url)
// ヘッダー情報です。アクセストークンを指定します
.headers({
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
})
// sendの中でパラメータを指定します
.send({
// Squareから取得したnonceを設定します
'card_nonce': nonce,
// 金額を指定します
'amount_money': {
'amount': 5000,
'currency': 'JPY'
},
// ユニークなIDを設定します
'idempotency_key': uuidv1()
})
.end(function (response) {
// 処理がうまくいけばこちらに結果がきます
// 再読込で処理が重複実行されないよう、リダイレクトします
res.redirect(`/success?data=${JSON.stringify(response.body.transaction)}`);
});
これで完了になります。カード情報は一度しか使えないnonceとなっていますので、番号などを知ることはありません。カード番号を知らずに決済できる仕組みは幾つかありますが、SquareのEコマースAPIはフォームも自前で持てるので自由度が高い仕組みになっています。JavaScriptの知識も必要ですが、ぜひ導入してみてください!
Embedding the Square Payment Form - Square Connect API Documentation