Railsでwebpayのカード定期決済を実装
小さな企業やスタートアップでカード決済機能を持ったウェブサービスを作ることはあるかと思います。
けれど、カード情報を持っておくことは極力避けたい。
不正アクセスや情報漏洩などあってはならないのだけれど、もし漏れてしまってもユーザーに金銭的な不利益があることは絶対に避けたいはずです。
そこでカード情報を持たずにカード決済を実装できるwebpayを使用します。
環境
Ruby on Rails 4.2.6
ruby 2.2.2
参考
https://webpay.jp
事前準備
webpayの登録をしておいてください
決済UIの実装
まず決済画面のUIを実装します
webpayではCheckoutHelperを使って決済のUIを実装します。
/payments/webpay.html.erb
<form action="/purchase" method="post"> <script src="https://checkout.webpay.jp/v3/" class="webpay-button" data-key="あなたの環境のID" data-lang="ja"></script> </form>
簡単にボタンを実装することができます。
ボタンを押すと
こんな感じで出てきます。おしゃれー。
簡単にボタンを実装することができます。
続いてコントローラーの実装
/payments_controller.rb
class PaymentsController < ApplicationController def webpay end def purchase # API リクエスト cardid = params[:"webpay-token"] webpay = WebPay.new('あなたの環境のID') customer = webpay.customer.create(card: cardid) purchase_data = webpay.recursion.create( amount: 2980, currency: "jpy", customer: customer.id, period: :month, description: "有料プラン" ) params[:"webpay-token"] end end
まずCheckoutHelperのactionがpurchaseでしたのでpurchase actionですね。
クレジットカードのデータは
params[:"webpay-token"]
で取り出すことができます。
カードIDからカスタマーを生成し、カスタマーのIDを使用して定期課金処理を行います。
customer = webpay.customer.create(card: cardid) purchase_data = webpay.recursion.create( amount: 2980, currency: "jpy", customer: customer.id, period: :month, description: "有料プラン" )
この時点でもう定期課金処理は終わっています。
成功するとpurchase_dataに定期課金に関するデータが返ってきます。
レスポンス例{ "id": "rec_ad9dHYeXE8aLfBK", "object": "recursion", "livemode": false, "created": 1469700813, "amount": 2980, "currency": "jpy", "period": "month", "description": "WebPayマガジン購読料", "customer": "cus_ad9dvw3MLa8KaTP", "last_executed": 1469700813, "next_scheduled": 1472379213, "status": "active" }
id:string (文字列)
rec_で始まる一意なオブジェクトを示す文字列
object:string (文字列) 値は”recursion”です。livemode:boolean (真偽値 true/false)
オブジェクトが保存されている環境。trueなら商用環境、falseならテスト環境を示します。
shop:string (文字列) もしくはnull
もし存在している場合は、この課金を作成した店子のID
created:timestamp (unixタイム)
unixタイムで表示される作成日時
amount:integer (0以上の整数)
1円単位での課金額。現在の最低課金額は50円です。
currency:string (3桁のISO通貨コード) 現在は円(“jpy”)のみ対応
三文字のISOコードで表される通貨の名称(例: jpy)
period:string (文字列)
課金間隔。現在はmonth(毎月)、year(毎年)が利用可能です。
description:string (文字列) もしくはnull
定期課金オブジェクトに添付することができる任意の文字列。ウェブ上のダッシュボードで定期課金情報を確認する際に表示されます。2016/06/01より、この内容は定期課金によって作成された課金オブジェクトにも引き継がれます。
customer:string (文字列)
この定期課金に紐付いている顧客のID。関連づけられている顧客は誤操作防止のため削除できなくなります。
last_executed:timestamp (unixタイム) もしくはnull
最後に課金を実行した日時。失敗した場合も更新されます。
next_scheduled:timestamp (unixタイム) もしくはnull
次回の課金実行予定時刻。状態が”suspended”か”closed”の場合はnilになります。
status:string (文字列)
active(次回の実行予定あり)、suspended(一時停止中。次回の実行予定はないが再開可能)、closed(停止。次回の実行予定がなく、再開できない)
webpayのAPIドキュメントより
このIDを保存しておいてwebpayに問い合わせます。
params[:"webpay-token"]
statusのデータを見て有料プランなどを分けるといいですね。
エラー処理
begin # API リクエスト rescue WebPay::ErrorResponse::ErrorResponseError => e case e.data.error.caused_by when 'buyer' # カードエラーなど、購入者に原因がある # エラーメッセージをそのまま表示するのがわかりやすい when 'insufficient' # 実装ミスに起因する when 'missing' # リクエスト対象のオブジェクトが存在しない when 'service' # WebPayに起因するエラー else # 未知のエラー end rescue WebPay::ApiError => e # APIからのレスポンスが受け取れない場合。接続エラーなど rescue # WebPayとは関係ない例外の場合 end
定期課金を削除するとき
params[:"webpay-token"]
で削除することができます。
これで管理が面倒なカード情報を持たずにカード決済を実装することができます。
細かいことは公式サイトで宜しくお願いします。
参考:webpay