Skip to content

Commit

Permalink
Adds Increment Authorization Payments
Browse files Browse the repository at this point in the history
  • Loading branch information
armando-rodriguez-cko committed Sep 29, 2023
1 parent d9427da commit 6eef116
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 8 deletions.
2 changes: 1 addition & 1 deletion issuing/client_issuing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var (
}
address = &common.Address{
AddressLine1: "Checkout.com",
AddressLine2: "90 Tottenham Court Road",
AddressLine2: "ABC build",
City: "London",
State: "London",
Zip: "W1T 4TJ",
Expand Down
25 changes: 25 additions & 0 deletions payments/nas/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,31 @@ func (c *Client) GetPaymentActions(paymentId string) (*GetPaymentActionsResponse
return &response, nil
}

func (c *Client) IncrementAuthorization(
paymentId string,
incrementAuthorizationRequest IncrementAuthorizationRequest,
idempotencyKey *string,
) (*IncrementAuthorizationResponse, error) {
auth, err := c.configuration.Credentials.GetAuthorization(configuration.SecretKeyOrOauth)
if err != nil {
return nil, err
}

var response IncrementAuthorizationResponse
err = c.apiClient.Post(
common.BuildPath(payments.PathPayments, paymentId, "authorizations"),
auth,
incrementAuthorizationRequest,
&response,
idempotencyKey,
)
if err != nil {
return nil, err
}

return &response, nil
}

func (c *Client) CapturePayment(
paymentId string,
captureRequest CaptureRequest,
Expand Down
200 changes: 200 additions & 0 deletions payments/nas/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package nas
import (
"net/http"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
Expand Down Expand Up @@ -602,6 +603,205 @@ func TestGetPaymentActions(t *testing.T) {
}
}

func TestIncrementAuthorization(t *testing.T) {
var (
incrementalAuthorizationRequest = IncrementAuthorizationRequest{
Amount: 6540,
Reference: "ORD-5023-4E89",
Metadata: map[string]interface{}{
"coupon_code": "NY2018",
"partner_id": 123989,
},
}

expiresOn = time.Now().Add(time.Hour * 24 * 5)
processedOn = time.Now()
balances = PaymentResponseBalances{
TotalAuthorized: 6540,
TotalVoided: 0,
AvailableToVoid: 6540,
TotalCaptured: 0,
AvailableToCapture: 6540,
TotalRefunded: 0,
AvailableToRefund: 0,
}

processing = payments.PaymentProcessing{
RetrievalReferenceNumber: "909913440644",
AcquirerTransactionId: "440644309099499894406",
RecommendationCode: "02",
}

incrementalAuthorizationResponse = IncrementAuthorizationResponse{
HttpMetadata: mocks.HttpMetadataStatusCreated,
ActionId: "act_y3oqhf46pyzuxjbcn2giaqnb44",
Amount: 6540,
Currency: common.USD,
Approved: true,
Status: payments.Authorized,
AuthCode: "643381",
ResponseCode: "10000",
ResponseSummary: "Approved",
ExpiresOn: &expiresOn,
Balances: &balances,
ProcessedOn: &processedOn,
Reference: "ORD-5023-4E89",
Processing: &processing,
Eci: "06",
SchemeId: "489341065491658",
Links: map[string]common.Link{
"self": {
HRef: &[]string{"https://www.test-link.com"}[0],
},
},
}
)

cases := []struct {
name string
paymentId string
request IncrementAuthorizationRequest
idempotencyKey *string
getAuthorization func(*mock.Mock) mock.Call
apiPost func(*mock.Mock) mock.Call
checker func(*IncrementAuthorizationResponse, error)
}{
{
name: "when request is correct then increment authorization",
paymentId: paymentId,
request: incrementalAuthorizationRequest,
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).(*IncrementAuthorizationResponse)
*respMapping = incrementalAuthorizationResponse
})
},
checker: func(response *IncrementAuthorizationResponse, err error) {
assert.Nil(t, err)
assert.NotNil(t, response)
assert.Equal(t, http.StatusCreated, response.HttpMetadata.StatusCode)
assert.Equal(t, incrementalAuthorizationResponse.ActionId, response.ActionId)
assert.Equal(t, incrementalAuthorizationResponse.Amount, response.Amount)
assert.Equal(t, incrementalAuthorizationResponse.Status, response.Status)
assert.Equal(t, incrementalAuthorizationResponse.Reference, response.Reference)
assert.Equal(t, incrementalAuthorizationResponse.Eci, response.Eci)
},
},
{
name: "when credentials invalid then return error",
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 *IncrementAuthorizationResponse, err error) {
assert.Nil(t, response)
assert.NotNil(t, err)
chkErr := err.(errors.CheckoutAuthorizationError)
assert.Equal(t, "Invalid authorization type", chkErr.Error())
},
},
{
name: "when capture not allowed then return error",
paymentId: paymentId,
request: IncrementAuthorizationRequest{},
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.StatusForbidden})
},
checker: func(response *IncrementAuthorizationResponse, err error) {
assert.Nil(t, response)
assert.NotNil(t, err)
chkErr := err.(errors.CheckoutAPIError)
assert.Equal(t, http.StatusForbidden, chkErr.StatusCode)
},
},
{
name: "when increment authorization not found then return error",
paymentId: "not_found",
request: IncrementAuthorizationRequest{},
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 *IncrementAuthorizationResponse, err error) {
assert.Nil(t, response)
assert.NotNil(t, err)
chkErr := err.(errors.CheckoutAPIError)
assert.Equal(t, http.StatusNotFound, chkErr.StatusCode)
},
},
{
name: "when request invalid then return error",
paymentId: paymentId,
request: IncrementAuthorizationRequest{},
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.StatusUnprocessableEntity,
Status: "422 Invalid Request",
Data: &errors.ErrorDetails{
ErrorType: "request_invalid",
ErrorCodes: []string{
"payment_source_required",
},
},
})
},
checker: func(response *IncrementAuthorizationResponse, err error) {
assert.Nil(t, response)
assert.NotNil(t, err)
chkErr := err.(errors.CheckoutAPIError)
assert.Equal(t, http.StatusUnprocessableEntity, chkErr.StatusCode)
assert.Equal(t, "request_invalid", chkErr.Data.ErrorType)
},
},
}

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.IncrementAuthorization(tc.paymentId, tc.request, tc.idempotencyKey))
})
}
}

func TestCapturePayment(t *testing.T) {
var (
captureRequest = CaptureRequest{
Expand Down
26 changes: 26 additions & 0 deletions payments/nas/payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ type (
Metadata map[string]interface{} `json:"metadata,omitempty"`
}

IncrementAuthorizationRequest struct {
Amount int64 `json:"amount,omitempty"`
Reference string `json:"reference,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}

CaptureRequest struct {
Amount int64 `json:"amount,omitempty"`
CaptureType CaptureType `json:"capture_type,omitempty"`
Expand Down Expand Up @@ -239,6 +245,26 @@ type (
TotalCount int `json:"total_count,omitempty"`
Data []GetPaymentResponse `json:"data,omitempty"`
}

IncrementAuthorizationResponse struct {
HttpMetadata common.HttpMetadata
ActionId string `json:"action_id,omitempty"`
Amount int64 `json:"amount,omitempty"`
Currency common.Currency `json:"currency,omitempty"`
Approved bool `json:"approved,omitempty"`
Status payments.PaymentStatus `json:"status,omitempty"`
AuthCode string `json:"auth_code,omitempty"`
ResponseCode string `json:"response_code,omitempty"`
ResponseSummary string `json:"response_summary,omitempty"`
ExpiresOn *time.Time `json:"expires_on,omitempty"`
Balances *PaymentResponseBalances `json:"balances,omitempty"`
ProcessedOn *time.Time `json:"processed_on,omitempty"`
Reference string `json:"reference,omitempty"`
Processing *payments.PaymentProcessing `json:"processing,omitempty"`
Eci string `json:"eci,omitempty"`
SchemeId string `json:"scheme_id,omitempty"`
Links map[string]common.Link `json:"_links"`
}
)

func (p *GetPaymentActionsResponse) UnmarshalJSON(data []byte) error {
Expand Down
1 change: 1 addition & 0 deletions test/disputes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ func TestGetFileDetails(t *testing.T) {
}

func TestGetDisputeSchemeFiles(t *testing.T) {
t.Skip("not available")
dispute := getDisputes(t).Data[0]

cases := []struct {
Expand Down
7 changes: 4 additions & 3 deletions test/issuing_card_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ func TestActivateCard(t *testing.T) {

func TestGetCardCredentials(t *testing.T) {
t.Skip("Avoid creating cards all the time")
query := cards.CardCredentialsQuery{
Credentials: "number, cvc2",
}
cases := []struct {
name string
cardId string
Expand All @@ -234,9 +237,7 @@ func TestGetCardCredentials(t *testing.T) {
{
name: "when get card credentials and this request is correct then should return a response",
cardId: virtualCardId,
query: cards.CardCredentialsQuery{
Credentials: "number, cvc2",
},
query: query,
checker: func(response *cards.CardCredentialsResponse, err error) {
assert.Nil(t, err)
assert.NotNil(t, response)
Expand Down
1 change: 1 addition & 0 deletions test/issuing_cardholder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

func TestCreateCardholder(t *testing.T) {
t.Skip("Avoid creating cards all the time")

cases := []struct {
name string
request cardholders.CardholderRequest
Expand Down
Loading

0 comments on commit 6eef116

Please sign in to comment.