ストライプ付きRailsで1回限りの購入を販売する方法
Stripeは、何百万もの企業で使用されており、サブスクリプションと1回限りの購入を処理するアプリケーションに支払いインフラストラクチャを提供します。 Stripe Checkoutを使用すると、コンバージョンを増やすために作成されたホスト型支払いページを介してカード支払いを簡単に受け入れることができます。これをWebhookと組み合わせると、開発者は製品やサブスクリプションを販売し、それらをデジタルで配信できます。
既存のプロバイダーを使用して自分で支払いを処理することは技術的に可能ですが、Stripeには多くの利点があります。手始めに、それはより速いです。 Stripeには、4,000人を超える人々が、可能な限りシンプル、安全、そして便利な支払いに取り組んでいます。
さらに、「Stripeを利用した」支払いを行うことは、顧客の信頼を築き、コンバージョンを増やす簡単な方法です。顧客は通常、アクセスするすべてのWebサイトにカードや銀行の情報を提供することを躊躇しますが、当然のことながらそうです。
オンライン決済分野のプロバイダーはStripeだけではありません。パドルは、オンライン決済の分野におけるもう1つの巨大なプレーヤーです。 Paddleは、Stripeと同様の多くの機能を提供しますが、料金がわずかに高く、開発者のエクスペリエンスが非常に悪くなります。他のいくつかの競合他社はStripeの代替品ですが、オンライン決済向けの製品の人気が非常に高いため、簡単に選択できます。
SaaS企業が定期的なサブスクリプションを処理することは一般的ですが、多くの製品はデジタル製品の1回限りの販売から利益を得るでしょう。これはStripeのインフラストラクチャでも同様に簡単ですが、彼らのドキュメントはトピックから遠ざかっているようです。
プロセスを説明するために、ユーザーがクレイグリストスタイルのボードに広告を投稿するために支払うことを可能にするアプリケーションを構築します。私たちの特定の例では、私たちのアプリケーションはルームメイトを探している人々のためのウェブサイトになります。ユーザーはボードを無料で閲覧できますが、自分の広告を投稿するには料金を支払う必要があります。
まず、StripeのWebサイトにアクセスしてアカウントを作成する必要があります。あなたの情報または該当する場合はあなたのビジネスの情報でサインアップしてください。
Stripeサインアップページのスクリーンショット
この記事では、アカウント作成の正確な詳細については説明しませんが、それらのドキュメントで質問に答えられる可能性があります。私たちは特に彼らの支払いと支払いに興味を持っています 製品、より具体的には Stripe Checkout 。
Stripeアカウントを設定したら、統合に使用する基本的なRailsアプリを作成します。既存のアプリを統合する場合、またはチュートリアルのStripe部分に関心がある場合は、「基本的なStripe統合」に進んでください。
この例では、次のバージョンを使用します。
- Rails 6.1
- ルビー3.0.0
RubyとRailsの両方がすでにインストールされていると仮定して、先に進んで以下を実行します。
rails new roommate-board
私がアプリに選んだ名前はroommate-board
です 、ただし、別のものを自由に選択できます。サンプルコードに記載されている他の場所で名前を入れ替えるだけです。
次のコマンドで作成したディレクトリに移動します。
cd roommate-board
次に、次のコマンドでアプリを実行します。
rails s
localhost:3000
にアクセスすると、一般的なRailsのウェルカムページが表示されます。 、おめでとうございます。コーディングの準備が整いました。
まず、ユーザー認証を処理するためにDeviseを追加します。 gem 'devise'
を追加するだけです Gemfileに移動してから、次のコマンドを実行します。
bundle install
次に、Deviseジェネレーターを使用して、次のコマンドを実行して設定します。
rails generate devise:install
次に、次のコマンドを実行して、Deviseをユーザーモデルに接続します。
rails generate devise User
最後に、次のコマンドで移行を実行します。
rails db:migrate
これを読んでいるなら、おそらくフロントエンドのデザインよりもStripeの統合に興味があるので、この例のスタイルについて心配する必要はありません。
次のステップは、投稿用のモデルを作成することです。 ! Railsの便利なジェネレーターを使用して、モデル、移行、コントローラー、およびルートを作成します。次を実行するだけです:
rails generate scaffold Post address:string rent:integer content:text
このモデルには、Stripeを統合するために必要なすべてのものが含まれているわけではありません。ゼロから始める余裕がないプロジェクトでこのチュートリアルを参照している場合に備えて、後で追加します。移行を実行して、次のデータベーステーブルを作成します。
rails db:migrate
次に、投稿のインデックスビューをアプリケーションのルートにします 便宜上。 config/routes.rb
内 、次の行を追加します:
root 'posts#index'
現在はかなり空であり、サインイン、サインアウト、またはサインアップする明確な方法はありません。機能はすでに存在するので、ヘッダーにいくつかのリンクを追加して、ユーザーにわかりやすくします。 app/views/layouts/application.html.erb
内 、必要なリンクを追加します。変更を加えた後の私のファイルは次のようになります:
<!DOCTYPE html>
<html>
<head>
<title>RoommateBoard</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<header>
<nav>
<a href="/#" class="block">
<h1>Roommate Board</h1>
</a>
<% if user_signed_in? %>
<%= link_to "Manage Posts", manage_posts_url %>
<%= link_to "Sign Out", destroy_user_session_url, :method => 'delete' %>
<% else %>
<%= link_to "New Post", new_user_registration_url %>
<% end %>
</nav>
</header>
<%= yield %>
</body>
</html>
これによりホームページへのリンクが表示され、ユーザーが[新しい投稿]をクリックすると、サインアップページに移動します。サインインしている場合は、[投稿の管理]ボタンと[サインアウト]ボタンに変わります。スタイリングもサインインもされていない場合、ルートページは次のようになります。
基本的な投稿のインデックスページのスクリーンショット
次に、各投稿を一意のユーザーにスコープします 。基本的に、いくつかの関連するロジックとともに、投稿とユーザーの間にbelongs_toアソシエーションを作成します。 Railsの便利な移行ジェネレーターから始めましょう。次を実行するだけです:
rails g migration AddUserIdToPosts
次に、db/migrate/
の移行ファイルを編集します このように見えるように:
class AddUserIdToPosts < ActiveRecord::Migration[6.1]
def change
add_column :posts, :user_id, :integer
end
end
最後に、次のコマンドで移行を実行します。
rails db migrate
次に、モデル自体に関連付けを追加します 。 app/models/post.rb
内 、次の行を追加します:
belongs_to :user
そしてapp/models/user.rb
、以下を追加します:
has_many :posts
この双方向の関連付けにより、createメソッドやnewメソッドで使用するメソッドのような便利なRailsメソッドがいくつか提供されます。 app/controllers/posts_controller.rb
に移動します (投稿コントローラー)そして new を見てください 方法。 @post = Post.new
の代わりに 、@post = current_user.posts.build
を使用します 。
create メソッド、私たちは同様のことをします。 @post = Post.new(post_params)
を置き換えます @post = current_user.posts.build(post_params)
を使用 。合わせて、newメソッドとcreateメソッドは次のようになります。
# GET /posts/new
def new
@post = current_user.posts.build
end
# POST /posts or /posts.json
def create
@post = current_user.posts.build(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: "Post was successfully created." }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
これにより、ユーザーのid属性がすべての投稿に保存されますが、他のユーザーが自分のものではない投稿を編集または削除するのを防ぐことはできません。同じPostsControllerで、ユーザーが投稿を所有しているかどうかのブールインジケーターを提供するメソッドを作成しましょう。これをコントローラーの下部に追加します:
def user_owns_post?
@post.user == current_user
end
編集 メソッドに、以下を追加します(そこにある唯一のコードになります):
unless user_owns_post?
# Redirect them to an error page
redirect_to posts_path, flash: { error: "You are not the owner of that post!" }
end
破壊で メソッド、これを先頭に追加します:
unless user_owns_post?
# Redirect them to an error page
redirect_to posts_path, flash: { error: "You are not the owner of that post!" }
end
次に、ユーザーが既存の投稿を管理するための機能が必要になります。 。最終的な目標は、ユーザーが支払いを行う前に投稿を作成してドラフト状態にすることができるようにすることです。彼らが支払うと、それは彼らのためにアクティブに設定されます! PostsControllerで、新しいメソッドを追加します:
def manage
@posts = current_user.posts
end
次に、ユーザーがそこに到達できるようにルートを追加します。 config/routes.rb
内 、以下を追加します:
get "/manage_posts/" =>'posts#manage'
最後に、投稿管理用のビューを作成します。新しいファイルapp/views/posts/manage.html.erb
を追加します 。次に、app/views/posts/index.html.erb
のコンテンツ全体をコピーします それに。ヘッダーを「投稿」から「投稿の管理」に変更するだけです。これは基本的にインデックスページですが、コントローラーロジックのおかげで、個々のユーザーの投稿だけがインデックスに登録されます。技術的には、個々のインデックスページでこれを行うことができますが、この分離により、後で他の機能を追加しやすくなります。たとえば、新しい投稿を作成するためのリンクを追加します この管理ページで。
ヘッダーの下に、次を追加するだけです。
<%= link_to "New Post", new_post_url%>
これが私たちが必要としたすべてのセットアップです!すべてが正しく機能していることを確認するために、それを確認することをお勧めします。これで、次のことができるようになります。
- ユーザーアカウントを作成する
- サインイン
- サインアウト
- 既存の投稿のインデックスを表示する
- 新しい投稿を作成する
すべてが期待どおりに機能している場合は、Stripe統合に移りましょう!
まず、StripeRubygemを追加します。 Gemfileに、次の行を追加します。
gem 'stripe'
実行してそれに従ってください:
bundle install
次のパートでは、StripeAPIキーが必要になります 。 Stripeコンソールで、サイドバーの[Developer]をクリックします。 「APIキー」のオプションが表示されるので、先に進んで次をクリックします。 「秘密鍵」はまもなく必要になりますので、メモしておいてください。
ただし、最初に、config/initializers
で初期化子を作成します 。 stripe.rb
という名前のファイルを作成します 。このファイルに、次のような1行を追加します(ただし、秘密鍵を置き換えます):
Stripe.api_key = <insert your key here as a string>
ただし、この資格情報を保存する方法は安全ではありません。プロダクションシークレットをプレーンテキストで保存するべきではありません。プレーンテキストでは、gitによって追跡され、コードベースを読んでいる人なら誰でもアクセスできます。幸い、Railsは資格情報を安全に保存する方法を提供します。
シェルで、EDITOR=vim bin/rails credentials:edit
を実行します 暗号化を解除して、vimでクレデンシャルファイルを開きます。キーボードの「i」キーを押して、挿入モードに切り替えます。次のような新しいセクションを追加します:
stripe:
secret: your-secret-key
public: your-public-key
次に、ファイルを保存してvimを終了します。これを行うにはいくつかの方法がありますが、私のお気に入りは、エスケープキーを押して(挿入モードを終了するため)、:wq
と入力することです。 、その後にEnterキーが続きます。 Railsが暗号化されたクレデンシャルを処理する方法について詳しく知りたい場合は、これが優れたリソースです。
クレデンシャルが安全に保存されたので、安全でない初期化コードを次のように交換します。
Stripe.api_key = Rails.application.credentials[:stripe][:secret]
Stripeを利用して支払いを行う方法はいくつかありますが、優れたオプションはStripeCheckoutです。 StripeCheckoutはホストされた支払いページです 、つまり、実際のトランザクション用のユーザーインターフェイスは作成しません。ユーザーはボタンをクリックし、Stripeにリダイレクトされ、支払いが完了するとアプリケーションにリダイレクトされます。これにより、コンテキストの管理が少し難しくなりますが、支払いフォームを作成する負担がなくなり、Stripeはコンバージョンを最大化するために多くの作業を行うことができます。 ACH取引や多くの国際的な支払い方法など、カード以外の支払いタイプを簡単に受け入れることができます。
まず、チェックアウトプロセスを処理するコントローラーを作成します 。 app/controllers/checkout_controller.rb
を作成します 。その中に、チェックアウトセッションの作成を処理するメソッドを記述します。
def create
@session = Stripe::Checkout::Session.create({
success_url: root_url,
cancel_url: manage_posts_url,
payment_method_types: ['card'],
line_items: [{
name: "Roommate Posting",
amount: 2000,
currency: "usd",
quantity: 1
}],
mode: 'payment',
metadata: {post_id: params[:post_id]},
customer_email: current_user.email,
success_url: manage_posts_url,
cancel_url: manage_posts_url
})
respond_to do |format|
format.js
end
end
これにより、Stripeが魔法をかけるために必要なコンテキストを持つ1つのチェックアウトセッションが作成されます。アプリケーションには製品が1つしかないため、ここでハードコーディングした単一の広告申込情報を渡します。ただし、これは、渡されたパラメーターを使用して特定の製品のチェックアウトをカスタマイズするのに簡単な場所です。 「金額」変数は、製品のコストセントです。 。わかりやすくするために、現在のユーザーの電子メールを渡すことにも言及する価値があります。最後に重要なのは、投稿のIDをメタデータとして渡すことです。 。これにより、Webフックセクションでユーザーの購入を簡単に実行できるようになります!
次に、メソッドを呼び出す方法が明らかに必要になります。
config/routes.rb
内 、次の行を追加して、コントローラーへのルートを作成します。
post 'checkout/create' => 'checkout#create', as: "checkout_create"
次に、支払いを送信するためのボタンを追加します 投稿の管理ビューのすべての投稿。 app/views/manage.html.erb
内 、これを最後に追加して、ヘッダーに列を追加します:
<th>Payment</th>
また、<th colspan="3"></th>
を切り替えます <th colspan="4"></th>
へ 。
次に、支払いボタン自体のテーブル本体に別のアイテムを追加します。本文の4番目の項目として、次を追加します。
<td><%= button_to "Submit Payment", checkout_create_path, params: {:post_id => post.id }, remote: true %></td>
全体として、投稿の管理ビューは次のようになります。
<p id="notice"><%= notice %></p>
<h1>Manage Posts</h1>
<%= link_to "New Post", new_post_url%>
<table>
<thead>
<tr>
<th>Address</th>
<th>Rent</th>
<th>Content</th>
<th>Payment</th>
<th colspan="4"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.address %></td>
<td><%= post.rent %></td>
<td><%= post.content %></td>
<td><%= button_to "Submit Payment", checkout_create_path, params: {:post_id => post.id }, remote: true %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Post', new_post_path %>
JavaScript
StripeJavaScriptパッケージインクルードをapp/views/application.html.erb
に追加することを忘れないでください この行で:
<script src="https://js.stripe.com/v3/"></script>
次に、app/views/checkout/create.js.erb
に新しいファイル(およびディレクトリ!)を追加する必要があります。 。このファイルに以下を追加するだけで、コントローラーを使用してボタンをクリックしたときにチェックアウトセッションを作成できるようになります。
var stripe = Stripe("<%= Rails.application.credentials[:stripe][:public] %>")
stripe.redirectToCheckout({
sessionId: '<%= @session.id %>'
}).then(function (result) {
console.log(result.error_message)
});
これで、ユーザーが投稿の料金を支払う方法ができました。ただし、投稿が支払われているかどうかをアプリケーションが認識したり、支払われたときにアクティブ化したりする方法はありません。まず、投稿モデルにブール値を追加して、投稿の料金が支払われているかどうかを示します。 Rails移行ジェネレーターを使用するには、次のコマンドを実行します。
rails g migration AddPaymentDetailsToPost
この移行を開き、次の行を追加します。
add_column :posts, :is_paid, :boolean, :default => false
これにより、is_paid
という属性/列が投稿テーブル/モデルに追加されます。 。この属性はブール値であり、デフォルトはfalseです。つまり、投稿が作成されるたびに、支払いが行われていないとマークされます。 。投稿の支払いが完了すると、ブール値を手動で反転します。ただし、最初に、作成したばかりの移行を実行します:
rails db:migrate
支払いは即座に処理されないため、StripeからのAPI応答の成功に依存して、ジョブの支払いが行われたかどうかを判断することはできません。代わりに、支払いの処理が終了したときにStripeがPOSTリクエストを行うようにアプリケーションのエンドポイントを指定できます。このプロセスは一般にWebhookと呼ばれ、実際には思ったよりも簡単です!
開始するには、app/controllers/
に新しいコントローラーを作成します WebhooksControllerと呼ばれます。このapp/controllers/webhooks_controller.rb
で 、次のように記述します:
class WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
payload = request.body.read
sig_header = request.env['HTTP_STRIPE_SIGNATURE']
event = nil
begin
event = Stripe::Webhook.construct_event(
payload, sig_header, Rails.application.credentials[:stripe][:webhook]
)
rescue JSON::ParserError => e
status 400
return
rescue Stripe::SignatureVerificationError => e
# Invalid signature
puts "Signature error"
p e
return
end
# Handle the event
case event.type
when 'checkout.session.completed'
session = event.data.object
post = Post.find_by(id: session.metadata.post_id)]
post.is_paid = true
post.save!
end
render json: { message: 'success' }
end
end
必要なボイラープレート以外に、このメソッドはcheckout.session.completed
と呼ばれる特定のイベントタイプを渡します。 。 Rails側に残っているのは、ルートをconfig/routes.rb
に追加することだけです。 :
resources :webhooks, only: [:create]
最後に、StripeアカウントをStripeダッシュボード自体のこのエンドポイントに接続する必要があります。 StripeダッシュボードにURLを指定するため、これはローカルでは機能しません。 Webhookが正しく機能するには、これをインターネットにアクセス可能なエンドポイントにデプロイする必要があります。
Stripeダッシュボードの「Developers」に戻りますが、今回は左側のパネルで「Webhooks」を選択します。 [エンドポイント]セクションで、[エンドポイントの追加]をクリックします。 /webhooks
を追加したアプリケーションのURLを指定します イベント「checkout.session.completed」を割り当てます。
Stripeの統合は以上です。私たちの模擬アプリケーションの最後の実用的なステップは、インデックスページに支払い済みの投稿のみを表示させることです。これは、app/controllers/posts_controller.rb
のインデックスメソッドで簡単に実行できます。 。メソッドを次のように変更します:
def index
@posts = Post.where(:is_paid => true)
end
これで、ユーザーは投稿を作成し、Stripeチェックアウトで支払いを行い、アプリケーションのホームページに自動的に表示することができます。
Webhookはライブサイトにデプロイされた場合にのみ機能するため、デプロイに必要な変更について説明することは価値があります。手始めに、あなたのコミュニケーションはしなければならない Stripeチェックアウトが機能するにはHTTPSである必要があります。問題が発生した場合は、JavaScriptコンソールでStripeからのヒントを確認してください。
初期設定で、Stripeのテストキーを使用した可能性があります。そうした場合、StripeダッシュボードのAPIキーセクションは次のようになります。
StripeダッシュボードAPIキーのスクリーンショット
「テストデータの表示」の横にあるトグルをクリックするだけで、本番環境の秘密鍵と公開鍵が表示されます。アプリケーションがライブデータを処理するには、以前と同じ方法でRailsクレデンシャルマネージャーを開き、テストキーをこれに置き換える必要があります。ただし、テスト環境は、偽のクレジットカード番号を使用してテストトランザクションを実行する場合に役立ちます。複数の環境がある場合、またはこれを頻繁に切り替える予定がある場合は、資格情報マネージャーで別のキーと値のペアを作成し、コードで動的に使用することをお勧めします。
サンプルアプリケーションの作成に多くの時間を費やし、Stripeの統合にそれほど時間はかかりませんでした。 Stripeチェックアウトのおかげで、ユーザーインターフェイスを含む多くの責任を放棄し、多くのコードを節約できます。 Stripeがオンライン市場で広く採用されていることを考えると、これによりユーザーに一貫したエクスペリエンスが提供されます。 Stripeの使命はインターネットのGDPを増やすことであり、そのためにはあなたのようなアプリケーションが必要です。このため、彼らは常にさらに簡単なを探しています。 支払いを処理する方法。 Stripe Checkoutの実装はかなり簡単ですが、最近、さらに高速な方法を考えています。
Stripe Payment Linksは、Checkoutの統合をほとんど不要にする可能性のあるStripeの新製品です。私たちが実際に行ったのは、ユーザーをホストされたチェックアウトページにリダイレクトすることだけでした。単純なリンクを使用すると、それがさらに簡単になる可能性があります。支払いリンクは、小売業者を対象としているように見えるノーコードソリューションですが、このユースケースで機能する可能性があります。とにかく、Stripe Checkoutはまだ市場でもう少し柔軟性と採用を誇っているので、完全に理解することが重要です。
多くの企業が苦労していることの1つは、特に国際的に税金を処理することです。 Stripeは最近、これをビジネス向けに自動的に処理する新機能を導入しましたが、まだベータ版です。利用可能になると、支払い処理にStripeを使用する人の会計上の負担が大幅に軽減されます!
StripeのドキュメントとRubyonRails向けの既存の記事は、1回限りの購入ではなくサブスクリプションに傾いています。サブスクリプションは、ユーザーと製品に付随する定期的な料金です。 Stripeの側では、実装は1回限りの購入によく似ています。ただし、アプリケーション側では、サブスクリプション管理を統合し、ユーザーがサブスクリプションを管理できるようにし、サブスクリプションのステータスを定期的に確認する必要があります。この記事は1回限りの購入に焦点を当てていますが、サブスクリプションを管理する必要がある場合は、コミュニティに十分なリソースがあります。
-
Rubyでパーサーを構築する方法
構文解析は、一連の文字列を理解し、それらを理解できるものに変換する技術です。正規表現を使用することもできますが、必ずしもその仕事に適しているとは限りません。 たとえば、HTMLを正規表現で解析することはおそらく良い考えではないことは一般的な知識です。 Rubyには、この作業を実行できるnokogiriがありますが、独自のパーサーを作成することで多くのことを学ぶことができます。始めましょう! Rubyでの解析 パーサーの中核はStringScannerです クラス。 このクラスは、文字列のコピーと位置ポインタを保持します。ポインタを使用すると、特定のトークンを検索するために文字列をトラバ
-
RailsアプリケーションでOmniAuth-Twitterを使用する方法
このチュートリアルでは、アプリケーションのユーザーがTwitterアカウントを使用してログインできるようにする方法を学習します。これを行うには、OAuthなどのツールを使用すると簡単になります。 OmniAuthのTwitter戦略を含むOmniAuth-Twitterを利用します。 飛び込みましょう! はじめに Railsアプリケーションを生成することから始めます。ターミナルから、コマンドを実行して実行します。 rails new Tuts-Social -T Gemfileを開き、ブートストラップgemを追加します。 #Gemfile...gem bootstra