2013-11-04 35 views
2

我在提交新的客户表单时出现问题。如果我从上到下填写表格,电子邮件,信用卡信息,然后点击提交,表格将失败(“您的信用卡存在问题”)。在条纹结束时,电子邮件被发送,但卡信息为空。使用Stripe和Rails提交表单

但是,如果我先填写信用卡信息,点击提交,然后填写电子邮件,一切正常。新的订阅是在应用程序上创建的,并且新的客户是以条带创建的。

我敢肯定,我做错了什么。下面的代码:

new.html.erb

<h1>Signing up for <%= @subscription.plan.name %></h1> 
<strong><%= @subscription.plan.price %></strong> per month!</p> 

<%= form_for @subscription do |f| %> 
    <% if @subscription.errors.any? %> 
    <div class="error_messages"> 
     <h2><%= pluralize(@subscription.errors.count, "error") %> prohibited this subscription from being saved:</h2> 
     <ul> 
     <% @subscription.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <%= f.hidden_field :plan_id %> 

    <%= f.hidden_field :stripe_card_token %> 

    <div class="field"> 
    <%= f.label :email %> 
    <%= f.text_field :email, "data-stripe" => "email" %> 
    </div> 

    <% if @subscription.stripe_card_token.present? %> 
    <p>Credit card has been provided.</p> 
    <% else %> 
    <div class="field"> 
     <%= label_tag :card_number, "Credit Card Number" %> 
     <%= text_field_tag :card_number, nil, name: nil, "data-stripe" => "number" %> 
    </div> 
    <div class="field"> 
     <%= label_tag :card_code, "Security Code on Card (CVV)" %> 
     <%= text_field_tag :card_code, nil, name: nil, "data-stripe" => "cvc" %> 
    </div> 
    <div class="field"> 
     <%= label_tag :card_month, "Card Expiration" %> 
     <%= text_field_tag :card_month, nil, name: nil, "data-stripe" => "exp-month", class: "input-mini", "placeholder" => "MM" %> 
     <%= text_field_tag :card_year, nil, name: nil, "data-stripe" => "exp-year", class: "input-mini", "placeholder" => "YYYY" %> 
    </div> 
    <% end %> 
    <div id="stripe_error"> 
    <noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript> 
    </div> 
    <div class="actions"> 
    <%= f.submit "Subscribe", class: "btn btn-primary" %> 
    </div> 
<% end %> 

subcriptions_controller.rb

class SubscriptionsController < ApplicationController 

    def index 
    @subscriptions = Subscription.all 
    end 

    def show 
    @subscription = Subscription.find(params[:id]) 
    end 

    def new 
    plan = Plan.find(params[:plan_id]) 
    @subscription = plan.subscriptions.build 
    end 

    def create 
    @subscription = Subscription.new(subscription_params) 
    if @subscription.save_with_payment 
     redirect_to @subscription, :notice => "Thank you for subscribing!" 
    else 
     render :new 
    end 
    end 

    private 
    def subscription_params 
     params.require(:subscription).permit(:plan_id, :email, :stripe_card_token) 
    end 
end 

模型subscription.rb

class Subscription < ActiveRecord::Base 
    before_save { self.email = email.downcase } 
    belongs_to :plan 
    validates_presence_of :plan_id 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } 

    attr_accessor :stripe_card_token 

    def save_with_payment 
    if valid? 
     customer = Stripe::Customer.create(card: stripe_card_token, email: email, plan: plan_id) 
     self.stripe_customer_token = customer.id 
     save! 
    end 
    rescue Stripe::InvalidRequestError => e 
    logger.error "Stripe error while creating customer: #{e.message}" 
    errors.add :base, "There was a problem with your credit card." 
    false 
    end 
end 

最后,JavaScript的(主要来自条纹的文档,但略有修改):

// This identifies your website in the createToken call below 
Stripe.setPublishableKey('<%= Rails.configuration.stripe[:publishable_key] %>'); 

var stripeResponseHandler = function(status, response) { 
    var $form = $('#new_subscription'); 

    if (response.error) { 
    // Show the errors on the form 
    $form.find('#stripe_error').text(response.error.message); 
    $form.find('input[type=submit]').prop('disabled', false); 
    } else { 
    // token contains id, last4, and card type 
    var token = response.id; 
    // Insert the token into the form so it gets submitted to the server 
    $form.find($('#subscription_stripe_card_token').val(token)); 
    // and re-submit 
    $form.get(0).submit(); 
    } 
}; 

jQuery(function($) { 
     $('#new_subscription').submit(function(e) { 
     var $form = $(this); 

     // Disable the submit button to prevent repeated clicks 
     $form.find('input[type=submit]').prop('disabled', true); 

     Stripe.createToken($form, stripeResponseHandler); 

     // Prevent the form from submitting with the default action 
     return false; 
     }); 
    }); 

感谢您的阅读!任何帮助将不胜感激。

+0

我不知道问题是什么,但它不可能与填写字段的顺序有关。 – woz

+0

是的,其他的事情正在进行中。另一个线索,如果有帮助的话,是如果我填写任何信用卡详细信息,比如说卡号,但没有过期日期或CVC并点击提交,Stripe会发送一个错误,如“失效失效日期”或其他。如果我然后完成表格并点击提交它传递和工作。这就像条形图元素在您完整提交表单时不会以某种方式被查看或初始化。 – andrewmarkle

回答

3

好的,所以我想出了这里发生了什么。经过多次测试后,我意识到如果我在页面上刷新,然后填写表单并提交,每次都会有效。但是,如果我通过应用导航到subscription_path,它将创建一个错误,除非您在到达之后手动刷新页面。

所以......经过大量的挖掘后,我发现问题在于Turbolinks。这篇文章帮助我弄清楚如何解决这个问题:Rails 4: how to use $(document).ready() with turbo-links。从我可以收集的信息来看,jQuery并没有因为turbo链接而加载Stripe.js。

有几个选项如何解决它。

  1. 禁用turbolinks
  2. 添加一些代码,您的JavaScript(见上面的链接)
  3. 加入jQuery的turbolinks宝石有助于jQuery的发挥好与turbolinks。

(我选择了选项3,因为它似乎是最简单的解决方案)。

无论如何,现在的形式工作!

+0

或者您可以指定有问题的链接不使用Turbolinks – tommyd456