在我的网站上,用户以相同的形式注册并提供其信用卡信息。表单使用Devise来保存用户。我需要将实际的设计代码导入控制器(一个不好的做法,我知道,但是对于Braintree,我看不到任何其他方式来包装用户并收取一笔交易)。我终于完成了所有工作,除了我遇到Braintree错误消息的问题。我刚尝试创建一个金额为2600美元的交易,它应该触发Braintree错误并显示一条消息,但是没有触发这样的错误。这是我的代码:
def create
nonce_from_the_client = params[:payment_method_nonce]
# code taken from devise
build_resource(sign_up_params)
begin
@charge = resource.charges.build
@charge.nonce = nonce_from_the_client
braintree_call = nil
@braintree_errors = nil
ActiveRecord::Base.transaction do
puts "beforer resource saved".green
resource.save!
puts "resource saved".green
puts "charge built".green
puts "before call_braintree".green
braintree_call = @charge.call_braintree!
if braintree_call.success? && !braintree_call.errors.any?
puts "braintree_call was a success".green
@charge.save
#do nothing. All good
else
puts "braintree error".red
@braintree_errors = braintree_call.errors
braintree_call.errors.each do |error|
puts "#{error.code}\n".red
puts "#{error.message}".red
end
raise "@Charge Failed"
end
end
rescue
puts "@charge #{@charge.inspect}".red
puts "@charge errors: #{@charge.errors.inspect}".red
end
yield resource if block_given?
if resource.persisted?
puts "resource persisted".green
if resource.active_for_authentication?
flash[:success] = "Welcome! You have signed up successfully."
# set_flash_message! :notice, :signed_up
sign_up(resource_name, resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
puts "not sure about this".blue
# set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
flash[:danger] = "signed_up_but_#{resource.inactive_message}"
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
puts "resource did not persist".red
clean_up_passwords resource
set_minimum_password_length
# respond_with resource
puts "NOW WE KNOW".on_red
render 'new' #not sure if this works
end
puts "resource errors are #{resource.errors.inspect}".red
end
以下是Charge的模型,其中包含上面的call_braintree方法:
class Charge < ActiveRecord::Base
belongs_to :user
attr_accessor :nonce
after_create :activate_user_account
def activate_user_account
puts "in the activate user account after_Create method".green
self.user.activate
end
def set_amount
amount = self.user.plan.amount * self.user.plan.length
puts "amount is #{amount} and is class #{amount.class}".green
return amount
end
def call_braintree!
puts "in call braintree".green
result = Braintree::Transaction.sale(
:amount => "#{self.set_amount}",
:payment_method_nonce => self.nonce,
:options => {
:submit_for_settlement => true
}
)
end
end
以下是生成的服务器日志:
Started POST "/users" for 127.0.0.1 at 2016-02-26 15:06:29 -0500
Processing by Users::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Z0jHeFqXJk6iEwdEohilVd2Io85NKoPuzUepjfSXxU0=", "user"=>{"type"=>"Presenter", "plan_id"=>"2", "organization_name"=>"", "first_name"=>"David", "last_name"=>"Applebau,", "email"=>"asfdjhfasdlk@dffadsdf.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "telephone"=>"6462343800", "group_code"=>""}, "field-fnames"=>"", "field-lnames"=>"", "payment_method_nonce"=>"815abd1c-0be5-40e4-8135-a468021c8b75"}
(0.2ms) BEGIN
beforer resource saved
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'asfdjhfasdlk@dffadsdf.com' LIMIT 1
Plan Load (0.1ms) SELECT "plans".* FROM "plans" WHERE "plans"."id" = $1 LIMIT 1 [["id", 2]]
SQL (0.2ms) INSERT INTO "users" ("created_at", "email", "encrypted_password", "first_name", "last_name", "organization_name", "plan_id", "plan_length", "plan_start_date", "plan_status", "telephone", "type", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING "id" [["created_at", "2016-02-26 20:06:29.294712"], ["email", "asfdjhfasdlk@dffadsdf.com"], ["encrypted_password", "$2a$10$jeIa3c.i73f/hBV7ne/Dfu0MAawQzoNak808zLqjjkFeJKmXt78yK"], ["first_name", "David"], ["last_name", "Applebau,"], ["organization_name", ""], ["plan_id", 2], ["plan_length", 1], ["plan_start_date", "2016-02-26 20:06:29.289691"], ["plan_status", "active"], ["telephone", "6462343800"], ["type", "Presenter"], ["updated_at", "2016-02-26 20:06:29.294712"]]
SQL (0.1ms) INSERT INTO "charges" ("created_at", "updated_at", "user_id") VALUES ($1, $2, $3) RETURNING "id" [["created_at", "2016-02-26 20:06:29.307071"], ["updated_at", "2016-02-26 20:06:29.307071"], ["user_id", 20]]
in the activate user account after_Create method
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 20]]
in the after method of the state machine
Plan Load (0.1ms) SELECT "plans".* FROM "plans" WHERE "plans"."id" = $1 LIMIT 1 [["id", 2]]
SQL (0.2ms) UPDATE "users" SET "plan_start_date" = $1, "updated_at" = $2 WHERE "users"."type" IN ('Presenter') AND "users"."id" = 20 [["plan_start_date", "2016-02-26 20:06:29.310158"], ["updated_at", "2016-02-26 20:06:29.311003"]]
resource saved
charge built
before call_braintree
in call braintree
braintree error
(0.2ms) ROLLBACK
ichabod is yolo
@charge #<Charge id: nil, user_id: 20, stripe_id: nil, created_at: "2016-02-26 20:06:29", updated_at: "2016-02-26 20:06:29">
@charge errors: #<ActiveModel::Errors:0x007ffac3f16790 @base=#<Charge id: nil, user_id: 20, stripe_id: nil, created_at: "2016-02-26 20:06:29", updated_at: "2016-02-26 20:06:29">, @messages={}>
resource did not persist
NOW WE KNOW
Rendered layouts/logged_in/_error_messages.html.erb (0.0ms)
@type is Presenter
@free_trial is
in here
Plan Load (0.3ms) SELECT "plans".* FROM "plans" WHERE "plans"."user_type" = 'Presenter' AND ("plans"."name" != 'free_trial') ORDER BY "plans"."display_order_number" ASC
Rendered layouts/logged_in/_registration_form_header.html.erb (1.7ms)
Rendered layouts/logged_in/_payment_form.html.erb (0.1ms)
Rendered layouts/logged_in/_registration_submit_button.html.erb (0.1ms)
Rendered charges/_braintree_js.html.erb (0.0ms)
Rendered devise/registrations/new.html.erb within layouts/logged_in (8.3ms)
Rendered layouts/logged_in/_navbar.html.erb (0.4ms)
resource errors are #<ActiveModel::Errors:0x007ffac3fd6ae0 @base=#<Presenter id: nil, email: "asfdjhfasdlk@dffadsdf.com", encrypted_password: "$2a$10$jeIa3c.i73f/hBV7ne/Dfu0MAawQzoNak808zLqjjkF...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2016-02-26 20:06:29", updated_at: "2016-02-26 20:06:29", confirmation_token: nil, confirmed_at: nil, confirmation_sent_at: nil, organization_id: nil, type: "Presenter", organization_name: "", organization_code: nil, identifier: nil, stripe_customer_id: nil, plan_id: 2, presenter_maximum: nil, workshop_id: nil, presentation_allowance: 2, plan_status: "active", plan_start_date: "2016-02-26 20:06:29", plan_length: 1, contact_name: nil, contact_phone: nil, first_name: "david", last_name: "applebaum", telephone: "6462343800", group_id: nil>, @messages={:plan_id=>[], :organization_name=>[], :first_name=>[], :last_name=>[], :email=>[], :password=>[], :password_confirmation=>[], :telephone=>[], :group_code=>[]}>
Completed 200 OK in 2171ms (Views: 81.0ms | ActiveRecord: 1.8ms)
我为了获得braintree错误而做的唯一不同的事情是使用2600切换call_braintree方法中的金额。
正如您在日志中看到的那样,抛出了某种类型的错误或调用没有成功,但Braintree没有提供错误。每当用户卡无法工作时,无论出于何种原因,我都需要来自braintree的错误消息来向用户显示。如何正确显示braintree错误?
答案 0 :(得分:0)
完全披露:我在Braintree工作。如果您有任何其他问题,请随时与我们的support小组联系。
仅为Braintree验证错误填充错误。处理程序错误在交易processor_response_code
在处理器级别失败的事务的适当错误处理如下所示:
if braintree_call.success? && !braintree_call.errors.any?
puts "braintree_call was a success".green
@charge.save
#do nothing. All good
elsif braintree_call.transaction
puts "Transaction processing error: #{braintree_call.transaction.status}: Response Code: #{braintree_call.transaction.processor_response_code}\n".red
raise "@Charge Failed"
else
puts "braintree error".red
@braintree_errors = braintree_call.errors
braintree_call.errors.each do |error|
puts "#{error.code}\n".red
puts "#{error.message}".red
end
raise "@Charge Failed"
end
查看我们的文档,了解有关transaction statuses和processor response codes
的更多信息