将 Stripe 集成到您的 Ruby on Rails 应用中

2025-06-09

将 Stripe 集成到您的 Ruby on Rails 应用中

创建工作区

我们将首先创建一个 Ruby on Rails 应用程序

$ rails new tuto
$ cd tuto
$ bundle install
Enter fullscreen mode Exit fullscreen mode

然后,我们将借助以下代码生成一个名为 Billing 的控制器

rails generate

$ rails generate controller Billing

Enter fullscreen mode Exit fullscreen mode

之后,我们将在config/routes.rb中添加路由:

root 'billing#index', as: :billing 
Enter fullscreen mode Exit fullscreen mode

最后,我们必须在app/controllers/billing_controller.rb中创建一个空的动作索引:

class BillingController < ApplicationController

  def index
  end

end
Enter fullscreen mode Exit fullscreen mode

在app/views/billing 目录中,我们将创建一个 index.html.erb 文件,在其中添加一个按钮,用于显示“Stripe Checkout”模态框,以便我们将信用卡关联到用户。在本教程中,我将(一如既往地)使用 bootstrap 库。如果您也想使用它,请不要忘记将其添加到您的应用中。如果您想了解如何操作,可以阅读这篇文章。因此,在app/views/billing/index.html.erb 目录中:

<div class="container">
  <div class="row">
    <h1 class="col-md-12 mt-5 text-center">
      Are you ready to pay?
    </h1>
  </div>
  <div class="row">
    <div class="col-md-12 mt-4 text-center">
      <button class="btn btn-primary">Let's go </button>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

现在,我们将保留这样的按钮,稍后我们将使用 Rails 语法对其进行更改。

使用 Devise 创建用户

现在,我们将借助“devise” gem 实现基本身份验证。我们希望只有已连接的用户才能访问结算页面。首先在Gemfile中添加以下行:

gem 'devise'
Enter fullscreen mode Exit fullscreen mode

要设置设备,我们必须在终端中输入以下内容:

$ bundle install
$ rails g devise:install
Enter fullscreen mode Exit fullscreen mode

运行这两个命令后,终端将显示配置 devise 的说明。它告诉我们必须在config/environments/development.rb中添加以下代码行

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
Enter fullscreen mode Exit fullscreen mode

下一步是创建用户模型:

$ rails g devise User
$ rails db:migrate
Enter fullscreen mode Exit fullscreen mode

就这样。我们用 devise 添加了身份验证。现在我们可以创建第一个用户了。我们需要在终端中运行“rails s”,然后转到以下页面:localhost:3000/users/sign_up。创建帐户后,它会自动将我们重定向到 localhost:3000 的根页面。

我们现在希望只有登录用户才能访问 localhost:3000。为此,我们需要在app/controllers/billing_conroller.rb中添加:

class BillingController < ApplicationController
  before_action :authenticate_user!

  def index
   @user=current_user.email
  end

end
Enter fullscreen mode Exit fullscreen mode

因此,在计费控制器执行任何操作之前,它都会检查用户是否已登录。此外,在索引操作中,我添加了一个全局变量 @user,用于获取当前用户的邮箱地址。我将在app/views/billing/index.html.erb中使用它:

<div class="container">
  <div class="row">
    <div class="col-md-12 mt-4 text-center">
      <h1> Welcome  <%= @user %></h1>
    </div>
  </div>
  <div class="row">
    <h2 class="col-md-12 mt-5 text-center">
      Are you ready to pay?
    </h2>
  </div>
  <div class="row">
    <div class="col-md-12 mt-4 text-center">
      <button class="btn btn-primary">Let's go </button>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

为了检查一切是否正常,我们将访问 localhost:3000 并清除 Cookie。刷新页面后,您应该会自动重定向到登录页面。

整合 Stripe

添加 Stripe 凭证

首先,您需要在 Stripe 上注册。然后,您可以在控制面板的“开发者” => “API 密钥”
下找到 Stripe 的开发密钥和生产密钥。您现在看到的密钥是生产密钥。要查看开发密钥,请点击“查看测试数据”
替代文本

现在我们将密钥添加到 Rails 加密凭证中。为此,我使用 MacOS 和 Linux 上默认安装的 GNU nano 编辑器。

$ EDITOR=nano rails credentials:edit

替代文本

在这里我们添加用于开发和生产的密钥。

stripe:
  development:
    publishable_key: 'pk_test_...'
    secret_key: 'sk_test_...'
  production:
    publishable_key: 'pk_live_...'
    secret_key: 'sk_live_...'

Enter fullscreen mode Exit fullscreen mode

安装 Stripe

您还需要在app/views/layouts/application.html.erb中添加条纹结帐 javascript

<%= javascript_include_tag 'https://checkout.stripe.com/checkout.js' %>
Enter fullscreen mode Exit fullscreen mode

另外,在config/enviroments/development.rb中我们添加:

config.stripe.secret_key = Rails.application.credentials.stripe[:development][:secret_key]
config.stripe.publishable_key = Rails.application.credentials.stripe[:development][:publishable_key]
Enter fullscreen mode Exit fullscreen mode

config/enviroments/production.rb中:

config.stripe.secret_key = Rails.application.credentials.stripe[:production][:secret_key]
config.stripe.publishable_key = Rails.application.credentials.stripe[:production][:publishable_key]
Enter fullscreen mode Exit fullscreen mode

最后,我们将在Gemfile中添加条纹宝石

gem 'stripe-rails'
Enter fullscreen mode Exit fullscreen mode

并在终端中运行“bundle install”。

设置路线

现在我们返回config/routes.rb并添加到文件:

get '/card/new' => 'billing#new_card', as: :add_payment_method`
Enter fullscreen mode Exit fullscreen mode

将卡片与用户关联

app/controllers/billing_controller.rb中我们正在创建新的动作:

def new_card
    respond_to do |format|
      format.js
    end
  end
Enter fullscreen mode Exit fullscreen mode

它会将我们引导至我们将在app/views/billing中创建的new_card.js.erb文件。因此,在app/views/billing/new_card.js.erb文件中:

var handler = StripeCheckout.configure({
    key: '<%= Rails.application.credentials.stripe[Rails.env.to_sym][:publishable_key] %>',
    //get a publishable key that we put in editor depending on environment: production or development
    locale: 'auto',
    //handle translation
    name: "upload.express",
    description: "Add your credit card information",
    email: "<%= current_user.email %>",
    panelLabel: "Add payment method",
    allowRememberMe: false,
    token: function (token) {
        var form = document.getElementById('billing-create-payment-method');
        //we will create element with this id in the next step
        var hiddenInput = document.createElement('input');
        hiddenInput.setAttribute('type', 'hidden');
        hiddenInput.setAttribute('name', 'stripeToken');
        hiddenInput.setAttribute('value', token.id);
        //creating an <input type="hidden" name="stripeToken" value="<id>"/>. We will need this information in the next steps to link a user to his card 
        form.appendChild(hiddenInput);
        //adding this input when we use a form.
        form.submit();
    }
});

handler.open();

window.addEventListener('popstate', function() {
    handler.close();
});
Enter fullscreen mode Exit fullscreen mode

然后我们将app/views/billing/index.html.erb中的按钮更改 为 id 为“billing-create-payment-method”的表单:

<%= form_tag id: "billing-create-payment-method" do  %>
        <%= link_to "Let's go", add_payment_method_path, remote: true, class: "btn btn-primary" %>
      <% end %>
Enter fullscreen mode Exit fullscreen mode

之后在终端中运行“rails s”,单击按钮后,我们应该看到如下内容:
替代文本

快完成了!现在我们需要将当前用户与指定的卡片关联起来。为此,我们需要在 User 模型中添加一个字符串类型的新列 stripe_id,具体操作如下:

$ rails g migration AddStripeIdToUsers stripe_id:string
$ rails db:migrate
Enter fullscreen mode Exit fullscreen mode

config/routes.rb中我们创建了一条新路线:

post "/card" => "billing#create_card", as: :create_payment_method
Enter fullscreen mode Exit fullscreen mode

现在,在app/controllers/billing_controller.rb中的控制器中,我们正在创建动作 create_card:

def create_card 
    respond_to do |format|
      if current_user.stripe_id.nil?
        customer = Stripe::Customer.create({"email": current_user.email}) 
        #here we are creating a stripe customer with the help of the Stripe library and pass as parameter email. 
        current_user.update(:stripe_id => customer.id)
        #we are updating current_user and giving to it stripe_id which is equal to id of customer on Stripe
      end

      card_token = params[:stripeToken]
      #it's the stripeToken that we added in the hidden input
      if card_token.nil?
        format.html { redirect_to billing_path, error: "Oops"}
      end
      #checking if a card was giving.

      customer = Stripe::Customer.new current_user.stripe_id
      customer.source = card_token
      #we're attaching the card to the stripe customer
      customer.save

      format.html { redirect_to success_path }
    end
  end
Enter fullscreen mode Exit fullscreen mode

我们对app/views/billing/index.html.erb进行了一些修改,以便在提交表单时调用操作 create_card。

<%= form_tag create_payment_method_path, id: "billing-create-payment-method" do  %>
        <%= link_to "Let's go", add_payment_method_path, remote: true, class: "btn btn-primary" %>
      <% end %>
Enter fullscreen mode Exit fullscreen mode

很快,我们将添加成功页面。创建一个路由、空操作和视图。

config/routes.rb中:

get '/success' => 'billing#success', as: :success
Enter fullscreen mode Exit fullscreen mode

app/controllers/billing_controller.rb中:

def success
end
Enter fullscreen mode Exit fullscreen mode

app/views/billing/success.html.erb中:

<div class="container">
  <div class="row">
    <div class="col-md-12 mt-4 text-center">
      <h2>You successfully linked a credit card to your account</h2>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

现在在终端“rails s”中运行。点击网站上的“开始”。为了测试,您可以使用卡号 4242 4242 4242 4242 以及随机 CVC 代码和日期。提交后,我们将被重定向到成功页面。如果我们在“客户”页面中访问 Stripe (别忘了切换到测试数据),我们应该会看到用户的电子邮件和卡信息。
替代文本

现在我们需要让客户在注册卡后进行实际付款。这意味着我们必须订阅我们的客户。

订阅

首先,我们需要创建一个产品。最简单的方法是通过 Stripe 控制面板。然后,我们将为该产品添加两个定价方案。例如,在我们的产品 upload.express 中,您可以支付 7 欧元/月,或者 60 欧元/年。我们需要前往Stripe 控制面板 => 账单 => 产品,然后点击“新建”按钮。创建包含两个定价方案的产品。我建议您为定价方案的昵称选择明确的定义,例如“月度”和“年度”。如果您添加年度方案,请不要忘记将间隔设置为“年度”。要添加定价方案,您需要点击刚刚创建的产品,然后点击“添加定价方案”按钮。

现在,我们需要获取在应用中创建的定价计划。我们将在“success”页面上执行此操作。因此,在app/controllers/billing_controller.rb中的success 部分中:

def success
    @plans = Stripe::Plan.list.data
  end
Enter fullscreen mode Exit fullscreen mode

现在我们需要让用户订阅他/她选择的套餐。因此,我们需要创建一个新的操作,将客户与套餐关联起来并创建订阅。

config/root.rb中:

post '/subscription' => 'billing#subscribe', as: :subscribe
Enter fullscreen mode Exit fullscreen mode

app/views/billing/success.html.erb中我们添加:

<div class="row">
  <div class="col-md-12 mt-3 text-center">
    <h3>Now you need to choose your plan</h3>
  </div>
</div>
<!-- creating a form -->
<%=form_tag subscribe_path, method: :post do %>
<div class="row">
  <div class="col-md-4"></div>
  <div class="col-md-4 text-center">
    <div class="form-group">
      <select class="form-control" name="plan_id">
        <% @plans.each do |plan| %>
        <option value="<%= plan.id %>"><%= plan.amount/100 %>/€ <%= plan.nickname %></option>
        <!-- we pass id chosen by custmer as a value  to use it for subscription -->
        <%end%>
      </select>
    </div>
  </div>
  <div class="col-md-4"></div>
</div>
<div class="row">
  <div class="col-md-12 mt-2 text-center">
    <%= submit_tag 'Save changes', class: "btn btn-primary" %>
  </div>
</div>
<% end %>
Enter fullscreen mode Exit fullscreen mode

app/controllers/billnig_controller.rb中:

def subscribe
      if current_user.stripe_id.nil?
        redirect_to success_path, :flash => {:error => 'Firstly you need to enter your card'}
        return
      end
      #if there is no card

      customer = Stripe::Customer.new current_user.stripe_id
      #we define our customer

      subscriptions = Stripe::Subscription.list(customer: customer.id)
      subscriptions.each do |subscription|
        subscription.delete
      end
      #we delete all subscription that the customer has. We do this because we don't want that our customer to have multiple subscriptions

      plan_id = params[:plan_id]
      subscription = Stripe::Subscription.create({
                                                     customer: customer,
                                                     items: [{plan: plan_id}], })
   #we are creating a new subscription with the plan_id we took from our form

      subscription.save
      redirect_to success_path
    end
  end
Enter fullscreen mode Exit fullscreen mode

一切就绪。现在我们要检查一下我们的应用。选择一个定价方案,然后提交。
要检查一切是否正常,请前往 Stripe,点击“控制面板” => “账单” => “订阅”。我们的订阅应该在这里。如果你更改了方案,并查看 Stripe,订阅信息也会随之更改。

就这样!你已将 Stripe 集成到你的 Rails 应用上。恭喜!

PS 这是我的第一篇技术文章,我希望它易于理解并且您喜欢它!

鏂囩珷鏉ユ簮锛�https://dev.to/ksushiva/integrate-stripe-in​​-your-ruby-on-rails-app-3dc4
PREV
如何使用 Socket.IO 构建你的第一个多人游戏!先决条件:简介 设置环境 构建应用程序
NEXT
如何使用 i18next 翻译你的 React.js 应用