Skip to content

Commit

Permalink
Merchant-specific DNS names Support (#390)
Browse files Browse the repository at this point in the history
- Adds subdomain for merchants
- Adds new field challenge_notification_url to the completion object
- Fix payment context details response
  • Loading branch information
armando-rodriguez-cko authored Feb 15, 2024
1 parent 95854ed commit d2543c0
Show file tree
Hide file tree
Showing 17 changed files with 168 additions and 15 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ jobs:
CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET }}
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID }}
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET }}
CHECKOUT_MERCHANT_SUBDOMAIN: ${{ secrets.IT_CHECKOUT_MERCHANT_SUBDOMAIN }}
run: ./gradlew build test --fail-fast
1 change: 1 addition & 0 deletions .github/workflows/build-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET }}
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID }}
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET }}
CHECKOUT_MERCHANT_SUBDOMAIN: ${{ secrets.IT_CHECKOUT_MERCHANT_SUBDOMAIN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./gradlew build
1 change: 1 addition & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET }}
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID }}
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET }}
CHECKOUT_MERCHANT_SUBDOMAIN: ${{ secrets.IT_CHECKOUT_MERCHANT_SUBDOMAIN }}
run: ./gradlew build test --fail-fast jar
- id: publish
env:
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public static void main(String[] args) {
.publicKey("public_key") // optional, only required for operations related with tokens
.secretKey("secret_key")
.environment(Environment.PRODUCTION) // required
.environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
.executor() // optional for a custom Executor Service
.build();

Expand All @@ -105,6 +106,7 @@ final CheckoutApi checkoutApi = CheckoutSdk.builder()
//.clientCredentials(new URI("https://access.sandbox.checkout.com/connect/token"), "client_id", "client_secret")
.scopes(OAuthScope.GATEWAY, OAuthScope.VAULT, OAuthScope.FX)
.environment(Environment.PRODUCTION) // required
.environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
.executor() // optional for a custom Executor Service
.build();

Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/checkout/AbstractCheckoutApmApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public SepaClient sepaClient() {
}

private ApiClient getBaseApiClient(final CheckoutConfiguration configuration) {

return new ApiClientImpl(configuration, new BaseUriStrategy(configuration));
}

Expand All @@ -50,7 +51,12 @@ private BaseUriStrategy(final CheckoutConfiguration configuration) {

@Override
public URI getUri() {
return configuration.getEnvironment().getCheckoutApi();

if (configuration.getEnvironmentSubdomain() != null) {
return configuration.getEnvironmentSubdomain().getCheckoutApi();
}else {
return configuration.getEnvironment().getCheckoutApi();
}
}
}

Expand Down
15 changes: 14 additions & 1 deletion src/main/java/com/checkout/AbstractCheckoutSdkBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public abstract class AbstractCheckoutSdkBuilder<T extends CheckoutApiClient> {

protected HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
private IEnvironment environment;
private EnvironmentSubdomain environmentSubdomain;
private Executor executor = ForkJoinPool.commonPool();
private TransportConfiguration transportConfiguration;

Expand All @@ -16,6 +17,14 @@ public AbstractCheckoutSdkBuilder<T> environment(final IEnvironment environment)
return this;
}

public AbstractCheckoutSdkBuilder<T> environmentSubdomain(final String subdomain) {
if (subdomain == null) {
throw new CheckoutArgumentException("subdomain must be specified");
}
this.environmentSubdomain = new EnvironmentSubdomain(this.environment, subdomain);
return this;
}

public AbstractCheckoutSdkBuilder<T> httpClientBuilder(final HttpClientBuilder httpClientBuilder) {
this.httpClientBuilder = httpClientBuilder;
return this;
Expand All @@ -35,6 +44,10 @@ protected IEnvironment getEnvironment() {
return environment;
}

protected EnvironmentSubdomain getEnvironmentSubdomain() {
return environmentSubdomain;
}

protected abstract SdkCredentials getSdkCredentials();

protected CheckoutConfiguration getCheckoutConfiguration() {
Expand All @@ -49,7 +62,7 @@ protected CheckoutConfiguration getCheckoutConfiguration() {
}

private CheckoutConfiguration buildCheckoutConfiguration(final SdkCredentials sdkCredentials) {
return new DefaultCheckoutConfiguration(sdkCredentials, getEnvironment(), httpClientBuilder, executor, transportConfiguration);
return new DefaultCheckoutConfiguration(sdkCredentials, getEnvironment(), getEnvironmentSubdomain(), httpClientBuilder, executor, transportConfiguration);
}

public abstract T build();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/checkout/CheckoutConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public interface CheckoutConfiguration {

IEnvironment getEnvironment();

EnvironmentSubdomain getEnvironmentSubdomain();

SdkCredentials getSdkCredentials();

HttpClientBuilder getHttpClientBuilder();
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/checkout/DefaultCheckoutConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class DefaultCheckoutConfiguration implements CheckoutConfiguration {
private final HttpClientBuilder httpClientBuilder;
private final Executor executor;
private final IEnvironment environment;
private final EnvironmentSubdomain environmentSubdomain;
private final TransportConfiguration transportConfiguration;

DefaultCheckoutConfiguration(final SdkCredentials sdkCredentials,
Expand All @@ -24,6 +25,22 @@ class DefaultCheckoutConfiguration implements CheckoutConfiguration {
this.httpClientBuilder = httpClientBuilder;
this.executor = executor;
this.environment = environment;
this.environmentSubdomain = null;
this.transportConfiguration = transportConfiguration;
}

DefaultCheckoutConfiguration(final SdkCredentials sdkCredentials,
final IEnvironment environment,
final EnvironmentSubdomain environmentSubdomain,
final HttpClientBuilder httpClientBuilder,
final Executor executor,
final TransportConfiguration transportConfiguration) {
validateParams("sdkCredentials", sdkCredentials, "environment", environment, "httpClientBuilder", httpClientBuilder, "executor", executor, "transportConfiguration", transportConfiguration);
this.sdkCredentials = sdkCredentials;
this.httpClientBuilder = httpClientBuilder;
this.executor = executor;
this.environment = environment;
this.environmentSubdomain = environmentSubdomain;
this.transportConfiguration = transportConfiguration;
}

Expand All @@ -47,6 +64,11 @@ public IEnvironment getEnvironment() {
return environment;
}

@Override
public EnvironmentSubdomain getEnvironmentSubdomain() {
return environmentSubdomain;
}

@Override
public TransportConfiguration getTransportConfiguration() {
return transportConfiguration;
Expand Down
44 changes: 44 additions & 0 deletions src/main/java/com/checkout/EnvironmentSubdomain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.checkout;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class EnvironmentSubdomain {

private URI checkoutApi;

public EnvironmentSubdomain(IEnvironment environment, String subdomain) {
checkoutApi = addSubdomainToApiUrlEnvironment(environment, subdomain);
}

public URI getCheckoutApi() {
return checkoutApi;
}

private static URI addSubdomainToApiUrlEnvironment(IEnvironment environment, String subdomain) {
URI apiUrl = environment.getCheckoutApi();
URI newEnvironment = null;
try {
newEnvironment = new URI(apiUrl.toString());
} catch (final URISyntaxException e) {
throw new CheckoutException(e);
}
Pattern pattern = Pattern.compile("^[0-9a-z]{8}$");
Matcher matcher = pattern.matcher(subdomain);
if (matcher.matches()) {
String host = apiUrl.getHost();
String scheme = apiUrl.getScheme();
int port = apiUrl.getPort();
String newHost = subdomain + "." + host;
try {
newEnvironment = new URI(scheme, null, newHost, port, apiUrl.getPath(), apiUrl.getQuery(), apiUrl.getFragment());
} catch (final URISyntaxException e) {
throw new CheckoutException(e);
}
}
return newEnvironment;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,4 @@ public final class PaymentContextDetailsResponse extends HttpMetadata {

@SerializedName("partner_metadata")
private PaymentContextsPartnerMetadata partnerMetadata;

private Object customer;

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ public final class NonHostedCompletionInfo extends CompletionInfo {
@SerializedName("callback_url")
private final String callbackUrl;

@SerializedName("challenge_notification_url")
private final String challengeNotificationUrl;

@Builder
private NonHostedCompletionInfo(final String callbackUrl) {
private NonHostedCompletionInfo(final String callbackUrl, final String challengeNotificationUrl) {
super(CompletionInfoType.NON_HOSTED);
this.callbackUrl = callbackUrl;
this.challengeNotificationUrl = challengeNotificationUrl;
}

}
1 change: 1 addition & 0 deletions src/test/java/com/checkout/CheckoutApiImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class CheckoutApiImplTest {
void shouldInstantiateAndRetrieveClients() {
final CheckoutConfiguration configuration = mock(CheckoutConfiguration.class);
when(configuration.getEnvironment()).thenReturn(Environment.SANDBOX);
when(configuration.getEnvironmentSubdomain()).thenReturn(new EnvironmentSubdomain(Environment.SANDBOX, "subdomain"));
when(configuration.getHttpClientBuilder()).thenReturn(HttpClientBuilder.create());
when(configuration.getExecutor()).thenReturn(mock(Executor.class));
final CheckoutApi checkoutApi = new CheckoutApiImpl(configuration);
Expand Down
23 changes: 23 additions & 0 deletions src/test/java/com/checkout/CheckoutPreviousSdkBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,29 @@ void shouldCreateCheckoutSdks() {

}

@Test
void shouldCreateCheckoutWithSubdomainSdks() {

final CheckoutApi checkoutApi1 = new CheckoutPreviousSdkBuilder()
.staticKeys()
.publicKey(VALID_PREVIOUS_PK)
.secretKey(VALID_PREVIOUS_SK)
.environment(Environment.SANDBOX)
.environmentSubdomain("123dmain")
.build();

assertNotNull(checkoutApi1.tokensClient());

final CheckoutApi checkoutApi2 = new CheckoutPreviousSdkBuilder().staticKeys()
.secretKey(VALID_PREVIOUS_SK)
.environment(Environment.SANDBOX)
.environmentSubdomain("123dmain")
.build();

assertNotNull(checkoutApi2.tokensClient());

}

@Test
void shouldFailToCreateCheckoutSdks() {

Expand Down
22 changes: 22 additions & 0 deletions src/test/java/com/checkout/CheckoutSdkBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ void shouldCreateStaticKeysCheckoutSdks() {

}

@Test
void shouldCreateStaticKeysCheckoutWithSubdomainSdks() {

final CheckoutApi checkoutApi1 = new CheckoutSdkBuilder().staticKeys()
.publicKey(VALID_DEFAULT_PK)
.secretKey(VALID_DEFAULT_SK)
.environment(Environment.SANDBOX)
.environmentSubdomain("123dmain")
.build();

assertNotNull(checkoutApi1);

final CheckoutApi checkoutApi2 = new CheckoutSdkBuilder().staticKeys()
.secretKey(VALID_DEFAULT_SK)
.environment(Environment.SANDBOX)
.environmentSubdomain("123dmain")
.build();

assertNotNull(checkoutApi2);

}

@Test
void shouldCreateCheckoutAndInitOAuthSdk() throws URISyntaxException {

Expand Down
21 changes: 20 additions & 1 deletion src/test/java/com/checkout/DefaultCheckoutConfigurationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ void shouldCreateConfiguration() {

}

@Test
void shouldCreateConfigurationWithSubdomain() {

final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);
final EnvironmentSubdomain environmentSubdomain = new EnvironmentSubdomain(Environment.SANDBOX, "123dmain");

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, environmentSubdomain, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
assertEquals("https://123dmain.api.sandbox.checkout.com/", configuration.getEnvironmentSubdomain().getCheckoutApi().toString());
}

@Test
void shouldCreateConfigurationWithBadSubdomain() {

final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);
final EnvironmentSubdomain environmentSubdomain = new EnvironmentSubdomain(Environment.SANDBOX, "123bad");

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, environmentSubdomain, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
assertEquals("https://api.sandbox.checkout.com/", configuration.getEnvironmentSubdomain().getCheckoutApi().toString());
}

@Test
void shouldCreateConfiguration_defaultHttpClientBuilderAndExecutor() {

Expand Down Expand Up @@ -81,7 +101,6 @@ void shouldCreateConfigurationForProd() {

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
assertEquals(Environment.PRODUCTION, configuration.getEnvironment());

}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,14 +388,7 @@ void shouldMakeBancontactPayment() {
.failureUrl("https://testing.checkout.com/failure")
.build();

//checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), PAYEE_NOT_ONBOARDED);
final com.checkout.payments.response.PaymentResponse paymentResponse = blocking(() -> paymentsClient.requestPayment(paymentRequest));
assertNotNull(paymentResponse);

final com.checkout.payments.response.GetPaymentResponse paymentDetails = blocking(() -> paymentsClient.getPayment(paymentResponse.getId()));
assertNotNull(paymentDetails);
assertTrue(paymentDetails.getSource() instanceof com.checkout.payments.response.source.AlternativePaymentSourceResponse);
assertEquals(PaymentSourceType.BANCONTACT, paymentDetails.getSource().getType());
checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), APM_SERVICE_UNAVAILABLE);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ void shouldMakeKnetPayment() {
assertEquals(PaymentSourceType.KNET, paymentDetails.getSource().getType());
}

@Disabled("not available")
@Test
void shouldMakePrzelewy24Payment() {
final PaymentRequest paymentRequest = PaymentRequest.builder()
Expand Down Expand Up @@ -358,6 +359,7 @@ void shouldMakePoliPayment() {
assertEquals(PaymentSourceType.POLI, paymentDetails.getSource().getType());
}

@Disabled("not available")
@Test
void shouldMakeBancontactPayment() {
final PaymentRequest paymentRequest = PaymentRequest.builder()
Expand Down

0 comments on commit d2543c0

Please sign in to comment.