Skip to main content

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

Rails • Asked by Taylor Cooney
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

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 24,647+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.