Rails + Stripe:如何使用AJAX发送表单(和处理错误)?

时间:2015-01-16 18:10:18

标签: jquery ruby-on-rails ruby ajax stripe-payments

我最近几天与Stripe作战。我的问题是我正在尝试使用AJAX(我现在失败的地方)创建订阅,并且还要验证输入的信用卡信息。

这是我的工作流程:

处理表格的JS代码:

$('.show_subscriptions').hide();
$("#display_checkout_box").html("<%= escape_javascript(render 'new_just_form') %>");

var subscription;
jQuery(function() {         
    // VALIDATIONS
    $('#card_number').payment('formatCardNumber');
    $('#card_expiration').payment('formatCardExpiry');
    $('#card_code').payment('formatCardCVC');

    $.fn.toggleInputError = function(erred) {
      this.parent('.form-group').toggleClass('has-error', erred);
      return this;
    };
    // end VALIATIONS

    Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'));
    return subscription.setupForm();
});
subscription = {
    setupForm: function() {     
      $('#new_subscription').submit(function() {            
            subscription.processCard();
            return false;
    });
  },
  processCard: function() {
        $('input[type=submit]').attr('disabled', true).val('Processing. Please, wait...');
        $('input[type=submit]').addClass('processing');

        // STRIPE JS VALIDATION
        var cardType = $.payment.cardType($('#card_number').val());
        $('#card_number').toggleInputError(!$.payment.validateCardNumber($('#card_number').val()));
        $('#card_expiration').toggleInputError(!$.payment.validateCardExpiry($('#card_expiration').payment('cardExpiryVal')));
        $('#card_code').toggleInputError(!$.payment.validateCardCVC($('#card_code').val(), cardType));
        // end STRIPE JS VALIDATION

    var card;
    var exp_date = $('#card_expiration').val().split("/");

    card = {
      number: $('#card_number').val(),
      cvc: $('#card_code').val(),
      expMonth: parseInt(exp_date[0]),
      expYear: parseInt(exp_date[1])
    };
    return Stripe.createToken(card, subscription.handleStripeResponse);
  },
  handleStripeResponse: function(status, response) {
    if (status === 200) {
      $('#subscription_stripe_card_token').val(response.id);
      return $('#new_subscription')[0].submit();
    } else {
      console.log("Stripe Error: "+response.error.message);
      $('#subscribe_button').removeClass('processing');
      return $('input[type=submit]').attr('disabled', false).val('Subscribe');
    }
  }
};

控制器:

  def create
    @subscription = Subscription.new(subscription_params)
    if @subscription.save_with_payment(params[:coupon_id])
      redirect_to my_subscriptions_path, :notice => "You've successfully create a subscription for your team member!"
    else
      redirect_to '/account', :alert => "There is a problem with your credit card, we are unable to make the charge."
    end
  end

MODEL:

def save_with_payment(coupon_id)
    if valid?
      plan = Plan.find(plan_id)    
      Stripe.api_key = STRIPE_CONFIG['secret_key']

       description = "#{plan.name} subscription for #{email}"

      # create a subscription on Stripe
      unless coupon_id.empty?
        customer = Stripe::Customer.create(description: description,
                                           email: email, 
                                           plan: plan.plan_code, 
                                           card: stripe_card_token, 
                                           trial_end: 'now', 
                                           coupon: coupon_id)
        coupon_data = Coupon.where('coupon_name = ?', coupon_id).first
      else
        customer = Stripe::Customer.create(description: description, 
                                           email: email, 
                                           plan: plan.plan_code, 
                                           card: stripe_card_token, 
                                           trial_end: 'now')      
      end
      self.stripe_customer_token = customer.id
      # retrieve information about the current subscription
      cstmr = Stripe::Customer.retrieve(customer.id)
      subscr = cstmr.subscriptions.first
      self.start = Time.at(subscr.start)
      self.status = subscr.status
      self.subscription_code = subscr.id
      unless coupon_id.empty? # there was applied a coupon code on this subscription
        self.coupon_id = coupon_data.id        
      end
      # end of: retrieve information about the current subscription


      # fetch user.id
      user_id = User.where('email = ?', email).first
      self.user_id = user_id.id
      # end of: fetch user.id
      save!
    end

  rescue Stripe::CardError => e
    logger.error "Stripe error while creating customer (That card is presently on fire!): #{e.message}"
    errors.add :base, "That card is presently on fire!"
    false
  rescue => e
    logger.error "Stripe error while creating customer: #{e.message}"
    errors.add :base, "There was a problem with your credit card."
    false
  end

如果我输入的所有信用卡信息都正确无误,则会以常规方式发送表格并创建相应的订阅。如何使用AJAX发送此表单,所以发送表单后不会重定向页面?

我也试图在表单中显示(可能的)错误(或者通常说 - 在同一页面上)。现在,当用户填写错误的CVC代码时,一旦页面被重定向,就会显示错误消息(rescue部分)? 如何在表单中显示它?

我会非常感激每一个建议,我的头发已经变灰了。

先谢谢你们,伙计们。

修改 对于jQuery验证,我使用Stripe jQuery库。

1 个答案:

答案 0 :(得分:0)

您希望将JQuery用于AJAX将表单和条带标记发布到控制器。确保首先阻止默认表单提交。如果您从服务器获得了大量响应数据,那么最好使用JSON进行返回。

var form_data = {
  name: name,
  email: email,
  plan_id: plan_id,
  stripe_token: stripeToken,
} 

$.post( "#{subscriptions_path}",  form_data, function(server_data) {
   result = jQuery.parseJSON(server_data);
   if (result.status == 'success') {
     // redirect to their dashboard or wherever you want to take them
     window.location = '/dashboard';
   }else {
     //print the errors in the page.
     $('#error_message').show().text(result.error_msg)
   }

)};

def create
  @subscription = Subscription.new(subscription_params)
  if @subscription.save_with_payment(params[:coupon_id])
    render json: {status: 'success', subscription: @subscription}
  else
    render json: {status: 'failed', subscription: @subscription, error_msg: @subscription.errors.full_messages.to_sentence }
 end
end