インターネットで商売をするのに、決済機能は欠かせません。Stripeは「決済API」で、今回取り扱う「Stripe Connect」はマーケットプレイスに特化した「決済フローAPI」です。
買い手と、売り手がいるマーケットプレイスを構築するためには、買い手によるクレジットカードの決済処理だけでなく、売り手への入金、またそのプラットフォーム(開発者側)による仲介手数料の回収も行なう必要があります。こういう状況に、Stripe Connectは最適です。
Stripe Connectの概念的な説明に関しましては、下記の記事をご参照ください。今回は、Railsで0) Stripeアカウントを作成、1) Stripeのセットアップ、2) 売り手への入金処理、3) 買い手のクレジットカード登録までを実装していく流れを紹介していきます。
https://qiita.com/y_toku/items/7bfa42793801dfc5415d
開発環境
Ruby 2.4.0
Rails 5.2.2
Devise
Stripe Standard
0) Stripeアカウントを作成する
Stripe Connectを開発環境で動かすためには、3つのAPIを取得する必要があります。
0-1) 公開可能キー(publishable_key)を取得します
0-2) シークレットキー(secret_key)を取得します
ダッシュボード > 開発者 > APIキーより取得できます。
0-3) クライアントID(client_id)を取得します
ダッシュボード > Connect > 設定より取得できます。
1) Stripeのセットアップ
まず、0)で取得してきたAPIをCredentials Keyに保存します。
stripe:
publishable_key: pk_test_************
secret_key: sk_test_************
client_id: ca_************
必要なライブラリをbundle install
でインストールしていきます。
gem 'stripe'
gem 'omniauth-stripe-connect'
2) 売り手への入金処理を実装する
rails g migration AddStripeAccountToUsers access_code:string publishable_key:string
を実行して、UserモデルにStripeアカウントと紐づけるカラムを追加します。
class AddStripeAccountToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :access_code, :string
add_column :users, :publishable_key, :string
end
end
続いて、Stripeの設定とコールバックのコントローラーを追加していきます。
・・・
config.omniauth :stripe_connect,
Rails.application.credentials[Rails.env.to_sym][:stripe][:client_id],
Rails.application.credentials[Rails.env.to_sym][:stripe][:secret_key],
scode: 'read_write',
stripe_landing: 'login'
・・・
・・・
def stripe_connect
auth_data = request.env["omniauth.auth"]
@user = current_user
if @user.persisted?
@user.access_code = auth_data.credentials.token
@user.publishable_key = auth_data.info.stripe_publishable_key
@user.save
sign_in_and_redirect @user, event: :authentication
flash[:notice] = 'Stripe Account Created And Connected' if is_navigational_format?
else
session["devise.stripe_connect_data"] = request.env["omniauth.auth"]
redirect_to root_path
end
end
・・・
ViewにStripe Connectボタンを追加します。
・・・
<%= link_to stripe_url do %>
<%= image_tag ("connect-with-stripe.png") %>
<% end %>
・・・
module ApplicationHelper
def stripe_url
"https://connect.stripe.com/oauth/authorize?response_type=code&client_id=#{Rails.application.credentials[Rails.env.to_sym][:stripe][:client_id]}&scope=read_write"
end
end
開発モードでは「このアカウントフォームをスキップ」で入金口座の登録などをスキップできます。
最後に、StripeダッシュボードでリダイレクトURLを設定します。
access_codeと、publishable_keyが取得できていれば完了です。
3) 買い手のクレジットカード登録を実装する
クレジットカード情報を自身のアプリケーション上で持たず、フロントから直接Stripeに送るために、JSを使う必要があります。
今回は、RailsアプリケーションとJavaScriptの連携をスムーズに実現してくれるgon
というgemを使います。
gem 'gon'
インストールしたgonをViewにセットアップします。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Stripe Application</title>
<%= include_gon %>
<%= Gon::Base.render_data %>
・・・
class ApplicationController < ActionController::Base
before_action :assign_env_variable
def after_sign_out_path_for(resource)
new_user_session_path
end
def assign_env_variable
gon.stripe_key = Rails.application.credentials[Rails.env.to_sym][:stripe][:publishable_key]
end
・・・
続いて、Stripeのクレジットカード情報と紐づけるトークンを保存しておくカラムを追加します。
class AddStripeCustomerIdToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :stripe_customer_id, :string
end
end
config/initializers配下に、stripe.rb
を設定します。
Rails.configuration.stripe = {
:publishable_key => Rails.application.credentials[Rails.env.to_sym][:stripe][:publishable_key],
:secret_key => Rails.application.credentials[Rails.env.to_sym][:stripe][:secret_key]
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
UserコントローラーとUserモデルに、下記を追加していきます。
class UsersController < ApplicationController
def update
@user = User.find(params[:id])
if @user.update(user_params)
if @user.stripe_temporary_token.present?
customer = Stripe::Customer.create(
email: @user.email,
source: @user.stripe_temporary_token
)
@user.update_attribute(:stripe_customer_id, customer.id)
end
else
render :show
end
redirect_to @user
end
private
def user_params
params.require(:user).permit(:email, :stripe_customer_id, :stripe_temporary_token, :provider, :uid, :publishable_key, :access_code)
end
end
class User < ApplicationRecord
・・・
attr_accessor :stripe_temporary_token
・・・
end
クレジットカードフォームをStripeに送るViewとJS部分を追加します。
・・・
<%= form_for(@user, html: {class:'add-card'}) do |f| %>
<div class="block">
<%= f.hidden_field :stripe_temporary_token %>
<div class="formItem">
<%= f.label :card_number %>
<div class="formInput"><%= text_field :card_number, placeholder: "Enter card number", data: {stripe: 'number'} %></div>
</div>
<div class="formItem">
<%= f.label :expiration_month %>
<div class="formInput"><%= select_month(Date.today, {add_month_numbers: true}, id: 'card_month', data: {stripe: 'exp-month'}) %></div>
</div>
<div class="formItem">
<%= f.label :expiration_month %>
<div class="formInput"><%= select_year(Date.today.year, {start_year: Date.today.year, end_year: Date.today.year + 10}, id: 'card_year', data: {stripe: 'exp-year'}) %></div>
</div>
<div class="formItem">
<%= f.label :security_code %>
<div class="formInput"><%= text_field :card_cvc, data: {stripe: 'cvc'}, placeholder: 'CVV/CVC' %></div>
</div>
</div>
<div class="block">
<div class="button">
<%= f.submit "Update", id: "submit-card", class: "btn btnSubmit" %>
</div>
</div>
<% end %>
・・・
jQuery(function($) {
Stripe.setPublishableKey(gon.stripe_key);
function createCardToken(event) {
function createCardToken() {
Stripe.card.createToken(
{
number: $("#card_number").val(),
cvc: $("#card-cvc").val(),
number: $("#card_number_").val(),
cvc: $("#card_cvc_").val(),
exp_month: $("#card_month").val(),
exp_year: $("#card_year").val()
},
stripeResponseHandler
);
console.log("token created");
}
$("#submit-card").on("click", function(e) {
createCardToken();
});
function stripeResponseHandler(status, response) {
var $form = $(".add-card");
if (response.error) {
// Show the error on the form
$("#error").text(response.error.message);
$form.find("input[type=submit]").prop("disabled", false);
} else {
// response contains id and card, which contains additional card details
var token = response.id;
console.log(token);
// Insert the token into the form so it gets submitted to the server
$("input[id=stripe_temporary_token]").val(token);
// and submit manually
$form.get(0).submit();
}
}
// If the user doesn't have a stripe customer account & credit card currently tied to their account, this function will execute and intercept the submit event to obtain a stripe token. Once it has it, it will execute the submit action
$("#card-unavailable").each(function() {
$(".add-card").submit(function(event) {
console.log("no card");
createCardToken();
// Prevent the form from submitting with the default action, we want the token first.
return false;
});
});
});
これで、stripe_customer_idが取れていれば完了です。
さいごに
実装にあたって、Stripeにお問い合わせをしてみました。担当者の方が親身でかつ、迅速に対応してくれたため、開発の目処をすぐに立てることができました。
まだ日本ではStripe文献は少なく感じましたが、大変便利なのでぜひ使ってみましょう。
参考
Stripe Connect & Rails — Part 1
Stripe Connect & Rails — Part 2