From ab39478f70461c0daad09c22883690b489ab5f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:49:30 +0200 Subject: [PATCH] Knet Updates. Workflow updates (#436) --- .../payments/PaymentMethodsDetails.java | 20 ++++++++++++ .../request/source/apm/RequestKnetSource.java | 31 ++++++++++++++---- .../request/source/apm/RequestKnetSource.java | 19 ++++++++++- .../workflows/UpdateWorkflowRequest.java | 11 +++++++ .../workflows/UpdateWorkflowResponse.java | 17 ++++++++-- .../checkout/workflows/WorkflowsClient.java | 3 ++ .../workflows/WorkflowsClientImpl.java | 13 ++++++++ .../response/WorkflowActionInvocation.java | 1 + .../events/EventActionInvocation.java | 22 +++++++++++++ .../workflows/events/EventTypesRequest.java | 17 ++++++++++ .../workflows/events/GetEventResponse.java | 12 +++++-- .../payments/RequestApmPaymentsIT.java | 7 +++- .../previous/RequestApmPaymentsIT.java | 8 ++++- .../workflows/WorkflowsClientImplTest.java | 21 +++++++++++- .../checkout/workflows/WorkflowsTestIT.java | 32 +++++++++++++++++++ 15 files changed, 219 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/checkout/payments/PaymentMethodsDetails.java create mode 100644 src/main/java/com/checkout/workflows/events/EventActionInvocation.java create mode 100644 src/main/java/com/checkout/workflows/events/EventTypesRequest.java diff --git a/src/main/java/com/checkout/payments/PaymentMethodsDetails.java b/src/main/java/com/checkout/payments/PaymentMethodsDetails.java new file mode 100644 index 00000000..e2db7a6d --- /dev/null +++ b/src/main/java/com/checkout/payments/PaymentMethodsDetails.java @@ -0,0 +1,20 @@ +package com.checkout.payments; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@AllArgsConstructor +public final class PaymentMethodsDetails { + + @SerializedName("display_name") + private String displayName; + + private String type; + + private String network; + +} diff --git a/src/main/java/com/checkout/payments/previous/request/source/apm/RequestKnetSource.java b/src/main/java/com/checkout/payments/previous/request/source/apm/RequestKnetSource.java index 5df5466a..1b179ff2 100644 --- a/src/main/java/com/checkout/payments/previous/request/source/apm/RequestKnetSource.java +++ b/src/main/java/com/checkout/payments/previous/request/source/apm/RequestKnetSource.java @@ -1,7 +1,9 @@ package com.checkout.payments.previous.request.source.apm; import com.checkout.common.PaymentSourceType; +import com.checkout.payments.PaymentMethodsDetails; import com.checkout.payments.previous.request.source.AbstractRequestSource; +import com.checkout.tokens.ApplePayTokenData; import com.google.gson.annotations.SerializedName; import lombok.Builder; import lombok.EqualsAndHashCode; @@ -37,15 +39,27 @@ public final class RequestKnetSource extends AbstractRequestSource { private String ptlf; + @SerializedName("token_type") + private String tokenType; + + @SerializedName("token_data") + private ApplePayTokenData tokenData; + + @SerializedName("payment_method_details") + private PaymentMethodsDetails paymentMethodsDetails; + @Builder private RequestKnetSource(final String language, - final String userDefinedField1, - final String userDefinedField2, - final String userDefinedField3, - final String userDefinedField4, - final String userDefinedField5, - final String cardToken, - final String ptlf) { + final String userDefinedField1, + final String userDefinedField2, + final String userDefinedField3, + final String userDefinedField4, + final String userDefinedField5, + final String cardToken, + final String ptlf, + final String tokenType, + final ApplePayTokenData tokenData, + final PaymentMethodsDetails paymentMethodsDetails) { super(PaymentSourceType.KNET); this.language = language; this.userDefinedField1 = userDefinedField1; @@ -55,6 +69,9 @@ private RequestKnetSource(final String language, this.userDefinedField5 = userDefinedField5; this.cardToken = cardToken; this.ptlf = ptlf; + this.tokenType = tokenType; + this.tokenData = tokenData; + this.paymentMethodsDetails = paymentMethodsDetails; } public RequestKnetSource() { diff --git a/src/main/java/com/checkout/payments/request/source/apm/RequestKnetSource.java b/src/main/java/com/checkout/payments/request/source/apm/RequestKnetSource.java index badb1b92..7d94d002 100644 --- a/src/main/java/com/checkout/payments/request/source/apm/RequestKnetSource.java +++ b/src/main/java/com/checkout/payments/request/source/apm/RequestKnetSource.java @@ -1,7 +1,9 @@ package com.checkout.payments.request.source.apm; import com.checkout.common.PaymentSourceType; +import com.checkout.payments.PaymentMethodsDetails; import com.checkout.payments.request.source.AbstractRequestSource; +import com.checkout.tokens.ApplePayTokenData; import com.google.gson.annotations.SerializedName; import lombok.Builder; import lombok.EqualsAndHashCode; @@ -37,6 +39,15 @@ public final class RequestKnetSource extends AbstractRequestSource { private String ptlf; + @SerializedName("token_type") + private String tokenType; + + @SerializedName("token_data") + private ApplePayTokenData tokenData; + + @SerializedName("payment_method_details") + private PaymentMethodsDetails paymentMethodsDetails; + @Builder private RequestKnetSource(final String language, final String userDefinedField1, @@ -45,7 +56,10 @@ private RequestKnetSource(final String language, final String userDefinedField4, final String userDefinedField5, final String cardToken, - final String ptlf) { + final String ptlf, + final String tokenType, + final ApplePayTokenData tokenData, + final PaymentMethodsDetails paymentMethodsDetails) { super(PaymentSourceType.KNET); this.language = language; this.userDefinedField1 = userDefinedField1; @@ -55,6 +69,9 @@ private RequestKnetSource(final String language, this.userDefinedField5 = userDefinedField5; this.cardToken = cardToken; this.ptlf = ptlf; + this.tokenType = tokenType; + this.tokenData = tokenData; + this.paymentMethodsDetails = paymentMethodsDetails; } public RequestKnetSource() { diff --git a/src/main/java/com/checkout/workflows/UpdateWorkflowRequest.java b/src/main/java/com/checkout/workflows/UpdateWorkflowRequest.java index baa0ffb0..fb6d6e0e 100644 --- a/src/main/java/com/checkout/workflows/UpdateWorkflowRequest.java +++ b/src/main/java/com/checkout/workflows/UpdateWorkflowRequest.java @@ -1,9 +1,14 @@ package com.checkout.workflows; +import com.checkout.workflows.actions.request.WorkflowActionRequest; +import com.checkout.workflows.conditions.request.WorkflowConditionRequest; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import java.util.ArrayList; +import java.util.List; + @Data @Builder @AllArgsConstructor @@ -13,4 +18,10 @@ public final class UpdateWorkflowRequest { private Boolean active; + @Builder.Default + private List conditions = new ArrayList<>(); + + @Builder.Default + private List actions = new ArrayList<>(); + } diff --git a/src/main/java/com/checkout/workflows/UpdateWorkflowResponse.java b/src/main/java/com/checkout/workflows/UpdateWorkflowResponse.java index dd250b4a..16c9f01a 100644 --- a/src/main/java/com/checkout/workflows/UpdateWorkflowResponse.java +++ b/src/main/java/com/checkout/workflows/UpdateWorkflowResponse.java @@ -1,15 +1,28 @@ package com.checkout.workflows; -import com.checkout.HttpMetadata; +import com.checkout.common.Resource; +import com.checkout.workflows.actions.response.WorkflowActionResponse; +import com.checkout.workflows.conditions.response.WorkflowConditionResponse; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.ArrayList; +import java.util.List; @Data @EqualsAndHashCode(callSuper = true) -public final class UpdateWorkflowResponse extends HttpMetadata { +@ToString(callSuper = true) +public final class UpdateWorkflowResponse extends Resource { + + private String id; private String name; private Boolean active; + private List conditions = new ArrayList<>(); + + private List actions = new ArrayList<>(); + } diff --git a/src/main/java/com/checkout/workflows/WorkflowsClient.java b/src/main/java/com/checkout/workflows/WorkflowsClient.java index c598a94c..2edfe084 100644 --- a/src/main/java/com/checkout/workflows/WorkflowsClient.java +++ b/src/main/java/com/checkout/workflows/WorkflowsClient.java @@ -6,6 +6,7 @@ import com.checkout.workflows.actions.request.WorkflowActionRequest; import com.checkout.workflows.actions.response.WorkflowActionInvocationsResponse; import com.checkout.workflows.conditions.request.WorkflowConditionRequest; +import com.checkout.workflows.events.EventTypesRequest; import com.checkout.workflows.events.GetEventResponse; import com.checkout.workflows.events.SubjectEventsResponse; import com.checkout.workflows.events.WorkflowEventTypes; @@ -38,6 +39,8 @@ public interface WorkflowsClient { CompletableFuture removeWorkflowCondition(String workflowId, String conditionId); + CompletableFuture testWorkflow(String workflowId, EventTypesRequest eventTypesRequest); + CompletableFuture> getEventTypes(); CompletableFuture getEvent(String eventId); diff --git a/src/main/java/com/checkout/workflows/WorkflowsClientImpl.java b/src/main/java/com/checkout/workflows/WorkflowsClientImpl.java index a8fe7365..06f7b5aa 100644 --- a/src/main/java/com/checkout/workflows/WorkflowsClientImpl.java +++ b/src/main/java/com/checkout/workflows/WorkflowsClientImpl.java @@ -10,6 +10,7 @@ import com.checkout.workflows.actions.request.WorkflowActionRequest; import com.checkout.workflows.actions.response.WorkflowActionInvocationsResponse; import com.checkout.workflows.conditions.request.WorkflowConditionRequest; +import com.checkout.workflows.events.EventTypesRequest; import com.checkout.workflows.events.GetEventResponse; import com.checkout.workflows.events.SubjectEventsResponse; import com.checkout.workflows.events.WorkflowEventTypes; @@ -33,6 +34,7 @@ public class WorkflowsClientImpl extends AbstractClient implements WorkflowsClie private static final String REFLOW_PATH = "reflow"; private static final String SUBJECT_PATH = "subject"; private static final String WORKFLOW_ID = "workflowId"; + private static final String TEST_PATH = "test"; private static final Type WORKFLOWS_EVENT_TYPES_TYPE = new TypeToken>() { }.getType(); @@ -151,6 +153,17 @@ public CompletableFuture removeWorkflowCondition(final String wor sdkAuthorization()); } + @Override + public CompletableFuture testWorkflow(String workflowId, EventTypesRequest eventTypesRequest) { + validateParams(WORKFLOW_ID, workflowId, "eventTypesRequest", eventTypesRequest); + return apiClient.postAsync( + buildPath(WORKFLOWS_PATH, workflowId, TEST_PATH), + sdkAuthorization(), + EmptyResponse.class, + eventTypesRequest, + null); + } + @Override public CompletableFuture> getEventTypes() { return apiClient.getAsync( diff --git a/src/main/java/com/checkout/workflows/actions/response/WorkflowActionInvocation.java b/src/main/java/com/checkout/workflows/actions/response/WorkflowActionInvocation.java index 5253c2a4..689c4d8f 100644 --- a/src/main/java/com/checkout/workflows/actions/response/WorkflowActionInvocation.java +++ b/src/main/java/com/checkout/workflows/actions/response/WorkflowActionInvocation.java @@ -21,5 +21,6 @@ public final class WorkflowActionInvocation { @SerializedName("final") private Boolean finalAttempt; + @SerializedName("result_details") private Map result; } diff --git a/src/main/java/com/checkout/workflows/events/EventActionInvocation.java b/src/main/java/com/checkout/workflows/events/EventActionInvocation.java new file mode 100644 index 00000000..c7ccbc60 --- /dev/null +++ b/src/main/java/com/checkout/workflows/events/EventActionInvocation.java @@ -0,0 +1,22 @@ +package com.checkout.workflows.events; + +import com.checkout.common.Resource; +import com.checkout.workflows.actions.WorkflowActionStatus; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public final class EventActionInvocation extends Resource { + + @SerializedName("workflow_id") + private String workflowId; + + @SerializedName("workflow_action_id") + private String workflowActionId; + + private WorkflowActionStatus status; +} diff --git a/src/main/java/com/checkout/workflows/events/EventTypesRequest.java b/src/main/java/com/checkout/workflows/events/EventTypesRequest.java new file mode 100644 index 00000000..8be8b716 --- /dev/null +++ b/src/main/java/com/checkout/workflows/events/EventTypesRequest.java @@ -0,0 +1,17 @@ +package com.checkout.workflows.events; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +public final class EventTypesRequest { + + @SerializedName("event_types") + private List eventTypes; +} diff --git a/src/main/java/com/checkout/workflows/events/GetEventResponse.java b/src/main/java/com/checkout/workflows/events/GetEventResponse.java index 787c9bc6..0e176b14 100644 --- a/src/main/java/com/checkout/workflows/events/GetEventResponse.java +++ b/src/main/java/com/checkout/workflows/events/GetEventResponse.java @@ -1,14 +1,19 @@ package com.checkout.workflows.events; -import com.checkout.HttpMetadata; +import com.checkout.common.Resource; +import com.checkout.workflows.actions.response.WorkflowActionInvocation; +import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.ToString; +import java.util.List; import java.util.Map; @Data @EqualsAndHashCode(callSuper = true) -public final class GetEventResponse extends HttpMetadata { +@ToString(callSuper = true) +public final class GetEventResponse extends Resource { private String id; @@ -22,4 +27,7 @@ public final class GetEventResponse extends HttpMetadata { private Map data; + @SerializedName("action_invocations") + private List actionInvocations; + } diff --git a/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java b/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java index d4acb448..0110602a 100644 --- a/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java +++ b/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java @@ -365,6 +365,11 @@ void shouldMakeKnetPayment() { final PaymentRequest paymentRequest = PaymentRequest.builder() .source(RequestKnetSource.builder() .language("en") + .paymentMethodsDetails(PaymentMethodsDetails.builder() + .displayName("name") + .type("type") + .network("card_network") + .build()) .build()) .currency(Currency.KWD) .amount(1000L) @@ -373,7 +378,7 @@ void shouldMakeKnetPayment() { .failureUrl("https://testing.checkout.com/failure") .build(); - checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), APM_SERVICE_UNAVAILABLE); + checkErrorItem(() -> paymentsClient.requestPayment(paymentRequest), PAYEE_NOT_ONBOARDED); } @Test diff --git a/src/test/java/com/checkout/payments/previous/RequestApmPaymentsIT.java b/src/test/java/com/checkout/payments/previous/RequestApmPaymentsIT.java index 5610b5a7..4f5ad2c4 100644 --- a/src/test/java/com/checkout/payments/previous/RequestApmPaymentsIT.java +++ b/src/test/java/com/checkout/payments/previous/RequestApmPaymentsIT.java @@ -3,6 +3,7 @@ import com.checkout.common.CountryCode; import com.checkout.common.Currency; import com.checkout.common.PaymentSourceType; +import com.checkout.payments.PaymentMethodsDetails; import com.checkout.payments.previous.request.PaymentRequest; import com.checkout.payments.previous.request.source.apm.IntegrationType; import com.checkout.payments.previous.request.source.apm.RequestAlipaySource; @@ -278,12 +279,17 @@ void shouldMakeSofortPayment() { assertEquals(PaymentSourceType.SOFORT, paymentDetails.getSource().getType()); } - @Disabled("not available") + //@Disabled("not available") @Test void shouldMakeKnetPayment() { final PaymentRequest paymentRequest = PaymentRequest.builder() .source(RequestKnetSource.builder() .language("en") + .paymentMethodsDetails(PaymentMethodsDetails.builder() + .displayName("name") + .type("type") + .network("card_network") + .build()) .build()) .currency(Currency.KWD) .amount(1000L) diff --git a/src/test/java/com/checkout/workflows/WorkflowsClientImplTest.java b/src/test/java/com/checkout/workflows/WorkflowsClientImplTest.java index d78aa48a..105768b7 100644 --- a/src/test/java/com/checkout/workflows/WorkflowsClientImplTest.java +++ b/src/test/java/com/checkout/workflows/WorkflowsClientImplTest.java @@ -12,6 +12,7 @@ import com.checkout.workflows.actions.request.WorkflowActionRequest; import com.checkout.workflows.actions.response.WorkflowActionInvocationsResponse; import com.checkout.workflows.conditions.request.WorkflowConditionRequest; +import com.checkout.workflows.events.EventTypesRequest; import com.checkout.workflows.events.GetEventResponse; import com.checkout.workflows.events.SubjectEventsResponse; import com.checkout.workflows.events.WorkflowEventTypes; @@ -19,7 +20,6 @@ import com.checkout.workflows.reflow.ReflowResponse; import com.google.gson.reflect.TypeToken; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -356,6 +356,25 @@ void shouldRemoveWorkflowCondition() throws ExecutionException, InterruptedExcep } + @Test + void shouldTestWorkflow() throws ExecutionException, InterruptedException { + + when(sdkCredentials.getAuthorization(SdkAuthorizationType.SECRET_KEY_OR_OAUTH)).thenReturn(authorization); + when(configuration.getSdkCredentials()).thenReturn(sdkCredentials); + + final EmptyResponse response = Mockito.mock(EmptyResponse.class); + final EventTypesRequest eventTypesRequest = Mockito.mock(EventTypesRequest.class); + + when(apiClient.postAsync("workflows/workflow_id/test", authorization, EmptyResponse.class, eventTypesRequest, null)) + .thenReturn(CompletableFuture.completedFuture(response)); + + final CompletableFuture future = workflowsClient.testWorkflow("workflow_id", eventTypesRequest); + + assertNotNull(future.get()); + assertEquals(response, future.get()); + + } + @Test void shouldFailUpdateWorkflowCondition_invalidParams() { try { diff --git a/src/test/java/com/checkout/workflows/WorkflowsTestIT.java b/src/test/java/com/checkout/workflows/WorkflowsTestIT.java index 1428f665..85688c72 100644 --- a/src/test/java/com/checkout/workflows/WorkflowsTestIT.java +++ b/src/test/java/com/checkout/workflows/WorkflowsTestIT.java @@ -1,5 +1,6 @@ package com.checkout.workflows; +import com.checkout.EmptyResponse; import com.checkout.common.IdResponse; import com.checkout.workflows.actions.request.WebhookWorkflowActionRequest; import com.checkout.workflows.actions.response.WebhookWorkflowActionResponse; @@ -7,6 +8,7 @@ import com.checkout.workflows.conditions.request.EventWorkflowConditionRequest; import com.checkout.workflows.conditions.response.EntityWorkflowConditionResponse; import com.checkout.workflows.conditions.response.EventWorkflowConditionResponse; +import com.checkout.workflows.events.EventTypesRequest; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -186,6 +188,36 @@ void shouldUpdateWorkflowCondition() { } + @Test + void shouldCreateAndTestWorkflows() { + + final CreateWorkflowResponse createWorkflowResponse = createWorkflow(); + final EventTypesRequest eventTypesRequest = EventTypesRequest.builder() + .eventTypes(Arrays.asList("payment_approved", + "payment_declined", + "card_verification_declined", + "card_verified", + "payment_authorization_incremented", + "payment_authorization_increment_declined", + "payment_capture_declined", + "payment_captured", + "payment_refund_declined", + "payment_refunded", + "payment_void_declined", + "payment_voided", + "dispute_canceled", + "dispute_evidence_required", + "dispute_expired", + "dispute_lost", + "dispute_resolved", + "dispute_won")) + .build(); + + final EmptyResponse response = blocking(() -> checkoutApi.workflowsClient().testWorkflow(createWorkflowResponse.getId(), eventTypesRequest)); + assertNotNull(response); + + } + protected CreateWorkflowResponse createWorkflow() { final CreateWorkflowRequest request = CreateWorkflowRequest.builder()