Squareの決済処理をAPIで行うためのJavaScriptライブラリ、Square Connect Node SDKがリリースされました。今回はこのSDKを使って、Expressで決済処理を実装してみます。
ベース
ベースは express-generator を使って生成します。
$ npm install express-generator -g
$ express express_square
$ cd express_square
$ npm i
ライブラリのインストール
使うライブラリは square-connect
です。
$ npm install square-connect --save
設定ファイルの作成
Square Connect APIを使うための各種設定を記載した設定ファイルを準備します。
$ cat config.json
{
"square": {
"applicationId": "YOUR_APPLICATION_ID",
"accessToken": "YOUR_ACCESS_TOKEN",
"locationId": "YOUR_LOCATION_ID"
}
}
Square Connectの初期化
まずSquare Connectの初期化を行います。作成した設定ファイルを読み込みつつ、そこに記載されているアクセストークンを適用します。
// routes/index.js
const config = require('../config');
// Square Connect JavaScript SDKを初期化します
const SquareConnect = require('square-connect');
SquareConnect
.ApiClient
.instance
.authentications
.oauth2
.accessToken = config.square.accessToken;
決済入力画面の表示
決済入力画面を生成する際にはSquare ConnectのアプリケーションID、ロケーションIDが必要になります。これはクレジットカード番号を一時的に使えるトークンに置き換える際に、開発者側は一切カード番号に触れることなく変換を行うためです。
この時、描画するHTMLに対してアプリケーションIDとロケーションIDを送ります。
// routes/index.js
// 決済ページです
router.get('/', (req, res, next) => {
res.render('index', {
applicationId: config.square.applicationId,
locationId: config.square.locationId
});
});
HTMLの表示
デフォルトの設定なので views/index.jade
が読み込まれます。この時、アプリケーションIDとロケーションIDをHTML側で定義してしまいます。後はBootstrapを使ってフォームを作っています。注意点として、カード番号の一時的なトークンを受け取る場所を input#card-nonce(type="hidden",name="nonce")
として用意していることです。
extends layout
block content
script.
const applicationId = "#{applicationId}";
const locationId = "#{locationId}";
script(src="https://js.squareup.com/v2/paymentform")
script(src="/Javascripts/app.js")
div.row
div.col-md-12
h1 JavaScript SDKデモ
p カード番号は 5409889944179029 を使ってください。
form#nonce-form(action="/pay",method="post")
div.form-group
label 住所
input.form-control(type="text",name="address")
div.form-group
label カード番号
div#sq-card-number
div.form-group
label 有効期限
div#sq-expiration-date
div.form-group
label CVV
div#sq-cvv
div.form-group
label 郵便番号
div#sq-postal-code
input#card-nonce(type="hidden",name="nonce")
button.btn.btn-default(type="submit",onclick="requestCardNonce(event)") 注文する
JavaScriptの作成
次にクライアント側のJavaScriptを作成します。パスは public/javascripts/app.js
になります。ここに書いてある内容はSqPaymentForm Overviewにある内容ほぼそのままです。
SqPaymentForm
が定義されると自動的にHTMLフォームを生成します。そして注文するボタンを押した時の処理で requestCardNonce
を呼び出すように指定していますので、その中で paymentForm.requestCardNonce()
を呼び出します。このメソッドがSquareのAPIを実行し、クレジットカード情報から一時的なトークン(nonceと呼びます)を生成します。生成後 cardNonceResponseReceived
が呼び出されます。
// 注文するボタンが押された時の処理
function requestCardNonce(event) {
event.preventDefault();
paymentForm.requestCardNonce();
}
// Squareの決済フォーム周りの処理を行うオブジェクト
var paymentForm = new SqPaymentForm({
// 個人の設定
applicationId: applicationId,
locationId: locationId,
// Bootstrap用に変更
inputClass: 'form-control',
inputStyles: [{
fontSize: '.9em'
}],
// プレイスホルダーを日本語に変更しています
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: {
methodsSupported: function (methods) {},
createPaymentRequest: function () {
var paymentRequestJson ;
return paymentRequestJson ;
},
// カードの一時トークンを受け取った時の処理
cardNonceResponseReceived: function(errors, nonce, cardData) {
if (errors) {
console.log("Encountered errors:");
errors.forEach(function(error) {
console.log(' ' + error.message);
});
return;
}
// 一時トークンを保存
document.getElementById('card-nonce').value = nonce;
// フォームを送信
document.getElementById('nonce-form').submit();
},
unsupportedBrowserDetected: function() {
},
inputEventReceived: function(inputEvent) {
},
paymentFormLoaded: function() {
}
}
});
決済処理の実行
決済処理は生成されたトークンを使って行います。店舗IDに加えて、最低限必要な情報(ランダムな文字列、金額、nonce)を送信して完了です。決済処理を繰り返し行わないよう、別なページにリダイレクトさせます。
// 決済処理です
router.post('/pay', (req, res, next) => {
// Square APIから取得した一時的に使えるカードトークン
const nonce = req.body.nonce;
// 店舗ID
const locationId = config.square.locationId;
const api = new SquareConnect.TransactionsApi();
// リクエストパラメータを組み立てます
// ランダムなキー、金額、カードトークンが最低限必要です
const body = {
idempotency_key: `ORDER.${Math.random() * 10000000000000}`,
amount_money: {
amount: 1000,
currency: 'JPY'
},
card_nonce: nonce
}
// 決済処理を実行します
api.charge(locationId, body).then(data => {
// 完了したらリダイレクトします(再読み込み防止のため)
res.redirect(`/complete?id=${data.transaction.id}`);
}, (err) => {
console.error(err);
res.render('error', {error: err})
});
});
完了ページの表示
決済完了ページでは単に受け取ったIDを表示するだけです。
// 注文完了ページ用です
router.get('/complete', (req, res, next) => {
res.render('complete', {
id: req.query.id
});
});
extends layout
block content
div.row
div.col-md-12
注文が完了しました。IDは #{id} になります。
ここまでのコード
これだけでクレジットカードを使った決済処理が実装できます。カード番号に触れることもないので安全です。コードは goofmint/SquareConnect-Express-Demo: Square Connect Node SDKでExpressを使ってクレジットカード決済を提供するデモです。 にアップロードしてありますので実装時の参考にしてください。