Stripe::InvalidRequestError Must provide source or customer - ruby-on-rails

order controller page
begin
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
charge = Stripe::Charge.create(
:amount => (#listing.price * 100).floor,
:currency => "usd",
:source => params[:stripeToken],
:destination => #seller.recipient
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
order.js.coffee
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
payment.setupForm()
payment =
setupForm: ->
$('#new_order').submit ->
$('input[type=submit]').attr('disabled', true)
Stripe.card.createToken($('#new_order'), payment.handleStripeResponse)
false
handleStripeResponse: (status, response) ->
if status == 200
$('#new_order').append($('<input type="hidden" name="stripeToken" />').val(response.id))
$('#new_order')[0].submit()
else
$('#stripe_error').text(response.error.message).show()
$('input[type=submit]').attr('disabled', false)
I am not sure why the source => params[:stripeToken] is not passing thru when I check the log in my stripe account. Is the token null?

Usually when you receive this error is because the publishable key is not in your form so when you send the form to stripe it doesn´t recognize you and it doesn´t send you back the token.
The process of charging a client goes this way.
1.- In your site you tell the user to type his card information in a form (hosted locally or just created by stripe script).
2.- Once the user submit the form. The information is submitted to stripe server with your publishable key. You receive a response from the server with a token. This token is forwarded to the action in your controller and since is linked to your account you can create a customer, a charge or join the user to a plan. This is the 'params[:stripeToken]'. The card information never reaches your controller, you just receive this token.
You can do two things to charge your clients, the first is create the form your self and the second just delegate it to the stripe script.
The first one is more tricky since stripe updates their api from time to time. It requires some knowledge of js and their api. For example Stripe v3 is different from v2. Allows more rationalization but requires more knowledge of js. The information and examples of how to configure can be found in stripe elements.
The second one is pretty easy. I recommend it to not advanced users. You can implement it just following the instructions in this link using checkout and rails.
I usually use the second option since it just takes 5 minutes and you delegate the hard work to stripe.

Related

Code was already redeemed ... But where?

I am stuck / block on this point, I keep on having this error message 'Code was already redeemed'
3 steps :
Getting the authorization URL (SignetLogin)
Calling it and retrieving the authorization code (SignetAuth)
Getting the refresh token and calling google API (SignetInsert)
When I try to use the API I always get this error message : Code was already redeemed'.
I ask for some help, what's wrong and where can I find some tips about it ? What did I missed ?
Thanks - Gregoire
def SignetLogin
auth = Signet::OAuth2::Client.new(
:authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
:scope => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar',
# :state => 'useful_dynamic_string', # What is that ?
:redirect_uri => 'http://localhost:3000/auth/google_oauth2/callback',
:client_id => $client_id,
:client_secret => $client_secret
)
redirect_to auth.authorization_uri.to_s
end
def SignetAuth
$code = request['code']
auth = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:redirect_uri => 'http://localhost:3000/SignetInsert',
:client_id => $client_id,
:client_secret => $client_secret,
:code => request['code']
)
end
def SignetInsert
auth = Signet::OAuth2::Client.new(
token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
redirect_uri: 'http://localhost:3000/',
# redirect_uri: 'http://localhost:3000/auth/google_oauth2/callback',
:client_id => $client_id,
:client_secret => $client_secret,
:code => $code
)
# puts auth.fetch_access_token!
calendar = Google::Apis::CalendarV3::CalendarService.new
calendar.authorization = auth
calendar_id = 'primary'
#result = calendar.list_events(calendar_id,
max_results: 10,
single_events: true,
order_by: 'startTime',
time_min: Time.now.iso8601)
end
I cant help you much with ruby but i can tell you what "Code was already redeemed' means.
When you authenticate to Google there are three steps.
User is shown a consent form
Assuming the user accepted consent an authentication code is returned to the calling client application.
The calling client exchanges the authentication code for an access token and sometimes a refresh token.
The access token can then be used to access the API. Access tokens expire after an hour and you can use a Refresh token to request a new access token.
The authentication code that you get back as part of the auth flow can only be used once to get the access token and refresh token. "Code was already redeemed' means that you are trying to use a code you have already used.
Like i said i dont know much about ruby but this might help google apis ruby client
Thanks all for your tips and answers, you gave me the way !
It's not that easy, but I did it, with your help, thanks again
So, the answer is multiple :
1/ The refresh token is not served every time, only the first time, this url allow you to dis-authorize your app and have it again in the answer
2/ this article gave some tips on how to start but definitivly down't give you the 'right' way 2
3/ As far as I understood, using a 'clean' request (see step 1)
$auth = Signet::OAuth2::Client.new and you retrieve an authorization_uri, you redirect to (don't forget to_s)
Google display it's form, asking for authorization
- Google redirect the user on your server, you retrieve the access_token and the refresh_token THE FIRST TIME ONLY (see step 1 to de-authorize and having again your refresh_token
-
and, because you (or I) just can't guess it :
$auth.code = request['code']
$auth.grant_type = 'authorization_code'
$token = $auth.fetch_access_token!
you can use your token and so on
it's not that easy but I hope facebook will not be too different

Securely Submitting a Subscription's tax_percent to Stripe API in Rails

So I have a rails app where I'm selling subscriptions to access content. For users in NJ, I have to charge them 7% sales tax. Everywhere else is 0. So when they register an account with Devise, I record their state.
Then in my SubscriptionsController.rb, I check to see if they live in NJ:
data = if current_user.home_state == "NJ"
subscription_params.merge(tax_percent: 7)
else
subscription_params
end
#subscription = ::Subscription.new(data)
When the subscription gets created, the subscription table gets updated properly. I also assumed that when the user makes a purchase this tax_percent would also hit Stripe's API, but it doesn't.
So I tried adding this to the subscription creation form:
<%= f.hidden_field :tax_percent %>
and it does hit Stripe's API, but hits as tax_percent: '', which is null.
So I can always perform a logic check like this:
<% if current_user.home_state == "NJ" %>
<%= hidden_field :tax_percent, :value => '7' %>
<% end %>
But then I'm exposing the value to the client, which can be manipulated.
What's the best 'rails' way to submit this value to Stripe's API?
It's a bit hard to tell what's going on based on the code-sample you've provided, but ultimately you want to set the tax-rate on individual users when you Create the Subscription [1].
If you're going to be doing one-off payments, you'll need to also store that information somewhere else on the Customer record. I might recommend you utilize the metadata-parameter [2] of the Customer record. You can set it by making an Update Customer [3] API Request. Then, when you're making a charge [4], you'll want to multiply it by whatever tax coefficient you've stored.
Another (probably better) approach, would be to create a pending invoice item [5] for the one-time purchase (without tax being included). Then create an Invoice [6] with the tax_percent-parameter being populated. And finally, pay the Invoice [7]. This will make a trackable record of purchases made with line-items for their tax percent kept separate.
Hope that helps!
[1] https://stripe.com/docs/api#create_subscription
[2] https://stripe.com/docs/api#metadata
[3] https://stripe.com/docs/api#update_customer
[4] https://stripe.com/docs/api#create_charge
[5] https://stripe.com/docs/api#create_invoiceitem
[6] https://stripe.com/docs/api#create_invoice
[7] https://stripe.com/docs/api#pay_invoice

Can't get Google Analytics user data to show in Rails app

I'm attempting a server-to-server connection between my Google Analytics account and my Rails app. For this, I'm using the Legato, omniauth-google-oauth2, and google-api-client gems. My intention is to have a rake task that sieves out pageview data from a particular site. However, I can't seem to get any user data out of it. Here's the code:
require 'google/api_client'
def service_account_user(scope="https://www.googleapis.com/auth/analytics.readonly")
client = Google::APIClient.new(
:application_name => "Listmaker",
:application_version => "2.0"
)
key = OpenSSL::PKey::RSA.new(Figaro.env.google_private_key, "notasecret")
service_account = Google::APIClient::JWTAsserter.new(Figaro.env.google_app_email_address, scope, key)
client.authorization = service_account.authorize
oauth_client = OAuth2::Client.new("", "", {
:authorize_url => 'https://accounts.google.com/o/oauth2/auth',
:token_url => 'https://accounts.google.com/o/oauth2/token'
})
token = OAuth2::AccessToken.new(oauth_client, client.authorization.access_token)
Legato::User.new(token)
end
class Pageviews
extend Legato::Model
metrics :pageviews
dimensions :page_path
filter :for_page_path, &lambda {|page_path| matches(:page_path, page_path)}
end
puts profile = service_account_user.profiles.first
I appear to be getting an empty array for the profile variable after running the task. I've definitely added the developer email address to the Google Analytics View I'm interested in. Not sure what's wrong.
For a service account to work with Google Analytics the Service account email must be added at the Account level. It wont work if it was only added at the view level.

Stripe error: "The card object must have a value for 'number'" when creating a Customer

I am using Stripe's ruby gem to (try to) perform two steps:
Collect a card using Stripe's "Checkout" form
Create a Customer using the token provided by the redirect from the form submission
The latter of these steps raises a Stripe::CardError whose message is:
The card object must have a value for 'number'
The API doc describes the process: https://stripe.com/docs/tutorials/subscriptions#subscribing-a-customer-to-a-plan
My code (a Rails controller action)
def receive_redirect
customer = Stripe::Customer.create(
plan: "stripe_plan_name",
card: params[:stripeToken]
)
end
params[:stripeToken] looks like this:
{"id"=>"tok_1044TY4GgNdNSosPXdAmIZdt", "livemode"=>"false",
"created"=>"1400620581", "used"=>"false", "object"=>"token",
"type"=>"card", "card"=>{"id"=>"card_1044TY4GgNdNSosPuDSuygow",
"object"=>"card", "last4"=>"9424", "type"=>"Discover",
"exp_month"=>"9", "exp_year"=>"2014",
"fingerprint"=>"Lz5ASwlmyseG0gYo", "customer"=>"", "country"=>"US",
"name"=>"manderson#pinneyinsurance.com", "address_line1"=>"",
"address_line2"=>"", "address_city"=>"", "address_state"=>"",
"address_zip"=>"", "address_country"=>""},
"email"=>"<my_email>#<my_host>"}
...As you can see, they don't give me a number, so what am I to do?
Stack
stripe 1.8.8 (ruby gem)
Rails 3.2.13
Ruby 1.9.3
The value you should be setting card: to is just the id of the token and not the entire object you are passing right now. Something like this (my ruby is a bit rusty):
card: params[:stripeToken][:id]
You can see an example of valid inputs to Customer.create in the Stripe API Docs.

confused and disoriented with paypal ipn

I am using this gem for payments in paypal https://github.com/tc/paypal_adaptive
I am very confused and disoriented with this gem. It has a poorly documented and is difficult for me to understand how to get the data from paypal on ipn response.
I hope this question will help more people having the same problem.
My steps are:
1º I send request to paypal from my orders_controller.rb with method preaproval_payment.
def preapproval_payment
preapproval_request = PaypalAdaptive::Request.new
data = {
"returnUrl" => response_paypal_user_orders_url(current_user),
"cancelUrl"=> cancel_payment_gift_url(#gift),
"requestEnvelope" => {"errorLanguage" => "en_US"},
"senderEmail" => "gift_1342711309_per#gmail.com",
"startingDate" => Time.now,
"endingDate" => Time.now + (60*60*24) * 30,
"currencyCode"=>"USD",
"maxAmountPerPayment" => "#gift.price",
"ipnNotificationUrl" => ipn_notification_url,
"ip" => request.remote_ip
}
preapproval_response = preapproval_request.preapproval(data)
puts data
if preapproval_response.success?
redirect_to preapproval_response.preapproval_paypal_payment_url
else
redirect_to gift_url(#gift), alert: t(".something_was_wrong")
end
end
2º These are the data of my request in my log console from command puts data :
{"returnUrl"=>"http://localhost:3000/en/u/maserranocaceres/orders/response_paypal", "cancelUrl"=>"http://localhost:3000/en/gifts/gift-1/cancel_payment", "requestEnvelope"=>{"errorLanguage"=>"en_US"}, "senderEmail"=>"gift_1342711309_per#gmail.com", "startingDate"=>2012-07-29 13:05:49 +0200, "endingDate"=>2012-08-28 13:05:49 +0200, "currencyCode"=>"USD", "maxAmountPerPayment"=>9, "ipnNotificationUrl"=>"http://localhost:3000/ipn_notification?locale=en", "ip"=>"127.0.0.1"}
3º I redirect to paypal page, and I make the payment on paypal successfully :D.
4º When payment is completed successfully, I am directed to:
http://localhost:3000/en/u/maserranocaceres/orders/response_paypal
I have response_paypal action in orders_controller.rb. It is GET action and my code for this action is:
def response_paypal
respond_to do |format|
format.html { redirect_to user_orders_url(current_user), :alert => "works fine return url"}
end
end
Up to this point everything works fine.
Now what I need is to get the data I received from paypal and save my database a new order if payment is successfully processed.
5º For this purpose I make a file in lib/paypal_ipn.rb and I add to this file the content from https://github.com/tc/paypal_adaptive/blob/master/templates/paypal_ipn.rb
# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
class PaypalIpn
def self.call(env)
if env["PATH_INFO"] =~ /^\/paypal_ipn/
request = Rack::Request.new(env)
params = request.params
ipn = PaypalAdaptive::IpnNotification.new
ipn.send_back(env['rack.request.form_vars'])
if ipn.verified?
#mark transaction as completed in your DB
output = "Verified."
else
output = "Not Verified."
end
[200, {"Content-Type" => "text/html"}, [output]]
else
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
end
end
end
In my routes.rb I add:
match "/ipn_notification" => PaypalIpn
My 2 problems are:
a) I do not see that after making the payment this file to be fired and I can not see in my console data I get from paypal.
b) I want to send to paypal in my request, the id of object #gift for being able to recover later in paypal_ipn.rb and to save my database.
What am I doing wrong and how I can solve these problems?
Thank you
I haven't used that gem, but I've used PayPal IPN before. Here are some things you should check:
Do you have your PayPal account set up to use IPN? You must enable this setting on the account for this to work.
Have you verified that when you pass ipn_notification_url during the payment process, that it matches your "/ipn_notification" route?
For this to work, PayPal must be able to communicate directly with the server that is running this app. This means that typically, unless you have a custom setup on your local machine with dynamic DNS or something, that you will need to actually deploy this code to a server in order for PayPal to be able to communicate with your app. In other words, if this is running on http://localhost:3000, this will not work.
To answer your second question, how to recover #gift in order to record the fact it was paid in your database, I'm not entirely sure how to do it with this gem, but I'll tell you how I do it using ActiveMerchant - it is probably quite similar.
In your payment request to PayPal, you can pass in an invoice number. I believe the field is just called "invoice". Here you would pass the ID of the gift.
When PayPal notifies your app via IPN that the order was paid for, it will pass the invoice number back to you. Retrieve the #gift using this invoice number and then you can do what you need with it.
Here are the relevant parts of my working PayPal code, using the ActiveMerchant gem: https://gist.github.com/3198178
Good luck!

Resources