Search code examples
ruby-on-railsstripe-paymentswicked-gem

Stripe checkout on wizard page via wicked gem gives error on loading, how to resolve?


Right now I get this error message when the submit.html.erb loads: Cannot charge a customer that has no active card.

I want to understand how I can improve my controller. The goal is to not have the error message when the submit page loads. But only if there's an actual user submitting false information.

class SubmissionsController < ApplicationController
include Wicked::Wizard
steps :name, :details, :comments, :submit, :thankyou

def show
  @company = Company.find(params[:company_id])
  render_wizard
end

def update
  @company = Company.find(params[:company_id])

  # one time checkout
  @amount = 50
  @description = 'Premium Package'

  customer = Stripe::Customer.create(
    :email => params[:stripeEmail],
    :source  => params[:stripeToken]
  )

  Stripe::Charge.create(
    :customer    => customer.id,
    :amount      => @amount,
    :description => @description,
    :currency    => 'eur'
  )

  rescue Stripe::CardError => e
    flash[:error] = e.message

  params[:company][:status] = step.to_s
  params[:company][:status] = 'active' if step == steps.last
  @company.update_attributes(company_params)
  render_wizard @company
end

private ...

Here's the submit.html.erb

<%= form_for @company, url: wizard_path, method: :put do |f| %>
  <article>
    <% if flash[:error].present? %>
      <div id="error_explanation">
        <p><%= flash[:error] %></p>
      </div>
    <% end %>
    <label class="amount">
      <span>Amount: €0.50</span>
    </label>
  </article>

  <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
          data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
          data-description=<% @description %>
          data-amount=<% @amount %>
          data-locale="auto"></script>
<% end %>

If I can provide more context, please advise.


Solution

  • Refactored into this, now it works:

    class SubmissionsController < ApplicationController
      include Wicked::Wizard
      steps :name, :details, :comments, :submit, :thankyou
    
      def show
        get_company
        set_package
        render_wizard
      end
    
      def update
        case step
        when :thankyou
          get_company
          render_wizard @company
        when :submit
          get_company
          set_package
          if request.put?
            create_customer
            do_payment
            render_wizard @company
          end
        else
          get_company
          params[:company][:status] = 'active' if step == steps.last
          @company.update_attributes(company_params)
          render_wizard @company
        end
      end
    
      def get_company
        @company = Company.find(params[:company_id])
      end
    
      def create_customer
        @customer = Stripe::Customer.create(
          :email => params[:stripeEmail],
          :source  => params[:stripeToken]
        )
      end
    
      def set_package
        @amount = 50
        @amount_in_decimals = @amount / 100.00
        @description = "Premium Package"
      end
    
      def do_payment
        Stripe::Charge.create(
          :customer    => @customer.id,
          :amount      => @amount,
          :description => @description,
          :currency    => "eur"
        )
    
        rescue Stripe::CardError => e
          flash[:error] = e.message
      end
    

    and for the view

        <label class="amount">
          <span>Amount: <%= number_to_currency(@amount_in_decimals, :precision => 2, :locale => :nl) %></span>
        </label>
      </article>
    
      <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
              data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
              data-name="RailsApp!"
              data-description='<%= @description %>'
              data-amount=<%= @amount %>
              data-locale="auto"
              data-currency="eur"></script>
    <% end %>