8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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/

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?