Permalink
Browse files

Rework Braintree update method

- Use combined customer/card update to eliminate unneccessary remote calls.
- Use update_existing_token option to update the default card
- Support verify_card option in update
- Include customer vault id and card tokens in update response
- Add processor response text for failed verification
  • Loading branch information...
1 parent 2fc4199 commit 815b23bbe6d1a646496fa1d875840e088024a28b @brentmc79 brentmc79 committed Apr 2, 2012
View
37 lib/active_merchant/billing/gateways/braintree_blue.rb
@@ -100,24 +100,25 @@ def update(vault_id, creditcard, options = {})
customer_update_result = commit do
braintree_credit_card = Braintree::Customer.find(vault_id).credit_cards.detect { |cc| cc.default? }
return Response.new(false, 'Braintree::NotFoundError') if braintree_credit_card.nil?
- result = Braintree::Customer.update(vault_id,
- :first_name => creditcard.first_name,
- :last_name => creditcard.last_name,
- :email => options[:email]
- )
- Response.new(result.success?, message_from_result(result),
- :braintree_customer => (customer_hash(Braintree::Customer.find(vault_id)) if result.success?)
- )
- end
- return customer_update_result unless customer_update_result.success?
- credit_card_update_result = commit do
- result = Braintree::CreditCard.update(braintree_credit_card.token,
+
+ options.merge!(:update_existing_token => braintree_credit_card.token)
+ credit_card_params = merge_credit_card_options({
+ :credit_card => {
:number => creditcard.number,
:expiration_month => creditcard.month.to_s.rjust(2, "0"),
:expiration_year => creditcard.year.to_s
+ }
+ }, options)[:credit_card]
+
+ result = Braintree::Customer.update(vault_id,
+ :first_name => creditcard.first_name,
+ :last_name => creditcard.last_name,
+ :email => options[:email],
+ :credit_card => credit_card_params
)
Response.new(result.success?, message_from_result(result),
- :braintree_customer => (customer_hash(Braintree::Customer.find(vault_id)) if result.success?)
+ :braintree_customer => (customer_hash(Braintree::Customer.find(vault_id)) if result.success?),
+ :customer_vault_id => (result.customer.id if result.success?)
)
end
end
@@ -135,7 +136,7 @@ def unstore(customer_vault_id)
def merge_credit_card_options(parameters, options)
valid_options = {}
options.each do |key, value|
- valid_options[key] = value if [:verify_card, :verification_merchant_account_id].include?(key)
+ valid_options[key] = value if [:update_existing_token, :verify_card, :verification_merchant_account_id].include?(key)
end
parameters[:credit_card] ||= {}
@@ -166,6 +167,8 @@ def commit(&block)
def message_from_result(result)
if result.success?
"OK"
+ elsif result.errors.size == 0 && result.credit_card_verification
+ "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
else
result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
end
@@ -220,15 +223,17 @@ def customer_hash(customer)
credit_cards = customer.credit_cards.map do |cc|
{
"bin" => cc.bin,
- "expiration_date" => cc.expiration_date
+ "expiration_date" => cc.expiration_date,
+ "token" => cc.token
}
end
{
"email" => customer.email,
"first_name" => customer.first_name,
"last_name" => customer.last_name,
- "credit_cards" => credit_cards
+ "credit_cards" => credit_cards,
+ "id" => customer.id
}
end
View
21 test/remote/gateways/remote_braintree_blue_test.rb
@@ -83,7 +83,7 @@ def test_failed_validate_on_store
card = credit_card('4000111111111115', :verification_value => '200')
assert response = @gateway.store(card, :verify_card => true)
assert_failure response
- assert_equal '', response.message
+ assert_equal 'Processor declined: Do Not Honor (2000)', response.message
end
def test_successful_store_with_no_validate
@@ -396,6 +396,8 @@ def test_successful_update
assert_equal "Old Last", response.params["braintree_customer"]["last_name"]
assert_equal "411111", response.params["braintree_customer"]["credit_cards"][0]["bin"]
assert_equal "09/2012", response.params["braintree_customer"]["credit_cards"][0]["expiration_date"]
+ assert_not_nil response.params["braintree_customer"]["credit_cards"][0]["token"]
+ assert_equal customer_vault_id, response.params["braintree_customer"]["id"]
assert response = @gateway.update(
customer_vault_id,
@@ -411,6 +413,8 @@ def test_successful_update
assert_equal "New Last", response.params["braintree_customer"]["last_name"]
assert_equal "510510", response.params["braintree_customer"]["credit_cards"][0]["bin"]
assert_equal "10/2014", response.params["braintree_customer"]["credit_cards"][0]["expiration_date"]
+ assert_not_nil response.params["braintree_customer"]["credit_cards"][0]["token"]
+ assert_equal customer_vault_id, response.params["braintree_customer"]["id"]
end
def test_failed_customer_update
@@ -450,6 +454,21 @@ def test_failed_credit_card_update
assert_equal 'Credit card number is invalid. (81715)', response.message
end
+ def test_failed_credit_card_update_on_verify
+ assert response = @gateway.store(credit_card('4111111111111111'))
+ assert_success response
+ assert_equal 'OK', response.message
+ assert customer_vault_id = response.params["customer_vault_id"]
+
+ assert response = @gateway.update(
+ customer_vault_id,
+ credit_card('4000111111111115'),
+ {:verify_card => true}
+ )
+ assert_failure response
+ assert_equal 'Processor declined: Do Not Honor (2000)', response.message
+ end
+
def test_customer_does_not_have_credit_card_failed_update
customer_without_credit_card = Braintree::Customer.create!
assert response = @gateway.update(customer_without_credit_card.id, credit_card('5105105105105100'))
View
27 test/unit/gateways/braintree_blue_test.rb
@@ -86,14 +86,14 @@ def test_merchant_account_id_absent_if_not_provided
end
def test_store_with_verify_card_true
- customer_attributes = {
+ customer = mock(
:credit_cards => [],
:email => 'email',
:first_name => 'John',
- :last_name => 'Smith',
- :id => "123"
- }
- result = Braintree::SuccessfulResult.new(:customer => mock(customer_attributes))
+ :last_name => 'Smith'
+ )
+ customer.stubs(:id).returns('123')
+ result = Braintree::SuccessfulResult.new(:customer => customer)
Braintree::Customer.expects(:create).with do |params|
params[:credit_card][:options].has_key?(:verify_card)
assert_equal true, params[:credit_card][:options][:verify_card]
@@ -104,14 +104,14 @@ def test_store_with_verify_card_true
end
def test_store_with_verify_card_false
- customer_attributes = {
+ customer = mock(
:credit_cards => [],
:email => 'email',
:first_name => 'John',
- :last_name => 'Smith',
- :id => "123"
- }
- result = Braintree::SuccessfulResult.new(:customer => mock(customer_attributes))
+ :last_name => 'Smith'
+ )
+ customer.stubs(:id).returns('123')
+ result = Braintree::SuccessfulResult.new(:customer => customer)
Braintree::Customer.expects(:create).with do |params|
params[:credit_card][:options].has_key?(:verify_card)
assert_equal false, params[:credit_card][:options][:verify_card]
@@ -126,8 +126,7 @@ def test_store_with_billing_address_options
:credit_cards => [],
:email => 'email',
:first_name => 'John',
- :last_name => 'Smith',
- :id => "123"
+ :last_name => 'Smith'
}
billing_address = {
:address1 => "1 E Main St",
@@ -137,7 +136,9 @@ def test_store_with_billing_address_options
:zip => "60622",
:country_name => "US"
}
- result = Braintree::SuccessfulResult.new(:customer => mock(customer_attributes))
+ customer = mock(customer_attributes)
+ customer.stubs(:id).returns('123')
+ result = Braintree::SuccessfulResult.new(:customer => customer)
Braintree::Customer.expects(:create).with do |params|
assert_not_nil params[:credit_card][:billing_address]
[:street_address, :extended_address, :locality, :region, :postal_code, :country_name].each do |billing_attribute|

0 comments on commit 815b23b

Please sign in to comment.