Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
swarup98 committed May 3, 2021
2 parents b58c437 + 7c4b3ae commit 5f60f25
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 29 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
* BraintreeBlue: Add support for $0 auth verification [meagabeth] #3944
* JCB: Add additional BIN ranges [dsmcclain] #3946
* vPOS: Support new gateway type [therufs] #3906
* Braintree: Add support for AVS and CVV results in $0 credit card verification transactions [meagabeth] #3951
* Braintree: Return cvv_code and avs_code in response [meagabeth] #3952
* vPOS: Stringify values [therufs] #3954
* Payeezy: Send level2 fields [dsmcclain] #3953
* Credorax: adjust logic for sending 3ds shipping address fields [dsmcclain] #3959
* Orbital: Ensure ECP always sends AVSName [jessiagee] #3963
* Orbital: Add middle name to EWSMiddleName for ECP [jessiagee] #3962
* Support Canadian Bank Accounts [naashton] #3964

== Version 1.119.0 (February 9th, 2021)
* Payment Express: support verify/validate [therufs] #3874
Expand Down
10 changes: 10 additions & 0 deletions lib/active_merchant/billing/check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ class Check < Model
# Used for Canadian bank accounts
attr_accessor :institution_number, :transit_number

# Canadian Institution Numbers
# Found here: https://en.wikipedia.org/wiki/Routing_number_(Canada)
INSTITUTION_NUMBERS = %w(
001 002 003 004 006 010 016 030 039 117 127 177 219 245 260 269 270 308
309 310 315 320 338 340 509 540 608 614 623 809 815 819 828 829 837 839
865 879 889 899
)

def name
@name ||= "#{first_name} #{last_name}".strip
end
Expand Down Expand Up @@ -67,6 +75,8 @@ def valid_routing_number?
else
false
end
when 8
true if INSTITUTION_NUMBERS.include?(routing_number[0..2].to_s)
else
false
end
Expand Down
18 changes: 17 additions & 1 deletion lib/active_merchant/billing/gateways/braintree_blue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ def verify(creditcard, options = {})
result = @braintree_gateway.verification.create(payload)
response = Response.new(result.success?, message_from_transaction_result(result), response_options(result))
response.cvv_result['message'] = ''
response.cvv_result['code'] = response.params['cvv_result']
response.avs_result['code'] = response.params['avs_result'][:code]
response
end

Expand Down Expand Up @@ -392,7 +394,11 @@ def response_params(result)

def response_options(result)
options = {}
if result.transaction
if result.credit_card_verification
options[:authorization] = result.credit_card_verification.id
options[:avs_result] = { code: avs_code_from(result.credit_card_verification) }
options[:cvv_result] = result.credit_card_verification.cvv_response_code
elsif result.transaction
options[:authorization] = result.transaction.id
options[:avs_result] = { code: avs_code_from(result.transaction) }
options[:cvv_result] = result.transaction.cvv_response_code
Expand Down Expand Up @@ -616,6 +622,7 @@ def create_transaction_parameters(money, credit_card_or_vault_id, options)
add_addresses(parameters, options)

add_descriptor(parameters, options)
add_risk_data(parameters, options)
add_travel_data(parameters, options) if options[:travel_data]
add_lodging_data(parameters, options) if options[:lodging_data]
add_channel(parameters, options)
Expand Down Expand Up @@ -676,6 +683,15 @@ def add_descriptor(parameters, options)
}
end

def add_risk_data(parameters, options)
return unless options[:risk_data]

parameters[:risk_data] = {
customer_browser: options[:risk_data][:customer_browser],
customer_ip: options[:risk_data][:customer_ip]
}
end

def add_level_2_data(parameters, options)
parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
Expand Down
20 changes: 12 additions & 8 deletions lib/active_merchant/billing/gateways/credorax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -346,14 +346,7 @@ def add_3d_secure(post, options)
post[:d6] = browser_info[:language]
post[:'3ds_browserjavaenabled'] = browser_info[:java]
post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
if (shipping_address = options[:shipping_address])
post[:'3ds_shipaddrstate'] = shipping_address[:state]
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
post[:'3ds_shipaddrcity'] = shipping_address[:city]
end
add_complete_shipping_address(post, options[:shipping_address]) if options[:shipping_address]
elsif options[:three_d_secure]
add_normalized_3d_secure_2_data(post, options)
end
Expand All @@ -373,6 +366,17 @@ def add_3d_secure_1_data(post, options)
end
end

def add_complete_shipping_address(post, shipping_address)
return if shipping_address.values.any?(&:blank?)

post[:'3ds_shipaddrstate'] = shipping_address[:state]
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
post[:'3ds_shipaddrcity'] = shipping_address[:city]
end

def add_normalized_3d_secure_2_data(post, options)
three_d_secure_options = options[:three_d_secure]

Expand Down
25 changes: 14 additions & 11 deletions lib/active_merchant/billing/gateways/orbital.rb
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def purchase(money, payment_source, options = {})
add_managed_billing(xml, options)
end
end

commit(order, :purchase, options[:retry_logic], options[:trace_number])
end

Expand Down Expand Up @@ -449,15 +450,7 @@ def add_card_indicators(xml, options)
end

def add_address(xml, payment_source, options)
address = (options[:billing_address] || options[:address])

# always send the AVSname if the payment is a check regardless
# if there's an address or not
if payment_source.is_a?(Check) && address.blank?
xml.tag! :AVSname, (payment_source&.name ? payment_source.name[0..29] : nil)

return
end
address = get_address(options)

unless address.blank?
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s) || empty?(address[:country])
Expand Down Expand Up @@ -497,7 +490,9 @@ def add_destination_address(xml, address)

# For Profile requests
def add_customer_address(xml, options)
if (address = (options[:billing_address] || options[:address]))
address = get_address(options)

unless address.blank?
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s)

xml.tag! :CustomerAddress1, byte_limit(format_address_field(address[:address1]), 30)
Expand Down Expand Up @@ -537,6 +532,8 @@ def add_echeck(xml, check, options = {})
else
xml.tag! :BankPmtDelv, 'B'
end

xml.tag! :AVSname, (check&.name ? check.name[0..29] : nil) if get_address(options).blank?
end
end

Expand Down Expand Up @@ -669,7 +666,9 @@ def add_managed_billing(xml, options)
end

def add_ews_details(xml, payment_source, parameters = {})
xml.tag! :EWSFirstName, payment_source.first_name
split_name = payment_source.first_name.split if payment_source.first_name
xml.tag! :EWSFirstName, split_name[0]
xml.tag! :EWSMiddleName, split_name[1..-1].join(' ')
xml.tag! :EWSLastName, payment_source.last_name
xml.tag! :EWSBusinessName, parameters[:company] if payment_source.first_name.empty? && payment_source.last_name.empty?

Expand Down Expand Up @@ -974,6 +973,10 @@ def salem_mid?
@options[:merchant_id].length == 6
end

def get_address(options)
options[:billing_address] || options[:address]
end

# The valid characters include:
#
# 1. all letters and digits
Expand Down
9 changes: 9 additions & 0 deletions lib/active_merchant/billing/gateways/payeezy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def purchase(amount, payment_method, options = {})
add_address(params, options)
add_amount(params, amount, options)
add_soft_descriptors(params, options)
add_level2_data(params, options)
add_stored_credentials(params, options)

commit(params, options)
Expand All @@ -53,6 +54,7 @@ def authorize(amount, payment_method, options = {})
add_address(params, options)
add_amount(params, amount, options)
add_soft_descriptors(params, options)
add_level2_data(params, options)
add_stored_credentials(params, options)

commit(params, options)
Expand Down Expand Up @@ -246,6 +248,13 @@ def add_soft_descriptors(params, options)
params[:soft_descriptors] = options[:soft_descriptors] if options[:soft_descriptors]
end

def add_level2_data(params, options)
return unless level2_data = options[:level2]

params[:level2] = {}
params[:level2][:customer_ref] = level2_data[:customer_ref]
end

def add_stored_credentials(params, options)
if options[:sequence] || options[:stored_credential]
params[:stored_credentials] = {}
Expand Down
6 changes: 3 additions & 3 deletions lib/active_merchant/billing/gateways/vpos.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ def purchase(money, payment, options = {})

post = {}
post[:token] = token
post[:commerce] = commerce
post[:commerce_branch] = commerce_branch
post[:commerce] = commerce.to_s
post[:commerce_branch] = commerce_branch.to_s
post[:shop_process_id] = @shop_process_id
post[:number_of_payments] = options[:number_of_payments] || 1
post[:recursive] = options[:recursive] || false
Expand Down Expand Up @@ -106,7 +106,7 @@ def add_card_data(post, payment)
end

def add_customer_data(post, options)
post[:additional_data] = options[:additional_data] # must be passed even if empty
post[:additional_data] = options[:additional_data] || '' # must be passed even if empty
end

def parse(body)
Expand Down
17 changes: 15 additions & 2 deletions test/remote/gateways/remote_braintree_blue_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ def test_successful_purchase_with_level_2_and_3_data
assert_equal '1000 Approved', response.message
end

def test_successful_purchase_sending_risk_data
options = @options.merge(
risk_data: {
customer_browser: 'User-Agent Header',
customer_ip: '127.0.0.1'
}
)
assert response = @gateway.purchase(@amount, @credit_card, options)
assert_success response
end

def test_successful_verify
assert response = @gateway.verify(@credit_card, @options)
assert_success response
Expand All @@ -184,6 +195,8 @@ def test_successful_credit_card_verification
assert response = @gateway.verify(card, @options.merge({ allow_card_verification: true }))
assert_success response
assert_match 'OK', response.message
assert_equal 'M', response.cvv_result['code']
assert_equal 'P', response.avs_result['code']
end

def test_successful_verify_with_device_data
Expand All @@ -197,7 +210,7 @@ def test_successful_verify_with_device_data
assert transaction['risk_data']['id']
assert_equal 'Approve', transaction['risk_data']['decision']
assert_equal false, transaction['risk_data']['device_data_captured']
assert_equal 'kount', transaction['risk_data']['fraud_service_provider']
assert_equal 'fraud_protection', transaction['risk_data']['fraud_service_provider']
end

def test_successful_validate_on_store
Expand Down Expand Up @@ -449,7 +462,7 @@ def test_successful_purchase_with_device_data
assert transaction['risk_data']['id']
assert_equal 'Approve', transaction['risk_data']['decision']
assert_equal false, transaction['risk_data']['device_data_captured']
assert_equal 'kount', transaction['risk_data']['fraud_service_provider']
assert_equal 'fraud_protection', transaction['risk_data']['fraud_service_provider']
end

def test_purchase_with_store_using_random_customer_id
Expand Down
6 changes: 6 additions & 0 deletions test/remote/gateways/remote_payeezy_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ def test_successful_purchase_with_soft_descriptors
assert_success response
end

def test_successful_purchase_with_customer_ref
assert response = @gateway.purchase(@amount, @credit_card, @options.merge(level2: { customer_ref: 'An important customer' }))
assert_match(/Transaction Normal/, response.message)
assert_success response
end

def test_successful_purchase_with_stored_credentials
assert response = @gateway.purchase(@amount, @credit_card, @options.merge(@options_stored_credentials))
assert_match(/Transaction Normal/, response.message)
Expand Down
11 changes: 11 additions & 0 deletions test/unit/check_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class CheckTest < Test::Unit::TestCase
VALID_ABA = '111000025'
INVALID_ABA = '999999999'
MALFORMED_ABA = 'I like fish'
VALID_CBA = '00194611'

ACCOUNT_NUMBER = '123456789012'

Expand Down Expand Up @@ -78,4 +79,14 @@ def test_account_type
c.account_type = nil
assert !c.validate[:account_type]
end

def test_valid_canada_routing_number
assert_valid Check.new(
name: 'Tim Horton',
routing_number: VALID_CBA,
account_number: ACCOUNT_NUMBER,
account_holder_type: 'personal',
account_type: 'checking'
)
end
end
16 changes: 14 additions & 2 deletions test/unit/gateways/braintree_blue_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def test_verify_bad_credentials

def test_zero_dollar_verification_transaction
Braintree::CreditCardVerificationGateway.any_instance.expects(:create).
returns(braintree_result)
returns(braintree_result(cvv_response_code: 'M', avs_error_response_code: 'P'))

card = credit_card('4111111111111111')
options = {
Expand All @@ -141,7 +141,8 @@ def test_zero_dollar_verification_transaction
response = @gateway.verify(card, options)
assert_success response
assert_equal 'transaction_id', response.params['authorization']
assert_equal true, response.params['test']
assert_equal 'M', response.cvv_result['code']
assert_equal 'P', response.avs_result['code']
end

def test_user_agent_includes_activemerchant_version
Expand Down Expand Up @@ -194,6 +195,17 @@ def test_service_fee_amount_can_be_specified
@gateway.authorize(100, credit_card('41111111111111111111'), service_fee_amount: '2.31')
end

def test_risk_data_can_be_specified
risk_data = {
customer_browser: 'User-Agent Header',
customer_ip: '127.0.0.1'
}
Braintree::TransactionGateway.any_instance.expects(:sale).
with(has_entries(risk_data: risk_data)).returns(braintree_result)

@gateway.authorize(100, credit_card('4111111111111111'), risk_data: risk_data)
end

def test_hold_in_escrow_can_be_specified
Braintree::TransactionGateway.any_instance.expects(:sale).with do |params|
(params[:options][:hold_in_escrow] == true)
Expand Down
30 changes: 28 additions & 2 deletions test/unit/gateways/credorax_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def setup
shopper_email: 'john.smith@test.com',
shopper_ip: '77.110.174.153',
shopper_reference: 'John Smith',
billing_address: address(),
shipping_address: address(),
billing_address: address,
shipping_address: address,
order_id: '123',
execute_threed: true,
three_ds_initiate: '03',
Expand Down Expand Up @@ -284,6 +284,32 @@ def test_adds_3d2_secure_fields
assert response.test?
end

def test_does_not_add_incomplete_3d2_shipping_address
incomplete_shipping_address = {
state: 'ON',
zip: 'K1C2N6',
address1: '456 My Street',
address2: '',
country: 'CA',
city: 'Ottawa'
}
options_with_3ds = @normalized_3ds_2_options.merge(shipping_address: incomplete_shipping_address)

response = stub_comms do
@gateway.purchase(@amount, @credit_card, options_with_3ds)
end.check_request do |_endpoint, data, _headers|
assert_match(/3ds_initiate=03/, data)
assert_not_match(/3ds_shipaddrstate=/, data)
assert_not_match(/3ds_shipaddrpostcode=/, data)
assert_not_match(/3ds_shipaddrline1=/, data)
assert_not_match(/3ds_shipaddrline2=/, data)
assert_not_match(/3ds_shipaddrcountry=/, data)
assert_not_match(/3ds_shipaddrcity=/, data)
end.respond_with(successful_purchase_response)
assert_success response
assert response.test?
end

def test_adds_correct_3ds_browsercolordepth_when_color_depth_is_30
@normalized_3ds_2_options[:three_ds_2][:browser_info][:depth] = 30

Expand Down
Loading

0 comments on commit 5f60f25

Please sign in to comment.