Payjp.jsを導入するにあたって、理解するのに時間がかかってしまったので(なにせ記事が少ない!)今後導入される方の時間短縮のために、ここに残しておきます。
#Pay.jpとは
Pay.jpのサービスを利用することでクレジットカード決済機能を簡単に導入することができます。
gem'payjp'をインストールすることで使用可能に。
利用方法については大きく2通りあります。
###「チェックアウト」
公式で用意されたスクリプトタグをHTMLに記述すれば、デザインされた決済フォーム、カード情報のバリデーション、カード情報のトークン化を行うフォームを生成することができます。こちらを使用すれば、ささっとすぐに実装可能です。
ビューについてこだわりがないという方であればこちらで十分だと思います。
###「カスタムフォーム(payjp.js)」
payjp.jsを使うことで、好きなデザインや挙動でトークン化を行うフォームを組み込めます。
ここで注意をしたいのが、payjp.jsはトークン化に特化したライブラリであり、これを使用したからといって決済ができる訳ではありません。
クレジットカード情報入力ページは自分の好みのビューにしたい!という方はこちらです。
今回はこのpayjp.jsで実装していくための説明となります。
#トークンとは
クレジットカード情報を自身のデータベース上で管理するのはセキュリティの観点で好ましくないので、顧客が入力したカード情報をトークン化しなくてはいけません。
顧客情報を持った情報の塊のことをトークンを呼びます。IDを使用することで顧客情報を呼び出すことができます。
トークン化については公式を参考にしてください。
https://pay.jp/docs/cardtoken
またトークンは1度のみの使用しか出来ないので、2度以上使いたい場合は顧客カードを作成してカード情報をそこに紐付けることが必要です。顧客カードへの紐付けというのは後ほど説明します。
#いざ導入!
ここからは実際のコードを交えて説明します。
まずは、顧客がカード情報を入力するためのフォームを作成します。
%h2 クレジットカード情報入力
= form_tag("/users/purchase", method: "PATCH", id: "charge-form") do
%label カード番号
%input{maxlength: "16", type: "text", class: "number", id: "payment_card_no" name: "number", placeholder: "カード番号"}
%label CVC
%input{type: "text", class: "cvc", id: "payment_card_security_code", name: "cvc", maxlength: "3", placeholder: "CVC"}
%label 有効期限
%input{type: "text", class: "exp_month", id: "payment_card_expire_mm", name: "exp_month", maxlength: "2", placeholder: "月"}
%input{type: "text", class: "exp_year", name: "exp_year", maxlength: "4", placeholder: "年"}
Pay.jpにトークンを作成してもらうには、公式で用意されているフォームを活用しましょう。
(本記事では所々書き換えています。)
$(document).on('turbolinks:load', function() {
var form = $("#charge-form");
Payjp.setPublicKey('pk_test_0383a1b8f91e8a6e3ea0e2a9');
$("#charge-form").on("click", "#submit-button", function(e) {
e.preventDefault();
form.find("input[type=submit]").prop("disabled", true);
var card = {
number: parseInt($("#payment_card_no").val()),
cvc: parseInt($("#payment_card_security_code").val()),
exp_month: parseInt($("#payment_card_expire_mm").val()),
exp_year: parseInt($("#payment_card_expire_yy").val())
};
Payjp.createToken(card, function(s, response) {
if (response.error) {
alert("error")
form.find('button').prop('disabled', false);
}
else {
$(".number").removeAttr("name");
$(".cvc").removeAttr("name");
$(".exp_month").removeAttr("name");
$(".exp_year").removeAttr("name");
var token = response.id;
$("#charge-form").append($('<input type="hidden" name="payjp_token" class="payjp-token" />').val(token));
$("#charge-form").get(0).submit();
}
});
});
});
顧客がsubmitボタンを押した瞬間にこのjsファイルが反応するようにしてあげます。
このフォームの中のPayjp.createTokenで作成されたトークンIDがresponse.idに返ってきます。
後はif文で分岐をさせてあげて、最後にe.preventDefault();によって停止させていたsubmitを実行させます。
setPublicKeyにはpay.jpにログインした際の管理画面で確認できるAPIキーを入れてください。
APIキーはconfig/initializers/setting.rbを作成してその中に変数を定義して入れてあげるとrbファイル間で共有できるので、利便性・セキュア面で良いですね!
(記載しているAPIキーは公式のものなのでご心配なく)
%input.payjp-token{ type: "hidden", name: "payjpToken", value: "" }
そしてHTML上で上記の記述をして、jsファイルで作成したトークンIDが空のvalueに入ることで、paramsとしてコントローラーへ投げることができます。
inputタグをhiddenにすることでビュー上には反映されていません。
以上でトークン作成と、トークンIDをparamsとしてコントローラーへ渡せるようになりました。
###顧客カードとの紐付け
カード情報非通過対応により2018年6月頃からサーバーサイドからのカード情報のPOSTリクエストができなくなりました。
そのためトークン化はビュー上で行いましたが、顧客作成はコントローラーで行います。
Payjp.api_key = PAYJP_SECRET_KEY
customer = Payjp::Customer.create(card: params[:payjp_token])
Payjp::Customer.createで顧客カードが作成されたので、その中のcardキーのバリューとしてトークンIDを指定してあげます。
カード情報を取り出す際にもこのIDは使用するので、私はUserテーブルのカラムに入れてあげました。
他にも支払い等の詳しいやり方は公式のリファレンスを参照ください。
https://pay.jp/docs/api/#introduction
#終わりに
私自身まだエンジニアとしてプログラミングを学んで3ヶ月満たないので、ツッコミどころがあるかもしれません。
こういったやり方もあるんだな〜という、一つの実装方法として参考程度に見てください。
他に効率の良いやり方があるよ!この記述無駄じゃない?と気づいた方がいらしたらご指摘ください(_ _)