diff --git a/payments/abc/sources/apm/apm.go b/payments/abc/sources/apm/apm.go index d666fa8..aadec95 100644 --- a/payments/abc/sources/apm/apm.go +++ b/payments/abc/sources/apm/apm.go @@ -1,6 +1,7 @@ package apm import ( + "github.com/checkout/checkout-sdk-go/tokens" "time" "github.com/checkout/checkout-sdk-go/common" @@ -82,15 +83,18 @@ type ( } requestKnetSource struct { - Type payments.SourceType `json:"type,omitempty"` - Language string `json:"language,omitempty"` - UserDefinedField1 string `json:"user_defined_field1,omitempty"` - UserDefinedField2 string `json:"user_defined_field2,omitempty"` - UserDefinedField3 string `json:"user_defined_field3,omitempty"` - UserDefinedField4 string `json:"user_defined_field4,omitempty"` - UserDefinedField5 string `json:"user_defined_field5,omitempty"` - CardToken string `json:"card_token,omitempty"` - Ptlf string `json:"ptlf,omitempty"` + Type payments.SourceType `json:"type,omitempty"` + Language string `json:"language,omitempty"` + UserDefinedField1 string `json:"user_defined_field1,omitempty"` + UserDefinedField2 string `json:"user_defined_field2,omitempty"` + UserDefinedField3 string `json:"user_defined_field3,omitempty"` + UserDefinedField4 string `json:"user_defined_field4,omitempty"` + UserDefinedField5 string `json:"user_defined_field5,omitempty"` + CardToken string `json:"card_token,omitempty"` + Ptlf string `json:"ptlf,omitempty"` + TokenType string `json:"token_type,omitempty"` + TokenData *tokens.ApplePayTokenData `json:"token_data,omitempty"` + PaymentMethodDetails *payments.PaymentMethodDetails `json:"payment_method_details,omitempty"` } requestMultiBancoSource struct { diff --git a/payments/nas/sources/apm/apm.go b/payments/nas/sources/apm/apm.go index 95b9e46..22df80d 100644 --- a/payments/nas/sources/apm/apm.go +++ b/payments/nas/sources/apm/apm.go @@ -3,6 +3,7 @@ package apm import ( "github.com/checkout/checkout-sdk-go/common" "github.com/checkout/checkout-sdk-go/payments" + "github.com/checkout/checkout-sdk-go/tokens" "time" ) @@ -108,15 +109,18 @@ type ( } requestKnetSource struct { - Type payments.SourceType `json:"type,omitempty"` - Language string `json:"language,omitempty"` - UserDefinedField1 string `json:"user_defined_field1,omitempty"` - UserDefinedField2 string `json:"user_defined_field2,omitempty"` - UserDefinedField3 string `json:"user_defined_field3,omitempty"` - UserDefinedField4 string `json:"user_defined_field4,omitempty"` - UserDefinedField5 string `json:"user_defined_field5,omitempty"` - CardToken string `json:"card_token,omitempty"` - Ptlf string `json:"ptlf,omitempty"` + Type payments.SourceType `json:"type,omitempty"` + Language string `json:"language,omitempty"` + UserDefinedField1 string `json:"user_defined_field1,omitempty"` + UserDefinedField2 string `json:"user_defined_field2,omitempty"` + UserDefinedField3 string `json:"user_defined_field3,omitempty"` + UserDefinedField4 string `json:"user_defined_field4,omitempty"` + UserDefinedField5 string `json:"user_defined_field5,omitempty"` + CardToken string `json:"card_token,omitempty"` + Ptlf string `json:"ptlf,omitempty"` + TokenType string `json:"token_type,omitempty"` + TokenData *tokens.ApplePayTokenData `json:"token_data,omitempty"` + PaymentMethodDetails *payments.PaymentMethodDetails `json:"payment_method_details,omitempty"` } requestMbwaySource struct { diff --git a/payments/payments.go b/payments/payments.go index f9fea9d..ec8cbeb 100644 --- a/payments/payments.go +++ b/payments/payments.go @@ -455,6 +455,12 @@ type ( Type string `json:"type,omitempty"` ServiceEndsOn *time.Time `json:"service_ends_on,omitempty"` } + + PaymentMethodDetails struct { + DisplayName string `json:"display_name,omitempty"` + Type string `json:"type,omitempty"` + Network string `json:"network,omitempty"` + } ) // Request diff --git a/test/payments_request_apm_previous_test.go b/test/payments_request_apm_previous_test.go index e866006..792fcdd 100644 --- a/test/payments_request_apm_previous_test.go +++ b/test/payments_request_apm_previous_test.go @@ -832,8 +832,15 @@ func getKlarnaSourceRequest() payments.PaymentSource { } func getKnetSourceRequest() payments.PaymentSource { + paymentMethodDetails := payments.PaymentMethodDetails{ + DisplayName: "name", + Type: "type", + Network: "card_network", + } + source := apm.NewRequestKnetSource() source.Language = "en" + source.PaymentMethodDetails = &paymentMethodDetails return source } diff --git a/test/payments_request_apm_test.go b/test/payments_request_apm_test.go index 81c8107..2b80a95 100644 --- a/test/payments_request_apm_test.go +++ b/test/payments_request_apm_test.go @@ -572,8 +572,15 @@ func getP24Source() payments.PaymentSource { } func getKnetSource() payments.PaymentSource { + paymentMethodDetails := payments.PaymentMethodDetails{ + DisplayName: "name", + Type: "type", + Network: "card_network", + } + source := apm.NewRequestKnetSource() source.Language = "en" + source.PaymentMethodDetails = &paymentMethodDetails return source } diff --git a/test/workflows_test.go b/test/workflows_test.go index 9fb8f52..a82b8f4 100644 --- a/test/workflows_test.go +++ b/test/workflows_test.go @@ -694,6 +694,69 @@ func TestRemoveWorkflowConditions(t *testing.T) { } } +func TestTestWorkflow(t *testing.T) { + //t.Skip("Skipping because it returns http 422 status") + workflow := getWorkflow(t, createWorkflow(t).Id) + + var request = events.EventTypesRequest{ + []string{"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"}, + } + + cases := []struct { + name string + workflowId string + request events.EventTypesRequest + checker func(*common.MetadataResponse, error) + }{ + { + name: "when workflow and condition exists then delete workflow condition", + workflowId: workflow.Id, + request: request, + checker: func(response *common.MetadataResponse, err error) { + assert.Nil(t, err) + assert.NotNil(t, response) + assert.Equal(t, http.StatusNoContent, response.HttpMetadata.StatusCode) + }, + }, + { + name: "when workflow not_found then return error", + workflowId: "not_found", + request: request, + checker: func(response *common.MetadataResponse, err error) { + assert.Nil(t, response) + assert.NotNil(t, err) + chkErr := err.(errors.CheckoutAPIError) + assert.Equal(t, http.StatusNotFound, chkErr.StatusCode) + }, + }, + } + + client := DefaultApi().WorkFlows + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + tc.checker(client.TestWorkflow(tc.workflowId, request)) + }) + } +} + func TestGetEventTypes(t *testing.T) { t.Skip("Skipping tests because this suite is unstable ") cases := []struct { diff --git a/workflows/actions/actions.go b/workflows/actions/actions.go index 00c61da..4f55f75 100644 --- a/workflows/actions/actions.go +++ b/workflows/actions/actions.go @@ -82,10 +82,12 @@ type WebhookAction struct { } type WorkflowActionInvocation struct { - InvocationId string `json:"invocation_id,omitempty"` - Timestamp *time.Time `json:"timestamp,omitempty"` - Retry bool `json:"retry,omitempty"` - Succeeded bool `json:"succeeded,omitempty"` - FinalAttempt bool `json:"final,omitempty"` - Result map[string]interface{} `json:"result,omitempty"` + InvocationId string `json:"invocation_id,omitempty"` + Timestamp *time.Time `json:"timestamp,omitempty"` + Retry bool `json:"retry,omitempty"` + Succeeded bool `json:"succeeded,omitempty"` + FinalAttempt bool `json:"final,omitempty"` + // Deprecated: This property will be removed in the future, and should not be used. Use ResultDetails instead. + Result map[string]interface{} `json:"result,omitempty"` + ResultDetails map[string]interface{} `json:"result_details,omitempty"` } diff --git a/workflows/client.go b/workflows/client.go index 377b4bd..9a26da8 100644 --- a/workflows/client.go +++ b/workflows/client.go @@ -231,6 +231,30 @@ func (c *Client) RemoveWorkflowCondition(workflowId, conditionId string) (*commo return &response, nil } +func (c *Client) TestWorkflow( + workflowId string, + request events.EventTypesRequest, +) (*common.MetadataResponse, error) { + auth, err := c.configuration.Credentials.GetAuthorization(configuration.SecretKeyOrOauth) + if err != nil { + return nil, err + } + + var response common.MetadataResponse + err = c.apiClient.Post( + common.BuildPath(WorkflowsPath, workflowId, TestPath), + auth, + request, + &response, + nil, + ) + if err != nil { + return nil, err + } + + return &response, nil +} + func (c *Client) GetEventTypes() (*events.EventTypesResponse, error) { auth, err := c.configuration.Credentials.GetAuthorization(configuration.SecretKeyOrOauth) if err != nil { diff --git a/workflows/client_test.go b/workflows/client_test.go index dbdfb61..94806e6 100644 --- a/workflows/client_test.go +++ b/workflows/client_test.go @@ -740,6 +740,121 @@ func TestUpdateWorkflowCondition(t *testing.T) { } } +func TestTestWorkflow(t *testing.T) { + var ( + response = common.MetadataResponse{HttpMetadata: mocks.HttpMetadataStatusOk} + request = events.EventTypesRequest{ + EventTypes: []string{ + "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"}, + } + ) + + cases := []struct { + name string + workflowId string + request events.EventTypesRequest + getAuthorization func(*mock.Mock) mock.Call + apiPost func(*mock.Mock) mock.Call + checker func(*common.MetadataResponse, error) + }{ + { + name: "when request is correct then test workflow", + workflowId: "wor_1234", + request: request, + getAuthorization: func(m *mock.Mock) mock.Call { + return *m.On("GetAuthorization", mock.Anything). + Return(&configuration.SdkAuthorization{}, nil) + }, + apiPost: func(m *mock.Mock) mock.Call { + return *m.On("Post", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil). + Run(func(args mock.Arguments) { + respMapping := args.Get(3).(*common.MetadataResponse) + *respMapping = response + }) + }, + checker: func(response *common.MetadataResponse, err error) { + assert.Nil(t, err) + assert.NotNil(t, response) + assert.Equal(t, http.StatusOK, response.HttpMetadata.StatusCode) + }, + }, + { + name: "when credentials invalid then return error", + workflowId: "wor_1234", + getAuthorization: func(m *mock.Mock) mock.Call { + return *m.On("GetAuthorization", mock.Anything). + Return(nil, errors.CheckoutAuthorizationError("Invalid authorization type")) + }, + apiPost: func(m *mock.Mock) mock.Call { + return *m.On("Post", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil) + }, + checker: func(response *common.MetadataResponse, err error) { + assert.Nil(t, response) + assert.NotNil(t, err) + chkErr := err.(errors.CheckoutAuthorizationError) + assert.Equal(t, "Invalid authorization type", chkErr.Error()) + }, + }, + { + name: "when workflowId not found then return error", + workflowId: "not_found", + getAuthorization: func(m *mock.Mock) mock.Call { + return *m.On("GetAuthorization", mock.Anything). + Return(&configuration.SdkAuthorization{}, nil) + }, + apiPost: func(m *mock.Mock) mock.Call { + return *m.On("Post", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return( + errors.CheckoutAPIError{ + StatusCode: http.StatusNotFound, + Status: "404 Not Found", + }) + }, + checker: func(response *common.MetadataResponse, err error) { + assert.Nil(t, response) + assert.NotNil(t, err) + chkErr := err.(errors.CheckoutAPIError) + assert.Equal(t, http.StatusNotFound, chkErr.StatusCode) + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + apiClient := new(mocks.ApiClientMock) + credentials := new(mocks.CredentialsMock) + environment := new(mocks.EnvironmentMock) + + tc.getAuthorization(&credentials.Mock) + tc.apiPost(&apiClient.Mock) + + configuration := configuration.NewConfiguration(credentials, environment, &http.Client{}, nil) + client := NewClient(configuration, apiClient) + + tc.checker(client.TestWorkflow(tc.workflowId, tc.request)) + }) + } +} + func TestGetEventTypes(t *testing.T) { t.Skip("Skipping tests because this suite is unstable ") var ( diff --git a/workflows/events/events.go b/workflows/events/events.go index 99fed23..9357663 100644 --- a/workflows/events/events.go +++ b/workflows/events/events.go @@ -73,3 +73,7 @@ type SubjectEvent struct { Timestamp string `json:"timestamp,omitempty"` Links map[string]common.Link `json:"_links,omitempty"` } + +type EventTypesRequest struct { + EventTypes []string `json:"event_types,omitempty"` +} diff --git a/workflows/workflows.go b/workflows/workflows.go index 5a13219..2df936c 100644 --- a/workflows/workflows.go +++ b/workflows/workflows.go @@ -15,6 +15,7 @@ const ( SubjectPath = "subject" ReflowPath = "reflow" WorkflowPath = "workflow" + TestPath = "test" ) // Requests @@ -27,8 +28,10 @@ type ( } UpdateWorkflowRequest struct { - Name string `json:"name,omitempty"` - Active bool `json:"active,omitempty"` + Name string `json:"name,omitempty"` + Active bool `json:"active,omitempty"` + Conditions []conditions.ConditionsRequest `json:"conditions,omitempty"` + Actions []actions.ActionsRequest `json:"actions,omitempty"` } ) @@ -56,7 +59,9 @@ type ( UpdateWorkflowResponse struct { HttpMetadata common.HttpMetadata - Name string `json:"name,omitempty"` - Active bool `json:"active,omitempty"` + Name string `json:"name,omitempty"` + Active bool `json:"active,omitempty"` + Conditions []conditions.ConditionsResponse `json:"conditions,omitempty"` + Actions []actions.ActionsResponse `json:"actions,omitempty"` } )