Skip to content

Commit d2543c0

Browse files
Merchant-specific DNS names Support (#390)
- Adds subdomain for merchants - Adds new field challenge_notification_url to the completion object - Fix payment context details response
1 parent 95854ed commit d2543c0

17 files changed

+168
-15
lines changed

.github/workflows/build-master.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ jobs:
3030
CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET }}
3131
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID }}
3232
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET }}
33+
CHECKOUT_MERCHANT_SUBDOMAIN: ${{ secrets.IT_CHECKOUT_MERCHANT_SUBDOMAIN }}
3334
run: ./gradlew build test --fail-fast

.github/workflows/build-pull-request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET }}
3939
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID }}
4040
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET }}
41+
CHECKOUT_MERCHANT_SUBDOMAIN: ${{ secrets.IT_CHECKOUT_MERCHANT_SUBDOMAIN }}
4142
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4243
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
4344
run: ./gradlew build

.github/workflows/build-release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ACCOUNTS_CLIENT_SECRET }}
3636
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_ID }}
3737
CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET: ${{ secrets.IT_CHECKOUT_DEFAULT_OAUTH_ISSUING_CLIENT_SECRET }}
38+
CHECKOUT_MERCHANT_SUBDOMAIN: ${{ secrets.IT_CHECKOUT_MERCHANT_SUBDOMAIN }}
3839
run: ./gradlew build test --fail-fast jar
3940
- id: publish
4041
env:

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public static void main(String[] args) {
8080
.publicKey("public_key") // optional, only required for operations related with tokens
8181
.secretKey("secret_key")
8282
.environment(Environment.PRODUCTION) // required
83+
.environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
8384
.executor() // optional for a custom Executor Service
8485
.build();
8586

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

src/main/java/com/checkout/AbstractCheckoutApmApi.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public SepaClient sepaClient() {
3737
}
3838

3939
private ApiClient getBaseApiClient(final CheckoutConfiguration configuration) {
40+
4041
return new ApiClientImpl(configuration, new BaseUriStrategy(configuration));
4142
}
4243

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

5152
@Override
5253
public URI getUri() {
53-
return configuration.getEnvironment().getCheckoutApi();
54+
55+
if (configuration.getEnvironmentSubdomain() != null) {
56+
return configuration.getEnvironmentSubdomain().getCheckoutApi();
57+
}else {
58+
return configuration.getEnvironment().getCheckoutApi();
59+
}
5460
}
5561
}
5662

src/main/java/com/checkout/AbstractCheckoutSdkBuilder.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public abstract class AbstractCheckoutSdkBuilder<T extends CheckoutApiClient> {
88

99
protected HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
1010
private IEnvironment environment;
11+
private EnvironmentSubdomain environmentSubdomain;
1112
private Executor executor = ForkJoinPool.commonPool();
1213
private TransportConfiguration transportConfiguration;
1314

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

20+
public AbstractCheckoutSdkBuilder<T> environmentSubdomain(final String subdomain) {
21+
if (subdomain == null) {
22+
throw new CheckoutArgumentException("subdomain must be specified");
23+
}
24+
this.environmentSubdomain = new EnvironmentSubdomain(this.environment, subdomain);
25+
return this;
26+
}
27+
1928
public AbstractCheckoutSdkBuilder<T> httpClientBuilder(final HttpClientBuilder httpClientBuilder) {
2029
this.httpClientBuilder = httpClientBuilder;
2130
return this;
@@ -35,6 +44,10 @@ protected IEnvironment getEnvironment() {
3544
return environment;
3645
}
3746

47+
protected EnvironmentSubdomain getEnvironmentSubdomain() {
48+
return environmentSubdomain;
49+
}
50+
3851
protected abstract SdkCredentials getSdkCredentials();
3952

4053
protected CheckoutConfiguration getCheckoutConfiguration() {
@@ -49,7 +62,7 @@ protected CheckoutConfiguration getCheckoutConfiguration() {
4962
}
5063

5164
private CheckoutConfiguration buildCheckoutConfiguration(final SdkCredentials sdkCredentials) {
52-
return new DefaultCheckoutConfiguration(sdkCredentials, getEnvironment(), httpClientBuilder, executor, transportConfiguration);
65+
return new DefaultCheckoutConfiguration(sdkCredentials, getEnvironment(), getEnvironmentSubdomain(), httpClientBuilder, executor, transportConfiguration);
5366
}
5467

5568
public abstract T build();

src/main/java/com/checkout/CheckoutConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public interface CheckoutConfiguration {
88

99
IEnvironment getEnvironment();
1010

11+
EnvironmentSubdomain getEnvironmentSubdomain();
12+
1113
SdkCredentials getSdkCredentials();
1214

1315
HttpClientBuilder getHttpClientBuilder();

src/main/java/com/checkout/DefaultCheckoutConfiguration.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class DefaultCheckoutConfiguration implements CheckoutConfiguration {
1212
private final HttpClientBuilder httpClientBuilder;
1313
private final Executor executor;
1414
private final IEnvironment environment;
15+
private final EnvironmentSubdomain environmentSubdomain;
1516
private final TransportConfiguration transportConfiguration;
1617

1718
DefaultCheckoutConfiguration(final SdkCredentials sdkCredentials,
@@ -24,6 +25,22 @@ class DefaultCheckoutConfiguration implements CheckoutConfiguration {
2425
this.httpClientBuilder = httpClientBuilder;
2526
this.executor = executor;
2627
this.environment = environment;
28+
this.environmentSubdomain = null;
29+
this.transportConfiguration = transportConfiguration;
30+
}
31+
32+
DefaultCheckoutConfiguration(final SdkCredentials sdkCredentials,
33+
final IEnvironment environment,
34+
final EnvironmentSubdomain environmentSubdomain,
35+
final HttpClientBuilder httpClientBuilder,
36+
final Executor executor,
37+
final TransportConfiguration transportConfiguration) {
38+
validateParams("sdkCredentials", sdkCredentials, "environment", environment, "httpClientBuilder", httpClientBuilder, "executor", executor, "transportConfiguration", transportConfiguration);
39+
this.sdkCredentials = sdkCredentials;
40+
this.httpClientBuilder = httpClientBuilder;
41+
this.executor = executor;
42+
this.environment = environment;
43+
this.environmentSubdomain = environmentSubdomain;
2744
this.transportConfiguration = transportConfiguration;
2845
}
2946

@@ -47,6 +64,11 @@ public IEnvironment getEnvironment() {
4764
return environment;
4865
}
4966

67+
@Override
68+
public EnvironmentSubdomain getEnvironmentSubdomain() {
69+
return environmentSubdomain;
70+
}
71+
5072
@Override
5173
public TransportConfiguration getTransportConfiguration() {
5274
return transportConfiguration;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.checkout;
2+
3+
import java.net.URI;
4+
import java.net.URISyntaxException;
5+
import java.util.regex.Pattern;
6+
import java.util.regex.Matcher;
7+
8+
public class EnvironmentSubdomain {
9+
10+
private URI checkoutApi;
11+
12+
public EnvironmentSubdomain(IEnvironment environment, String subdomain) {
13+
checkoutApi = addSubdomainToApiUrlEnvironment(environment, subdomain);
14+
}
15+
16+
public URI getCheckoutApi() {
17+
return checkoutApi;
18+
}
19+
20+
private static URI addSubdomainToApiUrlEnvironment(IEnvironment environment, String subdomain) {
21+
URI apiUrl = environment.getCheckoutApi();
22+
URI newEnvironment = null;
23+
try {
24+
newEnvironment = new URI(apiUrl.toString());
25+
} catch (final URISyntaxException e) {
26+
throw new CheckoutException(e);
27+
}
28+
Pattern pattern = Pattern.compile("^[0-9a-z]{8}$");
29+
Matcher matcher = pattern.matcher(subdomain);
30+
if (matcher.matches()) {
31+
String host = apiUrl.getHost();
32+
String scheme = apiUrl.getScheme();
33+
int port = apiUrl.getPort();
34+
String newHost = subdomain + "." + host;
35+
try {
36+
newEnvironment = new URI(scheme, null, newHost, port, apiUrl.getPath(), apiUrl.getQuery(), apiUrl.getFragment());
37+
} catch (final URISyntaxException e) {
38+
throw new CheckoutException(e);
39+
}
40+
}
41+
return newEnvironment;
42+
}
43+
44+
}

src/main/java/com/checkout/payments/contexts/PaymentContextDetailsResponse.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,4 @@ public final class PaymentContextDetailsResponse extends HttpMetadata {
1818

1919
@SerializedName("partner_metadata")
2020
private PaymentContextsPartnerMetadata partnerMetadata;
21-
22-
private Object customer;
23-
2421
}

src/main/java/com/checkout/sessions/completion/NonHostedCompletionInfo.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ public final class NonHostedCompletionInfo extends CompletionInfo {
1616
@SerializedName("callback_url")
1717
private final String callbackUrl;
1818

19+
@SerializedName("challenge_notification_url")
20+
private final String challengeNotificationUrl;
21+
1922
@Builder
20-
private NonHostedCompletionInfo(final String callbackUrl) {
23+
private NonHostedCompletionInfo(final String callbackUrl, final String challengeNotificationUrl) {
2124
super(CompletionInfoType.NON_HOSTED);
2225
this.callbackUrl = callbackUrl;
26+
this.challengeNotificationUrl = challengeNotificationUrl;
2327
}
2428

2529
}

src/test/java/com/checkout/CheckoutApiImplTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class CheckoutApiImplTest {
1818
void shouldInstantiateAndRetrieveClients() {
1919
final CheckoutConfiguration configuration = mock(CheckoutConfiguration.class);
2020
when(configuration.getEnvironment()).thenReturn(Environment.SANDBOX);
21+
when(configuration.getEnvironmentSubdomain()).thenReturn(new EnvironmentSubdomain(Environment.SANDBOX, "subdomain"));
2122
when(configuration.getHttpClientBuilder()).thenReturn(HttpClientBuilder.create());
2223
when(configuration.getExecutor()).thenReturn(mock(Executor.class));
2324
final CheckoutApi checkoutApi = new CheckoutApiImpl(configuration);

src/test/java/com/checkout/CheckoutPreviousSdkBuilderTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ void shouldCreateCheckoutSdks() {
3434

3535
}
3636

37+
@Test
38+
void shouldCreateCheckoutWithSubdomainSdks() {
39+
40+
final CheckoutApi checkoutApi1 = new CheckoutPreviousSdkBuilder()
41+
.staticKeys()
42+
.publicKey(VALID_PREVIOUS_PK)
43+
.secretKey(VALID_PREVIOUS_SK)
44+
.environment(Environment.SANDBOX)
45+
.environmentSubdomain("123dmain")
46+
.build();
47+
48+
assertNotNull(checkoutApi1.tokensClient());
49+
50+
final CheckoutApi checkoutApi2 = new CheckoutPreviousSdkBuilder().staticKeys()
51+
.secretKey(VALID_PREVIOUS_SK)
52+
.environment(Environment.SANDBOX)
53+
.environmentSubdomain("123dmain")
54+
.build();
55+
56+
assertNotNull(checkoutApi2.tokensClient());
57+
58+
}
59+
3760
@Test
3861
void shouldFailToCreateCheckoutSdks() {
3962

src/test/java/com/checkout/CheckoutSdkBuilderTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,28 @@ void shouldCreateStaticKeysCheckoutSdks() {
3636

3737
}
3838

39+
@Test
40+
void shouldCreateStaticKeysCheckoutWithSubdomainSdks() {
41+
42+
final CheckoutApi checkoutApi1 = new CheckoutSdkBuilder().staticKeys()
43+
.publicKey(VALID_DEFAULT_PK)
44+
.secretKey(VALID_DEFAULT_SK)
45+
.environment(Environment.SANDBOX)
46+
.environmentSubdomain("123dmain")
47+
.build();
48+
49+
assertNotNull(checkoutApi1);
50+
51+
final CheckoutApi checkoutApi2 = new CheckoutSdkBuilder().staticKeys()
52+
.secretKey(VALID_DEFAULT_SK)
53+
.environment(Environment.SANDBOX)
54+
.environmentSubdomain("123dmain")
55+
.build();
56+
57+
assertNotNull(checkoutApi2);
58+
59+
}
60+
3961
@Test
4062
void shouldCreateCheckoutAndInitOAuthSdk() throws URISyntaxException {
4163

src/test/java/com/checkout/DefaultCheckoutConfigurationTest.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@ void shouldCreateConfiguration() {
4444

4545
}
4646

47+
@Test
48+
void shouldCreateConfigurationWithSubdomain() {
49+
50+
final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);
51+
final EnvironmentSubdomain environmentSubdomain = new EnvironmentSubdomain(Environment.SANDBOX, "123dmain");
52+
53+
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, environmentSubdomain, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
54+
assertEquals("https://123dmain.api.sandbox.checkout.com/", configuration.getEnvironmentSubdomain().getCheckoutApi().toString());
55+
}
56+
57+
@Test
58+
void shouldCreateConfigurationWithBadSubdomain() {
59+
60+
final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);
61+
final EnvironmentSubdomain environmentSubdomain = new EnvironmentSubdomain(Environment.SANDBOX, "123bad");
62+
63+
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, environmentSubdomain, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
64+
assertEquals("https://api.sandbox.checkout.com/", configuration.getEnvironmentSubdomain().getCheckoutApi().toString());
65+
}
66+
4767
@Test
4868
void shouldCreateConfiguration_defaultHttpClientBuilderAndExecutor() {
4969

@@ -81,7 +101,6 @@ void shouldCreateConfigurationForProd() {
81101

82102
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
83103
assertEquals(Environment.PRODUCTION, configuration.getEnvironment());
84-
85104
}
86105

87106
@Test

src/test/java/com/checkout/payments/RequestApmPaymentsIT.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,14 +388,7 @@ void shouldMakeBancontactPayment() {
388388
.failureUrl("https://testing.checkout.com/failure")
389389
.build();
390390

391-
//checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), PAYEE_NOT_ONBOARDED);
392-
final com.checkout.payments.response.PaymentResponse paymentResponse = blocking(() -> paymentsClient.requestPayment(paymentRequest));
393-
assertNotNull(paymentResponse);
394-
395-
final com.checkout.payments.response.GetPaymentResponse paymentDetails = blocking(() -> paymentsClient.getPayment(paymentResponse.getId()));
396-
assertNotNull(paymentDetails);
397-
assertTrue(paymentDetails.getSource() instanceof com.checkout.payments.response.source.AlternativePaymentSourceResponse);
398-
assertEquals(PaymentSourceType.BANCONTACT, paymentDetails.getSource().getType());
391+
checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), APM_SERVICE_UNAVAILABLE);
399392
}
400393

401394
@Test

src/test/java/com/checkout/payments/previous/RequestApmPaymentsIT.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ void shouldMakeKnetPayment() {
297297
assertEquals(PaymentSourceType.KNET, paymentDetails.getSource().getType());
298298
}
299299

300+
@Disabled("not available")
300301
@Test
301302
void shouldMakePrzelewy24Payment() {
302303
final PaymentRequest paymentRequest = PaymentRequest.builder()
@@ -358,6 +359,7 @@ void shouldMakePoliPayment() {
358359
assertEquals(PaymentSourceType.POLI, paymentDetails.getSource().getType());
359360
}
360361

362+
@Disabled("not available")
361363
@Test
362364
void shouldMakeBancontactPayment() {
363365
final PaymentRequest paymentRequest = PaymentRequest.builder()

0 commit comments

Comments
 (0)