From 44c2c5eef93a62dd32002fc025a3d0ed2998f782 Mon Sep 17 00:00:00 2001 From: Gregor MacDougall Date: Wed, 6 Jul 2016 15:48:16 -0400 Subject: [PATCH] Add config to disable ship address verification Braintree supports address verification if an address is present, however, this can sometimes lead to addresses being declined because they don't match the address on file with the PayPal account or credit card. As some people may wish to disable this, I have added this configuration to be able to disable sending the adderss to Braintree. --- .../solidus/gateway/braintree_gateway.rb | 11 +- .../solidus/gateway/braintree_gateway_spec.rb | 136 ++++++++++++------ 2 files changed, 101 insertions(+), 46 deletions(-) diff --git a/app/models/solidus/gateway/braintree_gateway.rb b/app/models/solidus/gateway/braintree_gateway.rb index 8ddf7cad..6bf7b7ff 100644 --- a/app/models/solidus/gateway/braintree_gateway.rb +++ b/app/models/solidus/gateway/braintree_gateway.rb @@ -7,6 +7,7 @@ class Gateway::BraintreeGateway < ::Spree::Gateway preference :public_key, :string preference :private_key, :string preference :always_send_bill_address, :boolean, default: false + preference :transmit_shipping_address, :boolean, default: true CARD_TYPE_MAPPING = { 'American Express' => 'american_express', @@ -254,7 +255,9 @@ def transaction_authorize_or_purchase_params(cents, creditcard, options = {}) params[:options] ||= {} params[:amount] = amount(cents) params[:channel] ||= "Solidus" - params[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address] + if (options[:shipping_address] && preferred_transmit_shipping_address) + params[:shipping] = map_address(options[:shipping_address]) + end if options[:payment_method_nonce] params[:payment_method_nonce] = options[:payment_method_nonce] @@ -264,8 +267,10 @@ def transaction_authorize_or_purchase_params(cents, creditcard, options = {}) # Send the bill address if we're using a nonce (i.e. doing a one-time # payment) or if we're configured to always send the bill address - if options[:payment_method_nonce] || preferred_always_send_bill_address - params[:billing] = map_address(options[:billing_address]) if options[:billing_address] + if ( + options[:payment_method_nonce] || preferred_always_send_bill_address + ) && options[:billing_address] + params[:billing] = map_address(options[:billing_address]) end # if has profile, set the customer_id to the profile_id and delete the customer key diff --git a/spec/solidus/gateway/braintree_gateway_spec.rb b/spec/solidus/gateway/braintree_gateway_spec.rb index 78b551bf..058287e1 100644 --- a/spec/solidus/gateway/braintree_gateway_spec.rb +++ b/spec/solidus/gateway/braintree_gateway_spec.rb @@ -61,32 +61,57 @@ end context 'payment has associated device_data' do - it 'sends it to Braintree' do - payment = FactoryGirl.build(:payment, - order: FactoryGirl.create(:order, - user: user, - braintree_device_data: device_data), - source: FactoryGirl.create(:credit_card, - name: "Card Holder", - user: user), + let(:payment) do + FactoryGirl.build( + :payment, + order: FactoryGirl.create( + :order, + user: user, + braintree_device_data: device_data + ), + source: FactoryGirl.create( + :credit_card, + name: "Card Holder", + user: user + ), payment_method: payment_method, - payment_method_nonce: nonce) - address = (payment.source.address || payment.order.bill_address).try(:active_merchant_hash) + payment_method_nonce: nonce + ) + end - expected_params = { + let(:address) do + ( + payment.source.address || payment.order.bill_address + ).try(:active_merchant_hash) + end + + let(:expected_params) do + { first_name: payment.source.first_name, last_name: payment.source.last_name, email: user.email, credit_card: { + billing_address: { + first_name: "John", + last_name: "Doe", + street_address: "10 Lovely Street", + extended_address: "Northwest", + locality: "Herndon", + region: "AL", + country_code_alpha2: "US", + postal_code: address[:zip] + }, cardholder_name: payment.source.name, payment_method_nonce: payment.payment_method_nonce, - billing_address: payment_method.send(:map_address, address), options: { verify_card: true, }, }, device_data: device_data } + end + + it 'sends it to Braintree' do expect_any_instance_of(::Braintree::CustomerGateway).to receive(:create).with(expected_params).and_call_original payment_method.create_profile(payment) end @@ -493,11 +518,12 @@ context 'when preferred_always_send_bill_address is true' do before do payment_method.update!(preferred_always_send_bill_address: true) + allow(payment_method).to receive(:handle_result) end - it 'sends a bill address' do - expected_params = { - billing: { + let(:expected_params) do + { + billing: { first_name: bill_address.first_name, last_name: bill_address.last_name, street_address: bill_address.address1, @@ -513,9 +539,13 @@ amount: "5.00", channel: "Solidus" } + end + + it 'sends a bill address' do + expect_any_instance_of( + ::Braintree::TransactionGateway + ).to receive(:sale).with(expected_params) - allow(payment_method).to receive(:handle_result) - expect_any_instance_of(::Braintree::TransactionGateway).to receive(:sale).with(expected_params) payment_method.authorize(500, creditcard, options) end end @@ -544,7 +574,11 @@ end context "with billing or shipping address" do - before { creditcard.update_attributes(gateway_customer_profile_id: 5) } + before do + creditcard.update_attributes(gateway_customer_profile_id: 5) + expect(payment_method).to receive(:handle_result) + end + let(:options) { { customer_id: user.id, payment_method_nonce: nonce, @@ -554,38 +588,54 @@ customer: user.email } } - it "should send billing and shipping address" do - expected_params = { + let(:expected_address) do + { + first_name: address.first_name, + last_name: address.last_name, + street_address: address.address1, + extended_address: address.address2, + locality: address.city, + region: address.state_text, + country_code_alpha2: address.country.iso, + postal_code: address.zipcode, + } + end + + let(:expected_params) do + { + billing: expected_address, customer_id: creditcard.gateway_customer_profile_id, options: {}, amount: "5.00", - shipping: { - first_name: address.first_name, - last_name: address.last_name, - street_address: address.address1, - extended_address: address.address2, - locality: address.city, - region: address.state_text, - country_code_alpha2: address.country.iso, - postal_code: address.zipcode, - }, - billing: { - first_name: address.first_name, - last_name: address.last_name, - street_address: address.address1, - extended_address: address.address2, - locality: address.city, - region: address.state_text, - country_code_alpha2: address.country.iso, - postal_code: address.zipcode, - }, payment_method_nonce: nonce, channel: "Solidus" } + end - expect(payment_method).to receive(:handle_result) - expect_any_instance_of(::Braintree::TransactionGateway).to receive(:sale).with(expected_params) - payment_method.authorize(500, creditcard, options) + context 'when transmit_shipping_address is true' do + let(:expected_params) do + super().tap do |params| + params[:shipping] = expected_address + end + end + + it "should send billing and shipping address" do + expect_any_instance_of( + ::Braintree::TransactionGateway + ).to receive(:sale).with(expected_params) + payment_method.authorize(500, creditcard, options) + end + end + + context 'when transmit_shipping_address is false' do + before { payment_method.preferred_transmit_shipping_address = false } + + it "should only send billing address" do + expect_any_instance_of( + ::Braintree::TransactionGateway + ).to receive(:sale).with(expected_params) + payment_method.authorize(500, creditcard, options) + end end end end