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
Related
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
I am integrating Stripe with Devise. I want to sign a user up with stripe and store that Stripe ID before the user is saved. The method is completing before the API call return the Customer hash. How can I fix this?
class User < ActiveRecord::Base
validates_presence_of :stripe_id
before_validation :create_stripe_customer
def create_stripe_customer
customer = Stripe::Customer.create(
:email => email,
:card => stripe_card_token
)
self.stripe_id = customer.id
end
end
When I inspect the User, stripe_id is nil, and validation fails.
The best way to achieve this is to wrap it with a protective block using Active Record Transaction.
Transactions are protective blocks where SQL statements are only permanent if they can all succeed as one atomic action.
begin
#user = User.new(strong_params)
User.transaction do
#user.save!
customer = Stripe::Customer.create(
:email => email,
:card => stripe_card_token
)
#user.update_attributes!(stripe_id: customer.id)
end
rescue Exception => ex
flash[:danger] = "#{ex}"
render 'new'
end
This will enforce that the statement will be executed together or not at all.
so I just noticed I had a small problem. I'm using Stripe as my payment processor, and what happened was quite simple. I had a bug in my code which didn't allow me to save the customer_id_token and change a boolean called subscription active.
However the payment still went through (confirmed in stripe logs). Thus it's obvious I don't have proper validations in place as this should never happen. Here's what my code looks like now:
def create
customer = Stripe::Customer.create(
:email => current_user.email,
:plan => params[:plan_id],
:card => params[:stripeToken]
)
current_user.update_attributes!(
:stripe_customer_token => customer.id,
:subscription_active => true,
:plan_id => params[:plan_id]
)
redirect_to root_url, notice: 'Successfully subscribed'
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
I can see that they are obviously not really connected with one another, and my question is how can I turn this into something that if the customer_token is not saved it won't go through with the payment either?
Okay,
I'm going to take a shot at this, problem is I do not know how Stripe works, so I cannot guarantee this to work.
I just want to demonstrate the usage of transactions:
def create
ActiveRecord::Base.transaction do
customer = Stripe::Customer.create(
email: current_user.email,
plan: params[:plan_id],
card: params[:stripeToken]
)
current_user.update_attributes!(
stripe_customer_token: customer.id,
subscription_active: true,
plan_id: params[:plan_id]
)
end
redirect_to root_url, notice: 'Successfully subscribed'
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
What I would definitely add to your current_user model, is a validation to check that the token cannot be null:
class User < ActiveRecord::Base
validates :stripe_customer_token, presence: true
end
That way the update fails when the token is not provided, rolling back the transaction. Although with this it should also work if the first call fails.
However this will only work if this Stripe::Customer supports transactions. I do not know or gurantee this to be the solution.
If the Customer call still goes through and does not validate whether the payment is valid, then there's not much you can do.
I'm using Active Merchant to try to implement recurring payments in the PaypalExpressCheckout module, but I keep on getting this error:
"message"=>"The token is invalid", "error_codes"=>"11502"
The token is being properly returned and set and now I'm speculating the problem maybe because the Active Merchant gem was not written for PaypalExpress to work with recurring payments, but after looking at the documentation there are methods included from the PaypalRecurringApi that can be used in the PaypalExpress module.
This is the relevant code that is causing the problem.
In my paypal_subscriptions_controller.rb:
def create
#subscription = PaypalSubscription.new(subscription_params)
if #subscription.save
if #subscription.subscribe_with_paypal
render "success"
else
render "failure"
end
else
render :new
end
end
private
def subscription_params
params.require(:paypal_subscription).permit(:express_token,:payer_id,:email,:first_name,:last_name,:amount,:plan_id)
end
And the relevant code in my model PaypalSubscription.rb:
def express_token=(token)
write_attribute(:express_token, token)
if new_record? && !token.blank?
details = EXPRESS_GATEWAY.details_for(token)
self.email = details.params["email"]
self.payer_id = details.payer_id
self.profile_id = details.params["profile_id"]
self.first_name = details.params["first_name"]
self.last_name = details.params["last_name"]
self.amount = details.params["amount"]
end
end
def subscribe_with_paypal
response = process_purchase
Rails.logger.info response.inspect
response.success?
end
def process_purchase
EXPRESS_GATEWAY.recurring(amount, nil,{
:ip => ip_address,
:token => express_token,
:payer_id => payer_id,
:period => "Month",
:frequency => 3,
:start_date => Time.now,
:description => "Checking recurring auto-renewal"
})
end
If anyone could help me on this on that'd be great! Thanks
I use Authlogic for authentication users + Omniauth for social authentication.
After creating new account for user, who signed up with Facebook, I want to set up his role in the system.
user model
def self.create_user_from_facebook(auth_hash)
a = self.create!({
:facebook_uid => auth_hash["uid"],
...,
:crypted_password => "facebook",
:password_salt => "facebook",
:persistence_token => "facebook",
:provider => auth_hash["provider"]
})
puts a.errors.inspect #returns no errors, record is successfully saved
puts a.inspect # returns: last_request_at: "2012-10-01 08:12:51"
Assignment.create(:user_id => user.id, :role_id => 2)
end
And when I try to add new record into assignments table this way, I get the error
undefined method `last_request_at' for #<Assignment:0x0000012a1539e0>
The column last_request_at is in the table users.
How does the column last_request_at from the table users relate with the table assignments? (with only these two columns: role_id, user_id)?
**EDIT** another information:
class UserOauthController < ApplicationController
def create
#current_user = User.find_or_create_from_oauth(auth_hash)
if current_user
UserSession.create(current_user, true)
flash[:success] = 'Successfully logged in.'
redirect_to root_url
else
flash[:warning] = 'Authorization ERROR! Please, try it again.'
redirect_to root_url
end
end
end
class User < ActiveRecord::Base
attr_accessible list of atteibutes
acts_as_authentic do |c|
authlogic set up
end
...validations...
def self.find_or_create_from_oauth(auth_hash)
provider = auth_hash["provider"]
uid = auth_hash["uid"].to_s
case provider
when 'facebook'
if user = self.where('email = ? and provider = ?', auth_hash["info"]["email"], provider).first
return user
elsif user = self.find_by_facebook_uid(uid)
return user
else
return self.create_user_from_facebook(auth_hash)
end
end
def self.create_user_from_facebook(auth_hash)
a = self.create!({
:facebook_uid => auth_hash["uid"],
...,
:crypted_password => "facebook",
:password_salt => "facebook",
:persistence_token => "facebook",
:provider => auth_hash["provider"]
})
puts a.errors.inspect
puts a.inspect
a.assignments.create(:role_id => MEMBER)
end
end
How can I fix it?