【问题标题】:Only allow Stripe Purchases on certain model parameters仅允许对某些模型参数进行 Stripe Purchases
【发布时间】:2017-06-22 23:06:40
【问题描述】:

这里是 Rails 新手,使用 Stripe 的 API。我的 Rails 应用程序中有一个模型,称为 pieces。每一块都有一个称为状态的整数。我只希望人们能够购买状态为 1 的作品。在我当前的代码中,除非状态为 1,否则我将购买按钮隐藏在作品上。这在大多数情况下都有效,但是,如果两个人同时查看该作品,那么他们都可以购买。这是因为在重新加载页面之前,其他页面上的片段状态不会更新。

我的要求:我想在有人购买之前找到一种方法来检查该作品的状态是否为 1。如果不是 1,我希望有一个 rails flash 消息,说这件作品已经被购买。这应该可以防止向用户收费并防止创建charge

这是我的收费控制器:

class ChargesController < ApplicationController
  def create

    piece = Piece.find(params[:piece_id])

    customer = Stripe::Customer.create(
      :email => params[:stripeEmail],
      :source  => params[:stripeToken]
    )

    charge = Stripe::Charge.create(
      :customer    => customer.id,
      :amount      => piece.total_price_in_cents,
      :description => piece.title,
      :currency    => 'usd'
    )

    purchase = Purchase.create(
        customer_email: params[:stripeEmail],

        total_transaction: piece.total_price,
        stripe_fee: piece.stripe_fee,
        taxes: piece.taxes,
        artist_cut: piece.artist_cut,
        charity_cut: piece.charity_cut,
        our_cut: piece.our_cut,

        currency: charge.currency,
        card: params[:stripeToken],
        description: charge.description, 
        customer_id: customer.id,
        piece_id: piece.id, 

        customer_name: params[:stripeShippingName],
        customer_address_line_1: params[:stripeShippingAddressLine1],
        customer_city: params[:stripeShippingAddressCity],
        customer_state: params[:stripeShippingAddressState],
        customer_zip_code: params[:stripeShippingAddressZip],
        customer_country: params[:stripeShippingAddressCountry],

        seller_name: piece.user.name,
        seller_email: piece.user.email,
        seller_address_line_1: piece.user.address_line_1,
        seller_address_line_2: piece.user.address_line_2,
        seller_city: piece.user.city,
        seller_state: piece.user.state,
        seller_zip_code: piece.user.zip_code

    )

    purchase.ship_by = purchase.created_at + 7.days
    purchase.arrive_by = purchase.created_at + 21.days
    purchase.save!

    piece.status = 3
    piece.save!
    redirect_to pieces_path, notice: "Thanks for buying #{piece.title} for $#{'%.2f' % piece.total_price}. You should get an email shortly."

    rescue Stripe::CardError => e
      flash[:error] = e.message
      redirect_to new_charge_path
    end

  end

这是我的作品展示页面,上面有条纹购买按钮:

<div class="container">  
  <div class="row">
   <div class="col-md-offset-2 col-md-8">
    <div class="panel panel-default">
     <div class="panel-body">

      <!-- Stripe Form -->
      <% if current_user != @piece.user && @piece.status == 1 %>
         <%= form_tag charges_path, id: 'chargeForm' do %>
              <script src="https://checkout.stripe.com/checkout.js"></script>
              <%= hidden_field_tag 'stripeToken' %>
              <%= hidden_field_tag 'stripeEmail' %>


              <button id="btn-buy-show" type="button" class="btn btn-success btn-lg btn-block">Buy for $<%= number_with_precision(@piece.total_price, :precision => 2, :delimiter => ',')%></button>
              <script>
              var handler = StripeCheckout.configure({
                key: '<%= Rails.configuration.stripe[:publishable_key] %>',
                shippingAddress: true,
                token: function(token, arg) {
                  document.getElementById("stripeToken").value = token.id;
                  document.getElementById("stripeEmail").value = token.email;
                  document.getElementById("chargeForm").submit();
                }
              });
               document.getElementById('btn-buy-show').addEventListener('click', function(e) {
                handler.open({
                  name: 'Metallic Palette',
                  description: '<%= @piece.title %> ($<%= number_with_precision(@piece.total_price, :precision => 2, :delimiter => ',')%>)',
                  amount: document.getElementById("amount").value
              });
              e.preventDefault();
             })
            </script>
          <% end %>
      <% end %>

      <% if @piece.status == 3 %>
        <p>This piece has already been bought.
          <% if current_user == @piece.user || admin_user_signed_in? %>
            <%= render 'pieces/purchase_details' %>
          <% end %>
        </p>
      <% end %>
    </div>
  </div>
</div>

非常感谢你们。

【问题讨论】:

    标签: javascript ruby-on-rails ruby stripe-payments


    【解决方案1】:

    你只需要检查一下:)

    def create
      piece = Piece.find(params[:piece_id])
    
      if piece.status != 1
        flash[:error] = 'Piece is not available :('
        return redirect_to peaces_path # or whatever
      end
    
      ...
    end
    

    但是,很少有人建议您: 1) 不要在代码中使用数字。制作常量(如Piece::AVAILABLE)和方法(piece.available?)或使用enum。如果你只是使用你的数字,你将来会有很多问题

    2) 提取表单对象 - 您不希望控制器中有这么大的方法。如果您将其提取到单独的服务中 - 它将更加可测试、可预测和可更新。

    3) 提取 Piece.find 并将状态检查到 before_filters。

    【讨论】:

      猜你喜欢
      • 2014-07-07
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 2021-07-18
      • 1970-01-01
      • 2021-05-02
      • 2017-01-13
      相关资源
      最近更新 更多