diff --git a/payments/abc/client.go b/payments/abc/client.go index 6858ef9..25defb9 100644 --- a/payments/abc/client.go +++ b/payments/abc/client.go @@ -140,6 +140,30 @@ func (c *Client) CapturePayment( return &response, nil } +func (c *Client) CapturePaymentWithoutRequest( + paymentId string, + idempotencyKey *string, +) (*payments.CaptureResponse, error) { + auth, err := c.configuration.Credentials.GetAuthorization(configuration.SecretKey) + if err != nil { + return nil, err + } + + var response payments.CaptureResponse + err = c.apiClient.Post( + common.BuildPath(payments.PathPayments, paymentId, "captures"), + auth, + nil, + &response, + idempotencyKey, + ) + if err != nil { + return nil, err + } + + return &response, nil +} + func (c *Client) RefundPayment( paymentId string, refundRequest *payments.RefundRequest, diff --git a/payments/nas/client.go b/payments/nas/client.go index 0811d0e..3b78887 100644 --- a/payments/nas/client.go +++ b/payments/nas/client.go @@ -165,6 +165,30 @@ func (c *Client) CapturePayment( return &response, nil } +func (c *Client) CapturePaymentWithoutRequest( + paymentId string, + idempotencyKey *string, +) (*payments.CaptureResponse, error) { + auth, err := c.configuration.Credentials.GetAuthorization(configuration.SecretKeyOrOauth) + if err != nil { + return nil, err + } + + var response payments.CaptureResponse + err = c.apiClient.Post( + common.BuildPath(payments.PathPayments, paymentId, "captures"), + auth, + nil, + &response, + idempotencyKey, + ) + if err != nil { + return nil, err + } + + return &response, nil +} + func (c *Client) RefundPayment( paymentId string, refundRequest *payments.RefundRequest, diff --git a/test/payments_captures_previous_test.go b/test/payments_captures_previous_test.go index 060b225..3ee2ed0 100644 --- a/test/payments_captures_previous_test.go +++ b/test/payments_captures_previous_test.go @@ -58,6 +58,43 @@ func TestCaptureCardPaymentPrevious(t *testing.T) { } } +func TestCaptureCardPaymentWithoutRequestPrevious(t *testing.T) { + paymentResponse := makeCardPaymentPrevious(t, false, 10) + + cases := []struct { + name string + paymentId string + checker func(interface{}, error) + }{ + { + name: "when request is valid then capture payment", + paymentId: paymentResponse.Id, + checker: func(response interface{}, err error) { + assert.Nil(t, err) + assert.NotNil(t, response) + assert.NotEmpty(t, response.(*payments.CaptureResponse).Reference) + assert.NotEmpty(t, response.(*payments.CaptureResponse).ActionId) + assert.NotEmpty(t, response.(*payments.CaptureResponse).Links) + assert.NotEmpty(t, response.(*payments.CaptureResponse).Links["payment"]) + }, + }, + } + + client := PreviousApi().Payments + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + process := func() (interface{}, error) { return client.CapturePaymentWithoutRequest(tc.paymentId, nil) } + predicate := func(data interface{}) bool { + response := data.(*payments.CaptureResponse) + return response.Links != nil && len(response.Links) >= 0 + } + + tc.checker(retriable(process, predicate, 2)) + }) + } +} + func TestCaptureCardPaymentIdempotentlyPrevious(t *testing.T) { paymentResponse := makeCardPaymentPrevious(t, false, 10) @@ -135,3 +172,70 @@ func TestCaptureCardPaymentIdempotentlyPrevious(t *testing.T) { }) } } + +func TestCaptureCardPaymentIdempotentlyWithoutRequestPrevious(t *testing.T) { + paymentResponse := makeCardPaymentPrevious(t, false, 10) + + idempotencyKeyRandom1 := uuid.New().String() + + idempotencyKeyRandom2 := uuid.New().String() + + cases := []struct { + name string + paymentId string + idempotencyKeyRandom1 string + idempotencyKeyRandom2 string + checker func(interface{}, error, interface{}, error) + }{ + { + name: "when request is valid then capture payment idempotently", + paymentId: paymentResponse.Id, + idempotencyKeyRandom1: idempotencyKeyRandom1, + idempotencyKeyRandom2: idempotencyKeyRandom1, + checker: func(response1 interface{}, err1 error, response2 interface{}, err2 error) { + assert.Nil(t, err1) + assert.NotNil(t, response1) + assert.Nil(t, err2) + assert.NotNil(t, response2) + assert.Equal(t, response1.(*payments.CaptureResponse).ActionId, response2.(*payments.CaptureResponse).ActionId) + }, + }, + { + name: "when request is valid then capture payment idempotently error", + paymentId: paymentResponse.Id, + idempotencyKeyRandom1: idempotencyKeyRandom1, + idempotencyKeyRandom2: idempotencyKeyRandom2, + checker: func(response1 interface{}, err1 error, response2 interface{}, err2 error) { + assert.Nil(t, err1) + assert.NotNil(t, response1) + assert.NotNil(t, err2) + }, + }, + } + + client := PreviousApi().Payments + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + processOne := func() (interface{}, error) { + return client.CapturePaymentWithoutRequest(tc.paymentId, &tc.idempotencyKeyRandom1) + } + predicateOne := func(data interface{}) bool { + response := data.(*payments.CaptureResponse) + return response.Links != nil && len(response.Links) >= 0 + } + + processTwo := func() (interface{}, error) { + return client.CapturePaymentWithoutRequest(tc.paymentId, &tc.idempotencyKeyRandom2) + } + predicateTwo := func(data interface{}) bool { + response := data.(*payments.CaptureResponse) + return response.Links != nil && len(response.Links) >= 0 + } + + retriableOne, errOne := retriable(processOne, predicateOne, 2) + retriableTwo, errTwo := retriable(processTwo, predicateTwo, 2) + tc.checker(retriableOne, errOne, retriableTwo, errTwo) + }) + } +} diff --git a/test/payments_captures_test.go b/test/payments_captures_test.go index 5a58c15..0ef0f21 100644 --- a/test/payments_captures_test.go +++ b/test/payments_captures_test.go @@ -67,6 +67,37 @@ func TestCaptureCardPayment(t *testing.T) { } } +func TestCaptureCardPaymentWithoutRequest(t *testing.T) { + paymentResponse := makeCardPayment(t, false, 10) + + cases := []struct { + name string + paymentId string + checkerOne func(*payments.CaptureResponse, error) + }{ + { + name: "when get a capture payment request without request then return a response", + paymentId: paymentResponse.Id, + checkerOne: func(response *payments.CaptureResponse, err error) { + assert.Nil(t, err) + assert.NotNil(t, response) + assert.NotEmpty(t, response.ActionId) + assert.NotEmpty(t, response.Links) + assert.NotEmpty(t, response.Links["payment"]) + }, + }, + } + + client := DefaultApi().Payments + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + Wait(time.Duration(3)) + tc.checkerOne(client.CapturePaymentWithoutRequest(tc.paymentId, nil)) + }) + } +} + func TestCaptureCardPaymentIdempotently(t *testing.T) { paymentResponse := makeCardPayment(t, false, 10) @@ -113,7 +144,9 @@ func TestCaptureCardPaymentIdempotently(t *testing.T) { checker: func(response1 interface{}, err1 error, response2 interface{}, err2 error) { assert.Nil(t, err1) assert.NotNil(t, response1) - assert.NotNil(t, err2) + assert.Nil(t, err2) + assert.NotNil(t, response2) + assert.NotEqual(t, response1.(*payments.CaptureResponse).ActionId, response2.(*payments.CaptureResponse).ActionId) }, }, } @@ -144,3 +177,72 @@ func TestCaptureCardPaymentIdempotently(t *testing.T) { }) } } + +func TestCaptureCardPaymentWithoutrequestIdempotently(t *testing.T) { + paymentResponse := makeCardPayment(t, false, 10) + + idempotencyKeyRandom1 := uuid.New().String() + + idempotencyKeyRandom2 := uuid.New().String() + + cases := []struct { + name string + paymentId string + idempotencyKeyRandom1 string + idempotencyKeyRandom2 string + checker func(interface{}, error, interface{}, error) + }{ + { + name: "when request is valid then capture payment without request idempotently", + paymentId: paymentResponse.Id, + idempotencyKeyRandom1: idempotencyKeyRandom1, + idempotencyKeyRandom2: idempotencyKeyRandom1, + checker: func(response1 interface{}, err1 error, response2 interface{}, err2 error) { + assert.Nil(t, err1) + assert.NotNil(t, response1) + assert.Nil(t, err2) + assert.NotNil(t, response2) + assert.Equal(t, response1.(*payments.CaptureResponse).ActionId, response2.(*payments.CaptureResponse).ActionId) + }, + }, + { + name: "when request is valid then capture without request payment idempotently error", + paymentId: paymentResponse.Id, + idempotencyKeyRandom1: idempotencyKeyRandom1, + idempotencyKeyRandom2: idempotencyKeyRandom2, + checker: func(response1 interface{}, err1 error, response2 interface{}, err2 error) { + assert.Nil(t, err1) + assert.NotNil(t, response1) + assert.Nil(t, err2) + assert.NotNil(t, response2) + assert.NotEqual(t, response1.(*payments.CaptureResponse).ActionId, response2.(*payments.CaptureResponse).ActionId) + }, + }, + } + + client := DefaultApi().Payments + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + processOne := func() (interface{}, error) { + return client.CapturePaymentWithoutRequest(tc.paymentId, &tc.idempotencyKeyRandom1) + } + predicateOne := func(data interface{}) bool { + response := data.(*payments.CaptureResponse) + return response.Links != nil && len(response.Links) >= 0 + } + + processTwo := func() (interface{}, error) { + return client.CapturePaymentWithoutRequest(tc.paymentId, &tc.idempotencyKeyRandom2) + } + predicateTwo := func(data interface{}) bool { + response := data.(*payments.CaptureResponse) + return response.Links != nil && len(response.Links) >= 0 + } + + retriableOne, errOne := retriable(processOne, predicateOne, 2) + retriableTwo, errTwo := retriable(processTwo, predicateTwo, 2) + tc.checker(retriableOne, errOne, retriableTwo, errTwo) + }) + } +}