Rails Stripe Api Error: Invalid source object: must be a dictionary or a non-empty string

妖精的绣舞 提交于 2021-02-11 11:59:25

问题


I have successfully implemented stripe credit card processing (Stripe api v2) into my rails app following this railscast tutorial http://railscasts.com/episodes/288-billing-with-stripe. After styling the form I started receiving the following error:

There was a problem with your credit card. Invalid source object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'

In my console I can see that the stripe_card_token is being submitted as any empty value

 Parameters: {"utf8"=>"✓", "authenticity_token"=>"zCP+nFHj3JC0ZyceWOf9D+Vx6wZRfKA0LmZqL7faGzaM1E/k7GgKHCygCktH6mqe3oFNG1tqRpJpjKB728KE0g==", "subscription"=>{"stripe_card_token"=>"", "email"=>"test@outlook.com"}, "commit"=>"Create

I previously had this error and solved it by removing require_tree from application.js but the error keeps reappearing

I have also tried to disable turbolinks which is suggested in some other threads.

Here is my submission form:

<div ng-app="app" class="creditcontainer">
  <div ng-controller="PaymentFormCtrl" class="payment-form" name="paymentForm">
    <div class="notification">

      <span class="notification__text">
      We use secure 256 bit encryption and PCI compliant credit card processing, you data is save with us.
      </span>
    </div>
    <center><h2>12$/month</h2></center>
    <div class="card-type clearfix">
      <div class="card-type__label">
        Supported Cards
      </div>
      <div class="card-type__icons">

      </div><br>
    </div>
<%= form_for(@subscription) do |f| %>
  <% if @subscription.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@subscription.errors.count, "error") %> prohibited this subscription from being saved:</h2>

      <ul>
      <% @subscription.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <%= f.hidden_field :stripe_card_token %>



<% if @subscription.stripe_card_token.present? %>
  Credit card has been provided.
<% else %>
  <div>
    <%= f.text_field :email, class: "email-input card-input--full",placeholder: "Email" %>
  </div>
  <div>
  <%= text_field_tag :card_number, nil, name: nil, class: "card-input card-input--full",placeholder: "Credit card number", :ng => { :model => "card.number" } %>
  </div>


  <div class="card-info clearfix">


    <div class = "card-input--alldate" ng-model="card.date" card-date required >
    <%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month", class: "card-input--monthdatedrop"} %>
    <%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year", class: "card-input--yeardatedrop"} %>
  </div>
  <div ng-model="card.cvv" card-cvv required>
    <%= text_field_tag :card_code, nil, name: nil, class: "card-input card-input--cvv", placeholder: "CVV" %>
  </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 ng-disabled="paymentForm.$invalid">
    <%= f.submit class: "payment-form__button" %>
  </div>
  <div class="payment-form__agreement">
       We directly pass your data on to our payment processor and never store your credit card details. All our connections are encrypted to the highest standards. Your credit card information is safe with us. Upon paying your agree to our TOS.
    </div>
  </div>
</div>


<% end %>

This is my subscription.coffee file which handles the processing:

jQuery ->
  Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
  subscription.setupForm()

subscription =
  setupForm: ->
    $('#new_subscription').submit ->
      $('input[type=submit]').attr('disabled', true)
      if $('#card_number').length
        subscription.processCard()
        false
      else
        true



  processCard: ->
    card =
      {number: $('#card_number').val(),
      cvc: $('#card_code').val(),
      expMonth: $('#card_month').val(),
      expYear: $('#card_year').val()}
    Stripe.createToken(card, subscription.handleStripeResponse)

  handleStripeResponse: (status, response) ->
    if status == 200
      $('#subscription_stripe_card_token').val(response.id)
      $('#new_subscription')[0].submit()
    else
      $('#stripe_error').text(response.error.message)
      $('input[type=submit]').attr('disabled', false)

Anyone has any ideas why the stripe_card_token is empty?

Update

it seems that somehow the subscriptions.coffee file does not seem to get auto loaded (because of the removal of the require_tree . line in application.js). When I force it to load I get an error

SyntaxError: [stdin]:26:46: unexpected newline

in the application.html.erb, but weirdly for the stylesheet tag:

  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>

Changing the file to a .js file did not bring any change. Is there an error in my subscription.coffee file that I have overseen?


回答1:


In case of subscription update from Trial to Paid you need to first create the customer payment source

def update_subscription(params = {})
  if subscription.trial?
      stripe_customer = Stripe::Customer.retrieve(stripe_customer_token)
      stripe_card_token = params['subscription']['stripe_card_token']
      stripe_customer.sources.create(source: stripe_card_token)
  end
end

and then update the Stripe Subscription

begin
  Stripe::Subscription.update(
    stripe_subscription_id,
    { quantity: quantity, plan: plan }
  )
rescue
  /* Do Stuff Here! */
end


来源:https://stackoverflow.com/questions/43870145/rails-stripe-api-error-invalid-source-object-must-be-a-dictionary-or-a-non-emp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!