问题
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