From 3bcb89c5c74cdfc81d493506596316102b68e4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:54:07 +0200 Subject: [PATCH 1/3] Fix Rates property --- forex/forex.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forex/forex.go b/forex/forex.go index 9d1ae87..184cf76 100644 --- a/forex/forex.go +++ b/forex/forex.go @@ -52,7 +52,7 @@ type ( RatesResponse struct { Product string `json:"product,omitempty"` Source Source `json:"source,omitempty"` - Rates []Rate `json:"currency_pairs,omitempty"` + Rates []Rate `json:"rates,omitempty"` InvalidCurrencyPairs []string `json:"invalid_currency_pairs,omitempty"` } ) From fd1037ba03a7349c0c5dd6d0a6cea1bd02a8575a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:54:45 +0200 Subject: [PATCH 2/3] Fix LocalSchemes property --- metadata/metadata.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata/metadata.go b/metadata/metadata.go index bb307e5..0026a0b 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -79,7 +79,7 @@ type ( Scheme string `json:"scheme,omitempty"` // Deprecated: This property will be removed in the future, and should not be used. Use LocalSchemes instead. SchemeLocal SchemeLocalType `json:"scheme_local,omitempty"` - LocalSchemes SchemeLocalType `json:"local_schemes,omitempty"` + LocalSchemes []SchemeLocalType `json:"local_schemes,omitempty"` CardType common.CardType `json:"card_type,omitempty"` CardCategory common.CardCategory `json:"card_category,omitempty"` Currency common.Currency `json:"currency,omitempty"` From 09ec27afeeac52a043de1f65e1aaa3c9057dfc0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Tue, 16 Apr 2024 11:55:05 +0200 Subject: [PATCH 3/3] Add SEPA Direct Debit Core Support --- common/common.go | 1 + instruments/nas/client_test.go | 51 ++++++++++++++++++++++++++++++++++ instruments/nas/create.go | 26 +++++++++++++++++ instruments/nas/get.go | 19 +++++++++++++ instruments/nas/instuments.go | 12 ++++++++ payments/nas/payments.go | 1 + test/instruments_test.go | 29 +++++++++++++++++-- 7 files changed, 137 insertions(+), 2 deletions(-) diff --git a/common/common.go b/common/common.go index 5e2be40..dc26a9b 100644 --- a/common/common.go +++ b/common/common.go @@ -195,6 +195,7 @@ const ( Card InstrumentType = "card" BankAccount InstrumentType = "bank_account" Token InstrumentType = "token" + Sepa InstrumentType = "sepa" CardToken InstrumentType = "card_token" ) diff --git a/instruments/nas/client_test.go b/instruments/nas/client_test.go index 3190bbd..a515526 100644 --- a/instruments/nas/client_test.go +++ b/instruments/nas/client_test.go @@ -3,6 +3,7 @@ package nas import ( "net/http" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -11,6 +12,7 @@ import ( "github.com/checkout/checkout-sdk-go/configuration" "github.com/checkout/checkout-sdk-go/errors" "github.com/checkout/checkout-sdk-go/mocks" + "github.com/checkout/checkout-sdk-go/payments" ) const ( @@ -71,6 +73,17 @@ func TestCreate(t *testing.T) { HttpMetadata: mocks.HttpMetadataStatusCreated, CreateBankAccountInstrumentResponse: &bankAccount, } + + sepa = CreateSepaInstrumentResponse{ + Type: common.Sepa, + Id: "src_wmlfc3zyhqzehihu7giusaaawu", + Fingerprint: "vnsdrvikkvre3dtrjjvlm5du4q", + } + + createSepaResponse = CreateInstrumentResponse{ + HttpMetadata: mocks.HttpMetadataStatusCreated, + CreateSepaInstrumentResponse: &sepa, + } ) cases := []struct { @@ -126,6 +139,29 @@ func TestCreate(t *testing.T) { assert.Equal(t, bankAccount.Id, response.CreateBankAccountInstrumentResponse.Id) }, }, + { + name: "when request is for sepa instrument then create sepa instrument", + request: getCreateSepaInstrumentRequest(), + 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).(*CreateInstrumentResponse) + *respMapping = createSepaResponse + }) + }, + checker: func(response *CreateInstrumentResponse, err error) { + assert.Nil(t, err) + assert.NotNil(t, response) + assert.Equal(t, http.StatusCreated, response.HttpMetadata.StatusCode) + assert.NotNil(t, response.CreateSepaInstrumentResponse) + assert.Equal(t, sepa.Id, response.CreateSepaInstrumentResponse.Id) + }, + }, { name: "when credentials invalid then return error", getAuthorization: func(m *mock.Mock) mock.Call { @@ -199,6 +235,21 @@ func getCreateTokenInstrumentRequest() *createTokenInstrumentRequest { return r } +func getCreateSepaInstrumentRequest() *createSepaInstrumentRequest { + time := time.Now() + + r := NewCreateSepaInstrumentRequest() + r.InstrumentData = &InstrumentData{ + AccountNumber: "FR2810096000509685512959O86", + Country: common.GB, + Currency: common.GBP, + PaymentType: payments.Recurring, + MandateId: "1234567890", + DateOfSignature: &time, + } + return r +} + func getCreateBankAccountInstrumentRequest() *createBankAccountInstrumentRequest { r := NewCreateBankAccountInstrumentRequest() r.AccountType = common.Savings diff --git a/instruments/nas/create.go b/instruments/nas/create.go index 659f5fd..35ae813 100644 --- a/instruments/nas/create.go +++ b/instruments/nas/create.go @@ -32,6 +32,12 @@ type ( AccountHolder *common.AccountHolder `json:"account_holder" binding:"required"` Customer *CreateCustomerInstrumentRequest `json:"customer,omitempty"` } + + createSepaInstrumentRequest struct { + Type common.InstrumentType `json:"type" binding:"required"` + InstrumentData *InstrumentData `json:"instrument_data,omitempty"` + AccountHolder *common.AccountHolder `json:"account_holder" binding:"required"` + } ) func NewCreateBankAccountInstrumentRequest() *createBankAccountInstrumentRequest { @@ -46,11 +52,18 @@ func NewCreateTokenInstrumentRequest() *createTokenInstrumentRequest { } } +func NewCreateSepaInstrumentRequest() *createSepaInstrumentRequest { + return &createSepaInstrumentRequest{ + Type: common.Sepa, + } +} + type ( CreateInstrumentResponse struct { HttpMetadata common.HttpMetadata CreateBankAccountInstrumentResponse *CreateBankAccountInstrumentResponse CreateTokenInstrumentResponse *CreateTokenInstrumentResponse + CreateSepaInstrumentResponse *CreateSepaInstrumentResponse AlternativeResponse *common.AlternativeResponse } @@ -88,6 +101,13 @@ type ( ProductId string `json:"product_id,omitempty"` ProductType string `json:"product_type,omitempty"` } + + CreateSepaInstrumentResponse struct { + Type common.InstrumentType `json:"type" binding:"required"` + // common + Id string `json:"id,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + } ) func (s *CreateInstrumentResponse) UnmarshalJSON(data []byte) error { @@ -109,6 +129,12 @@ func (s *CreateInstrumentResponse) UnmarshalJSON(data []byte) error { return nil } s.CreateTokenInstrumentResponse = &response + case string(common.Sepa): + var response CreateSepaInstrumentResponse + if err := json.Unmarshal(data, &response); err != nil { + return nil + } + s.CreateSepaInstrumentResponse = &response default: var response common.AlternativeResponse if err := json.Unmarshal(data, &response); err != nil { diff --git a/instruments/nas/get.go b/instruments/nas/get.go index 68c843f..c74df08 100644 --- a/instruments/nas/get.go +++ b/instruments/nas/get.go @@ -2,6 +2,7 @@ package nas import ( "encoding/json" + "time" "github.com/checkout/checkout-sdk-go/common" "github.com/checkout/checkout-sdk-go/instruments" @@ -16,6 +17,7 @@ type ( GetInstrumentResponse struct { HttpMetadata common.HttpMetadata GetCardInstrumentResponse *GetCardInstrumentResponse + GetSepaInstrumentResponse *GetSepaInstrumentResponse GetBankAccountInstrumentResponse *GetBankAccountInstrumentResponse AlternativeResponse *common.AlternativeResponse } @@ -42,6 +44,17 @@ type ( ProductType string `json:"product_type,omitempty"` } + GetSepaInstrumentResponse struct { + Type common.InstrumentType `json:"type" binding:"required"` + Id string `json:"id,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + CreatedOn *time.Time `json:"created_on,omitempty"` + ModifiedOn *time.Time `json:"modified_on,omitempty"` + VaultId string `json:"vault_id,omitempty"` + InstrumentData *InstrumentData `json:"instrument_data,omitempty"` + AccountHolder *common.AccountHolder `json:"account_holder,omitempty"` + } + GetBankAccountInstrumentResponse struct { Type common.InstrumentType `json:"type" binding:"required"` Id string `json:"id,omitempty"` @@ -114,6 +127,12 @@ func (s *GetInstrumentResponse) UnmarshalJSON(data []byte) error { return nil } s.GetCardInstrumentResponse = &response + case string(common.Sepa): + var response GetSepaInstrumentResponse + if err := json.Unmarshal(data, &response); err != nil { + return nil + } + s.GetSepaInstrumentResponse = &response default: var response common.AlternativeResponse if err := json.Unmarshal(data, &response); err != nil { diff --git a/instruments/nas/instuments.go b/instruments/nas/instuments.go index 7577a05..3396769 100644 --- a/instruments/nas/instuments.go +++ b/instruments/nas/instuments.go @@ -1,7 +1,10 @@ package nas import ( + "time" + "github.com/checkout/checkout-sdk-go/common" + "github.com/checkout/checkout-sdk-go/payments" ) type PaymentNetwork string @@ -15,6 +18,15 @@ const ( Swift PaymentNetwork = "swift" ) +type InstrumentData struct { + AccountNumber string `json:"account_number,omitempty"` + Country common.Country `json:"country,omitempty"` + Currency common.Currency `json:"currency,omitempty"` + PaymentType payments.PaymentType `json:"payment_type,omitempty"` + MandateId string `json:"mandate_id,omitempty"` + DateOfSignature *time.Time `json:"date_of_signature,omitempty"` +} + type CreateCustomerInstrumentRequest struct { Id string `json:"id,omitempty"` Email string `json:"email,omitempty"` diff --git a/payments/nas/payments.go b/payments/nas/payments.go index 317296e..a16b5e6 100644 --- a/payments/nas/payments.go +++ b/payments/nas/payments.go @@ -112,6 +112,7 @@ type ( 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/instruments_test.go b/test/instruments_test.go index 54a811b..3516faa 100644 --- a/test/instruments_test.go +++ b/test/instruments_test.go @@ -1,14 +1,14 @@ package test import ( + "github.com/stretchr/testify/assert" "net/http" "testing" - "github.com/stretchr/testify/assert" - "github.com/checkout/checkout-sdk-go/common" "github.com/checkout/checkout-sdk-go/errors" "github.com/checkout/checkout-sdk-go/instruments/nas" + "github.com/checkout/checkout-sdk-go/payments" "github.com/checkout/checkout-sdk-go/tokens" ) @@ -18,6 +18,7 @@ var ( func TestSetupInstrument(t *testing.T) { cardTokenResponse := RequestCardToken(t) + _ = createSepaInstrument(t) instrumentToken = createTokenInstrument(t, cardTokenResponse) } @@ -211,6 +212,30 @@ func TestShouldDeleteInstrument(t *testing.T) { } } +func createSepaInstrument(t *testing.T) *nas.CreateSepaInstrumentResponse { + request := nas.NewCreateSepaInstrumentRequest() + request.InstrumentData = &nas.InstrumentData{ + AccountNumber: "FR7630006000011234567890189", + Country: common.FR, + Currency: common.EUR, + PaymentType: payments.Recurring, + } + request.AccountHolder = &common.AccountHolder{ + FirstName: "Ali", + LastName: "Farid", + BillingAddress: Address(), + Phone: Phone(), + } + + response, err := DefaultApi().Instruments.Create(request) + assert.Nil(t, err) + assert.NotNil(t, response.CreateSepaInstrumentResponse) + assert.Equal(t, common.Sepa, response.CreateSepaInstrumentResponse.Type) + assert.NotEmpty(t, response.CreateSepaInstrumentResponse.Id) + assert.NotEmpty(t, response.CreateSepaInstrumentResponse.Fingerprint) + return response.CreateSepaInstrumentResponse +} + func createTokenInstrument(t *testing.T, token *tokens.CardTokenResponse) *nas.CreateTokenInstrumentResponse { request := nas.NewCreateTokenInstrumentRequest() request.Token = token.Token