All threads / How do I charge a user to create a post using Stripe?

Ask A Question

Notifications

You’re not receiving notifications from this thread.

How do I charge a user to create a post using Stripe?

Taylor Cooney asked in Rails
It's been surprisingly difficult to find more information on creating one-off, or single charges for a user.

Currently I am making a job board where anyone can browse listings, and a user (Devise) has CRUD abilities for a job posting. I want to embed a Checkout in the Job#new form and charge a user $x.xx before the job is created. This Checkout would work with Stripe to capture credit card details, and not store the user as a repeating customer; a user should not have their credit card details stored on file and should have to input the credit card information each time they want to create a job.

Rough outline of how I'd approach this. Let me know if this seems logical:
1. adding the Stripe gem to the application’s Gemfile
2. create the actual charges in the existing Jobs Controller

 |   before_action :authenticate_user!, only: [:new]
 | 
 |   def new
 |     @job = current_user.jobs.build
 |   end
 | 

 |   def create
 |     @job = current_user.jobs.build(jobs_params)
 | 

 |     if @job.save
 |       # Pass Stripe::Charge.create
 |       redirect_to @job
 |     else
 |       # Handle rescue Stripe::CardError
 |       render 'new'
 |     end
 |   end

I'm not sure if this will have an impact on routes how this will change how I add the credit card form in Job#new in terms of getting the [:stripeToken].

= simple_form_for(@job) do |f|
 |   = f.input :title
 |   = f.input :company
 |   = f.input :location
 |   = f.input :url
 |   = f.button :submit

Hoping to get a clearer idea of how to implement one-off charges before diving into the implementation,

Cheers🍺
Hey Taylor,

One-off charges are basically the same as Subscriptions. You just create a Stripe::Charge object instead of a Stripe::Subscription. 

1. Add Stripe to the Gemfile
2. Add the Stripe JS and checkout form to the page
3. The form for a new job should POST to the create action, so in there you can process the payment. 
4. Handle the payment and job creation together in a transaction

def create
  @job = current_user.jobs.build(jobs_params)
  if @job.create_with_stripe(params[:stripeToken])
    redirect_to @job
  else
    render 'new'
  end
end

class Job < ApplicationRecord
  def create_with_stripe(token)
    if valid?
      # Charge the user's card:
      charge = Stripe::Charge.create(
        :amount => 999,
        :currency => "usd",
        :source => token,
      )
      update(charge_id: charge.id)
    else
      false
    end
  rescue Stripe::CardError, Stripe::InvalidRequestError => e
    errors.add :base, "Whoops! We were unable to process your card. #{e.message}"
    false
  end
end

This way your payment logic is nicely organized with your Job. You check if the job is valid first, then we can fail quickly if it isn't valid. Then if it is valid, we can create the charge, and then update the Job with the charge ID for refund / reporting purposes. And if Stripe's charge fails with an error, we catch that and add the error to the Job and return false. Then your controller is nice and simple and just has to check if the create with stripe method returns true or false.
Nice one, Chris👌Moving the payment logic to be inline with the Job makes a lot more sense. Can't wait to sign up for the video series, thanks!
Hey Chris...how do you differentiate your form, so that when a user edits a post they've already paid for, the Stripe pay button is replaced with a typical 'Submit' button. Thanks in advance
Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 33,665+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.