9

Tôi đang xây dựng một bằng chứng nhỏ về khái niệm với Stripe và Ruby on Rails 3.2. Cho đến nay tôi đã xem Railscast về cách triển khai Stripe trong một ứng dụng RoR và nó hoạt động rất tốt.Vị trí và cách xử lý ngoại lệ của Stripe?

Tôi đã tạo ứng dụng của mình bằng cách theo dõi RailsCast #288 Billing with Stripe. Bây giờ người dùng của tôi có thể thêm và chỉnh sửa thẻ tín dụng của họ và thậm chí đăng ký vào các lớp học và thẻ tín dụng của họ được lập hóa đơn sau khi hoàn thành.

Bây giờ tôi đã thử nghiệm với rất nhiều số test credit cards của Stripe và tôi muốn nắm bắt được nhiều ngoại lệ khi được nêu ra. Tôi đang sử dụng example lỗi sọc trong mô hình đăng ký của tôi như hiển thị ở đây:

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 

Tôi chỉ đơn thuần là giải cứu khỏi những lỗi ngay bây giờ và không thực sự hành động sau một được nâng lên và cuối cùng tôi muốn ngăn chặn các lớp hiện tại đăng ký xảy ra và chuyển hướng người dùng bằng lỗi flash.

Tôi đã đọc khoảng rescure_from nhưng tôi không chắc chắn cách tốt nhất để xử lý tất cả các lỗi Stripe có thể là gì. Tôi biết không thể chuyển hướng từ mô hình, các chuyên gia của bạn sẽ xử lý như thế nào?

Dưới đây là bộ điều khiển Đăng ký doanh nghiệp của tôi:

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 

Cảm ơn đã dành thời gian trả lời, nhiều đánh giá cao!

Francis

Trả lời

10

Bạn đã nghĩ đến việc đưa các cuộc gọi thực sự sọc trong một validator tùy chỉnh?

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

Bằng cách đó bạn có thể thêm lỗi đến đối tượng với một cái gì đó như sau

Logic đằng sau này là bạn chỉ muốn lưu các giao dịch thành công là 'giao dịch' anyway vì vậy tại sao không chỉ cần đặt phí Stripe trong trình xác thực.

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 

Bằng cách này bạn có thể xử lý các lỗi như bất kỳ lỗi nào khác bạn nhận được từ mục nhập không lưu, thay vì gửi thông báo lỗi trống hoặc phải xử lý mọi lỗi cuối cùng từ 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

Cảm ơn bạn đã nhập, tôi chưa bao giờ nghe nói về custom_validator trước đây (chỉ mới bắt đầu với đường ray). Vì vậy, nếu tôi hiểu chính xác, tôi nên đặt toàn bộ logic thanh toán của Stripe vào một phương thức trong mô hình Đăng ký của tôi? Điều gì xảy ra với bộ điều khiển đăng ký? Làm cách nào để chuyển hướng người dùng bằng lỗi flash? Xin lỗi cho nhiều câu hỏi, vẫn còn nhầm lẫn :) –

+1

Cập nhật câu trả lời của nó không chính xác 100% nhưng thường là ý tưởng – rovermicrover

+0

Tôi nghĩ rằng tôi đã nhận nó, mỗi khi một mô hình đăng ký được lưu vào cơ sở dữ liệu, xác nhận: card_validation sẽ được gọi (một chút giống như bộ lọc trước) và chỉ lưu giao dịch/thẻ hợp lệ. Cảm ơn bạn đã nhập !!! –