Skip to content

Commit 5b7dc76

Browse files
authored
Merge pull request #983 from commercetools/checkout-sdk
Checkout API
2 parents b46444c + d594d43 commit 5b7dc76

File tree

430 files changed

+52229
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

430 files changed

+52229
-4
lines changed

.git-blame-ignore-revs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ d0129c1095216d5c830900c8a6223ef5d4274de1
77
bbe9f971763ca1b27687a6a51067a385a0d23b04
88
de95c481329aa8b821e6e71ac35c1b8bc67e3e86
99
78c44064f4ec15091bde7a2dc590aa2b3a99341d
10+
03665b75a1e1c3a3cf28df1dec52e91b308e4368
11+
7e25c796da25ae080a952936de535a1228fed448

Makefile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,24 @@ SHELL := /bin/bash
22
CHANGES_PENDING := `git status --porcelain -- ':(exclude)*gen.properties' | grep -c ^ || true`
33
API_RAML ?= $(RAML_FILE)
44
IMPORT_RAML ?= $(RAML_FILE)
5-
ML_RAML ?= $(RAML_FILE)
5+
CHECKOUT_RAML ?= $(RAML_FILE)
66
HISTORY_RAML ?= $(RAML_FILE)
77
CPUS := `./tools/numcpu.sh`
88

9-
.PHONY: build build_api_sdk build_import_sdk build_import_sdk build_ml_sdk gen_api_sdk gen_import_sdk gen_ml_sdk gen_history_sdk
9+
.PHONY: build build_api_sdk build_import_sdk build_import_sdk build_ml_sdk gen_api_sdk gen_import_sdk gen_ml_sdk gen_history_sdk gen_checkout_sdk
1010

11-
build: codegen_install gen_api_sdk gen_import_sdk gen_history_sdk prettify verify
11+
build: codegen_install gen_api_sdk gen_import_sdk gen_history_sdk gen_checkout_sdk prettify verify
1212
build_api_sdk: codegen_install gen_api_sdk prettify verify
1313
build_import_sdk: codegen_install gen_import_sdk prettify verify
1414
build_ml_sdk: codegen_install gen_ml_sdk prettify verify
1515
build_history_sdk: codegen_install gen_history_sdk prettify verify
16+
build_checkout_sdk: codegen_install gen_checkout_sdk prettify verify
1617

1718
gen_api_sdk: generate_api
1819
gen_import_sdk: generate_import
1920
gen_ml_sdk: generate_ml
2021
gen_history_sdk: generate_history
22+
gen_checkout_sdk: generate_checkout
2123

2224
prettify:
2325
./gradlew spotlessApply
@@ -40,6 +42,9 @@ generate_ml:
4042
generate_history:
4143
$(MAKE) -C commercetools LIB_NAME="history" GEN_RAML_FILE=../$(HISTORY_RAML) generate_sdk
4244

45+
generate_checkout:
46+
$(MAKE) -C commercetools LIB_NAME="checkout" GEN_RAML_FILE=../$(CHECKOUT_RAML) generate_sdk
47+
4348
check_pending:
4449
git status --porcelain -- ':(exclude)*gen.properties'
4550
@echo "CHANGES_PENDING=$(CHANGES_PENDING)" >> $GITHUB_ENV

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ plugins {
1212
id 'java'
1313
id 'java-library' // needed to make sure that transitive deps have 'compile' scope
1414

15-
id "com.diffplug.spotless" version "7.0.4"
15+
id "com.diffplug.spotless" version "7.2.1"
1616

1717
id 'io.github.gradle-nexus.publish-plugin' version '2.0.0'
1818
id 'com.github.jk1.dependency-license-report' version '2.0'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
dependencies {
3+
api project(':rmf:rmf-java-base')
4+
api jackson_core.annotations
5+
api jackson_core.databind
6+
implementation google.findbugs
7+
implementation javax.validation
8+
api commons.lang3
9+
10+
integrationTestImplementation project(':commercetools:commercetools-http-client')
11+
integrationTestImplementation project(':commercetools:commercetools-sdk-java-api')
12+
}
13+
14+
sourceSets.main.java.srcDirs += "src/main/java-generated"
15+
sourceSets.test.java.srcDirs += "src/test/java-generated"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
package com.commercetools.checkout.client;
3+
4+
import java.lang.reflect.Method;
5+
import java.lang.reflect.Modifier;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
import org.assertj.core.api.Assertions;
10+
import org.assertj.core.util.Lists;
11+
import org.junit.jupiter.api.Test;
12+
13+
public class ProjectApiRootTest {
14+
15+
private static final List<String> ignoreMethods = Lists.newArrayList();
16+
17+
/**
18+
* Retrieves all public methods of the {@link ProjectScopedApiRoot} and the public methods of the {@link ByProjectKeyRequestBuilder} and
19+
* checks if project request builder methods are present in ProjectApiRoot methods
20+
*/
21+
@Test
22+
public void allSubResourcesSupported() {
23+
24+
final List<String> projectApiRootMethods = Lists.newArrayList(ProjectScopedApiRoot.class.getDeclaredMethods())
25+
.stream()
26+
.filter(method -> Modifier.isPublic(method.getModifiers()))
27+
.map(Method::getName)
28+
.distinct()
29+
.collect(Collectors.toList());
30+
31+
final List<String> resourceMethods = Lists.newArrayList(ByProjectKeyRequestBuilder.class.getDeclaredMethods())
32+
.stream()
33+
.filter(method -> Modifier.isPublic(method.getModifiers()))
34+
.map(Method::getName)
35+
.filter(methodName -> !ignoreMethods.contains(methodName))
36+
.filter(methodName -> !projectApiRootMethods.contains(methodName))
37+
.collect(Collectors.toList());
38+
39+
Assertions.assertThat(resourceMethods)
40+
.withFailMessage("missing endpoints in ProjectApiRoot: %s", resourceMethods)
41+
.isEmpty();
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
2+
package com.commercetools.checkout.defaultconfig;
3+
4+
import java.time.Duration;
5+
import java.util.UUID;
6+
import java.util.function.Consumer;
7+
8+
import com.commercetools.checkout.client.ProjectApiRoot;
9+
10+
import io.vrap.rmf.base.client.oauth2.ClientCredentials;
11+
12+
import org.apache.commons.lang3.StringUtils;
13+
import org.assertj.core.api.SoftAssertions;
14+
15+
public class CheckoutApiTestUtils {
16+
17+
private static final ProjectApiRoot projectRoot;
18+
19+
static {
20+
String logLevel = System.getenv("CTP_JVM_SDK_LOG_LEVEL");
21+
if ("OFF".equals(logLevel)) {
22+
projectRoot = CheckoutApiRootBuilder.of()
23+
.defaultClient(
24+
ClientCredentials.of().withClientId(getClientId()).withClientSecret(getClientSecret()).build(),
25+
ServiceRegion.GCP_EUROPE_WEST1)
26+
.build(getProjectKey());
27+
}
28+
else {
29+
projectRoot = CheckoutApiRootBuilder.of()
30+
.defaultClient(
31+
ClientCredentials.of().withClientId(getClientId()).withClientSecret(getClientSecret()).build(),
32+
ServiceRegion.GCP_EUROPE_WEST1)
33+
.build(getProjectKey());
34+
}
35+
}
36+
37+
public static String randomString() {
38+
return "random-string-" + UUID.randomUUID().toString();
39+
}
40+
41+
public static String randomId() {
42+
return "random-id-" + UUID.randomUUID().toString();
43+
}
44+
45+
public static String randomKey() {
46+
return "random-key-" + UUID.randomUUID().toString();
47+
}
48+
49+
public static String getProjectKey() {
50+
return System.getenv("CTP_PROJECT_KEY");
51+
}
52+
53+
public static String getClientId() {
54+
return System.getenv("CTP_CLIENT_ID");
55+
}
56+
57+
public static String getClientSecret() {
58+
return System.getenv("CTP_CLIENT_SECRET");
59+
}
60+
61+
public static ProjectApiRoot getProjectRoot() {
62+
return projectRoot;
63+
}
64+
65+
public static void assertEventually(final Duration maxWaitTime, final Duration waitBeforeRetry,
66+
final Runnable block) {
67+
final long timeOutAt = System.currentTimeMillis() + maxWaitTime.toMillis();
68+
while (true) {
69+
try {
70+
block.run();
71+
72+
// the block executed without throwing an exception, return
73+
return;
74+
}
75+
catch (AssertionError e) {
76+
if (System.currentTimeMillis() > timeOutAt) {
77+
throw e;
78+
}
79+
}
80+
81+
try {
82+
Thread.sleep(waitBeforeRetry.toMillis());
83+
}
84+
catch (InterruptedException e) {
85+
throw new RuntimeException(e);
86+
}
87+
}
88+
}
89+
90+
public static void assertEventually(final Consumer<SoftAssertions> assertionsConsumer) {
91+
final Runnable block = () -> {
92+
final SoftAssertions softly = new SoftAssertions();
93+
assertionsConsumer.accept(softly);
94+
softly.assertAll();
95+
};
96+
assertEventually(block);
97+
}
98+
99+
public static void assertEventually(final Runnable block) {
100+
final Boolean useLongTimeout = "true".equals(System.getenv("TRAVIS"))
101+
|| StringUtils.isNotEmpty(System.getenv("TEAMCITY_VERSION"))
102+
|| StringUtils.isNoneEmpty(System.getenv("GITHUB_WORKSPACE"));
103+
final Duration maxWaitTime = Duration.ofSeconds(useLongTimeout ? 60 : 30);
104+
final Duration waitBeforeRetry = Duration.ofMillis(100);
105+
assertEventually(maxWaitTime, waitBeforeRetry, block);
106+
}
107+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
package com.commercetools.checkout.defaultconfig;
3+
4+
import com.commercetools.api.client.ProjectApiRoot;
5+
import com.commercetools.api.defaultconfig.ApiRootBuilder;
6+
import com.commercetools.api.models.cart.CartDraft;
7+
import com.commercetools.checkout.models.transaction.TransactionDraft;
8+
9+
import io.vrap.rmf.base.client.oauth2.ClientCredentials;
10+
11+
import org.junit.jupiter.api.Assertions;
12+
import org.junit.jupiter.api.Test;
13+
14+
public class CheckoutIntegrationTests {
15+
16+
private static final ProjectApiRoot projectApiRoot;
17+
private static final com.commercetools.checkout.client.ProjectApiRoot checkoutApiRoot;
18+
19+
static {
20+
projectApiRoot = createApiClient();
21+
checkoutApiRoot = createCheckoutClient();
22+
}
23+
public static ProjectApiRoot createApiClient() {
24+
return ApiRootBuilder.ofEnvironmentVariables().buildProjectRoot();
25+
}
26+
27+
public static com.commercetools.checkout.client.ProjectApiRoot createCheckoutClient() {
28+
return CheckoutApiRootBuilder.of()
29+
.defaultClient(ClientCredentials.of()
30+
.withClientId(System.getenv("CTP_CLIENT_ID"))
31+
.withClientSecret(System.getenv("CTP_CLIENT_SECRET"))
32+
.build(),
33+
ServiceRegion.GCP_EUROPE_WEST1)
34+
.build(System.getenv("CTP_PROJECT_KEY"));
35+
}
36+
37+
// create client, then cart, then transaction
38+
@Test
39+
public void createAndGetTransactionTest() {
40+
var newCart = CartDraft.builder().currency("EUR").build();
41+
42+
var cart = projectApiRoot.carts().post(newCart).executeBlocking().getBody();
43+
Assertions.assertNotNull(cart);
44+
45+
var transactionKey = "transaction-" + CheckoutApiTestUtils.randomKey();
46+
var transaction = checkoutApiRoot.with()
47+
.transactions()
48+
.post(TransactionDraft.builder()
49+
.key(transactionKey)
50+
.application(a -> a.key("demo-commercetools-checkout"))
51+
.cart(c -> c.id(cart.getId()))
52+
.plusTransactionItems(t -> t.amount(a -> a.centAmount(100).currencyCode("EUR"))
53+
.paymentIntegration(p -> p.key("ci-payment-integration")))
54+
.build()
55+
56+
)
57+
.executeBlocking()
58+
.getBody();
59+
60+
// Create transaction
61+
Assertions.assertNotNull(transaction);
62+
63+
Assertions.assertNotNull(
64+
checkoutApiRoot.with().transactions().withId(transaction.getId()).get().executeBlocking().getBody());
65+
Assertions.assertEquals(transactionKey, transaction.getKey());
66+
Assertions.assertNotNull(
67+
checkoutApiRoot.with().transactions().withKey(transaction.getKey()).get().executeBlocking().getBody());
68+
}
69+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<configuration debug="false">
2+
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
3+
<resetJUL>true</resetJUL>
4+
</contextListener>
5+
6+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
7+
<encoder>
8+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
9+
</encoder>
10+
</appender>
11+
12+
<logger name="commercetools" level="WARN"/>
13+
14+
<root level="INFO">
15+
<appender-ref ref="STDOUT" />
16+
</root>
17+
</configuration>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
package com.commercetools.checkout.client;
3+
4+
import java.io.Closeable;
5+
6+
import io.vrap.rmf.base.client.ApiHttpClient;
7+
import io.vrap.rmf.base.client.SerializerOnlyApiHttpClient;
8+
import io.vrap.rmf.base.client.utils.Generated;
9+
10+
/**
11+
* Entrypoint for building requests against the API
12+
*/
13+
@Generated(value = "io.vrap.rmf.codegen.rendering.CoreCodeGenerator", comments = "https://github.com/commercetools/rmf-codegen")
14+
public class ApiRoot implements Closeable {
15+
16+
private final ApiHttpClient apiHttpClient;
17+
18+
private ApiRoot(final ApiHttpClient apiHttpClient) {
19+
this.apiHttpClient = apiHttpClient;
20+
}
21+
22+
public static ApiRoot of() {
23+
return new ApiRoot(SerializerOnlyApiHttpClient.of());
24+
}
25+
26+
public static ApiRoot fromClient(final ApiHttpClient apiHttpClient) {
27+
return new ApiRoot(apiHttpClient);
28+
}
29+
30+
public ByProjectKeyRequestBuilder withProjectKey(String projectKey) {
31+
return new ByProjectKeyRequestBuilder(this.apiHttpClient, projectKey);
32+
}
33+
34+
@Override
35+
public void close() {
36+
if (apiHttpClient == null) {
37+
return;
38+
}
39+
try {
40+
apiHttpClient.close();
41+
}
42+
catch (final Throwable ignored) {
43+
}
44+
}
45+
46+
}

0 commit comments

Comments
 (0)