LoginSignup
2
1

More than 5 years have passed since last update.

Square EコマースAPIをNode.jsで実装する

Posted at

Squareでは従来POSレジを提供してきましたが、今年から各種Web APIも提供しています。このWeb APIを使うことでオンライン決済なども可能になります。そのEコマースAPIは、サービス提供事業者はサービス利用者のカード番号を知らないままに決済が提供できるのが利点です。しかもよくある決済ASPのように別画面にいったりすることもなく、デザインの自由度も非常に高いものになっています。

今回はそんなEコマースAPIをNode.jsで実装する方法を紹介します。

フローについて

最初に処理フローについて紹介します。

  1. SquareのJavaScriptライブラリがフォームを生成する
  2. 入力されたカード番号などをSquareのサーバに送信する
  3. Squareのサーバから一時的に利用できるトークン(nonce)が返される
  4. 入力された顧客情報(名前、住所など)とトークンを自社サーバに送信する
  5. 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

2
1
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
2
1