まずは以下の手順でStripeのアカウントを取得してください。
mrradiology.hatenablog.jp
ダッシュボードで「公開可能キー」と「シークレットキー」をコピーします。
記述追加 GemFile(95,96行目)
gem 'stripe', '~> 3.0.0' gem 'rails-assets-card', source: 'https://rails-assets.org'
GemFile
source 'https://rubygems.org' git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{repo_name}.git" end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.7', '>= 5.0.7.1' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 3.0' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.2' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 3.0' # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platform: :mri end group :development do # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.0.5' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] # bulma gem 'bulma-rails', '~> 0.7.4' gem 'bulma-extensions-rails', '~> 1.0.30' # デバイス gem 'devise', '~>4.2' # アバター gem 'gravtastic' # toastr gem 'toastr-rails', '~> 1.0' # 日本語化 gem 'rails-i18n' # google認証 gem 'omniauth' gem 'omniauth-google-oauth2' # 管理ダッシュボード gem 'activeadmin' # 管理ダッシュボードのテーマ gem 'active_skin' #画像アップロード gem 'paperclip', '~> 5.1.0' # アマゾンS3 gem 'aws-sdk', '~> 2.8' # タスクの順番を変える gem "active_admin-sortable_tree", "~> 2.0.0" # Markdown関数 gem 'redcarpet', '~> 3.2.3' gem 'coderay', '~> 1.1.0' # Stripe決済 gem 'stripe', '~> 3.0.0' gem 'rails-assets-card', source: 'https://rails-assets.org'
コマンド
bundle update
記述追加 app\assets\javascripts\application.js
17行目に「//= require card」の記述追加
// This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. JavaScript code in this file should be added after the last require_* statement. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require jquery //= require jquery_ujs //= require toastr //= require gravtastic //= require card //= require turbolinks //= require_tree .
「config\initializers」フォルダに「stripe.rb」ファイルを新規作成して下さい。
config\initializers\stripe.rb(新規作成したファイル)
ご自分の公開可能キーとシークレットキーを入れて下さい。
Rails.configuration.stripe = { :publishable_key => 'pk_test_goyx2a9lI5DVBrzfO7zIVkll00Dhoy1H6m', :secret_key => 'sk_test_1zTyiM6KOMwzCXrtbUqXfD4Z00yYIhe6ER' } Stripe.api_key = Rails.configuration.stripe[:secret_key]
コマンド
rails g migration AddStripeIdToUser stripe_id
コマンド マイグレーション
rails db:migrate
「app\controllers」フォルダに「users_controller.rb」ファイルを新規作成してください。
app\controllers\users_controller.rb(新規作成したファイル)
class UsersController < ApplicationController def payment end def add_card if current_user.stripe_id.blank? customer = Stripe::Customer.create( email: current_user.email ) current_user.stripe_id = customer.id current_user.save # Stripeにカード情報を追加 customer.sources.create(source: params[:stripeToken]) else customer = Stripe::Customer.retrieve(current_user.stripe_id) customer.source = params[:stripeToken] customer.save end flash[:notice] = "カード情報が保存されました" redirect_to payment_method_path rescue Stripe::CardError => e flash[:alert] = e.message redirect_to payment_method_path end end
記述追加 config\routes.rb(16行目と19行目)
get '/payment_method' => "users#payment" post '/add_card' => "users#add_card"
config\routes.rb
Rails.application.routes.draw do devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) devise_for :users, path: '', path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'} # ルートページをapp\views\pages\about.html.erbに設定 root 'pages#about' get 'pages/about' get '/myprojects' => 'project#list' get '/payment_method' => "users#payment" post '/free' => 'charge#free' post '/add_card' => "users#add_card" resources :project do resources :task, only: [:show] end # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end
「app\views」フォルダに「users」フォルダを新規作成してください。
作成した「users」フォルダに「payment.html.erb」ファイルを新規作成します。
app\views\users\payment.html.erb(新規作成したファイル)
<section class="section"> <div class="container"> <div class="columns is-centered"> <div class="column is-8-tablet is-6-desktop is-6-widescreen"> <p class="title has-text-centered">クレジットカード登録</p> <div class="card"> <div class="card-header-title is-centered"> <% if current_user.stripe_id? %> クレジットカード登録済みです <% else %> まだクレジットカードが登録されていません <% end %> </div> </div> <div class="card"> <%= form_tag("/add_card", method: "post", id: "add-card") do %> <div class="card form-row"> <br/> <div class="card-content"> <span>氏名</span> <input name="cardholder-name" class="input" placeholder="GAKUSHUU TAROU" /> </div> <div class="card-content"> <span>カード番号</span> <div id="card-element" class="field"></div> </div> <div class="outcome"> <div class="error" role="alert"></div> </div> <div class="field is-grouped is-grouped-centered"> <% if current_user.stripe_id %> <button type="submit" class="button is-primary m-t-20" style="padding-top: 0;">カードの更新</button> <% else %> <button type="submit" class="button is-primary m-t-20" style="padding-top: 0;">カードを追加する</button> <% end %> </div> <br/> </div> <% end %> </div> </div> </div> </div> </section> <script src="https://js.stripe.com/v3/"></script> <script> $(function() { var stripe = Stripe('<%= Rails.configuration.stripe[:publishable_key] %>'); var elements = stripe.elements(); var card = elements.create('card', { hidePostalCode: true, style: { base: { iconColor: '#F99A52', color: '#32315E', lineHeight: '48px', fontWeight: 400, fontFamily: '"Helvetica Neue", "Helvetica", sans-serif', fontSize: '15px', '::placeholder': { color: '#CFD7DF', } }, } }); card.mount('#card-element'); function setOutcome(result) { var errorElement = document.querySelector('.error'); errorElement.classList.remove('visible'); if (result.token) { var form = $('#add-card'); form.append($('<input type="hidden" name="stripeToken">').val(result.token.id)); form.get(0).submit(); } else if (result.error) { errorElement.textContent = result.error.message; errorElement.classList.add('visible'); } } card.on('change', function(event) { setOutcome(event); }); $('#add-card').on('submit', function(e) { e.preventDefault(); var extraDetails = { name: $('input[name=cardholder-name]').value }; stripe.createToken(card, extraDetails).then(setOutcome); }); }); </script>
ブラウザ確認
http://localhost:3000/payment_method
テストカードは番号「4242 4242 4242 4242」を使用して下さい。
他の入力は何でも大丈夫です。
カードを登録するとユーザテーブルの「stripe_id」にストライプのIDが入ります。
Stripeのダッシュボードで「顧客」を見ると、カード登録されたのを確認することができます、
ナビゲーションバーにリンクを追加します。
記述追加 app\views\shared\_navbar.html.erb
37行目に「<%= link_to "クレジットカード登録", payment_method_path, class: "navbar-item", data: { turbolinks: false} %>」の記述を追加しています。
<nav class="navbar is-link" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="/"> <h1>テストサイトGakushuu</h1> </a> <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div id="navbarBasicExample" class="navbar-menu"> <div class="navbar-end"> <a class="navbar-item"></a> <a class="navbar-item"></a> <!-- もしログインしていなかったら--> <% if (!user_signed_in?) %> <div class="navbar-item"> <div class="buttons"> <%= link_to "新規ユーザ登録", new_user_registration_path, class: "button is-info" %> <%= link_to "ログイン", new_user_session_path, class: "button is-light" %> </div> </div> <!-- ログインしていたら --> <% else %> <div class="navbar-item has-dropdown is-hoverable" style="margin-right: 100px;"> <a class="navbar-item"> <%= image_tag current_user.gravatar_url, class: "img-circle avatar-small" %> <%= current_user.full_name %><i class="fas fa-angle-down"></i> </a> <div class="navbar-dropdown"> <%= link_to "マイプロジェクト", myprojects_path, class: "navbar-item" %> <%= link_to "プロジェクト", project_index_path, class: "navbar-item" %> <%= link_to "クレジットカード登録", payment_method_path, class: "navbar-item", data: { turbolinks: false} %> <%= link_to "ユーザ登録情報編集", edit_user_registration_path, class: "navbar-item" %> <hr class="navbar-divider"> <%= link_to "ログアウト", destroy_user_session_path, method: :delete, class: "navbar-item" %> </div> </div> <% end %> </div> </div> </nav> <script> $(document).ready(function() { // navbar burgerアイコンでクリックイベントを確認する $(".navbar-burger").click(function() { // 「navbar-burger」と「navbar-menu」の両方で「is-active」クラスを切り替えます $(".navbar-burger").toggleClass("is-active"); $(".navbar-menu").toggleClass("is-active"); }); }); </script>