9

Je construis une petite preuve de concept avec Stripe et Ruby on Rails 3.2. Jusqu'à présent, j'ai regardé le Railscast sur la façon d'implémenter Stripe dans une application RoR et ça marche très bien. J'ai construit mon application en suivant RailsCast #288 Billing with Stripe. Maintenant, mes utilisateurs peuvent ajouter et modifier leurs cartes de crédit et même s'inscrire à des cours et avoir leur carte de crédit facturée à la fin.Où et comment gérer les exceptions Stripe?

Maintenant, j'ai testé avec les nombreux test credit cards de Stripe et je veux attraper autant d'exceptions lorsqu'il est soulevé. J'utilise example erreurs de rayure dans mon modèle d'inscription comme indiqué ici:

class Registration < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :session 

    attr_accessible :session_id, :user_id, :session, :user, :stripe_payment_id 
    validates :user_id, :uniqueness => {:scope => :session_id} 

    def save_with_payment(user, stripe_card_token) 
    if valid? 
     if user.stripe_customer_id.present? 
     charge = Stripe::Charge.create(
      :customer => user.stripe_customer_id, 
      :amount => self.session.price.to_i * 100, 
      :description => "Registration for #{self.session.name} (Id:#{self.session.id})", 
      :currency => 'cad' 
     ) 
     else 
     customer = Stripe::Customer.create(
      :email => user.email, 
      :card => stripe_card_token, 
      :description => user.name 
     ) 
     charge = Stripe::Charge.create(
      :customer => customer.id, 
      :amount => self.session.price.to_i * 100, 
      :description => "Registration for #{self.session.name} (Id:#{self.session.id})", 
      :currency => 'cad' 
     ) 
     user.update_attribute(:stripe_customer_id, customer.id) 
     end 
     self.stripe_payment_id = charge.id 
     save! 
    end 
    rescue Stripe::CardError => e 
    body = e.json_body 
    err = body[:error] 
    logger.debug "Status is: #{e.http_status}" 
    logger.debug "Type is: #{err[:type]}" 
    logger.debug "Code is: #{err[:code]}" 
    logger.debug "Param is: #{err[:param]}" 
    logger.debug "Message is: #{err[:message]}" 
    rescue Stripe::InvalidRequestError => e 
    # Invalid parameters were supplied to Stripe's API 
    rescue Stripe::AuthenticationError => e 
    # Authentication with Stripe's API failed 
    # (maybe you changed API keys recently) 
    rescue Stripe::APIConnectionError => e 
    # Network communication with Stripe failed 
    rescue Stripe::StripeError => e 
    # Display a very generic error to the user, and maybe send 
    # yourself an email 
    rescue => e 
    # Something else happened, completely unrelated to Stripe 
    end 
end 

Je suis simplement sauvetage d'erreurs en ce moment et ne pas prendre vraiment l'action après un être élevé et, finalement, je voudrais arrêter la classe actuelle l'enregistrement de se produire et rediriger un utilisateur avec une erreur flash.

J'ai lu environ rescure_from mais je ne suis pas sûr de la meilleure façon de gérer toutes les erreurs possibles de Stripe. Je sais que je ne peux pas rediriger à partir du modèle, comment les experts pourraient gérer cela?

Voici mon contrôleur d'enregistrement:

class Classroom::RegistrationsController < ApplicationController 
    before_filter :authenticate_user! 

    def new 
    if params[:session_id] 
     @session = Session.find(params[:session_id]) 
     @registration = Registration.new(user: current_user, session: @session) 
    else 
     flash[:error] = "Course session is required" 
    end 

    rescue ActiveRecord::RecordNotFound 
     render file: 'public/404', status: :not_found 

    end 

    def create 
    if params[:session_id] 
     @session = Session.find(params[:session_id]) 
     @registration = Registration.new(user: current_user, session: @session) 
     if @registration.save_with_payment(current_user, params[:stripe_card_token]) 
     flash[:notice] = "Course registration saved with success." 
     logger.debug "Course registration saved with success." 
     mixpanel.track 'Registered to a session', { :distinct_id => current_user.id, 
              :id => @session.id, 
              'Name' => @session.name, 
              'Description' => @session.description, 
              'Course' => @session.course.name 
     } 
     mixpanel.increment current_user.id, { :'Sessions Registered' => 1} 
     mixpanel.track_charge(current_user.id, @session.price.to_i) 
     else 
     flash[:error] = "There was a problem saving the registration." 
     logger.debug "There was a problem saving the registration." 
     end 
     redirect_to root_path 
    else 
     flash[:error] = "Session required." 
     redirect_to root_path 
    end 
    end 

end 

Merci d'avoir pris le temps de répondre, très apprécié!

Francis

Répondre

10

Avez-vous pensé à mettre l'appel en fait Stripe dans un validateur personnalisé?

http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validate

De cette façon, vous pouvez ajouter des erreurs à l'objet avec quelque chose comme le

suivant la logique derrière cela est que vous souhaitez enregistrer des transactions réussies comme « transaction » de toute façon, alors pourquoi pas mettre la charge de bande dans le validateur.

validate :card_validation 

def card_validation 

    begin 
     charge = Stripe::Charge.create(
      :customer => user.stripe_customer_id, 
      :amount => self.session.price.to_i * 100, 
      :description => "Registration for #{self.session.name} (Id:#{self.session.id})", 
      :currency => 'cad' 
     ) 
     etc etc 
    rescue => e 
     errors.add(:credit_card, e.message) 
     #Then you might have a model to log the transaction error. 
     Error.create(charge, customer) 
    end 

end 

De cette façon, vous pouvez gérer les erreurs comme toute autre erreur que vous obtiendrez d'une entrée n'épargnent pas, au lieu de donner un message d'erreur en blanc, ou d'avoir à gérer toutes les erreurs de dernière Stripe.

class Classroom::RegistrationsController < ApplicationController 
    before_filter :authenticate_user! 

    def create 
    if params[:session_id] 
     @session = Session.find(params[:session_id]) 

     params[:registration][:user] = current_user 
     params[:registration][:session] = @session 
     params[:registration][:stripe_card_token] = params[:stripe_card_token] 

     @registration = Registration.new(params[:registration]) 
     respond_with(@registration) do |format| 
     if @registration.save 
      format.html {redirect_to root_path, :notice => "SOMETHING HERE TO TELL THEM SUC"} 
     else 
      format.html {render} 
     end 
     end 
    else 
     respond_with do |format| 
     format.html {redirect_to root_path, :error => "SOMETHING HERE TO TELL THEM GET SESSION"} 
     end 
    end 
    end 

end 
+0

Merci pour votre contribution, je n'avais jamais entendu parler de custom_validator avant (juste commencé avec des rails). Donc, si je comprends bien, je devrais mettre toute la logique de facturation Stripe dans une méthode dans mon modèle d'enregistrement? Que se passe-t-il avec le contrôleur d'inscription alors? Comment puis-je rediriger un utilisateur avec une erreur de flash? Désolé pour les nombreuses questions, encore confus :) –

+1

Mis à jour répondre non pas 100% exact mais généralement l'idée – rovermicrover

+0

Je pense que je l'ai eu, chaque fois qu'un modèle d'enregistrement est enregistré dans la base de données, la validation: card_validation sera appelée (un peu comme un filtre avant) et seulement enregistrer des transactions/cartes valides. Merci pour votre contribution !!! –

Questions connexes