LoginSignup
34
34

More than 5 years have passed since last update.

Webpay(stripe)でトークン決済とかJSONPとかクロスドメインリクエスト

Last updated at Posted at 2014-04-21

この記事では、実際にRails + Webpayのトークン決済を導入する方法を説明しながら、

裏側で使われている技術とかを紹介しますよ.

トークン決済!?(;゜0゜)

そもそもトークン決済て何。みたいな話はやりはwebpayのドキュメントを見るのが一番分かりやすそう

早速、動くコード(最小の構成)

動くコードを見るのが一番早いと思います.

説明はその後します.

例は短いに超した事がないと思ってるので最小構成で作ってみた.

最小の構成とは

フォームにカード情報を入力してもらい、ItemsControllerbuyアクションを叩く事を想定しましょうか.

このItemsController#buy の中でフォームから受け取ったカード情報で決済をゴニョゴニョしたい感じです.

  • view1つ(test.html.erb)
  • controllerのaction1つ(items_controller.rb#buy)

この2つがあればおk

test.html.erb
<script type="text/javascript" src="https://js.webpay.jp/v1/"></script>
<script type="text/javascript">

  // token生成のAPIを叩いた結果(statusとresponse)を引数として受け取る(コールバック)関数を定義する
  var webpayResponseHandler = function(status, response) {
    var form = $("#payment-form");
    if (response.error) {
      // token生成失敗後の処理を書く
    } else {
      // token生成成功後の処理を書く
      // この例では取得したtokenを<input type="hidden">にのせてappendしてる
      var token = response.id;
      var input = document.createElement("input");
      input.type = "hidden";
      input.name = "token";
      input.value = token;

      $(input).appendTo(form);

      form.get(0).submit();
    }
  };

  $(document).ready(function() {
    // フォームの送信がボタンが押されると..
    $("#payment-form").submit(function(event) {
      // Webpayで発行した公開鍵を入れましょう(商用、テスト環境はよしなに)
      WebPay.setPublishableKey("test_public_19DdUs78k2lV8PO8ZCaYX3JT");
      // こいつがAPIを叩きにいってる、上で定義したコールバック関数もご一緒に
      WebPay.createToken({
        number:    $("#card-number input").val(),
        name:      $("#card-name input").val(),
        cvc:       $("#card-cvc input").val(),
        exp_month: $("#card-expiry-month input").val(),
        exp_year:  $("#card-expiry-year input").val()
      }, webpayResponseHandler);
      return false;
    });
  });

 </script>

<%= form_tag buy_items_path, id: "payment-form" do %>

  <div id="card-number">カード番号: <%= text_field_tag "card[number]", "4242-4242-4242-4242"%></div>

  <div id="card-name"> 名義: <%= text_field_tag "card[name]", "KENGO HAMASAKI" %></div>

  <div id="card-cvc">セキュリティコード: <%= text_field_tag "card[cvc]", "123" %></div>

  <div id="card-expiry-month">
    有効期限(月): <%= text_field_tag "card[exp_month]", "12" %>
  </div>

  <div id="card-expiry-year">
    有効期限(年): <%= text_field_tag "card[exp_year]", "2015" %>
  </div>

  <%= submit_tag '送信' %>

<% end %>


items_controller.rb
class ItemsController < ApplicationController
  def buy
    binding.pry
    params[:token]
    # [大事]!!!↑ここにトークンが入ってる!!!
  end
end


実際に動かしてみた

Gyazo使ってみたかったので使ってみた

2a4ac8b2c16dd12f70e7f327a4bd7869.gif
(controller名とかはちょっと違うけどあんまり気にしないで)

ファッ!?(;゜0゜)

formにあるはずのない、params[:tokens]が!?

このトークンがカード情報(番号、CSV、有効期限、氏名)と等価に扱えるので、

僕たちはカード番号やCVCなどの取り扱いの面倒な情報を持たなくておk

トークン決済スゲー

以下説明

1.カード情報が入力されたformのsubmitボタンが押される

2.$("#payment-form").submit()が発火

このイベント発火後の処理の中で、
WebPayオブジェクト(https://js.webpay.jp/v1/ 内で定義されてる)に必要な情報を渡しAPIを叩く

3.webpayResponseHandlerがAPIの結果を受け取り処理

これは同一生成元ポリシーの元で許されていないクロスドメインリクエストですが、以下に説明するとJSONPというハックを使って実現している.

クライアントとクロスドメイン先のサーバーであらかじめ取り決めたコールバック関数を叩くというものだ.

今回はwebpayResponseHandlerが引数にHTTP(S)のステータスコードとレスポンスを取る。

今回の例では受け取ったtokenをhiddenタグとしてform内に仕込みsubmitし直している。

=====ここまで読めば動くものは作れる======

JSONP

JSONPを知らない方は、まあググって適当に調べてもらうと良い.

今回は、https://js.webpay.jp/v1/ 内で上記の機構をどう実現してるか書きますよ.

以下疲れたのでちょっと手抜き

Webpay.createTokenで必要な情報を受け取った後、

callbackId = "jsonp_" + new Date * 1;

の様にユニークなcallbackIdを作ります。

window[callbackId] = function (data, status) {
  window.clearTimeout(timeoutId);
  return webpayResponseHandler(status, data)
};

windowオブジェクトに対してこれをキーにコールバック関数をセットします。

script = document.createElement("script");

script.src = this.endpoint + option.path + "?" + toParam(option.data) + "&callback=" + callbackId;

document.getElementsByTagName("body")[0].appendChild(script)

srcの部分に叩きたいAPIのendpointとParamsをつめhtml内にappendします.

appendされたscriptタグが評価されるとAPIを叩きにいきます.

jsonp_1398067755529({"id":"tok_5Cb4bo3LidO6dDn","object":"token","livemode":false,"created":1398067774,"used":false,"card":{"object":"card","exp_year":2015,"exp_month":12,"fingerprint":"215b5b2fe460809b8bb90bae6eeac0e0e0987bd7","name":"KENGO HAMASAKI","country":"JP","type":"Visa","cvc_check":"pass","last4":"4242"}}, 201) 

callbackId という関数の呼び出し文が返されます.

callbackId(data,status)という形式になってます.

先ほどのwindowオブジェクトに埋め込んだ関数の引数としてこの(data,status)が入ってきます.

34
34
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
34
34