mirror of
https://github.com/hanzo-fi/payments.git
synced 2026-10-30 20:31:20 +00:00
- go.mod module path + all self-imports: github.com/formancehq/payments -> github.com/hanzo-fi/payments (1590 .go files / 3152 refs; 20 modules: root, pkg/client, pkg/domain, 18 ce/plugins). External dep kept: formancehq/go-libs. - plugins: each ce/plugins/* consumed a *published* pkg/domain; added local 'replace .../pkg/domain => ../../../pkg/domain' (consistent with root) so every standalone plugin module builds in-monorepo. compile-plugin.sh MOD var rebranded too. - branding: README, LICENSE (dual MIT+EE; upstream copyright retained + Hanzo added), goreleaser (release images -> registry.hanzo.ai/hanzo-fi, OCI labels, homepage), proto go_package, renovate, speakeasy gen.yaml, connector-template *.gotpl. - CI: removed Numary/Formance workflows + composite action; added canonical hanzo.yml + cicd.yml (hanzoai/ci, gated HANZO_CI_ENABLED) + secretless ci.yml (go build/vet). - kept as data/compat keys: wire capability enums ALLOW_FORMANCE_*, generated SDK type client.Formance, domain field FormanceRedirectURL, OTEL_SERVICE_NAME, upstream base image. - verified: go build ./... (default + -tags ee) + all 20 nested modules green.
109 lines
3.0 KiB
Go
109 lines
3.0 KiB
Go
package generic
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/hanzo-fi/payments/ce/plugins/generic/client"
|
|
"github.com/hanzo-fi/payments/pkg/domain/models"
|
|
errorsutils "github.com/hanzo-fi/payments/pkg/domain/errors"
|
|
)
|
|
|
|
func (p *Plugin) createTransfer(ctx context.Context, pi models.PSPPaymentInitiation) (models.PSPPayment, error) {
|
|
if err := p.validateTransferRequest(pi); err != nil {
|
|
return models.PSPPayment{}, err
|
|
}
|
|
|
|
if _, _, err := parseAssetUMN(pi.Asset); err != nil {
|
|
return models.PSPPayment{}, errorsutils.NewWrappedError(
|
|
fmt.Errorf("failed to parse asset %s: %w", pi.Asset, err),
|
|
models.ErrInvalidRequest,
|
|
)
|
|
}
|
|
|
|
req := &client.TransferRequest{
|
|
IdempotencyKey: pi.Reference,
|
|
Amount: pi.Amount.String(),
|
|
Currency: pi.Asset,
|
|
SourceAccountID: pi.SourceAccount.Reference,
|
|
DestinationAccountID: pi.DestinationAccount.Reference,
|
|
Description: &pi.Description,
|
|
Metadata: pi.Metadata,
|
|
}
|
|
|
|
resp, err := p.client.CreateTransfer(ctx, req)
|
|
if err != nil {
|
|
return models.PSPPayment{}, err
|
|
}
|
|
|
|
return transferResponseToPayment(resp)
|
|
}
|
|
|
|
func (p *Plugin) validateTransferRequest(pi models.PSPPaymentInitiation) error {
|
|
if pi.SourceAccount == nil {
|
|
return errorsutils.NewWrappedError(
|
|
fmt.Errorf("source account is required"),
|
|
models.ErrInvalidRequest,
|
|
)
|
|
}
|
|
|
|
if pi.DestinationAccount == nil {
|
|
return errorsutils.NewWrappedError(
|
|
fmt.Errorf("destination account is required"),
|
|
models.ErrInvalidRequest,
|
|
)
|
|
}
|
|
|
|
if pi.Amount == nil || pi.Amount.Cmp(big.NewInt(0)) <= 0 {
|
|
return errorsutils.NewWrappedError(
|
|
fmt.Errorf("amount must be positive"),
|
|
models.ErrInvalidRequest,
|
|
)
|
|
}
|
|
|
|
if pi.Reference == "" {
|
|
return errorsutils.NewWrappedError(
|
|
fmt.Errorf("reference is required"),
|
|
models.ErrInvalidRequest,
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func transferResponseToPayment(resp *client.TransferResponse) (models.PSPPayment, error) {
|
|
var amount big.Int
|
|
_, ok := amount.SetString(resp.Amount, 10)
|
|
if !ok {
|
|
return models.PSPPayment{}, fmt.Errorf("failed to parse amount %s as integer", resp.Amount)
|
|
}
|
|
|
|
createdAt, err := time.Parse(time.RFC3339, resp.CreatedAt)
|
|
if err != nil {
|
|
return models.PSPPayment{}, fmt.Errorf("failed to parse createdAt: %w", err)
|
|
}
|
|
|
|
raw, err := json.Marshal(resp)
|
|
if err != nil {
|
|
return models.PSPPayment{}, fmt.Errorf("failed to marshal raw response: %w", err)
|
|
}
|
|
|
|
return models.PSPPayment{
|
|
ParentReference: resp.IdempotencyKey,
|
|
Reference: resp.Id,
|
|
CreatedAt: createdAt,
|
|
Type: models.PAYMENT_TYPE_TRANSFER,
|
|
Amount: &amount,
|
|
Asset: resp.Currency,
|
|
Scheme: models.PAYMENT_SCHEME_OTHER,
|
|
Status: mapStringToPaymentStatus(resp.Status),
|
|
SourceAccountReference: &resp.SourceAccountID,
|
|
DestinationAccountReference: &resp.DestinationAccountID,
|
|
Metadata: resp.Metadata,
|
|
Raw: raw,
|
|
}, nil
|
|
}
|