diff --git a/src/main/java/com/checkout/CheckoutApi.java b/src/main/java/com/checkout/CheckoutApi.java index 2d10f3b6..71db611b 100644 --- a/src/main/java/com/checkout/CheckoutApi.java +++ b/src/main/java/com/checkout/CheckoutApi.java @@ -10,10 +10,10 @@ import com.checkout.issuing.IssuingClient; import com.checkout.metadata.MetadataClient; import com.checkout.payments.PaymentsClient; -import com.checkout.payments.contexts.PaymentContexts; import com.checkout.payments.contexts.PaymentContextsClient; import com.checkout.payments.hosted.HostedPaymentsClient; import com.checkout.payments.links.PaymentLinksClient; +import com.checkout.payments.sessions.PaymentSessionsClient; import com.checkout.reports.ReportsClient; import com.checkout.risk.RiskClient; import com.checkout.sessions.SessionsClient; @@ -61,5 +61,6 @@ public interface CheckoutApi extends CheckoutApmApi { PaymentContextsClient paymentContextsClient(); -} + PaymentSessionsClient paymentSessionsClient(); +} diff --git a/src/main/java/com/checkout/CheckoutApiImpl.java b/src/main/java/com/checkout/CheckoutApiImpl.java index 2054f5ae..27c18c78 100644 --- a/src/main/java/com/checkout/CheckoutApiImpl.java +++ b/src/main/java/com/checkout/CheckoutApiImpl.java @@ -20,13 +20,14 @@ import com.checkout.metadata.MetadataClientImpl; import com.checkout.payments.PaymentsClient; import com.checkout.payments.PaymentsClientImpl; -import com.checkout.payments.contexts.PaymentContexts; import com.checkout.payments.contexts.PaymentContextsClient; import com.checkout.payments.contexts.PaymentContextsClientImpl; import com.checkout.payments.hosted.HostedPaymentsClient; import com.checkout.payments.hosted.HostedPaymentsClientImpl; import com.checkout.payments.links.PaymentLinksClient; import com.checkout.payments.links.PaymentLinksClientImpl; +import com.checkout.payments.sessions.PaymentSessionsClient; +import com.checkout.payments.sessions.PaymentSessionsClientImpl; import com.checkout.reports.ReportsClient; import com.checkout.reports.ReportsClientImpl; import com.checkout.risk.RiskClient; @@ -63,6 +64,7 @@ public class CheckoutApiImpl extends AbstractCheckoutApmApi implements CheckoutA private final FinancialClient financialClient; private final IssuingClient issuingClient; private final PaymentContextsClient paymentContextsClient; + private final PaymentSessionsClient paymentSessionsClient; public CheckoutApiImpl(final CheckoutConfiguration configuration) { super(configuration); @@ -87,6 +89,7 @@ public CheckoutApiImpl(final CheckoutConfiguration configuration) { getFilesClient(configuration), configuration); this.paymentContextsClient = new PaymentContextsClientImpl(this.apiClient, configuration); + this.paymentSessionsClient = new PaymentSessionsClientImpl(this.apiClient, configuration); } @@ -179,6 +182,9 @@ public MetadataClient metadataClient() { @Override public PaymentContextsClient paymentContextsClient() { return paymentContextsClient; } + @Override + public PaymentSessionsClient paymentSessionsClient() { return paymentSessionsClient; } + private ApiClient getFilesClient(final CheckoutConfiguration configuration) { return new ApiClientImpl(configuration, new FilesApiUriStrategy(configuration)); } @@ -203,6 +209,7 @@ private FilesApiUriStrategy(final CheckoutConfiguration configuration) { public URI getUri() { return configuration.getEnvironment().getFilesApi(); } + } private static class TransfersApiUriStrategy implements UriStrategy { @@ -217,6 +224,7 @@ private TransfersApiUriStrategy(final CheckoutConfiguration configuration) { public URI getUri() { return configuration.getEnvironment().getTransfersApi(); } + } private static class BalancesApiUriStrategy implements UriStrategy { @@ -231,6 +239,7 @@ private BalancesApiUriStrategy(final CheckoutConfiguration configuration) { public URI getUri() { return configuration.getEnvironment().getBalancesApi(); } + } } diff --git a/src/main/java/com/checkout/payments/sessions/Billing.java b/src/main/java/com/checkout/payments/sessions/Billing.java new file mode 100644 index 00000000..d5df21e6 --- /dev/null +++ b/src/main/java/com/checkout/payments/sessions/Billing.java @@ -0,0 +1,17 @@ +package com.checkout.payments.sessions; + +import com.checkout.common.Address; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public final class Billing { + + private Address address; + +} diff --git a/src/main/java/com/checkout/payments/sessions/PaymentMethods.java b/src/main/java/com/checkout/payments/sessions/PaymentMethods.java new file mode 100644 index 00000000..33408c1c --- /dev/null +++ b/src/main/java/com/checkout/payments/sessions/PaymentMethods.java @@ -0,0 +1,22 @@ +package com.checkout.payments.sessions; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public final class PaymentMethods { + + private String type; + + @SerializedName("card_schemes") + private List cardSchemes; + +} diff --git a/src/main/java/com/checkout/payments/sessions/PaymentSessionsClient.java b/src/main/java/com/checkout/payments/sessions/PaymentSessionsClient.java new file mode 100644 index 00000000..8e2e509c --- /dev/null +++ b/src/main/java/com/checkout/payments/sessions/PaymentSessionsClient.java @@ -0,0 +1,9 @@ +package com.checkout.payments.sessions; + +import java.util.concurrent.CompletableFuture; + +public interface PaymentSessionsClient { + + CompletableFuture requestPaymentSessions(PaymentSessionsRequest paymentSessionsRequest); + +} diff --git a/src/main/java/com/checkout/payments/sessions/PaymentSessionsClientImpl.java b/src/main/java/com/checkout/payments/sessions/PaymentSessionsClientImpl.java new file mode 100644 index 00000000..0d9ae95f --- /dev/null +++ b/src/main/java/com/checkout/payments/sessions/PaymentSessionsClientImpl.java @@ -0,0 +1,29 @@ +package com.checkout.payments.sessions; + +import com.checkout.AbstractClient; +import com.checkout.ApiClient; +import com.checkout.CheckoutConfiguration; +import com.checkout.SdkAuthorizationType; + +import java.util.concurrent.CompletableFuture; + +import static com.checkout.common.CheckoutUtils.validateParams; + +public class PaymentSessionsClientImpl extends AbstractClient implements PaymentSessionsClient { + + private static final String PAYMENT_SESSIONS_PATH = "payment-sessions"; + + public PaymentSessionsClientImpl(final ApiClient apiClient, final CheckoutConfiguration configuration) { + super(apiClient, configuration, SdkAuthorizationType.SECRET_KEY); + } + + @Override + public CompletableFuture requestPaymentSessions(final PaymentSessionsRequest paymentSessionsRequest) { + + validateParams("paymentSessionsRequest", paymentSessionsRequest); + + return apiClient.postAsync(PAYMENT_SESSIONS_PATH, sdkAuthorization(), PaymentSessionsResponse.class, paymentSessionsRequest, null); + + } + +} diff --git a/src/main/java/com/checkout/payments/sessions/PaymentSessionsRequest.java b/src/main/java/com/checkout/payments/sessions/PaymentSessionsRequest.java new file mode 100644 index 00000000..26cee9bd --- /dev/null +++ b/src/main/java/com/checkout/payments/sessions/PaymentSessionsRequest.java @@ -0,0 +1,33 @@ +package com.checkout.payments.sessions; + +import com.checkout.common.Currency; +import com.checkout.common.CustomerRequest; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public final class PaymentSessionsRequest { + + private Long amount; + + private Currency currency; + + private String reference; + + private Billing billing; + + private CustomerRequest customer; + + @SerializedName("success_url") + private String successUrl; + + @SerializedName("failure_url") + private String failureUrl; + +} diff --git a/src/main/java/com/checkout/payments/sessions/PaymentSessionsResponse.java b/src/main/java/com/checkout/payments/sessions/PaymentSessionsResponse.java new file mode 100644 index 00000000..ac029296 --- /dev/null +++ b/src/main/java/com/checkout/payments/sessions/PaymentSessionsResponse.java @@ -0,0 +1,31 @@ +package com.checkout.payments.sessions; + +import com.checkout.common.Currency; +import com.checkout.common.CustomerResponse; +import com.checkout.common.Resource; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public final class PaymentSessionsResponse extends Resource { + + private String id; + + private Long amount; + + private String locale; + + private Currency currency; + + private CustomerResponse customer; + + @SerializedName("payment_methods") + private List paymentMethods; + +} diff --git a/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java b/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java index 250c1ad2..86441e3a 100644 --- a/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java +++ b/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java @@ -567,6 +567,7 @@ void shouldMakeCvConnectPayment() { checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), PAYEE_NOT_ONBOARDED); } + @Disabled("Temporarily skipped") @Test void shouldMakeSepaV4Payment() { final PaymentRequest paymentRequest = PaymentRequest.builder() diff --git a/src/test/java/com/checkout/payments/sessions/PaymentSessionsClientImplTest.java b/src/test/java/com/checkout/payments/sessions/PaymentSessionsClientImplTest.java new file mode 100644 index 00000000..aad67a0f --- /dev/null +++ b/src/test/java/com/checkout/payments/sessions/PaymentSessionsClientImplTest.java @@ -0,0 +1,64 @@ +package com.checkout.payments.sessions; + +import com.checkout.ApiClient; +import com.checkout.CheckoutConfiguration; +import com.checkout.SdkAuthorization; +import com.checkout.SdkAuthorizationType; +import com.checkout.SdkCredentials; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class PaymentSessionsClientImplTest { + + private PaymentSessionsClient client; + + @Mock + private ApiClient apiClient; + + @Mock + private CheckoutConfiguration configuration; + + @Mock + private SdkCredentials sdkCredentials; + + @Mock + private SdkAuthorization authorization; + + @BeforeEach + void setUp() { + when(sdkCredentials.getAuthorization(SdkAuthorizationType.SECRET_KEY)).thenReturn(authorization); + when(configuration.getSdkCredentials()).thenReturn(sdkCredentials); + client = new PaymentSessionsClientImpl(apiClient, configuration); + } + + @Test + void shouldRequestPaymentSessions() throws ExecutionException, InterruptedException { + + final PaymentSessionsRequest request = mock(PaymentSessionsRequest.class); + final PaymentSessionsResponse response = mock(PaymentSessionsResponse.class); + + when(apiClient.postAsync(eq("payment-sessions"), eq(authorization), eq(PaymentSessionsResponse.class), + eq(request), isNull())) + .thenReturn(CompletableFuture.completedFuture(response)); + + final CompletableFuture future = client.requestPaymentSessions(request); + + assertNotNull(future.get()); + assertEquals(response, future.get()); + + } +} diff --git a/src/test/java/com/checkout/payments/sessions/PaymentSessionsTestIT.java b/src/test/java/com/checkout/payments/sessions/PaymentSessionsTestIT.java new file mode 100644 index 00000000..e8391b50 --- /dev/null +++ b/src/test/java/com/checkout/payments/sessions/PaymentSessionsTestIT.java @@ -0,0 +1,47 @@ +package com.checkout.payments.sessions; + +import com.checkout.PlatformType; +import com.checkout.SandboxTestFixture; +import com.checkout.common.Currency; +import org.junit.jupiter.api.Test; + +import static com.checkout.TestHelper.createAddress; +import static com.checkout.TestHelper.createCustomer; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class PaymentSessionsTestIT extends SandboxTestFixture { + + PaymentSessionsTestIT() { + super(PlatformType.DEFAULT); + } + + @Test + void shouldMakeAPaymentSessionsRequest() { + + final Billing billing = Billing.builder() + .address(createAddress()) + .build(); + + final PaymentSessionsRequest request = PaymentSessionsRequest.builder() + .amount(1000L) + .currency(Currency.GBP) + .reference("ORD-123A") + .billing(billing) + .customer(createCustomer()) + .successUrl("https://example.com/payments/success") + .failureUrl("https://example.com/payments/failure") + .build(); + + final PaymentSessionsResponse response = blocking(() -> checkoutApi.paymentSessionsClient().requestPaymentSessions(request)); + + assertNotNull(response); + assertNotNull(response.getId()); + assertEquals("en-GB", response.getLocale()); + assertEquals(Currency.GBP, response.getCurrency()); + assertNotNull(response.getPaymentMethods()); + assertNotNull(response.getLinks()); + + } + +}