From cbc519c54530ee994099f4649a6e6019098dbbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:15:25 +0200 Subject: [PATCH] Add partial authorization in payment request --- payments/nas/payments.go | 67 +++++------ test/payments_increment_authorization_test.go | 104 +++++++++++++++--- 2 files changed, 127 insertions(+), 44 deletions(-) diff --git a/payments/nas/payments.go b/payments/nas/payments.go index 3cb5185..43d1c87 100644 --- a/payments/nas/payments.go +++ b/payments/nas/payments.go @@ -77,42 +77,47 @@ type ( IssuingCountry common.Country `json:"issuing_country,omitempty"` DateOfExpiry string `json:"date_of_expiry,omitempty"` } + + PartialAuthorization struct { + Enabled bool `json:"enabled,omitempty"` + } ) // Request type ( PaymentRequest struct { - PaymentContextId string `json:"payment_context_id,omitempty"` - Source payments.PaymentSource `json:"source,omitempty"` - Amount int64 `json:"amount,omitempty"` - Currency common.Currency `json:"currency,omitempty"` - PaymentType payments.PaymentType `json:"payment_type,omitempty"` - MerchantInitiated bool `json:"merchant_initiated"` - Reference string `json:"reference,omitempty"` - Description string `json:"description,omitempty"` - AuthorizationType AuthorizationType `json:"authorization_type,omitempty"` - Capture bool `json:"capture"` - CaptureOn *time.Time `json:"capture_on,omitempty"` - Customer *common.CustomerRequest `json:"customer,omitempty"` - BillingDescriptor *payments.BillingDescriptor `json:"billing_descriptor,omitempty"` - ShippingDetails *payments.ShippingDetails `json:"shipping,omitempty"` - Segment *payments.PaymentSegment `json:"segment,omitempty"` - ThreeDsRequest *payments.ThreeDsRequest `json:"3ds,omitempty"` - PreviousPaymentId string `json:"previous_payment_id,omitempty"` - ProcessingChannelId string `json:"processing_channel_id,omitempty"` - Risk *payments.RiskRequest `json:"risk,omitempty"` - SuccessUrl string `json:"success_url,omitempty"` - FailureUrl string `json:"failure_url,omitempty"` - PaymentIp string `json:"payment_ip,omitempty"` - Sender Sender `json:"sender,omitempty"` - Recipient *payments.PaymentRecipient `json:"recipient,omitempty"` - Marketplace *common.MarketplaceData `json:"marketplace,omitempty"` - AmountAllocations []common.AmountAllocations `json:"amount_allocations,omitempty"` - Processing *payments.ProcessingSettings `json:"processing,omitempty"` - Items []payments.Product `json:"items,omitempty"` - Retry *payments.PaymentRetryRequest `json:"retry,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` - Instruction *PaymentInstruction `json:"instruction,omitempty"` + PaymentContextId string `json:"payment_context_id,omitempty"` + Source payments.PaymentSource `json:"source,omitempty"` + Amount int64 `json:"amount,omitempty"` + Currency common.Currency `json:"currency,omitempty"` + PaymentType payments.PaymentType `json:"payment_type,omitempty"` + MerchantInitiated bool `json:"merchant_initiated"` + Reference string `json:"reference,omitempty"` + Description string `json:"description,omitempty"` + AuthorizationType AuthorizationType `json:"authorization_type,omitempty"` + PartialAuthorization *PartialAuthorization `json:"partial_authorization,omitempty"` + Capture bool `json:"capture"` + CaptureOn *time.Time `json:"capture_on,omitempty"` + Customer *common.CustomerRequest `json:"customer,omitempty"` + BillingDescriptor *payments.BillingDescriptor `json:"billing_descriptor,omitempty"` + ShippingDetails *payments.ShippingDetails `json:"shipping,omitempty"` + Segment *payments.PaymentSegment `json:"segment,omitempty"` + ThreeDsRequest *payments.ThreeDsRequest `json:"3ds,omitempty"` + PreviousPaymentId string `json:"previous_payment_id,omitempty"` + ProcessingChannelId string `json:"processing_channel_id,omitempty"` + Risk *payments.RiskRequest `json:"risk,omitempty"` + SuccessUrl string `json:"success_url,omitempty"` + FailureUrl string `json:"failure_url,omitempty"` + PaymentIp string `json:"payment_ip,omitempty"` + Sender Sender `json:"sender,omitempty"` + Recipient *payments.PaymentRecipient `json:"recipient,omitempty"` + Marketplace *common.MarketplaceData `json:"marketplace,omitempty"` + AmountAllocations []common.AmountAllocations `json:"amount_allocations,omitempty"` + Processing *payments.ProcessingSettings `json:"processing,omitempty"` + Items []payments.Product `json:"items,omitempty"` + Retry *payments.PaymentRetryRequest `json:"retry,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Instruction *PaymentInstruction `json:"instruction,omitempty"` } PayoutRequest struct { diff --git a/test/payments_increment_authorization_test.go b/test/payments_increment_authorization_test.go index 1dabe10..d98c377 100644 --- a/test/payments_increment_authorization_test.go +++ b/test/payments_increment_authorization_test.go @@ -7,13 +7,15 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/checkout/checkout-sdk-go/common" "github.com/checkout/checkout-sdk-go/payments" "github.com/checkout/checkout-sdk-go/payments/nas" + "github.com/checkout/checkout-sdk-go/payments/nas/sources" ) func TestIncrementAuthorization(t *testing.T) { - t.Skip("Skipping because increment authorization needs an authorized payment") - paymentResponse := makeCardPayment(t, false, 10) + paymentResponse := makeCardPaymentPartialAuthorization(t, false, 10) + assert.NotNil(t, paymentResponse, "Expected paymentResponse not to be nil") metadata := make(map[string]interface{}) metadata["TestIncrementAuthorization"] = "metadata" @@ -38,20 +40,26 @@ func TestIncrementAuthorization(t *testing.T) { checkerOne: func(response *nas.IncrementAuthorizationResponse, err error) { assert.Nil(t, err) assert.NotNil(t, response) - assert.NotEmpty(t, response.Reference) + assert.Equal(t, int64(5), response.Amount) assert.NotEmpty(t, response.ActionId) + assert.NotEmpty(t, response.Currency) + assert.False(t, response.Approved) + assert.NotEmpty(t, response.ResponseCode) + assert.NotEmpty(t, response.ResponseSummary) + assert.NotEmpty(t, response.ExpiresOn) + assert.NotEmpty(t, response.ProcessedOn) + assert.NotEmpty(t, response.Balances) assert.NotEmpty(t, response.Links) - assert.NotEmpty(t, response.Links["payment"]) }, checkerTwo: func(response *nas.GetPaymentResponse, err error) { assert.NotEmpty(t, response.Balances) assert.Equal(t, int64(10), response.Balances.TotalAuthorized) - assert.Equal(t, int64(5), response.Balances.TotalCaptured) + assert.Equal(t, int64(0), response.Balances.TotalCaptured) assert.Equal(t, int64(0), response.Balances.TotalRefunded) assert.Equal(t, int64(0), response.Balances.TotalVoided) - assert.Equal(t, int64(0), response.Balances.AvailableToCapture) - assert.Equal(t, int64(5), response.Balances.AvailableToRefund) - assert.Equal(t, int64(0), response.Balances.AvailableToVoid) + assert.Equal(t, int64(10), response.Balances.AvailableToCapture) + assert.Equal(t, int64(0), response.Balances.AvailableToRefund) + assert.Equal(t, int64(10), response.Balances.AvailableToVoid) }, }, } @@ -69,8 +77,8 @@ func TestIncrementAuthorization(t *testing.T) { } func TestIncrementAuthorizationIdempotently(t *testing.T) { - t.Skip("Skipping because increment authorization needs an authorized payment") - paymentResponse := makeCardPayment(t, false, 10) + paymentResponse := makeCardPaymentPartialAuthorization(t, false, 10) + assert.NotNil(t, paymentResponse, "Expected paymentResponse not to be nil") metadata := make(map[string]interface{}) metadata["TestIncrementAuthorization"] = "metadata" @@ -115,7 +123,9 @@ func TestIncrementAuthorizationIdempotently(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.(*nas.IncrementAuthorizationResponse).ActionId, response2.(*nas.IncrementAuthorizationResponse).ActionId) }, }, } @@ -128,7 +138,7 @@ func TestIncrementAuthorizationIdempotently(t *testing.T) { return client.IncrementAuthorization(tc.paymentId, tc.request, &tc.idempotencyKeyRandom1) } predicateOne := func(data interface{}) bool { - response := data.(*payments.CaptureResponse) + response := data.(*nas.IncrementAuthorizationResponse) return response.Links != nil && len(response.Links) >= 0 } @@ -136,7 +146,7 @@ func TestIncrementAuthorizationIdempotently(t *testing.T) { return client.IncrementAuthorization(tc.paymentId, tc.request, &tc.idempotencyKeyRandom2) } predicateTwo := func(data interface{}) bool { - response := data.(*payments.CaptureResponse) + response := data.(*nas.IncrementAuthorizationResponse) return response.Links != nil && len(response.Links) >= 0 } @@ -146,3 +156,71 @@ func TestIncrementAuthorizationIdempotently(t *testing.T) { }) } } + +func makeCardPaymentPartialAuthorization(t *testing.T, shouldCapture bool, amount int64) *nas.PaymentResponse { + currentYear := time.Now().Year() + 1 + + cardSource := sources.NewRequestCardSource() + cardSource.Name = "Mr. Test" + cardSource.Number = "4556447238607884" + cardSource.ExpiryYear = currentYear + cardSource.ExpiryMonth = 12 + cardSource.Cvv = "123" + cardSource.BillingAddress = &common.Address{ + AddressLine1: "CheckoutSdk.com", + AddressLine2: "90 Tottenham Court Road", + City: "London", + State: "London", + Zip: "W1T 4TJ", + Country: common.GB, + } + cardSource.Phone = &common.Phone{ + CountryCode: "44", + Number: "1234567890", + } + + customerRequest := &common.CustomerRequest{ + Email: "test@example.com", + Name: "Test Customer", + Phone: &common.Phone{ + CountryCode: "44", + Number: "1234567890", + }, + } + + paymentIndividualSender := nas.NewRequestIndividualSender() + paymentIndividualSender.FirstName = "Mr" + paymentIndividualSender.LastName = "Test" + paymentIndividualSender.Address = &common.Address{ + AddressLine1: "CheckoutSdk.com", + AddressLine2: "90 Tottenham Court Road", + City: "London", + State: "London", + Zip: "W1T 4TJ", + Country: common.GB, + } + + paymentRequest := nas.PaymentRequest{ + Source: cardSource, + Amount: amount, + Currency: common.USD, + Reference: uuid.New().String(), + Description: "Test Payment", + Capture: shouldCapture, + Customer: customerRequest, + Sender: paymentIndividualSender, + AuthorizationType: nas.EstimatedAuthorizationType, + PartialAuthorization: &nas.PartialAuthorization{ + Enabled: true, + }, + BillingDescriptor: &payments.BillingDescriptor{ + Name: "CheckoutSdk.com", + City: "London", + }, + } + + response, err := DefaultApi().Payments.RequestPayment(paymentRequest, nil) + assert.Nil(t, err, "Expected no error in RequestPayment") + assert.NotNil(t, response, "Expected response not to be nil") + return response +}