Skip to content

Commit

Permalink
Merchant-specific DNS names Support (#145)
Browse files Browse the repository at this point in the history
  • Loading branch information
armando-rodriguez-cko authored Jun 14, 2024
1 parent f790bf7 commit a7bfe71
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 34 deletions.
1 change: 1 addition & 0 deletions lib/checkout_sdk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
require 'checkout_sdk/checkout_utils'
require 'checkout_sdk/platform_type'
require 'checkout_sdk/environment'
require 'checkout_sdk/environment_subdomain'
require 'checkout_sdk/sdk_credentials'
require 'checkout_sdk/sdk_authorization'
require 'checkout_sdk/static_keys_sdk_credentials'
Expand Down
10 changes: 9 additions & 1 deletion lib/checkout_sdk/abstract_checkout_sdk_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ class AbstractCheckoutSdkBuilder
# @return [Faraday::Connection]
# @!attribute multipart_http_client
# @return [Faraday::Connection]
attr_accessor :environment, :http_client, :multipart_http_client, :logger
# @!attribute environment_subdomain
# @return [EnvironmentSubdomain, nil]
attr_accessor :environment, :http_client, :multipart_http_client, :logger, :environment_subdomain

# @param [Environment] environment
def with_environment(environment)
Expand All @@ -33,6 +35,12 @@ def with_logger(logger)
self
end

# @param [String, nil] subdomain
def with_environment_subdomain(subdomain)
@environment_subdomain = EnvironmentSubdomain.new(@environment, subdomain)
self
end

def build
with_environment(Environment.sandbox) if environment.nil?
if http_client.nil?
Expand Down
7 changes: 6 additions & 1 deletion lib/checkout_sdk/checkout_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ def initialize(configuration)
# @param [CheckoutConfiguration] configuration
# @return [ApiClient]
def base_api_client(configuration)
ApiClient.new(configuration, configuration.environment.base_uri)
base_uri = configuration.environment.base_uri
subdomain = configuration.environment_subdomain

base_uri = subdomain.base_uri if subdomain&.base_uri

ApiClient.new(configuration, base_uri)
end

# @param [CheckoutConfiguration] configuration
Expand Down
15 changes: 13 additions & 2 deletions lib/checkout_sdk/checkout_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,30 @@ module CheckoutSdk
# @return [Environment]
# @!attribute http_client
# @return [Faraday::Connection]
# @!attribute multipart_http_client
# @return [Faraday::Connection]
# @!attribute logger
# @return [Logger]
# @!attribute environment_subdomain
# @return [EnvironmentSubdomain, nil]
class CheckoutConfiguration
attr_accessor :credentials, :environment, :http_client, :multipart_http_client, :logger
attr_accessor :credentials, :environment, :http_client, :multipart_http_client, :logger, :environment_subdomain

# Initializes the CheckoutConfiguration.
#
# @param [SdkCredentials] credentials
# @param [Environment] environment
# @param [Faraday::Connection] http_client
# @param [Faraday::Connection] multipart_http_client
def initialize(credentials, environment, http_client, multipart_http_client, logger)
# @param [Logger] logger
# @param [EnvironmentSubdomain, nil] environment_subdomain (optional, default: nil)
def initialize(credentials, environment, http_client, multipart_http_client, logger, environment_subdomain = nil)
@credentials = credentials
@environment = environment
@http_client = http_client
@multipart_http_client = multipart_http_client
@logger = logger
@environment_subdomain = environment_subdomain
end
end
end
30 changes: 16 additions & 14 deletions lib/checkout_sdk/checkout_oauth_sdk_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,23 @@ def with_scopes(scopes)
# @return [CheckoutSdk::CheckoutApi]
def build
super
CheckoutSdk::CheckoutApi.new(
CheckoutConfiguration.new(
OAuthSdkCredentials.new(client_id,
client_secret,
scopes,
http_client,
environment,
logger,
authorization_uri),
environment,
http_client,
multipart_http_client,
logger
)
configuration = CheckoutConfiguration.new(
OAuthSdkCredentials.new(client_id,
client_secret,
scopes,
http_client,
environment,
logger,
authorization_uri),
environment,
http_client,
multipart_http_client,
logger
)

configuration.environment_subdomain = environment_subdomain if environment_subdomain

CheckoutApi.new(configuration)
end
end
end
18 changes: 10 additions & 8 deletions lib/checkout_sdk/checkout_static_keys_sdk_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ def build
@secret_key_pattern = SECRET_KEY_PATTERN
@public_key_pattern = PUBLIC_KEY_PATTERN
super
CheckoutApi.new(
CheckoutConfiguration.new(
StaticKeysSdkCredentials.new(secret_key, public_key),
environment,
http_client,
multipart_http_client,
logger
)
configuration = CheckoutConfiguration.new(
StaticKeysSdkCredentials.new(secret_key, public_key),
environment,
http_client,
multipart_http_client,
logger
)

configuration.environment_subdomain = environment_subdomain if environment_subdomain

CheckoutApi.new(configuration)
end
end
end
55 changes: 55 additions & 0 deletions lib/checkout_sdk/environment_subdomain.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

module CheckoutSdk
# @!attribute environment
# @return [Environment]
# @!attribute subdomain
# @return [String]
class EnvironmentSubdomain
attr_reader :base_uri, :environment, :subdomain

# Initializes the EnvironmentSubdomain with the given environment and subdomain.
#
# @param environment [Environment] The environment object which should have a base_uri method.
# @param subdomain [String] The subdomain to add to the environment's API URL.
def initialize(environment, subdomain)
@environment = environment
@subdomain = subdomain
@base_uri = add_subdomain_to_api_url_environment(environment, subdomain)
end

private

# Adds the subdomain to the API URL of the given environment.
#
# @param environment [Environment] The environment object which should have a base_uri method.
# @param subdomain [String] The subdomain to add to the environment's API URL.
# @return [String] The new environment URL with the subdomain added.
def add_subdomain_to_api_url_environment(environment, subdomain)
api_url = environment.base_uri
new_environment = api_url

# Regex to match a subdomain consisting of 8 to 11 lowercase alphanumeric characters
if subdomain =~ /^[0-9a-z]{8,11}$/
url_parts = URI.parse(api_url)
new_host = "#{subdomain}.#{url_parts.host}"

port = url_parts.scheme == 'https' && url_parts.port == 443 ? nil : url_parts.port

new_url_parts = URI::Generic.build(
scheme: url_parts.scheme,
userinfo: url_parts.userinfo,
host: new_host,
port: port,
path: url_parts.path,
query: url_parts.query,
fragment: url_parts.fragment
)

new_environment = new_url_parts.to_s
end

new_environment
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ def build
@secret_key_pattern = SECRET_KEY_PATTERN
@public_key_pattern = PUBLIC_KEY_PATTERN
super
CheckoutApi.new(
CheckoutConfiguration.new(
PreviousStaticKeysSdkCredentials.new(secret_key, public_key),
environment,
http_client,
multipart_http_client,
logger
)
configuration = CheckoutConfiguration.new(
PreviousStaticKeysSdkCredentials.new(secret_key, public_key),
environment,
http_client,
multipart_http_client,
logger
)

configuration.environment_subdomain = environment_subdomain if environment_subdomain

CheckoutApi.new(configuration)
end
end
end
Expand Down
82 changes: 82 additions & 0 deletions spec/checkout_sdk/configuration/configuration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
class FakeHttpClient
end

class FakeLogger
end

RSpec.describe CheckoutSdk::StaticKeysSdkCredentials do
before do
@secret_key = ENV['CHECKOUT_DEFAULT_SECRET_KEY']
@public_key = ENV['CHECKOUT_DEFAULT_PUBLIC_KEY']
@credentials = CheckoutSdk::StaticKeysSdkCredentials.new(@secret_key, @public_key)
@http_client = FakeHttpClient.new
@multipart_http_client = FakeHttpClient.new
@logger = FakeLogger.new
end

it 'should create configuration' do
configuration = CheckoutSdk::CheckoutConfiguration.new(
@credentials,
CheckoutSdk::Environment.sandbox,
@http_client,
@multipart_http_client,
@logger
)

expect(configuration.credentials).to eq(@credentials)
expect(configuration.environment.base_uri).to eq(CheckoutSdk::Environment.sandbox.base_uri)
expect(configuration.environment.base_uri).to eq("https://api.sandbox.checkout.com/")
expect(configuration.http_client).to eq(@http_client)
expect(configuration.environment_subdomain).to be_nil
end

[
%w[123dmain https://123dmain.api.sandbox.checkout.com/],
%w[123domain https://123domain.api.sandbox.checkout.com/],
%w[1234domain https://1234domain.api.sandbox.checkout.com/],
%w[12345domain https://12345domain.api.sandbox.checkout.com/]
].each do |subdomain, expected_url|
it "should create configuration with subdomain #{subdomain}" do
environment_subdomain = CheckoutSdk::EnvironmentSubdomain.new(CheckoutSdk::Environment.sandbox, subdomain)

configuration = CheckoutSdk::CheckoutConfiguration.new(
@credentials,
CheckoutSdk::Environment.sandbox,
@http_client,
@multipart_http_client,
@logger,
environment_subdomain
)

expect(configuration.credentials).to eq(@credentials)
expect(configuration.environment.base_uri).to eq(CheckoutSdk::Environment.sandbox.base_uri)
expect(configuration.http_client).to eq(@http_client)
expect(configuration.environment_subdomain.base_uri).to eq(expected_url)
end
end

[
['', 'https://api.sandbox.checkout.com/'],
%w[123 https://api.sandbox.checkout.com/],
%w[123bad https://api.sandbox.checkout.com/],
%w[12345domainBad https://api.sandbox.checkout.com/]
].each do |subdomain, expected_url|
it 'should create configuration with bad subdomain #{subdomain}' do
environment_subdomain = CheckoutSdk::EnvironmentSubdomain.new(CheckoutSdk::Environment.sandbox, subdomain)

configuration = CheckoutSdk::CheckoutConfiguration.new(
@credentials,
CheckoutSdk::Environment.sandbox,
@http_client,
@multipart_http_client,
@logger,
environment_subdomain
)

expect(configuration.credentials).to eq(@credentials)
expect(configuration.environment.base_uri).to eq(CheckoutSdk::Environment.sandbox.base_uri)
expect(configuration.http_client).to eq(@http_client)
expect(configuration.environment_subdomain.base_uri).to eq(expected_url)
end
end
end
48 changes: 48 additions & 0 deletions spec/checkout_sdk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
expect(default_sdk.class).to eq(CheckoutSdk::CheckoutApi)
end

it 'builds default sdk with both keys with subdomain' do
default_sdk = CheckoutSdk.builder
.static_keys
.with_secret_key(ENV['CHECKOUT_DEFAULT_SECRET_KEY'])
.with_public_key(ENV['CHECKOUT_DEFAULT_PUBLIC_KEY'])
.with_environment(CheckoutSdk::Environment.production)
.with_environment_subdomain('12345domain')
.build
expect(default_sdk.class).to eq(CheckoutSdk::CheckoutApi)
end

it 'builds default sdk with secret key only' do
default_sdk = CheckoutSdk.builder
.static_keys
Expand All @@ -27,6 +38,16 @@
.build
expect(default_sdk.class).to eq(CheckoutSdk::CheckoutApi)
end

it 'builds default sdk with secret key only with subdomain' do
default_sdk = CheckoutSdk.builder
.static_keys
.with_secret_key(ENV['CHECKOUT_DEFAULT_SECRET_KEY'])
.with_environment(CheckoutSdk::Environment.production)
.with_environment_subdomain('12345domain')
.build
expect(default_sdk.class).to eq(CheckoutSdk::CheckoutApi)
end
end

context 'when building default sdk with incorrect parameters' do
Expand Down Expand Up @@ -69,6 +90,21 @@
expect(oauth_sdk.class).to eq(CheckoutSdk::CheckoutApi)
end

it 'should build oauth sdk with default http client correctly with subdomain' do
oauth_sdk = CheckoutSdk.builder
.oauth
.with_client_credentials(ENV['CHECKOUT_DEFAULT_OAUTH_CLIENT_ID'],
ENV['CHECKOUT_DEFAULT_OAUTH_CLIENT_SECRET'])
.with_authorization_uri(CheckoutSdk::Environment.sandbox.authorization_uri)
.with_scopes([CheckoutSdk::OAuthScopes::VAULT,
CheckoutSdk::OAuthScopes::GATEWAY])
.with_environment(CheckoutSdk::Environment.sandbox)
.with_environment_subdomain('12345domain')
.build

expect(oauth_sdk.class).to eq(CheckoutSdk::CheckoutApi)
end

it 'should build oauth sdk with custom http client correctly' do
http_client = Faraday.new(CheckoutSdk::Environment.sandbox.base_uri) do |f|
f.response(:raise_error)
Expand Down Expand Up @@ -148,6 +184,18 @@
expect(default_sdk.class).to eq(CheckoutSdk::Previous::CheckoutApi)
end

it 'builds previous sdk with both keys with subdomain' do
default_sdk = CheckoutSdk.builder
.previous
.static_keys
.with_secret_key(ENV['CHECKOUT_PREVIOUS_SECRET_KEY'])
.with_public_key(ENV['CHECKOUT_PREVIOUS_PUBLIC_KEY'])
.with_environment(CheckoutSdk::Environment.production)
.with_environment_subdomain('12345domain')
.build
expect(default_sdk.class).to eq(CheckoutSdk::Previous::CheckoutApi)
end

it 'builds previous sdk with secret key only' do
default_sdk = CheckoutSdk.builder
.previous
Expand Down

0 comments on commit a7bfe71

Please sign in to comment.