Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SEPA Direct Debit Core Support #109

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ const (
Card InstrumentType = "card"
BankAccount InstrumentType = "bank_account"
Token InstrumentType = "token"
Sepa InstrumentType = "sepa"
CardToken InstrumentType = "card_token"
)

Expand Down
2 changes: 1 addition & 1 deletion forex/forex.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
)
Expand Down
51 changes: 51 additions & 0 deletions instruments/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 All @@ -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 (
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions instruments/nas/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
19 changes: 19 additions & 0 deletions instruments/nas/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nas

import (
"encoding/json"
"time"

"github.com/checkout/checkout-sdk-go/common"
"github.com/checkout/checkout-sdk-go/instruments"
Expand All @@ -16,6 +17,7 @@ type (
GetInstrumentResponse struct {
HttpMetadata common.HttpMetadata
GetCardInstrumentResponse *GetCardInstrumentResponse
GetSepaInstrumentResponse *GetSepaInstrumentResponse
GetBankAccountInstrumentResponse *GetBankAccountInstrumentResponse
AlternativeResponse *common.AlternativeResponse
}
Expand All @@ -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"`
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 12 additions & 0 deletions instruments/nas/instuments.go
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"`
Expand Down
2 changes: 1 addition & 1 deletion metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
1 change: 1 addition & 0 deletions payments/nas/payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
29 changes: 27 additions & 2 deletions test/instruments_test.go
Original file line number Diff line number Diff line change
@@ -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"
)

Expand All @@ -18,6 +18,7 @@ var (

func TestSetupInstrument(t *testing.T) {
cardTokenResponse := RequestCardToken(t)
_ = createSepaInstrument(t)
instrumentToken = createTokenInstrument(t, cardTokenResponse)
}

Expand Down Expand Up @@ -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
Expand Down
Loading