Skip to content

Commit

Permalink
Checkout V2: Update Authorization to include Bearer for secret_key
Browse files Browse the repository at this point in the history
Start sending requests using http Auth:Bearer

Spreedly reference:
[ECS-3487](https://spreedly.atlassian.net/browse/ECS-3487)

Unit:
66 tests, 403 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
2821.48 tests/s, 17228.11 assertions/s

Remote:
103 tests, 254 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
0.63 tests/s, 1.56 assertions/s
  • Loading branch information
Luis Urrea committed Apr 26, 2024
1 parent e8d04a1 commit 3099951
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 30 deletions.
18 changes: 12 additions & 6 deletions lib/active_merchant/billing/gateways/checkout_v2.rb
Expand Up @@ -16,6 +16,8 @@ class CheckoutV2Gateway < Gateway
LIVE_ACCESS_TOKEN_URL = 'https://access.checkout.com/connect/token'
TEST_ACCESS_TOKEN_URL = 'https://access.sandbox.checkout.com/connect/token'

BASIC_SECRET_KEY_FORMAT = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i

def initialize(options = {})
options.has_key?(:secret_key) ? requires!(options, :secret_key) : requires!(options, :client_id, :client_secret)

Expand Down Expand Up @@ -512,16 +514,20 @@ def response(action, succeeded, response, options = {}, source_id = nil)
end

def headers(action, options)
auth_token = @options[:access_token] ? "Bearer #{@options[:access_token]}" : @options[:secret_key]
auth_token = @options[:public_key] if action == :tokens
headers = {
'Authorization' => auth_token,
'Content-Type' => 'application/json;charset=UTF-8'
}
headers = { 'Authorization' => auth_token(action), 'Content-Type' => 'application/json;charset=UTF-8' }
headers['Cko-Idempotency-Key'] = options[:idempotency_key] if options[:idempotency_key]

headers
end

def auth_token(action)
return @options[:public_key] if action == :tokens

return "Bearer #{@options[:access_token]}" if @options[:access_token]

@options.fetch(:secret_key, '')[-36..-1]&.match?(BASIC_SECRET_KEY_FORMAT) ? @options[:secret_key] : "Bearer #{@options[:secret_key]}"
end

def tokenize(payment_method, options = {})
post = {}
add_authorization_type(post, options)
Expand Down
55 changes: 31 additions & 24 deletions test/remote/gateways/remote_checkout_v2_test.rb
Expand Up @@ -5,9 +5,9 @@ class RemoteCheckoutV2Test < Test::Unit::TestCase
def setup
gateway_fixtures = fixtures(:checkout_v2)
gateway_token_fixtures = fixtures(:checkout_v2_token)
@gateway = CheckoutV2Gateway.new(secret_key: gateway_fixtures[:secret_key])
@gateway_oauth = CheckoutV2Gateway.new({ client_id: gateway_fixtures[:client_id], client_secret: gateway_fixtures[:client_secret] })
@gateway_token = CheckoutV2Gateway.new(secret_key: gateway_token_fixtures[:secret_key], public_key: gateway_token_fixtures[:public_key])
@gateway = CheckoutV2Gateway.new(gateway_token_fixtures)
@gateway_basic_auth = CheckoutV2Gateway.new(secret_key: gateway_fixtures[:secret_key])
@gateway_oauth = CheckoutV2Gateway.new(client_id: gateway_fixtures[:client_id], client_secret: gateway_fixtures[:client_secret])

@amount = 200
@credit_card = credit_card('4242424242424242', verification_value: '100', month: '6', year: Time.now.year + 1)
Expand Down Expand Up @@ -87,8 +87,7 @@ def setup
@additional_options = @options.merge(
card_on_file: true,
transaction_indicator: 2,
previous_charge_id: 'pay_123',
processing_channel_id: 'pc_123'
previous_charge_id: 'pay_123'
)
@additional_options_3ds = @options.merge(
execute_threed: true,
Expand Down Expand Up @@ -214,7 +213,7 @@ def test_network_transaction_scrubbing
def test_store_transcript_scrubbing
response = nil
transcript = capture_transcript(@gateway) do
response = @gateway_token.store(@credit_card, @options)
response = @gateway.store(@credit_card, @options)
end
token = response.responses.first.params['token']
transcript = @gateway.scrub(transcript)
Expand Down Expand Up @@ -280,6 +279,12 @@ def test_successful_purchase_with_an_expired_access_token
end
end

def test_successful_purchase_for_secret_key_basic_authorization_header
response = @gateway_basic_auth.purchase(@amount, @credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
end

def test_successful_purchase_with_vts_network_token
response = @gateway.purchase(100, @vts_network_token, @options)
assert_success response
Expand Down Expand Up @@ -435,8 +440,8 @@ def test_successful_purchase_includes_avs_result
response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
assert_equal 'S', response.avs_result['code']
assert_equal 'U.S.-issuing bank does not support AVS.', response.avs_result['message']
assert_equal 'G', response.avs_result['code']
assert_equal 'Non-U.S. issuing bank does not support AVS.', response.avs_result['message']
end

def test_successful_purchase_includes_avs_result_via_oauth
Expand All @@ -451,8 +456,8 @@ def test_successful_authorize_includes_avs_result
response = @gateway.authorize(@amount, @credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
assert_equal 'S', response.avs_result['code']
assert_equal 'U.S.-issuing bank does not support AVS.', response.avs_result['message']
assert_equal 'G', response.avs_result['code']
assert_equal 'Non-U.S. issuing bank does not support AVS.', response.avs_result['message']
end

def test_successful_purchase_includes_cvv_result
Expand Down Expand Up @@ -505,7 +510,7 @@ def test_successful_authorize_with_estimated_type_via_oauth
end

def test_successful_authorize_with_processing_channel_id
response = @gateway.authorize(@amount, @credit_card, @options.merge({ processing_channel_id: 'pc_ovo75iz4hdyudnx6tu74mum3fq' }))
response = @gateway.authorize(@amount, @credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
end
Expand Down Expand Up @@ -540,7 +545,6 @@ def test_successful_purchase_with_processing_data
options = @options.merge(
processing: {
aft: true,
preferred_scheme: 'cartes_bancaires',
app_id: 'com.iap.linker_portal',
airline_data: [
{
Expand Down Expand Up @@ -635,19 +639,22 @@ def test_successful_purchase_with_metadata_via_oauth
end

def test_successful_purchase_with_minimal_options
response = @gateway.purchase(@amount, @credit_card, billing_address: address)
min_options = { billing_address: address, processing_channel_id: 'pc_lxgl7aqahkzubkundd2l546hdm' }
response = @gateway.purchase(@amount, @credit_card, min_options)
assert_success response
assert_equal 'Succeeded', response.message
end

def test_successful_purchase_with_shipping_address
response = @gateway.purchase(@amount, @credit_card, shipping_address: address)
min_options = { shipping_address: address, processing_channel_id: 'pc_lxgl7aqahkzubkundd2l546hdm' }
response = @gateway.purchase(@amount, @credit_card, min_options)
assert_success response
assert_equal 'Succeeded', response.message
end

def test_successful_purchase_without_phone_number
response = @gateway.purchase(@amount, @credit_card, billing_address: address.update(phone: nil))
min_options = { billing_address: address.update(phone: nil), processing_channel_id: 'pc_lxgl7aqahkzubkundd2l546hdm' }
response = @gateway.purchase(@amount, @credit_card, min_options)
assert_success response
assert_equal 'Succeeded', response.message
end
Expand All @@ -661,15 +668,15 @@ def test_successful_purchase_without_name
end

def test_successful_purchase_with_ip
response = @gateway.purchase(@amount, @credit_card, ip: '96.125.185.52')
response = @gateway.purchase(@amount, @credit_card, @options.merge(ip: '96.125.185.52'))
assert_success response
assert_equal 'Succeeded', response.message
end

def test_failed_purchase
response = @gateway.purchase(100, @credit_card_dnh, @options)
assert_failure response
assert_equal 'Invalid Card Number', response.message
assert_equal 'Declined - Do Not Honour', response.message
end

def test_failed_purchase_via_oauth
Expand All @@ -693,7 +700,7 @@ def test_avs_failed_authorize
def test_invalid_shipping_address
response = @gateway.authorize(@amount, @credit_card, shipping_address: address.update(country: 'Canada'))
assert_failure response
assert_equal 'request_invalid: country_address_invalid', response.message
assert_equal 'request_invalid: address_country_invalid', response.message
end

def test_successful_authorize_and_capture
Expand Down Expand Up @@ -860,17 +867,17 @@ def test_money_transfer_payout_handles_blank_destination_address
end

def test_successful_store
response = @gateway_token.store(@credit_card, @options)
response = @gateway.store(@credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
end

def test_successful_unstore_after_store
store = @gateway_token.store(@credit_card, @options)
store = @gateway.store(@credit_card, @options)
assert_success store
assert_equal 'Succeeded', store.message
source_id = store.params['id']
response = @gateway_token.unstore(source_id, @options)
response = @gateway.unstore(source_id, @options)
assert_success response
assert_equal response.params['response_code'], '204'
end
Expand Down Expand Up @@ -914,7 +921,7 @@ def test_failed_store_oauth_credit_card
end

def test_successful_purchase_oauth_after_store_credit_card
store = @gateway_token.store(@credit_card, @options)
store = @gateway.store(@credit_card, @options)
assert_success store
token = store.params['id']
response = @gateway_oauth.purchase(@amount, token, @options)
Expand Down Expand Up @@ -1075,8 +1082,8 @@ def test_failed_verify
def test_expired_card_returns_error_code
response = @gateway.purchase(@amount, @expired_card, @options)
assert_failure response
assert_equal 'request_invalid: card_expired', response.message
assert_equal 'request_invalid: card_expired', response.error_code
assert_equal 'processing_error: card_expired', response.message
assert_equal 'processing_error: card_expired', response.error_code
end

def test_successful_purchase_with_idempotency_key
Expand Down

0 comments on commit 3099951

Please sign in to comment.