EX-決済API と Ruby 🍣 時々 Rails

EX-Omise JapanのLead Developerです。

Omise.jsとCard.jsの謎に迫る

2016年11月18日に、Omise.jsがリニューアルされていましたが皆さんご存知でしょうか? Card.js と Omise.jsの違いがよく分からないとのお声がありましたので、この2つについてご紹介します。

Omise.jsとは

Omise.jsは、クレジットカード情報のトークン化を行うための機能を提供しています。

トークンとは、Omiseが運用するクレジットカード情報とのやりとりを間接的に行うための引換券のようなものです。 これにより、Omiseを利用される事業者さまが、クレジットカード情報を運用する手間とコストを省くことができ、できるだけ早くクレジットカード決済をサービスに取り込むことができるようになっています。

Omise.js経由で伝送するクレジットカード情報は、事業者さまのサーバーは経由せず、直接Omiseのサーバーへ伝送されて処理が行われるため、グローバルセキュリティ基準PCI DSS Version 3.2の元に運用される非常に高いセキュリティの元で支払いができます。

PCI DSS Version 3.2

Omise.jsの3つの機能

2017年2月6日現在のOmise.jsには大きく分けて下記の3つの機能を有しています。

  • クレジットカード情報のトークン化
  • 独自のクレジットカードフォームでトークン化のための Omise.createToken
  • Card.jsの進化版、PayによるUIと通貨の切り替え

それでは、ひとつずつ紹介していきます。

クレジットカード情報のトークン化

Omise.jsは、ユーザーさまがHTMLのフォームへ入力したクレジットカード情報をSubmitのタイミングでOmiseのサーバへ送信を行う機能を有していました。

それでは、なぜユーザーのサーバーではなく、Omiseのサーバーへクレジットカード情報を送信するのでしょうか。 理由は、リスク管理プログラムである PCI DSS と呼ばれるセキュリティ基準に準拠していない環境でのクレジットカード情報の取り扱いをさせないためです。

Omise(ペイメントプロバイダー)は、クレジットカード情報を運用するためのライセンス(PCI DSS)を所有している事業社ですので、ユーザーさまの代わりにクレジットカード情報を安全に運用することができるのです。

そのため、Omise.js経由でOmiseへ送信されてきたクレジットカードデータをOmiseで保管を行い、クライアントサイドへトークンを渡し、ユーザーはこのトークンを元にしてクレジットカード決済に関する処理を行うことができるようになります。

トークンは tokn_test_56wro5rcvo16xrsm795 の形式でユニークな値が割り当てられます。

独自のクレジットカードフォームでトークン化のための Omise.createToken

独自のクレジットカードフォームにてトークン化の仕組みを作る場合には Omise.createToken を利用してください。

# 日本のリージョンからOmise.jsを読み込む
<script src="https://cdn2.omise.co/omise.js"></script>

# 公開鍵を設定する
<script>
  Omise.setPublicKey("pkey_test_4xpip92iqmehclz4a4d");
</script>

# Omise.js自体はjQueryを必要としませんが、サンプルで利用するために読み込む
<script src="http://code.jquery.com/jquery-1.12.1.min.js"></script>

# カードフォームのHTML
<form action="/checkout" method="post" id="checkout">
  <div id="token_errors"></div>

  <input type="hidden" name="omise_token">

  <div>
    Name<br>
    <input type="text" data-omise="holder_name">
  </div>
  <div>
    Number<br>
    <input type="text" data-omise="number">
  </div>
  <div>
    Date<br>
    <input type="text" data-omise="expiration_month" size="4"> /
    <input type="text" data-omise="expiration_year" size="8">
  </div>
  <div>
    Security Code<br>
    <input type="text" data-omise="security_code" size="8">
  </div>

  <input type="submit" id="create_token">
</form>

# 上記クレジットカードフォームでトークン化させるための処理を書く
<script>
$("#checkout").submit(function () {

  var form = $(this);

  // Submitボタンを無効化にし、二重クリックを防ぐ
  form.find("input[type=submit]").prop("disabled", true);

  // formの値を変数cardにオブジェクトとして集める
  var card = {
    "name": form.find("[data-omise=holder_name]").val(),
    "number": form.find("[data-omise=number]").val(),
    "expiration_month": form.find("[data-omise=expiration_month]").val(),
    "expiration_year": form.find("[data-omise=expiration_year]").val(),
    "security_code": form.find("[data-omise=security_code]").val()
  };

  // Omiseへトークン作成のリクエストを行う
  Omise.createToken("card", card, function (statusCode, response) {
    if (response.object == "error" || !response.card.security_code_check) {
      // エラーが返ってきた場合のメッセージ
      var message_text = "SET YOUR SECURITY CODE CHECK FAILED MESSAGE";
      if(response.object == "error") {
        message_text = response.message;
      }
      $("#token_errors").html(message_text);

      // Submitボタンを有効化にする
      form.find("input[type=submit]").prop("disabled", false);
    } else {
      // Omiseが返してきたトークンをomise_tokenの値として設定
      form.find("[name=omise_token]").val(response.id);

      // フォームを送信する前に、カード情報を空にする
      form.find("[data-omise=number]").val("");
      form.find("[data-omise=security_code]").val("");

      // トークンを事業者さまのサーバーへ送信
      form.get(0).submit();
    };
  });

  return false;
});
</script>

Card.jsの進化版、PayによるUIと通貨の切り替え

Card.jsでは、JSを読み込むことでOmiseが提供するカードフォームを提供してきました。 しかしながら、Card.jsはタイ国内限定の仕様で設計されており、日本の通貨 jpy を利用することができません。

そのため、新しいカードフォームで通貨の指定ができる機能を2016年11月18日のOmise.jsに組込むことになったのです。

労力をかけずに、簡単にカードフォームを実装する場合にオススメの機能です。

下記のスニペットをHTMLへ記述をすると、カードフォームを表示するためのボタンが表示されます。

<form name="checkoutForm" method="POST" action="checkout">
  <input type="hidden" name="description" value="商品合計 10,025円" />
  <script type="text/javascript" src="https://cdn2.omise.co/omise.js.gz"
    data-key="YOUR_PUBLIC_KEY"
    data-image="https://cdn1.www.st-hatena.com/users/ak/akinrt/profile.gif"
    data-frame-label="決済APIとRuby🍣時々Rails[f:id:akinrt:20170206225750p:plain]"
    data-button-label="クレジットカードで支払う"
    data-submit-label="Submit"
    data-location="yes"
    data-locale="ja"
    data-amount="10025"
    data-currency="jpy"
    >
  </script>
</form>

そして、ここでは クレジットカードで支払う と表示されたボタンをクリックするとOmiseのカードフォームが表示されます。

f:id:akinrt:20170206230840p:plain

※ クレジットカードで支払う ボタンは、ご自身でCSSを変更してレイアウトしてください。

scriptに渡しているパラメーターの役割は下記です。

param value content
data-key 秘密鍵 ユーザーさまの秘密鍵を設定してください
data-image 画像URL カードフォームへ表示させるサムネイルのURLを設定してください
data-frame-label タイトル カードフォームへ表示するタイトルを設定してください
data-button-label Payボタンのタイトル Payボタンに表示したいテキストを設定してください
data-submit-label 支払いボタンのラベル 青いボタンの左に表示されるテキストを設定してください
data-location ‘yes’ または ‘no’ 住所 & 連絡事項を表示する場合に ‘yes'、非表示にしたい場合に 'no’
data-locale ‘en'、'ja’ または ‘th’ ラベルの言語を英語・日本語・タイ語の中から指定できます
data-amount ユーザーの支払い金額 ユーザーへ支払いさせる金額を入力してください
data-currency ‘thb’ または ‘jpy’ ご利用の通貨を指定してください

Omise.jsの配信元

Omise.jsはAWSのS3を使ってシンガポールと東京のリージョンから配信しています。

東南アジア向けにご利用の場合はシンガポールリージョンの下記をご利用ください。

Primary CDN (Singapore)
<script src="https://cdn.omise.co/omise.js.gz"></script>

日本からはご利用の場合は、東京リージョンの下記をご利用ください。

Secondary CDN (Japan)
<script src="https://cdn2.omise.co/omise.js.gz"></script>

Card.jsは。。。

こちらは、ご利用にならないようにお願いします。
以前よりご利用されているタイのユーザーさま向けに配信は続けていますが、現在メインテナンスは行われていません。

※ Omise.jsのみメインテナンスされています。

Omise.jsのブラウザ対応状況は?

Internet Explorer 9 〜、とモダンブラウザに対応しています。
Omise.jsに含まれているPayはReactで作成されており、ES5 methodsをサポートしていないブラウザでは正常に動作しません。

OmiseのWebhookをテスト環境で試すためのアプリを用意しました

はじめに

こんにちは、タイから帰国してOmise Japanでの勤務を2月からスタートしました。

Omiseでは開発本拠がタイのバンコクにあるため、日本でのエンジニア向け情報発信が滞っていましたが、帰国を機に、個人のブログでエンジニア視点で記事を書くことにしました。

今回は、ピティナ開発ブログ さまで取り上げられていた、OmiseのWebhookについて記事を書いてみます。

OmiseのWebhookとは

OmiseのWebhookは、新規のChargeやCustomerなどを作成、更新などが行われたタイミングに、指定のURLへPOSTリクエストでJSONをリクエストボディにて送信します。

試しにゲストアカウントのテスト環境で、トークンを使ったChargeオブジェクトの作成してみると、 Chargeが作成されたタイミングでWebhookにて通知されるイベントオブジェクトは下記のようなフォーマットになります。

テスト環境のWebhookを送る先のURLはこちらの設定画面から追加できます。

f:id:akinrt:20170203223819p:plain

設定画面の編集ボタンをクリックし、エンドポイント(送信先URL)を入力して更新することで、次回からのイベントオブジェクト生成時に送信先URLへPOSTリクエストが送信されるようになります。

※ OmiseのWebhookでは、有効なSSL証明証のあるHTTPSのURLがご利用いただけます。

参考ドキュメント: Omise: WebHooks

OmiseのWebhookが送信されるタイミングは?

2017年2月3日現在では、下記のイベントオブジェクトが生成されたタイミングになります。

Charge

イベント名 タイミング
charge.create Chargeが作成された後
charge.update Chargeが更新された後
charge.capture Chargeがキャプチャ(実売上)された後
charge.reverse Chargeが取り消された後
charge.complete 3D-SecureかInternet Bankingを使ったChargeが完了した後

Customer

イベント名 タイミング
customer.create Customerが作成された後
customer.update Customer更新された後
customer.destroy Customerが削除された後
customer.update.card CustomerのCardが更新された後

Card

イベント名 タイミング
card.update Cardが更新された後
card.destroy Cardが削除された後

Dispute

イベント名 タイミング
dispute.create Dispute(チャージバック)の要請を開始した後
dispute.update Disputeが更新された後
dispute.close Disputeの結果がでた後

Recipient

イベント名 タイミング
recipient.create Recipientが作成された後
recipient.update Recipientが更新された後
recipient.destroy Recipientが削除された後
recipient.activate Recipientが有効になった後
recipient.deactivate Recipientが無効になった後
recipient.verify Recipientが承認された後

Refund

イベント名 タイミング
refund.create Refundが作成された後

Transfer

イベント名 タイミング
transfer.create Transferが作成された後
transfer.update Transferが更新された後
transfer.destroy Transferが削除された後
transfer.send Transferのリクエストが送信された後
transfer.pay Transfer(振込)が完了した後
transfer.fail Transferのリクエスト後に振込が失敗したことが判明した後

OmiseのWebhookをテスト環境で試してみよう

ビズチーム経由で多くのユーザーさまからWebhookの挙動を確認するのがめんどくさいとの声を聞きましたので、個人的にomise-webhookを作成しました。

Rubyが好きなのでSinatraを使ったアプリを作り、ngrokを使ってHTTPSのURLをエンドポイントにすることで、ローカル上でアプリを起動してOmiseのWebhookより送信されるJSONのデータをログとして保管する機能を有しています。

git clone、homebrew、homebrew-cask、ruby v2.3.1があるような環境を想定していますので、ご利用になる際には、これらの設定が整っている状態にしてください。

git clone git@github.com:akinrt/omise-webhook.git
cd omise-webhook

# bundlerをインストール
gem install bundler

# 必要なgemのインストール
bundle install --path vendor/bundle

# ngrokのインストール
brew cask install ngrok

# .envをつくる
touch .env

.env には、Omiseのテスト環境の秘密鍵が必要になりますので、こちらから取得して設定してください。

# .env
OMISE_TEST_SECRET_KEY=skey_test_xxxREPLACE_THIS_KEY_WITH_YOURS

ここまでくれば、あとはアプリケーションとngrokを起動して、エンドポイントに設定するHTTPSのURLを確認します。

# アプリの起動
bundle exec ruby app.rb

# 別ウインドウでngrokの起動
ngrok http 3000

ngrokが下記のイメージのようなHTTPSのURLを発行しますので、これをOmiseでエンドポイントに設定します。

f:id:akinrt:20170203233233p:plain

こちらのアプリではOmiseのWebhookを/omise/webhookで受け取るようにしていますので、ngrokからコピーしてきたURLを下記のようにしてください。

f:id:akinrt:20170203233406p:plain

このあとにトークンでChargeを作成するなど実行すると、このアプリがomise-webhook/log/api/event/にJSONオブジェクトをファイルに保存してくれます。 レスポンスの確認などで使ってくだされば幸いです。

あとがき

新規に決済を取り入れる際に、決済事業社がこのようなアプリの提供まで行わないとユーザーにとって非常に不便だと感じました。 ライブラリと数行のコードで決済が完了するようなフレーズも聞いたりしますが、実際に実装する側の気持ちになることで、より便利に使いやすく成長していけるのではないかと思います。

そのため、Omiseをご利用のユーザーさまには、こちらの場でも構いませんので、Omiseの利用を考えられるようになるフィードバックをいただけると幸いです。