From 2780091103357fcaf4a83480846aa2edb13cb8f3 Mon Sep 17 00:00:00 2001 From: Paul Nicolas Date: Mon, 18 Dec 2023 19:34:51 +0100 Subject: [PATCH] fix(payments): fix stripe root account transfer initiation (#1025) --- .../cmd/api/internal/api/transfer_initiation.go | 3 +++ .../cmd/api/internal/api/transfer_initiation_test.go | 4 ++++ .../internal/connectors/stripe/task_fetch_accounts.go | 10 +++++++--- .../internal/connectors/stripe/task_fetch_balances.go | 2 +- .../internal/connectors/stripe/task_fetch_payments.go | 2 +- .../internal/connectors/stripe/task_payments.go | 5 ++++- components/payments/openapi.yaml | 3 +++ .../go/docs/models/shared/transferinitiation.md | 1 + .../clients/go/pkg/models/shared/transferinitiation.go | 8 ++++++++ 9 files changed, 32 insertions(+), 6 deletions(-) diff --git a/components/payments/cmd/api/internal/api/transfer_initiation.go b/components/payments/cmd/api/internal/api/transfer_initiation.go index 1edf4ee8ba..5d1bffaf4e 100644 --- a/components/payments/cmd/api/internal/api/transfer_initiation.go +++ b/components/payments/cmd/api/internal/api/transfer_initiation.go @@ -14,6 +14,7 @@ import ( type transferInitiationResponse struct { ID string `json:"id"` + Reference string `json:"reference"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` ScheduledAt time.Time `json:"scheduledAt"` @@ -60,6 +61,7 @@ func readTransferInitiationHandler(b backend.Backend) http.HandlerFunc { data := &readTransferInitiationResponse{ transferInitiationResponse: transferInitiationResponse{ ID: ret.ID.String(), + Reference: ret.ID.Reference, CreatedAt: ret.CreatedAt, UpdatedAt: ret.UpdatedAt, ScheduledAt: ret.ScheduledAt, @@ -115,6 +117,7 @@ func listTransferInitiationsHandler(b backend.Backend) http.HandlerFunc { for i := range ret { data[i] = &transferInitiationResponse{ ID: ret[i].ID.String(), + Reference: ret[i].ID.Reference, CreatedAt: ret[i].CreatedAt, UpdatedAt: ret[i].UpdatedAt, ScheduledAt: ret[i].ScheduledAt, diff --git a/components/payments/cmd/api/internal/api/transfer_initiation_test.go b/components/payments/cmd/api/internal/api/transfer_initiation_test.go index 9429083df5..d320b9da8b 100644 --- a/components/payments/cmd/api/internal/api/transfer_initiation_test.go +++ b/components/payments/cmd/api/internal/api/transfer_initiation_test.go @@ -226,6 +226,7 @@ func TestListTransferInitiations(t *testing.T) { expectedTFsResponse := []*transferInitiationResponse{ { ID: listTFsResponse[0].ID.String(), + Reference: listTFsResponse[0].ID.Reference, CreatedAt: listTFsResponse[0].CreatedAt, UpdatedAt: listTFsResponse[0].UpdatedAt, ScheduledAt: listTFsResponse[0].ScheduledAt, @@ -242,6 +243,7 @@ func TestListTransferInitiations(t *testing.T) { }, { ID: listTFsResponse[1].ID.String(), + Reference: listTFsResponse[1].ID.Reference, CreatedAt: listTFsResponse[1].CreatedAt, UpdatedAt: listTFsResponse[1].UpdatedAt, ScheduledAt: listTFsResponse[1].ScheduledAt, @@ -438,6 +440,7 @@ func TestGetTransferInitiation(t *testing.T) { expectedTransferInitiationResponse = &readTransferInitiationResponse{ transferInitiationResponse: transferInitiationResponse{ ID: getTransferInitiationResponse.ID.String(), + Reference: getTransferInitiationResponse.ID.Reference, CreatedAt: getTransferInitiationResponse.CreatedAt, UpdatedAt: getTransferInitiationResponse.UpdatedAt, ScheduledAt: getTransferInitiationResponse.ScheduledAt, @@ -491,6 +494,7 @@ func TestGetTransferInitiation(t *testing.T) { expectedTransferInitiationResponse = &readTransferInitiationResponse{ transferInitiationResponse: transferInitiationResponse{ ID: getTransferInitiationResponse.ID.String(), + Reference: getTransferInitiationResponse.ID.Reference, CreatedAt: getTransferInitiationResponse.CreatedAt, UpdatedAt: getTransferInitiationResponse.UpdatedAt, ScheduledAt: getTransferInitiationResponse.ScheduledAt, diff --git a/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_accounts.go b/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_accounts.go index 02059459ff..bd9b9d16e9 100644 --- a/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_accounts.go +++ b/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_accounts.go @@ -18,6 +18,10 @@ import ( "go.opentelemetry.io/otel/metric" ) +const ( + rootAccountReference = "root" +) + var ( accountsAttrs = metric.WithAttributes(append(connectorAttrs, attribute.String(metrics.ObjectAttributeKey, "accounts"))...) ) @@ -139,12 +143,12 @@ func registerRootAccount( if err := ingester.IngestAccounts(ctx, ingestion.AccountBatch{ { ID: models.AccountID{ - Reference: "root", + Reference: rootAccountReference, ConnectorID: connectorID, }, ConnectorID: connectorID, CreatedAt: time.Now().UTC(), - Reference: "root", + Reference: rootAccountReference, Type: models.AccountTypeInternal, }, }); err != nil { @@ -153,7 +157,7 @@ func registerRootAccount( balanceTask, err := models.EncodeTaskDescriptor(TaskDescriptor{ Name: "Fetch balance for the root account", Key: taskNameFetchBalances, - Account: "root", + Account: rootAccountReference, }) if err != nil { return errors.Wrap(err, "failed to transform task descriptor") diff --git a/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_balances.go b/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_balances.go index b42d85e4f2..0e4b37a47e 100644 --- a/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_balances.go +++ b/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_balances.go @@ -33,7 +33,7 @@ func balanceTask(account string, client *client.DefaultClient) func(ctx context. }() stripeAccount := account - if account == "root" { + if account == rootAccountReference { // special case for root account stripeAccount = "" } diff --git a/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_payments.go b/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_payments.go index 0f7189ed78..76ad1bec98 100644 --- a/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_payments.go +++ b/components/payments/cmd/connectors/internal/connectors/stripe/task_fetch_payments.go @@ -33,7 +33,7 @@ func fetchPaymentsTask(config TimelineConfig, client *client.DefaultClient) func logger, NewIngester( func(ctx context.Context, batch []*stripe.BalanceTransaction, commitState TimelineState, tail bool) error { - if err := ingestBatch(ctx, connectorID, "root", logger, ingester, batch, commitState, tail); err != nil { + if err := ingestBatch(ctx, connectorID, rootAccountReference, logger, ingester, batch, commitState, tail); err != nil { return err } metricsRegistry.ConnectorObjects().Add(ctx, int64(len(batch)), paymentsAttrs) diff --git a/components/payments/cmd/connectors/internal/connectors/stripe/task_payments.go b/components/payments/cmd/connectors/internal/connectors/stripe/task_payments.go index 54e343d4ff..5b2db71674 100644 --- a/components/payments/cmd/connectors/internal/connectors/stripe/task_payments.go +++ b/components/payments/cmd/connectors/internal/connectors/stripe/task_payments.go @@ -87,7 +87,10 @@ func initiatePaymentTask(transferID string, stripeClient *client.DefaultClient) } stripeClient := client.Client(stripeClient) - if transfer.SourceAccount != nil { + // If source account is nil, or equal to root (which is a special + // account we create for stripe for the balance platform), we don't need + // to set the stripe account. + if transfer.SourceAccount != nil && transfer.SourceAccount.Reference != rootAccountReference { stripeClient = stripeClient.ForAccount(transfer.SourceAccountID.Reference) } diff --git a/components/payments/openapi.yaml b/components/payments/openapi.yaml index 5bdf487268..ba9f1da2ea 100644 --- a/components/payments/openapi.yaml +++ b/components/payments/openapi.yaml @@ -1455,6 +1455,7 @@ components: type: object required: - id + - reference - createdAt - updatedAt - scheduledAt @@ -1471,6 +1472,8 @@ components: id: type: string example: XXX + reference: + type: string createdAt: type: string format: date-time diff --git a/libs/clients/go/docs/models/shared/transferinitiation.md b/libs/clients/go/docs/models/shared/transferinitiation.md index 30bb929bd9..07a59fe872 100755 --- a/libs/clients/go/docs/models/shared/transferinitiation.md +++ b/libs/clients/go/docs/models/shared/transferinitiation.md @@ -13,6 +13,7 @@ | `DestinationAccountID` | *string* | :heavy_check_mark: | N/A | | | `Error` | *string* | :heavy_check_mark: | N/A | | | `ID` | *string* | :heavy_check_mark: | N/A | XXX | +| `Reference` | *string* | :heavy_check_mark: | N/A | | | `RelatedPayments` | [][TransferInitiationPayments](../../models/shared/transferinitiationpayments.md) | :heavy_minus_sign: | N/A | | | `ScheduledAt` | [time.Time](https://pkg.go.dev/time#Time) | :heavy_check_mark: | N/A | | | `SourceAccountID` | *string* | :heavy_check_mark: | N/A | | diff --git a/libs/clients/go/pkg/models/shared/transferinitiation.go b/libs/clients/go/pkg/models/shared/transferinitiation.go index eb94ee9176..036386a2a3 100755 --- a/libs/clients/go/pkg/models/shared/transferinitiation.go +++ b/libs/clients/go/pkg/models/shared/transferinitiation.go @@ -46,6 +46,7 @@ type TransferInitiation struct { DestinationAccountID string `json:"destinationAccountID"` Error string `json:"error"` ID string `json:"id"` + Reference string `json:"reference"` RelatedPayments []TransferInitiationPayments `json:"relatedPayments,omitempty"` ScheduledAt time.Time `json:"scheduledAt"` SourceAccountID string `json:"sourceAccountID"` @@ -121,6 +122,13 @@ func (o *TransferInitiation) GetID() string { return o.ID } +func (o *TransferInitiation) GetReference() string { + if o == nil { + return "" + } + return o.Reference +} + func (o *TransferInitiation) GetRelatedPayments() []TransferInitiationPayments { if o == nil { return nil