Gdzie i jak radzić sobie z wyjątkami Stripe?

Buduję mały proof of concept z Stripe i Ruby on Rails 3.2. Do tej pory oglądałem Railscast o tym, jak zaimplementować Stripe w aplikacji RoR i działa naprawdę dobrze.

Aplikacja została stworzona w oparciu o RailsCast # 288. Teraz moi użytkownicy mogą dodawać i edytować swoje karty kredytowe, a nawet rejestrować się na zajęcia i rozliczać swoje karty kredytowe po zakończeniu.

Teraz testowałem z licznymi testowymi kartami kredytowymi i chcę aby złapać jak najwięcej WYJĄTKÓW, gdy podniesione. Używam Stripe ' s przykład błędy w moim modelu Rejestracji, jak pokazano tutaj:

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

Ja tylko ratuję od błędów w tej chwili i nie podejmuję działań po jednym z nich i ostatecznie chciałbym zatrzymać obecną rejestrację klasy i przekierować użytkownika z błędem Flasha.

Czytałem o rescure_from ale nie jestem pewien, jaki jest najlepszy sposób na obsługę wszystkich możliwych błędów Stripe. I wiem, że nie można przekierować z modelu, jak wy eksperci poradzicie sobie z tym?

Oto mój kontroler rejestracji:

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

Dzięki za poświęcenie czasu, aby odpowiedzieć, bardzo doceniam!

Franciszek

Author: Francis Ouellet, 2013-04-05

1 answers

Czy myślałeś o umieszczeniu połączenia actually Stripe w custom validator?

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

W ten sposób można dodać błędy do obiektu za pomocą czegoś takiego jak poniżej

Logika stojąca za tym jest taka, że chcesz tylko zapisać udane transakcje jako "transakcja", więc dlaczego nie po prostu umieścić opłatę Stripe w walidatorze.

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

W ten sposób możesz poradzić sobie z błędami jak każdy inne błędy, które można uzyskać z wpisu nie zapisywania, zamiast dać pusty komunikat o błędzie, lub konieczności obsługi każdego ostatniego błędu ze 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
 10
Author: rovermicrover,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-05 15:41:42