Ruby on Rails Stripe, setting default amount - ruby-on-rails

Trying to implement Stripe into my app, but my understanding of Ruby/Rails' syntax is, while functional, still very basic. How should I express a default amount? I'm being prompted to "create a Amount class and its default class method, which should return the number you wish to charge, in pennies. One such value might be 15_00, for fifteen dollars." Thanks in advance for the help!
class ChargesController < ApplicationController
def create
# Creates a Stripe Customer object, for associating
# with the charge
customer = Stripe::Customer.create(
email: current_user.email,
card: params[:stripeToken]
)
# Where the real magic happens
charge = Stripe::Charge.create(
customer: customer.id, # Note -- this is NOT the user_id in your app
amount: Amount.default,
description: "BigMoney Membership - #{current_user.email}",
currency: 'usd'
)
flash[:success] = "Thanks for all the money, #{current_user.email}! Feel free to pay me again."
redirect_to user_path(current_user) # or wherever
# Stripe will send back CardErrors, with friendly messages
# when something goes wrong.
# This `rescue block` catches and displays those errors.
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
def new
#stripe_btn_data = {
key: "#{ Rails.configuration.stripe[:publishable_key] }",
description: "BigMoney Membership - #{current_user.name}",
amount: Amount.default
}
end
end

Related

Rails Stripe Retrieve ID Error "No such plan"

So my Plan says Stripe::InvalidRequestError at /orders/26/payments
No such plan: The title of my plan.
This code should check if the the plan already exists and if not create it and subscribe the user to it. I thought this worked because it was working for the case where I already had a plan with the same ID and it said "Plan already exists". How can I prevent this Error from happening?
This is my code:
class PaymentsController < ApplicationController
before_action :set_order
def new
end
def create
#user = current_user
customer = Stripe::Customer.create(
source: params[:stripeToken],
email: params[:stripeEmail],
)
# Storing the customer.id in the customer_id field of user
#user.customer_id = customer.id
#plan = Stripe::Plan.retrieve(#order.service.title)
unless #plan
plan = Stripe::Plan.create(
:name => #order.service.title,
:id => #order.service.title,
:interval => "month",
:currency => #order.amount.currency,
:amount => #order.amount_pennies,
)
else
subscription = Stripe::Subscription.create(
:customer => #user.customer_id,
:plan => #order.service.title
)
end
#order.update(payment: plan.to_json, state: 'paid')
redirect_to order_path(#order)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_order_payment_path(#order)
end
private
def set_order
#order = Order.where(state: 'pending').find(params[:order_id])
end
end
The documentation says that if you try to retrieve a plan that does not exist, it will raise an error. So you just need to catch the error:
begin
#plan = Stripe::Plan.retrieve(#order.service.title)
rescue
#plan = Stripe::Plan.create(...)
end
Little bit improved version. It's sad that there is no way to check if plan exists and you have to rely on exception swallowing it. Here is my version, it tries to retrieve the plan, if error is 404, it creates the plan. Otherwise, lets exception to pop up. So it won't swallow all of the exceptions, which is important IMO when you work with finance API.
def retrieve_or_create_plan(id)
begin
Stripe::Plan.retrieve(id)
rescue Stripe::InvalidRequestError => e
if e.response.http_status == 404
Stripe::Plan.create(
name: 'Your plan name',
id: id,
interval: :month,
currency: :usd,
amount: 100
)
else
raise e
end
end
end

Rails / Stripe - undefined method `stripe_token' for nil:NilClass

I'm using Stripe for payments on my Rails app and I've hit the error above. I've recently moved a big chunk of my code from my controller to model and this is the first time I've hit this error (I've tested payments before and it never came up). Not really sure why this is coming up now.
Here's my Model code -
Booking.rb
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :user
def reserve
# Don't process this booking if it isn't valid
return unless valid?
# We can always set this, even for free events because their price will be 0.
self.total_amount = quantity.to_i * event.price_pennies.to_i
# Free events don't need to do anything special
if event.is_free?
save
# Paid events should charge the customer's card
else
begin
charge = Stripe::Charge.create(amount: total_amount, currency: "gbp", card: #booking.stripe_token, description: "Booking number #{#booking.id}", items: [{quantity: #booking.quantity}])
self.stripe_charge_id = charge.id
save
rescue Stripe::CardError => e
errors.add(:base, e.message)
false
end
end
end
end
And in my controller -
bookings_controller.rb
def create
# actually process the booking
#event = Event.find(params[:event_id])
#booking = #event.bookings.new(booking_params)
#booking.user = current_user
if #booking.reserve
flash[:success] = "Your place on our event has been booked"
redirect_to event_path(#event)
else
flash[:error] = "Booking unsuccessful"
render "new"
end
end
Here's the error message -
I'm pretty new to Rails so apologies if this seems straightforward, any help would be appreciated.
#booking is an instance variable that is only available in the context of the controller/view. Since reserve is an instance method on the model, you probably just want to refer to self or nothing, i.e #booking.method => self.method or method.

Stripe Payment in Rails only showing up in logs as v1/token

Building an application in rails that uses stripe for its payment/checkout system. I have the charges controller, new.html.erb and all the necessary gems in place but for some reason whenever I use my credit card to test stripe with a real payment (the charge is only $2 so it doesn't hurt to test) it appears in my logs as a v1/token rather than a v1/charge and does not appear in the payments section. I have researched extensively the conversion from token to charge and have found multiple answers pointing to the same solution (creating a begin method that turns tokens into charges which I have) but when implementing it doesn't work for me. this is my current charges controller:
require "stripe"
class ChargesController < ApplicationController
def new
# this will remain empty unless you need to set some instance variables to pass on
end
def create
# Amount in cents
#amount = 200
# Set your secret key: remember to change this to your live secret key in production
# See your keys here https://dashboard.stripe.com/account/apikeys
Stripe.api_key = "pk_live_z....." //taken out for security reasons
# Get the credit card details submitted by the form
token = params[:stripeToken]
# Create the charge on Stripe's servers - this will charge the user's card
begin
charge = Stripe::Charge.create(
:amount => #amount, # amount in cents, again
:currency => "usd",
:source => token,
:description => "Example charge"
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
end
your create method is not being called which executes the logic of payment.

How to fix this error "undefined method `encoding' for nil:NilClassa " and get canceling subscription plan worked?

This is my first time working with Stripe and Rails and now I am trying to allow premium users to cancel their subscriptions.
I can upgrade a user from standard level to premium level with my code, but I am having issues when I attempt to downgrade a premium user to the standard level.
I have followed Stripe Ruby API References of "Cancel a subscription": https://stripe.com/docs/api?lang=ruby#cancel_subscription, but I got this error when I clicked the "cancel subscription" button:
NoMethodError - undefined method encoding' for nil:NilClass:
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/cgi/util.rb:7:inescape'
stripe (1.21.0) lib/stripe/list_object.rb:19:in retrieve'
app/controllers/subscriptions_controller.rb:55:indowngrade'
My rails version is 4.2.1.
My code:
class SubscriptionsController < ApplicationController
def create
subscription = Subscription.new
stripe_sub = nil
if current_user.stripe_customer_id.blank?
# Creates a Stripe Customer object, for associating with the charge
customer = Stripe::Customer.create(
email: current_user.email,
card: params[:stripeToken],
plan: 'premium_plan'
)
current_user.stripe_customer_id = customer.id
current_user.save!
stripe_sub = customer.subscriptions.first
else
customer = Stripe::Customer.retrieve(current_user.stripe_customer_id)
stripe_sub = customer.subscriptions.create(
plan: 'premium_plan'
)
end
current_user.subid = stripe_sub.id
current_user.subscription.save!
update_user_to_premium
flash[:success] = "Thank you for your subscription!"
redirect_to root_path
# Handle exceptions
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_subscriptions_path
end
def downgrade
customer = Stripe::Customer.retrieve(current_user.stripe_customer_id)
customer.subscriptions.retrieve(current_user.subid).delete
downgrade_user_to_standard
flash[:success] = "Sorry to see you go."
redirect_to user_path(current_user)
end
end
ApplitionController:
class ApplicationController < ActionController::Base
def update_user_to_premium
current_user.update_attributes(role: "premium")
end
def downgrade_user_to_standard
current_user.update_attributes(role: "standard")
end
end
config/initializers/stripe.rb:
Rails.configuration.stripe = {
publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
secret_key: ENV['STRIPE_SECRET_KEY']
}
# Set our app-stored secret key with Stripe
Stripe.api_key = Rails.configuration.stripe[:secret_key]
Any help will be appreciated!
Update:
Thanks for help from stacksonstacks, all I need is asserting 'subscription.user = current_user' under 'current_user.subid = stripe_sub.id', and then call subscription id with "subscription = current_user.subscription" in downgrade method. Now subscription cancelling works!
It seems current_user.subid returns nil on this line:
customer.subscriptions.retrieve(current_user.subid).delete
You assign subid for current_user but you never save the changes.
You only save the newly created subscription.
current_user.subid = stripe_sub.id
current_user.subscription.save!
If you add current_user.save! I think this will solve the problem.
Hope that helps

Checking for a successful charge using Stripe for rails

Context:
I am using Stripe checkout to accept one-time payment in rails.
I have a charges controller as shown below.
I was initially using stripe webhook to listen to charge.succeeded, but running into some issues due to the async nature of webhooks.
My I have moved the business logic to the controller.
If the customer charge is a success, then I save the customer and some other details to the db.
My question:
Is this check enough to ensure that a charge is successful ?
if charge["paid"] == true
The Stripe documentation for Stripe::Charge.create states, "
Returns a charge object if the charge succeeded. Raises an error if something goes wrong. A common source of error is an invalid or expired card, or a valid card with insufficient available balance."
My ChargesController:
class ChargesController < ApplicationController
def new
end
def create
# Amount in cents
#amount = 100
temp_job_id = cookies[:temp_job_id]
customer_email = TempJobPost.find_by(id: temp_job_id).company[:email]
customer = Stripe::Customer.create(
:email => customer_email,
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Rails Stripe customer',
:currency => 'usd',
:metadata => {"job_id"=> temp_job_id}
)
# TODO: charge.paid or charge["paid"]
if charge["paid"] == true
#Save customer to the db
end
# need to test this and refactor this using begin-->rescue--->end
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
end
Yes, that's all you need to do. If the charge succeeded, Stripe will return a Charge object, and you can check its paid parameter. If the charge failed, we'd throw an exception.
Cheers,
Larry
PS I work on Support at Stripe.

Resources