仅允许对某些模型参数进行条带购买

时间:2017-02-06 04:47:57

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

Rails新手,使用Stripe的API。我的rails应用程序中有一个名为pieces的模型。每个部分都有一个名为status的整数。我只希望人们能够购买该作品,如果该作品的状态为1.在我目前的代码中,我已经隐藏了碎片上的购买按钮,除非状态为1.这大部分时间都有效,但是,如果两个人同时看到这件作品,那么他们都可以买到它们。这是因为在重新加载页面之前,其他页面上的文件状态不会更新。

我的要求:我希望找到一种方法来检查作品的状态是否为1,就在有人购买之前。如果它不是1,我希望有一条铁路闪存消息说这件作品已经被买了。这样可以防止用户收费并阻止创建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>

非常感谢你们。

1 个答案:

答案 0 :(得分:0)

你只需要检查一下:)

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。