1
votes

I've found that if a user purchases a product a second time, a new customer is created in my Stripe dashboard. I would like it so once a customer makes their first purchase, following purchases will be charged to that existing customer and their saved card. My app is running Rails 4.

charges_controller.rb

def create
  @user = current_user
  @gift = Gift.friendly.find(params[:gift_id])
  @charge = Charge.new(charge_params)
  @codes = Code.all
  @code = @gift.codes.where(:used => false).order("created_at ASC").first
  token = params[:stripeToken]
  if @user.customer_id.nil?
    # Create customer
      customer = Stripe::Customer.create(
      :card => token,
      :email => @user.email
    )
    # Charge the customer instead of the card
    Stripe::Charge.create(
      :amount => (@gift.price * 100).to_i,
      :currency => "cad",
      :customer => customer.id
    )
    # Customer_id is set to the Stripe customer.id
    customer_id = customer.id
    # If the transaction is approved
    if @charge.save
      # And user selects save_cc
      if @charge.save_cc == true
        # Update User's cusomter_id field to the var
        @user.update_attributes(:customer_id => customer_id)
        send_code(@user, @gift, @charge, @code)
      else 
        send_code(@user, @gift, @charge, @code)                     
      end 
    else 
      render 'charges/new'
    end 
  else
    # If user already has customer_id
    Stripe::Charge.create(
      :amount => (@gift.price * 100).to_i,
      :currency => "cad",
      :customer => @user.customer_id
    )
    if @charge.save 
      send_code(@user, @gift, @charge, @code)
    else 
      render 'charges/new'
    end 
  end 
end
1
Allow me a positive critic. This code is ugly, you are repeating a lot of code and is too much for a controller action. Try to DRY it first and I am sure some bugs will be fixed. - Rafa Paez

1 Answers

2
votes

You can try to retrieve the customer first from Stripe (if she already exists) and then make the transaction.

In this example, customer_token is the customer id which I store in the database.

customer = nil
if self.customer_token.present?
  customer = Stripe::Customer.retrieve(self.customer_token)
else
  customer = Stripe::Customer.create(
    :email => self.manager.email,
    :card  => stripe_token
  )
end

charge = Stripe::Charge.create(
  :customer    => customer.id,
  :amount      => total_amount_cents,
  :description => "...",
  :currency    => 'cad'
)

self.update_attributes(has_membership: true,
                       customer_token: customer.id,
                       last_payment_at: Time.zone.now)

PS: I recommend to enclose this in a transaction block to make sure that everything goes smoothly.