Posted at

Square Connect JavaScript SDKを使って決済処理を実装する

More than 1 year has passed since last update.

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が必要になります。これはクレジットカード番号を一時的に使えるトークンに置き換える際に、開発者側は一切カード番号に触れることなく変換を行うためです。

Screenshot_ 2017-12-13 18.34.53.png

この時、描画する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} になります。

Screenshot_ 2017-12-13 18.34.46.png


ここまでのコード

これだけでクレジットカードを使った決済処理が実装できます。カード番号に触れることもないので安全です。コードは goofmint/SquareConnect-Express-Demo: Square Connect Node SDKでExpressを使ってクレジットカード決済を提供するデモです。 にアップロードしてありますので実装時の参考にしてください。

square/connect-javascript-sdk: Javascript client library for the Square Connect APIs https://docs.connect.squareup.com/