I want Stripe to check if the customer already exists and if yes associate it to the checkout session.
class OrdersController < ApplicationController
#session = Stripe::Checkout::Session.create(
payment_method_types: ['card'],
shipping_address_collection: {
allowed_countries: ['GB']
},
customer_email: current_user.email,
line_items: line_items_order,
success_url: new_order_message_url(#order),
cancel_url: order_url(#order)
)
if #user.stripe_id != nil
Stripe::Customer.retrieve(#user.stripe_id)
#session.customer = customer.id
#session.customer_email =customer.email
else
customer = Stripe::Customer.create({
email: current_user.email,
name: current_user.username,
metadata: {
},
})
#user.stripe_id = customer.id
#user.save
end
#order.checkout_session_id = #session.id
#order.save
end
I checked with byebug and saw that Stripe::Customer.retrieve(#user.stripe_id) is working, Stripe API is able to find te right customer, but still create a new customer for each checkout session. I have read the documentation about the sessions objetc and found that about the customer attribute:
customer attribute:
The ID of the customer for this Session. For Checkout Sessions in payment or subscription mode, Checkout will create a new customer object based on information provided during the payment flow unless an existing customer was provided when the Session was created.
What do I miss here?
The issue is that you are calling Stripe::Checkout::Session.create without passing in the customer. As mentioned in the doc for customer, it should be passed when creating the session if you want to use an existing customer
customer string EXPANDABLE
The ID of the customer for this Session. For Checkout Sessions in
payment or subscription mode, Checkout will create a new customer
object based on information provided during the payment flow unless an
existing customer was provided when the Session was created.
So just make sure you have the customer in the create method
#session = Stripe::Checkout::Session.create(
customer: customer.id
...
)
Related
Payments are going through stripe but customers are not being created in the Stripe dashboard. There is already code to create customer that is called, but the API to create customer is not listed in the Stripe dashboard logs:
def create_customer(stripe_token, email)
customer = Stripe::Customer.create(source: stripe_token, email: email)
customer.save
end
Am I missing anything? It was working fine before Nov 2022.
I have a user_id attached to the Store model for a Shopify App. I want to be able to have a user login with their user account to have the shopify session start instead of using needing to open the app from their app section of their store. This is a standalone app btw.
I have tried this for when users sign in:
if Shop.find_by(user_id: current_user)
shop = Shop.find_by(user_id: current_user)
shop = ShopifyAPI::Session.new(shop.shopify_domain, shop.shopify_token)
ShopifyAPI::Base.activate_session(shop)
end
and:
if Shop.find_by(user_id: current_user)
shop = Shop.find_by(user_id: current_user)
shop = ShopifyApp::SessionRepository.retrieve(shop.id)
ShopifyAPI::Base.activate_session(shop)
end
I tried this in my session create method and as a after_action callback for the create method in the sessions controller...
Is there something I am doing wrong?
I tested this in console to make sure all of the assocations were correct. The token and shopify_domain are all there attached to the user
I am using payola which is a rails engine for stripe payment. am using the subscriptions method to make subscription. currently users are able to make subscription and can save the data on stripe. how do i save the return data to my database.
on my subscription controller i have it set like this
def create
# do any required setup here, including finding or creating the owner object
owner = current_user # this is just an example for Devise
# set your plan in the params hash
params[:plan] = SubscriptionPlan.find_by(id: params[:plan_id])
# call Payola::CreateSubscription
subscription = Payola::CreateSubscription.call(params, owner)
# Render the status json that Payola's javascript expects
render_payola_status(subscription)
subscriptions = Subscription.new
subscriptions.stripeid = subscription.id
subscriptions.customer = subscription.customer
subscriptions.plan = subscription.plan.name
subscriptions.subscriptiondate = subscription.current_period_start
subscriptions.subscriptionenddate = subscription.current_period_end
subscriptions.save
end
but when i check in my database its empty
I want customers to be able to update their credit card details in my Rails app. Stripe has documentation on how to achieve this, but the article is showing an example in PHP, but I need an example for Rails: https://stripe.com/docs/recipes/updating-customer-cards
Basically, I need to save a customer's credit card without charging it.
This is subscribers_controller.rb:
class SubscribersController < ApplicationController
before_filter :authenticate_user!
def new
end
def update
token = params[:stripeToken]
customer = Stripe::Customer.create(
card: token,
plan: 1212,
email: current_user.email
)
current_user.subscribed = true
current_user.stripeid = customer.id
current_user.save
redirect_to profiles_user_path
end
end
You might also want to check out this SO answer How to create a charge and a customer in Stripe ( Rails) for more details on using Stripe in a Rails application.
For Ruby documentation, you can find great examples at on the Stripe Ruby API. In Stripe terminology, a card is called a source for the customer. You can create a source from a token, but once it's created, you deal with source and default_source elements on the Customer object, and retrieve card objects from the customer's source. Also note that you should never try to use the token beyond creating the source (or for one-time charges).
The Stripe Ruby API for Customers shows that you can create a customer and assign the source at the same time:
customer = Stripe::Customer.create(
source: token,
email: current_user.email
)
You do not have to assign a source to create a customer. However, if you set the customer up on a subscription, they will require a source to be available, and the charges will be made to the customer's default_source. If a customer has only one source, it is automatically the default_source.
The Stripe Ruby API for Cards, shows that you can also add a new card to an existing customer, using a token:
customer = Stripe::Customer.retrieve(customer_id)
customer.sources.create({source: token_id})
Once you have a card assigned to the customer, you can make it the default_source, using this:
customer.default_source = customer.sources.retrieve(card_id)
And that's what it takes to get setup and ready to start charging customers. Happy billing!
To update the card for an existing customer, the relevant snippet from the PHP recipe you mentioned is:
$cu = \Stripe\Customer::retrieve($customer_id); // stored in your application
$cu->source = $_POST['stripeToken']; // obtained with Checkout
$cu->save();
In Ruby, this would be:
cu = Stripe::Customer.retrieve(customer_id)
cu.source = params[:stripeToken]
cu.save
This will update the existing customer with the card from the token contained in the stripeToken parameter.
So I have an e commerce type rails app where users are able to list spaces to be booked, and other users are able to book these spaces for a specified amount of time.
I used this tutorial, http://www.gotealeaf.com/blog/basic-paypal-checkout-processing-in-rails, to set up my system.
Once a user submits a form to create a new booking, they are redirected to the PayPal website where they log in to paypal, confirm they are paying, and once they have paid they have an option to return to my website and see their booking invoice.
My issue is that when a user clicks submit on their new booking form and they are taken to the paypal website, they may press back on their browser, taking them back to my website, but their booking is now recorded.
How do I stop a booking from being recorded unless it has been paid for through paypal?
Here is my create action from my bookings controller:
def create
#booking = Booking.new(params[:booking].permit(booking_params)
#booking.space = #space
Space.find(#space.id).update_attributes( :balance => #space.balance + (#booking.length * #space.hourly_rate))
if #booking.save
redirect_to #booking.paypal_url(space_booking_path(#space, #booking))
else
render 'new'
end
end
Also my app/models/booking.rb:
class Booking < ActiveRecord::Base
include Bookable
def paypal_url(return_path)
values = {
business: "nikia.i-facilitator#peerparking.ca",
cmd: "_xclick",
upload: 1,
return: "#{Rails.application.secrets.app_host}#{return_path}",
invoice: id * rand(19284),
amount: space.hourly_rate * length,
item_name: space.address,
item_number: space.id,
quantity: '1',
notify_url: "#{Rails.application.secrets.app_host}/hook"
}
"#{Rails.application.secrets.paypal_host}/cgi-bin/webscr?" + values.to_query
end
end
And the relevant route in my routes.rb
post "spaces/:space_id/bookings/:id" => "bookings#show"
A browser back-arrow should return to the URL at your site that the user was already at. This URL should not consider payment complete (and booking in order). Would hitting browser reload on your page that precedes the redirect to PayPal also allow the user to complete the booking?
Assuming you are using Website Payments Stnadard, you would normally process a booking only upon the user reaching the return_url that you provide to PayPal, and then your code successfully processing the result variables that PayPal will include in the post back to you. (Or for customers who pay but do not return to your site directly, you would use IPN to associate the payment to the customer's account so that their order can be fulfilled asynchronously.)