Skip to content

Commit

Permalink
source account id is not optional
Browse files Browse the repository at this point in the history
  • Loading branch information
paul-nicolas committed Sep 25, 2023
1 parent 7f05faa commit 8ad2098
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 61 deletions.
33 changes: 19 additions & 14 deletions components/payments/internal/app/api/transfer_initiation.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type createTransferInitiationRequest struct {
Validated bool `json:"validated"`
}

func (r *createTransferInitiationRequest) Validate() error {
func (r *createTransferInitiationRequest) Validate(repo createTransferInitiationRepository) error {
if r.UniqueRequestID == "" {
return errors.New("uniqueRequestId is required")
}
Expand All @@ -55,12 +55,14 @@ func (r *createTransferInitiationRequest) Validate() error {
return errors.New("description is required")
}

_, err := models.AccountIDFromString(r.SourceAccountID)
if err != nil {
return err
if r.SourceAccountID != "" {
_, err := models.AccountIDFromString(r.SourceAccountID)
if err != nil {
return err
}
}

_, err = models.AccountIDFromString(r.DestinationAccountID)
_, err := models.AccountIDFromString(r.DestinationAccountID)
if err != nil {
return err
}
Expand Down Expand Up @@ -105,7 +107,7 @@ func createTransferInitiationHandler(
return
}

if err := payload.Validate(); err != nil {
if err := payload.Validate(repo); err != nil {
handleValidationError(w, r, err)

return
Expand All @@ -120,14 +122,16 @@ func createTransferInitiationHandler(
status = models.TransferInitiationStatusValidated
}

sourceAccount, err := repo.GetAccount(r.Context(), payload.SourceAccountID)
if err != nil {
handleStorageErrors(w, r, fmt.Errorf("failed to get source account: %w", err))
if payload.SourceAccountID != "" {
_, err := repo.GetAccount(r.Context(), payload.SourceAccountID)
if err != nil {
handleStorageErrors(w, r, fmt.Errorf("failed to get source account: %w", err))

return
return
}
}

destinationAccount, err := repo.GetAccount(r.Context(), payload.DestinationAccountID)
_, err := repo.GetAccount(r.Context(), payload.DestinationAccountID)
if err != nil {
handleStorageErrors(w, r, fmt.Errorf("failed to get destination account: %w", err))

Expand All @@ -143,15 +147,16 @@ func createTransferInitiationHandler(
CreatedAt: payload.CreatedAt,
UpdatedAt: payload.CreatedAt, // When created, should be the same
Description: payload.Description,
SourceAccountID: models.MustAccountIDFromString(payload.SourceAccountID),
DestinationAccountID: models.MustAccountIDFromString(payload.DestinationAccountID),
Provider: provider,
Type: models.MustTransferInitiationTypeFromString(payload.Type),
Amount: payload.Amount,
Asset: models.Asset(payload.Asset),
Status: status,
SourceAccount: sourceAccount,
DestinationAccount: destinationAccount,
}

if payload.SourceAccountID != "" {
tf.SourceAccountID = models.MustAccountIDFromString(payload.SourceAccountID)
}

if err := repo.CreateTransferInitiation(r.Context(), tf); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ func taskInitiatePayment(logger logging.Logger, currencyCloudClient *client.Clie
metricsRegistry.ConnectorObjectsLatency().Record(ctx, time.Since(now).Milliseconds(), attrs)
}()

if transfer.SourceAccount == nil {
err = errors.New("no source account provided")
return err
}

if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
Expand All @@ -98,8 +103,8 @@ func taskInitiatePayment(logger logging.Logger, currencyCloudClient *client.Clie
// Transfer between internal accounts
var resp *client.TransferResponse
resp, err = currencyCloudClient.InitiateTransfer(ctx, &client.TransferRequest{
SourceAccountID: transfer.SourceAccount.Reference,
DestinationAccountID: transfer.DestinationAccount.Reference,
SourceAccountID: transfer.SourceAccountID.Reference,
DestinationAccountID: transfer.DestinationAccountID.Reference,
Currency: curr,
Amount: amount,
Reason: transfer.Description,
Expand All @@ -112,7 +117,7 @@ func taskInitiatePayment(logger logging.Logger, currencyCloudClient *client.Clie
connectorPaymentID = resp.ID
case models.AccountTypeExternal:
// Payout to an external account
contact, err := currencyCloudClient.GetContactID(ctx, transfer.SourceAccount.Reference)
contact, err := currencyCloudClient.GetContactID(ctx, transfer.SourceAccount.ID.Reference)
if err != nil {
return err
}
Expand Down Expand Up @@ -282,11 +287,13 @@ func getTransfer(
}

if expand {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
if transfer.SourceAccountID.Reference != "" {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
}
transfer.SourceAccount = sourceAccount
}
transfer.SourceAccount = sourceAccount

destinationAccount, err := reader.GetAccount(ctx, transfer.DestinationAccountID.String())
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func taskInitiatePayment(logger logging.Logger, mangopayClient *client.Client, t
metricsRegistry.ConnectorObjectsLatency().Record(ctx, time.Since(now).Milliseconds(), attrs)
}()

if transfer.SourceAccount == nil {
err = errors.New("no source account provided")
return err
}

if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
Expand Down Expand Up @@ -113,8 +118,8 @@ func taskInitiatePayment(logger logging.Logger, mangopayClient *client.Client, t
Currency: curr,
Amount: "0",
},
DebitedWalletID: transfer.SourceAccount.Reference,
CreditedWalletID: transfer.DestinationAccount.Reference,
DebitedWalletID: transfer.SourceAccountID.Reference,
CreditedWalletID: transfer.DestinationAccountID.Reference,
})
if err != nil {
return err
Expand All @@ -135,7 +140,7 @@ func taskInitiatePayment(logger logging.Logger, mangopayClient *client.Client, t
Amount: json.Number("0"),
},
DebitedWalletID: transfer.SourceAccountID.Reference,
BankAccountID: transfer.DestinationAccount.Reference,
BankAccountID: transfer.DestinationAccountID.Reference,
BankWireRef: bankWireRef,
})
if err != nil {
Expand Down Expand Up @@ -294,11 +299,13 @@ func getTransfer(
}

if expand {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
if transfer.SourceAccountID.Reference != "" {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
}
transfer.SourceAccount = sourceAccount
}
transfer.SourceAccount = sourceAccount

destinationAccount, err := reader.GetAccount(ctx, transfer.DestinationAccountID.String())
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func taskInitiatePayment(logger logging.Logger, modulrClient *client.Client, tra
metricsRegistry.ConnectorObjectsLatency().Record(ctx, time.Since(now).Milliseconds(), attrs)
}()

if transfer.SourceAccount == nil {
err = errors.New("no source account provided")
return err
}

if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
Expand Down Expand Up @@ -101,10 +106,10 @@ func taskInitiatePayment(logger logging.Logger, modulrClient *client.Client, tra
// Transfer between internal accounts
var resp *client.TransferResponse
resp, err = modulrClient.InitiateTransfer(&client.TransferRequest{
SourceAccountID: transfer.SourceAccount.Reference,
SourceAccountID: transfer.SourceAccountID.Reference,
Destination: client.Destination{
Type: string(client.DestinationTypeAccount),
ID: transfer.DestinationAccount.Reference,
ID: transfer.DestinationAccountID.Reference,
},
Currency: curr,
Amount: amount,
Expand All @@ -121,7 +126,7 @@ func taskInitiatePayment(logger logging.Logger, modulrClient *client.Client, tra
// Payout to an external account
var resp *client.PayoutResponse
resp, err = modulrClient.InitiatePayout(&client.PayoutRequest{
SourceAccountID: transfer.SourceAccount.Reference,
SourceAccountID: transfer.SourceAccountID.Reference,
Destination: client.Destination{
Type: string(client.DestinationTypeBeneficiary),
ID: transfer.DestinationAccountID.Reference,
Expand Down Expand Up @@ -287,11 +292,13 @@ func getTransfer(
}

if expand {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
if transfer.SourceAccountID.Reference != "" {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
}
transfer.SourceAccount = sourceAccount
}
transfer.SourceAccount = sourceAccount

destinationAccount, err := reader.GetAccount(ctx, transfer.DestinationAccountID.String())
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ func taskInitiatePayment(logger logging.Logger, moneycorpClient *client.Client,
metricsRegistry.ConnectorObjectsLatency().Record(ctx, time.Since(now).Milliseconds(), attrs)
}()

if transfer.SourceAccount == nil {
err = errors.New("no source account provided")
}

if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
Expand All @@ -99,9 +103,9 @@ func taskInitiatePayment(logger logging.Logger, moneycorpClient *client.Client,
// Transfer between internal accounts
var resp *client.TransferResponse
resp, err = moneycorpClient.InitiateTransfer(ctx, &client.TransferRequest{
SourceAccountID: transfer.SourceAccount.Reference,
SourceAccountID: transfer.SourceAccountID.Reference,
IdempotencyKey: transfer.ID.UniqueRequestID,
ReceivingAccountID: transfer.DestinationAccount.Reference,
ReceivingAccountID: transfer.DestinationAccountID.Reference,
TransferAmount: amount,
TransferCurrency: curr,
TransferReference: transfer.Description,
Expand All @@ -116,9 +120,9 @@ func taskInitiatePayment(logger logging.Logger, moneycorpClient *client.Client,
// Payout to an external account
var resp *client.PayoutResponse
resp, err = moneycorpClient.InitiatePayout(ctx, &client.PayoutRequest{
SourceAccountID: transfer.SourceAccount.Reference,
SourceAccountID: transfer.SourceAccountID.Reference,
IdempotencyKey: transfer.ID.UniqueRequestID,
RecipientID: transfer.DestinationAccount.Reference,
RecipientID: transfer.DestinationAccountID.Reference,
PaymentAmount: amount,
PaymentCurrency: curr,
PaymentMethgod: "Standard",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ type CreatePayoutRequest struct {
}

func (d *DefaultClient) CreatePayout(ctx context.Context, createPayoutRequest *CreatePayoutRequest, options ...ClientOption) (*stripe.Payout, error) {
if d.stripeAccount == "" {
return nil, errors.New("stripe account is required")
}

data := url.Values{}
data.Add("amount", strconv.FormatInt(createPayoutRequest.Amount, 10))
data.Add("currency", createPayoutRequest.Currency)
Expand All @@ -47,7 +43,9 @@ func (d *DefaultClient) CreatePayout(ctx context.Context, createPayoutRequest *C
opt.Apply(req)
}

req.Header.Set("Stripe-Account", d.stripeAccount)
if d.stripeAccount != "" {
req.Header.Set("Stripe-Account", d.stripeAccount)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(d.apiKey, "") // gfyrag: really weird authentication right?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ type CreateTransferRequest struct {
}

func (d *DefaultClient) CreateTransfer(ctx context.Context, createTransferRequest *CreateTransferRequest, options ...ClientOption) (*stripe.Transfer, error) {
if d.stripeAccount == "" {
return nil, errors.New("stripe account is required")
}

data := url.Values{}
data.Add("amount", strconv.FormatInt(createTransferRequest.Amount, 10))
data.Add("currency", createTransferRequest.Currency)
Expand All @@ -47,7 +43,9 @@ func (d *DefaultClient) CreateTransfer(ctx context.Context, createTransferReques
opt.Apply(req)
}

req.Header.Set("Stripe-Account", d.stripeAccount)
if d.stripeAccount != "" {
req.Header.Set("Stripe-Account", d.stripeAccount)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(d.apiKey, "") // gfyrag: really weird authentication right?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ func InitiatePaymentTask(logger logging.Logger, transferID string, stripeClient
metricsRegistry.ConnectorObjectsLatency().Record(ctx, time.Since(now).Milliseconds(), attrs)
}()

if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
if transfer.SourceAccount != nil {
if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
}
}

var curr string
Expand All @@ -83,7 +85,10 @@ func InitiatePaymentTask(logger logging.Logger, transferID string, stripeClient
return err
}

c := stripeClient.ForAccount(transfer.SourceAccountID.Reference)
c := client.Client(stripeClient)
if transfer.SourceAccount != nil {
c = stripeClient.ForAccount(transfer.SourceAccountID.Reference)
}

var connectorPaymentID string
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
Expand Down Expand Up @@ -242,11 +247,13 @@ func getTransfer(
}

if expand {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
if transfer.SourceAccountID.Reference != "" {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
}
transfer.SourceAccount = sourceAccount
}
transfer.SourceAccount = sourceAccount

destinationAccount, err := reader.GetAccount(ctx, transfer.DestinationAccountID.String())
if err != nil {
Expand Down
15 changes: 11 additions & 4 deletions components/payments/internal/app/connectors/wise/task_payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func taskInitiatePayment(logger logging.Logger, wiseClient *client.Client, trans
metricsRegistry.ConnectorObjectsLatency().Record(ctx, time.Since(now).Milliseconds(), attrs)
}()

if transfer.SourceAccount == nil {
err = errors.New("missing source account")
return err
}

if transfer.SourceAccount.Type == models.AccountTypeExternal {
err = errors.New("payin not implemented: source account must be an internal account")
return err
Expand Down Expand Up @@ -285,11 +290,13 @@ func getTransfer(
}

if expand {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
if transfer.SourceAccountID.Reference != "" {
sourceAccount, err := reader.GetAccount(ctx, transfer.SourceAccountID.String())
if err != nil {
return nil, err
}
transfer.SourceAccount = sourceAccount
}
transfer.SourceAccount = sourceAccount

destinationAccount, err := reader.GetAccount(ctx, transfer.DestinationAccountID.String())
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions components/payments/internal/app/models/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ type AccountID struct {
}

func (aid AccountID) String() string {
if aid.Reference == "" {
return ""
}

data, err := canonicaljson.Marshal(aid)
if err != nil {
panic(err)
Expand Down
Loading

0 comments on commit 8ad2098

Please sign in to comment.