-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #121 from formancehq/feat/banking-circle-transfer-…
…payout feat(bankingcircle): add transfer/payout creation
- Loading branch information
Showing
7 changed files
with
244 additions
and
7 deletions.
There are no files selected for viewing
3 changes: 1 addition & 2 deletions
3
internal/connectors/plugins/public/bankingcircle/bank_account_creation.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
internal/connectors/plugins/public/bankingcircle/payouts.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package bankingcircle | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/formancehq/payments/internal/connectors/plugins/currency" | ||
"github.com/formancehq/payments/internal/connectors/plugins/public/bankingcircle/client" | ||
"github.com/formancehq/payments/internal/models" | ||
) | ||
|
||
func (p *Plugin) validatePayoutRequest(pi models.PSPPaymentInitiation) error { | ||
if pi.SourceAccount == nil { | ||
return fmt.Errorf("source account is required: %w", models.ErrInvalidRequest) | ||
} | ||
|
||
if pi.DestinationAccount == nil { | ||
return fmt.Errorf("destination account is required: %w", models.ErrInvalidRequest) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *Plugin) createPayout(ctx context.Context, pi models.PSPPaymentInitiation) (models.PSPPayment, error) { | ||
if err := p.validatePayoutRequest(pi); err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
curr, precision, err := currency.GetCurrencyAndPrecisionFromAsset(supportedCurrenciesWithDecimal, pi.Asset) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get currency and precision from asset: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
amount, err := currency.GetStringAmountFromBigIntWithPrecision(pi.Amount, precision) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get string amount from big int: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
var sourceAccount *client.Account | ||
sourceAccount, err = p.client.GetAccount(ctx, pi.SourceAccount.Reference) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get source account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
if len(sourceAccount.AccountIdentifiers) == 0 { | ||
return models.PSPPayment{}, fmt.Errorf("no account identifiers provided for source account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
var destinationAccount *client.Account | ||
destinationAccount, err = p.client.GetAccount(ctx, pi.DestinationAccount.Reference) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get destination account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
if len(destinationAccount.AccountIdentifiers) == 0 { | ||
return models.PSPPayment{}, fmt.Errorf("no account identifiers provided for destination account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
resp, err := p.client.InitiateTransferOrPayouts(ctx, &client.PaymentRequest{ | ||
IdempotencyKey: pi.Reference, | ||
RequestedExecutionDate: pi.CreatedAt, | ||
DebtorAccount: client.PaymentAccount{ | ||
Account: sourceAccount.AccountIdentifiers[0].Account, | ||
FinancialInstitution: sourceAccount.AccountIdentifiers[0].FinancialInstitution, | ||
Country: sourceAccount.AccountIdentifiers[0].Country, | ||
}, | ||
DebtorReference: pi.Description, | ||
CurrencyOfTransfer: curr, | ||
Amount: struct { | ||
Currency string "json:\"currency\"" | ||
Amount json.Number "json:\"amount\"" | ||
}{ | ||
Currency: curr, | ||
Amount: json.Number(amount), | ||
}, | ||
ChargeBearer: "SHA", | ||
CreditorAccount: &client.PaymentAccount{ | ||
Account: destinationAccount.AccountIdentifiers[0].Account, | ||
FinancialInstitution: destinationAccount.AccountIdentifiers[0].FinancialInstitution, | ||
Country: destinationAccount.AccountIdentifiers[0].Country, | ||
}, | ||
}) | ||
if err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
payment, err := p.client.GetPayment(ctx, resp.PaymentID) | ||
if err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
res, err := translatePayment(*payment) | ||
if err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
return *res, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
internal/connectors/plugins/public/bankingcircle/transfers.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package bankingcircle | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/formancehq/payments/internal/connectors/plugins/currency" | ||
"github.com/formancehq/payments/internal/connectors/plugins/public/bankingcircle/client" | ||
"github.com/formancehq/payments/internal/models" | ||
) | ||
|
||
func (p *Plugin) validateTransferRequest(pi models.PSPPaymentInitiation) error { | ||
if pi.SourceAccount == nil { | ||
return fmt.Errorf("source account is required: %w", models.ErrInvalidRequest) | ||
} | ||
|
||
if pi.DestinationAccount == nil { | ||
return fmt.Errorf("destination account is required: %w", models.ErrInvalidRequest) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *Plugin) createTransfer(ctx context.Context, pi models.PSPPaymentInitiation) (models.PSPPayment, error) { | ||
if err := p.validateTransferRequest(pi); err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
curr, precision, err := currency.GetCurrencyAndPrecisionFromAsset(supportedCurrenciesWithDecimal, pi.Asset) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get currency and precision from asset: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
amount, err := currency.GetStringAmountFromBigIntWithPrecision(pi.Amount, precision) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get string amount from big int: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
var sourceAccount *client.Account | ||
sourceAccount, err = p.client.GetAccount(ctx, pi.SourceAccount.Reference) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get source account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
if len(sourceAccount.AccountIdentifiers) == 0 { | ||
return models.PSPPayment{}, fmt.Errorf("no account identifiers provided for source account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
var destinationAccount *client.Account | ||
destinationAccount, err = p.client.GetAccount(ctx, pi.DestinationAccount.Reference) | ||
if err != nil { | ||
return models.PSPPayment{}, fmt.Errorf("failed to get destination account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
if len(destinationAccount.AccountIdentifiers) == 0 { | ||
return models.PSPPayment{}, fmt.Errorf("no account identifiers provided for destination account: %v: %w", err, models.ErrInvalidRequest) | ||
} | ||
|
||
resp, err := p.client.InitiateTransferOrPayouts( | ||
ctx, | ||
&client.PaymentRequest{ | ||
IdempotencyKey: pi.Reference, | ||
RequestedExecutionDate: pi.CreatedAt, | ||
DebtorAccount: client.PaymentAccount{ | ||
Account: sourceAccount.AccountIdentifiers[0].Account, | ||
FinancialInstitution: sourceAccount.AccountIdentifiers[0].FinancialInstitution, | ||
Country: sourceAccount.AccountIdentifiers[0].Country, | ||
}, | ||
DebtorReference: pi.Description, | ||
CurrencyOfTransfer: curr, | ||
Amount: struct { | ||
Currency string "json:\"currency\"" | ||
Amount json.Number "json:\"amount\"" | ||
}{ | ||
Currency: curr, | ||
Amount: json.Number(amount), | ||
}, | ||
ChargeBearer: "SHA", | ||
CreditorAccount: &client.PaymentAccount{ | ||
Account: destinationAccount.AccountIdentifiers[0].Account, | ||
FinancialInstitution: destinationAccount.AccountIdentifiers[0].FinancialInstitution, | ||
Country: destinationAccount.AccountIdentifiers[0].Country, | ||
}, | ||
}, | ||
) | ||
if err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
payment, err := p.client.GetPayment(ctx, resp.PaymentID) | ||
if err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
res, err := translatePayment(*payment) | ||
if err != nil { | ||
return models.PSPPayment{}, err | ||
} | ||
|
||
return *res, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters