Stripe API in Rails - ruby-on-rails

I'm trying to use source_transaction with the Rails API so that I can have managed accounts that create payments and are later sent to other accounts.
I'm getting the error Stripe::InvalidRequestError: Insufficient funds in Stripe account. In test mode, you can add funds to your available bal
ance (bypassing your pending balance) by creating a charge with 4000 0000 0000 0077 as the card number. You can use th
e the /v1/balance endpoint to view your Stripe balance (for more details, see stripe.com/docs/api#balance).
But usinrg source_transaction I thought was supposed to bypass using my balance and only transfer funds once the transaction cleared.
Here is the code I'm using
charge = Stripe::Charge.create(
:customer => stripe_cust_id,
:amount => total_amount_owed,
:description => 'Groundwork Subscription Charge',
:currency => 'usd',
:transfer_group => invoice_number
)
...
transfer = Stripe::Transfer.create({
:amount => amount_to_transfer,
:currency => "usd",
:destination => StripeInfo.where(account_id: project_owner.accounts.first.id).first.stripe_id,
:application_fee => (amount_to_transfer*0.05).round,
:source_transaction => charge[:charge_id]
# :transfer_group => invoice_number
})

Related

Update stripe subscription payment card details rails

I am Using ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux],Rails 5.2.4.4 and Using stripe 5.26.0
I have created stripe subscription
customer = if current_user.stripe_customer_id?
Stripe::Customer.retrieve(current_user.stripe_customer_id)
else
Stripe::Customer.create({
:email => current_user.email,
:source => params[:stripeToken],
:description => "Tukaweb Stripe Subscriptions customer= #{current_user.email}"
},
{
api_key: Rails.configuration.stripe[:secret_key]
}
)
end
## check if user have already took the subscription
if current_user.subscriptions.where(payment_status: 'paid', software_package_id: #subscription.software_package_id).empty?
## with trail period
subscription = Stripe::Subscription.create({
customer: customer,
items: [
{price: 'price_1HVF68E9ijv19IzXdDVmKN5e'},
],
trial_end: (Time.now + 1.month).to_i,
})
else
## without trail period
subscription = Stripe::Subscription.create({
customer: customer,
items: [
{price: 'price_1HVF68E9ijv19IzXdDVmKN5e'},
],
})
end
current_user.update({
stripe_customer_id: customer.id
})
Now I want to update stripe subscriptions card details it giving error:
customer = Stripe::Customer.retrieve(current_user.stripe_customer_id)
stripe_subscription = SoftwareUser.find(params[:software_user_id])
subscription = customer.subscriptions.retrieve(stripe_subscription.stripe_subscription_id)
subscription.source = params[:stripeToken]
subscription.save
Error as:
Stripe::InvalidRequestError (Received unknown parameter: source):
can you please suggest how to update the card details for a subscription.
This is failing because there is no source attribute on a Subscription.
In this particular case, you're relying on the fact that when the Subscription is created, that it will fall back to using the default source of the Customer to fund the Subscription [1] because there is no default payment method. If you want to change the Source that pays the Subscription, you would have to change the default source of the Customer [2].
All that being said, the recommendation today is not to use Sources at all but rather to create a PaymentMethod [3] using Stripe.js and Elements. You attach this PaymentMethod to the Customer [4] Then you would set this payment method as default on either the Invoice [5], Subscription [6] or Customer [7].
The steps are outlined in more detail here [8].
[1] https://stripe.com/docs/api/subscriptions/create?lang=ruby#create_subscription-default_payment_method
[2] https://stripe.com/docs/api/customers/object?lang=ruby#customer_object-default_source
[3] https://stripe.com/docs/js/payment_intents/confirm_card_payment
[4] https://stripe.com/docs/api/payment_methods/attach?lang=ruby
[5] https://stripe.com/docs/api/invoices/object?lang=ruby#invoice_object-default_payment_method
[6] https://stripe.com/docs/api/subscriptions/object?lang=ruby#subscription_object-default_payment_method
[7] https://stripe.com/docs/api/customers/object?lang=ruby#customer_object-invoice_settings-default_payment_method
[8] https://stripe.com/docs/billing/subscriptions/fixed-price#create-subscription

Stripe Payment Works on LocalHost but Does not work on Heroku

Hope all is good
I am baffled by why my stripe payment in ruby on rails works on my localhost which is c9.io account but when I deployed my code in Heroku, it gives me this error:
Cannot charge a customer that has no active card
my orders.coffee file:
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
payment.setupForm()
payment =
setupForm: ->
$('#new_order').submit ->
$('input[type=submit]').attr('disabled', true)
obj = Stripe.card.createToken($('#new_order'), payment.handleStripeResponse)
alert(JSON.stringify(obj));
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)
out come of my orders.coffee in localhost:
my application.html.erb header section
<head>
<title>Estydemo</title>
<%= stylesheet_link_tag 'application', media: 'all'%>
<%= javascript_include_tag 'https://js.stripe.com/v2/', type: 'text/javascript' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
<%= tag :meta, :name=> 'stripe-key', :content => STRIPE_PUBLIC_KEY %>
</head>
my orders_controller.rb stripe section:
Stripe.api_key = ENV["stripe_api_key"]
#flash[:notice] = Stripe.api_key
#puts "stripe api key is " + Stripe.api_key
token = params[:stripeToken]
begin
customer = Stripe::Customer.create(
:source => token,
:description => "Customer.create"
)
charge = Stripe::Charge.create(
:amount => (#listing.price * 100).floor,
:description => 'charge.create',
:currency => "usd",
:customer => customer.id
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
my application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .
my stripe dashboard for a sample where I get from heroku
Could anyone let me know why I have such an odd issue?
left one is from heroku and right one is from localhost
If there is more info needed, please ask it away.
So this error means that the charge creation request (Stripe::Charge.create(...)) failed because the customer has no payment source.
This in turn means that when you created the customer:
customer = Stripe::Customer.create(
:source => token,
:description => "Customer.create"
)
token must have been either nil or an empty string, and as a result no source parameter was sent to Stripe. You can check this by looking at the log entry for the customer creation request in your Stripe dashboard.
This in turn means that params[:stripeToken] was itself nil or an empty string.
Unfortunately I'm not sure why that's the case. I'd recommend adding some logs, both in the stripeResponseHandler callback in your CoffeeScript file and in the Rails controller, to check whether the token was created and submitted successfully.
I think when test on Heroku, you create charge with new customer and this customer haven't any card default active. Please add create new card before create charge on orders_controller.rb
Stripe.api_key = ENV["stripe_api_key"]
#flash[:notice] = Stripe.api_key
#puts "stripe api key is " + Stripe.api_key
token = params[:stripeToken]
begin
customer = Stripe::Customer.create(
:source => token,
:description => "Customer.create"
)
card = customer.sources.create({:source => token})
charge = Stripe::Charge.create(
:amount => (#listing.price * 100).floor,
:description => 'charge.create',
:currency => "usd",
:customer => customer.id,
:source => card.id
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
I think your error is simply that you're creating a Stripe customer account and passing the token to the Customer but not passing the token to the actual Charge. This needs to be done in both cases. Many use cases for Stripe can be for creating subscriptions or for processing the payment later which is why the Customer Create will take the token on file. But to create a charge you also need to do this. So I would edit the code to include the token in the Charge create like this:
Edited 11/03
Actually I went ahead and reverted the code back to what you had. From reading through the API some more I think that you may be able to make it work this way just fine. That is if you intend on creating a customer that can be charged again later.The direction I would look then is at the fact that it works locally but not on Heroku. I think this is less about the Stripe code and more about the change to production. Look at the ENV variable and seeing if it's set for both dev and production. But not only that, I would precompile your assets as Heroku tends to have an issue with CSS or jQuery at least for me when I go from dev to production. Run RAILS_ENV=production bundle exec rake assets:precompile and that should do the trick, then push to master.
See: https://devcenter.heroku.com/articles/rails-asset-pipeline
token = params[:stripeToken]
begin
customer = Stripe::Customer.create(
:source => token,
:description => "Customer.create"
)
charge = Stripe::Charge.create(
:amount => (#listing.price * 100).floor,
:description => 'charge.create',
:currency => "usd",
:customer => customer.id
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
If you're just looking to charge them but not retain the information in Stripe you can just use:
token = params[:stripeToken]
begin
charge = Stripe::Charge.create(
:amount => (#listing.price * 100).floor,
:currency => "usd",
:source => token,
:description => "Example charge"
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
Edit 11/07
Ok so in looking through the actual repo, I think that you are having an issue because you don't have the necessary javascript call to create the token in the first place. I would reference the Stripe Api here:
https://stripe.com/docs/stripe.js#collecting-card-details
and insert this into your orders.js file, but that's contingent on the various input fields being named with those classes in the form you use to create the order. I hope this now helps point you in the correct direction. Everything else is looking like it should be good from what I can tell.
Stripe.card.createToken({
number: $('.card-number').val(),
cvc: $('.card-cvc').val(),
exp_month: $('.card-expiry-month').val(),
exp_year: $('.card-expiry-year').val()
}, stripeResponseHandler);

How to get IPN notification in PayPal on localhost

I am using Adaptive Payment in PayPal.
I am following the https://github.com/paypal/adaptivepayments-sdk-ruby.
All is working fine except I am not able to receive IPN notofications locally.
#api = PayPal::SDK::AdaptivePayments.new
#pay = #api.build_pay({
:actionType => "PAY",
:cancelUrl => "http://"+Rails.application.config.app_name+"/admin/dashboard",
:currencyCode => "USD",
:feesPayer => "SENDER",
:ipnNotificationUrl => "http://"+Rails.application.config.app_name+"/admin/receive_notification",
:receiverList => {
:receiver => [{
:amount => amount,
:email => #paypal_id }] },
:returnUrl => "http://"+Rails.application.config.app_name+"/admin/dashboard" })
So , how to receive notifications on localhost
Paypal will not be able to route to localhost to send the IPN. You would need to setup a publicly available domain name and the appropriate dns.
Localhost is always specific to your machine, you might be able to use dynamicdns but it would require network changes on your machine and network.

recurring paypal with preapproval adaptive payment

I have create rails application and implemented preapproval payment using adaptivepayments-sdk-ruby gem. I plan to use this as recurring payment.
this is my code for create preapproval:
ADAPTIVE_PAYMENT.build_preapproval({
:cancelUrl => my_cancel_url,
:currencyCode => "USD",
:paymentPeriod => "DAILY",
:returnUrl => my_return_url,
:startingDate => DateTime.now.in_time_zone
})
and then I use this code to charge:
ADAPTIVE_PAYMENT.build_pay({
:actionType => "PAY",
:cancelUrl => my_cancel_url,
:currencyCode => "USD",
:feesPayer => "PRIMARYRECEIVER",
:preapprovalKey => Preapproval_key,
:receiverList => {
:receiver => [{
:amount => 100,
:email => example#example.com,
:primary => true},
{
:amount => $100,
:email => example#example.com,
:primary => false }
]
},
:returnUrl => my_return_url
})
How to make it automatically charged every day without execute the pay code again?
Im pretty sure there is no automatic pay feature from paypals side. I know that you can setup how many monthly / weekly payments they are signing up for but I think thats just for the pre-approval agreement.
However, why dont you just setup a CRON job and let it take care of it for you? I was super nervous about doing this with paypal adaptive payments the first time but its actually saved me SO much time and its a lot more reliable than any human could be with its ability to send job reports after its done.

Paypal adaptive payments for digital goods

I am struggling to figure out how to get Digital goods to work with my adaptive payments. I am using the Paypal ruby gem can someone please show me a code sample for a payments with 2 receivers and for Digital Goods?
I already am approved for micro payments by paypal.
# Build request object
#pay = #api.build_pay({
:actionType => "PAY",
:cancelUrl => "http://localhost:3000/account", #sandbox
:currencyCode => "USD",
#:feesPayer => "SENDER",
:ipnNotificationUrl => "http://596w.localtunnel.com/pay/#{purchased.id}", #sandbox
:memo => "Test payment",
:receiverList => {
:receiver => [{
:amount => price.round(2),
:email => "an email", #sandbox
:paymentType => "DIGITALGOODS",
:primary => true
},
unless account.user.email == "an email"
{
:amount => mycut.round(2),
:email => "anemail", #sandbox
:paymentType => "DIGITALGOODS"
}
end
] },
:returnUrl => "http://localhost:3000/pay/complete/" #sandbox
})
I get the error:
This feature (Digital Goods) is not supported.
As far as i know on the the Express Payment option of Paypal supports digital good. if you can replace your integration to use activemerchant and use the PaypalDigitalGoodsGateway you'd do yourself a favor.
Log a ticket at https://www.paypal.com/mts and they'll enable it for you.
For what it's worth, the product you're trying to use is: Digital Goods for Express Checkout.
Express Checkout itself is available by default on all accounts, but that team can enable Digital Goods on your Sandbox account.
This error may appear if you get the payKey successfully but redirect user to wrong url later.
Here is haml code for form for embedded payments, including Digital Goods.
= javascript_include_tag "//www.paypalobjects.com/js/external/apdg.js"
%form.text-center{:action => ::PAYPAL_ADAPTIVE_GATEWAY.embedded_flow_url, :target => "PPDGFrame"}
%input#type{:name => "expType", :type => "hidden", :value => "light"}
%input#paykey{:name => "payKey", :type => "hidden", :value => #payKey}
%input#submitBtn{:type => "submit", :value => 'Pay with PayPal' }
:javascript
var returnFromPayPal = function(){
//do something on PayPal popup closing here
};
var dgFlowMini = new PAYPAL.apps.DGFlowMini({ trigger: 'submitBtn', callbackFunction: returnFromPayPal});
//works only for lightbox mode
function MyEmbeddedFlow(embeddedFlow) {
this.embeddedPPObj = embeddedFlow;
this.paymentSuccess = function () {
this.embeddedPPObj.closeFlow();
// handle payment success here
window.location.reload(true);
};
this.paymentCanceled = function () {
this.embeddedPPObj.closeFlow();
// handle payment cancellation here
window.location.reload(true);
};
}
var myEmbeddedPaymentFlow = new MyEmbeddedFlow(dgFlowMini);
::PAYPAL_ADAPTIVE_GATEWAY.embedded_flow_url is from activemerchant, you may use 'https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay' for sandbox or 'https://www.paypal.com/webapps/adaptivepayment/flow/pay' for production.

Resources