Bootstrap copied BFF and local accounts with public Sendico contracts (#34)
This commit is contained in:
1 parent
67dc5b5b1e
commit
7062672a87
556 files changed
+42291
-777
No files matched your search
@@ -0,0 +1,276 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"git.sendico.io/tech/sxchnge/bff/pkg/merrors"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type PaymentType int
|
||||
|
||||
const (
|
||||
PaymentTypeIban PaymentType = iota
|
||||
PaymentTypeCard
|
||||
PaymentTypeCardToken
|
||||
PaymentTypeBankAccount
|
||||
PaymentTypeWallet
|
||||
PaymentTypeCryptoAddress
|
||||
PaymentTypeLedger
|
||||
)
|
||||
|
||||
var paymentTypeToString = map[PaymentType]string{
|
||||
PaymentTypeIban: "iban",
|
||||
PaymentTypeCard: "card",
|
||||
PaymentTypeCardToken: "cardToken",
|
||||
PaymentTypeBankAccount: "bankAccount",
|
||||
PaymentTypeWallet: "wallet",
|
||||
PaymentTypeCryptoAddress: "cryptoAddress",
|
||||
PaymentTypeLedger: "ledger",
|
||||
}
|
||||
|
||||
var paymentTypeFromString = map[string]PaymentType{
|
||||
"iban": PaymentTypeIban,
|
||||
"card": PaymentTypeCard,
|
||||
"cardToken": PaymentTypeCardToken,
|
||||
"bankAccount": PaymentTypeBankAccount,
|
||||
"wallet": PaymentTypeWallet,
|
||||
"cryptoAddress": PaymentTypeCryptoAddress,
|
||||
"ledger": PaymentTypeLedger,
|
||||
}
|
||||
|
||||
func (t PaymentType) String() string {
|
||||
if v, ok := paymentTypeToString[t]; ok {
|
||||
return v
|
||||
}
|
||||
return "iban"
|
||||
}
|
||||
|
||||
func (t PaymentType) IsValid() bool {
|
||||
_, ok := paymentTypeToString[t]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (t PaymentType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(t.String())
|
||||
}
|
||||
|
||||
func (t *PaymentType) UnmarshalJSON(data []byte) error {
|
||||
var val string
|
||||
if err := json.Unmarshal(data, &val); err != nil {
|
||||
return err
|
||||
}
|
||||
v, ok := paymentTypeFromString[val]
|
||||
if !ok {
|
||||
return merrors.InvalidArgument(fmt.Sprintf("unknown PaymentType: %q", val))
|
||||
}
|
||||
*t = v
|
||||
return nil
|
||||
}
|
||||
|
||||
type PaymentMethodOwnerKind string
|
||||
|
||||
const (
|
||||
PaymentMethodOwnerKindUnspecified PaymentMethodOwnerKind = ""
|
||||
PaymentMethodOwnerKindAccount PaymentMethodOwnerKind = "ACCOUNT"
|
||||
PaymentMethodOwnerKindRecipient PaymentMethodOwnerKind = "RECIPIENT"
|
||||
)
|
||||
|
||||
func (k PaymentMethodOwnerKind) String() string {
|
||||
return string(k)
|
||||
}
|
||||
|
||||
func (k PaymentMethodOwnerKind) IsValid() bool {
|
||||
switch k {
|
||||
case PaymentMethodOwnerKindAccount, PaymentMethodOwnerKindRecipient:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type PaymentMethod struct {
|
||||
PermissionBound `bson:",inline" json:",inline"`
|
||||
Describable `bson:",inline" json:",inline"`
|
||||
|
||||
OwnerKind PaymentMethodOwnerKind `bson:"ownerKind" json:"ownerKind"`
|
||||
OwnerRef bson.ObjectID `bson:"ownerRef" json:"ownerRef"`
|
||||
Type PaymentType `bson:"type" json:"type"`
|
||||
Data bson.Raw `bson:"data" json:"data"`
|
||||
IsMain bool `bson:"isMain" json:"isMain"`
|
||||
}
|
||||
|
||||
type paymentMethodJSON struct {
|
||||
PermissionBound `json:",inline"`
|
||||
Describable `json:",inline"`
|
||||
|
||||
OwnerKind PaymentMethodOwnerKind `json:"ownerKind"`
|
||||
OwnerRef bson.ObjectID `json:"ownerRef"`
|
||||
Type PaymentType `json:"type"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
IsMain bool `json:"isMain"`
|
||||
}
|
||||
|
||||
func (m PaymentMethod) MarshalJSON() ([]byte, error) {
|
||||
marshaledData, err := m.marshalDataJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payload := paymentMethodJSON{
|
||||
PermissionBound: m.PermissionBound,
|
||||
Describable: m.Describable,
|
||||
OwnerKind: m.OwnerKind,
|
||||
OwnerRef: m.OwnerRef,
|
||||
Type: m.Type,
|
||||
Data: marshaledData,
|
||||
IsMain: m.IsMain,
|
||||
}
|
||||
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func (m *PaymentMethod) UnmarshalJSON(data []byte) error {
|
||||
var payload paymentMethodJSON
|
||||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.PermissionBound = payload.PermissionBound
|
||||
m.Describable = payload.Describable
|
||||
m.OwnerKind = payload.OwnerKind
|
||||
m.OwnerRef = payload.OwnerRef
|
||||
m.Type = payload.Type
|
||||
m.IsMain = payload.IsMain
|
||||
|
||||
if len(payload.Data) == 0 || bytes.Equal(payload.Data, []byte("null")) {
|
||||
m.Data = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if raw, ok, err := m.unmarshalTypedDataJSON(payload.Data); ok || err != nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Data = raw
|
||||
return nil
|
||||
}
|
||||
|
||||
var rawData map[string]any
|
||||
if err := json.Unmarshal(payload.Data, &rawData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
raw, err := bson.Marshal(rawData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Data = raw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m PaymentMethod) marshalDataJSON() (json.RawMessage, error) {
|
||||
if len(m.Data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var payload any
|
||||
var err error
|
||||
switch m.Type {
|
||||
case PaymentTypeIban:
|
||||
payload, err = marshalTypedPaymentData[IbanPaymentData](m.Data)
|
||||
case PaymentTypeCard:
|
||||
payload, err = marshalTypedPaymentData[CardPaymentData](m.Data)
|
||||
case PaymentTypeCardToken:
|
||||
payload, err = marshalTypedPaymentData[TokenPaymentData](m.Data)
|
||||
case PaymentTypeBankAccount:
|
||||
payload, err = marshalTypedPaymentData[RussianBankAccountPaymentData](m.Data)
|
||||
case PaymentTypeWallet:
|
||||
payload, err = marshalTypedPaymentData[WalletPaymentData](m.Data)
|
||||
case PaymentTypeCryptoAddress:
|
||||
payload, err = marshalTypedPaymentData[CryptoAddressPaymentData](m.Data)
|
||||
case PaymentTypeLedger:
|
||||
payload, err = marshalTypedPaymentData[LedgerPaymentData](m.Data)
|
||||
default:
|
||||
var data bson.M
|
||||
if err := bson.Unmarshal(m.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data == nil {
|
||||
return nil, nil
|
||||
}
|
||||
payload = data
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (m PaymentMethod) unmarshalTypedDataJSON(data json.RawMessage) (bson.Raw, bool, error) {
|
||||
switch m.Type {
|
||||
case PaymentTypeIban:
|
||||
return unmarshalTypedPaymentData[IbanPaymentData](data)
|
||||
case PaymentTypeCard:
|
||||
return unmarshalTypedPaymentData[CardPaymentData](data)
|
||||
case PaymentTypeCardToken:
|
||||
return unmarshalTypedPaymentData[TokenPaymentData](data)
|
||||
case PaymentTypeBankAccount:
|
||||
return unmarshalTypedPaymentData[RussianBankAccountPaymentData](data)
|
||||
case PaymentTypeWallet:
|
||||
return unmarshalTypedPaymentData[WalletPaymentData](data)
|
||||
case PaymentTypeCryptoAddress:
|
||||
return unmarshalTypedPaymentData[CryptoAddressPaymentData](data)
|
||||
case PaymentTypeLedger:
|
||||
return unmarshalTypedPaymentData[LedgerPaymentData](data)
|
||||
default:
|
||||
return nil, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func marshalTypedPaymentData[T any](raw bson.Raw) (T, error) {
|
||||
var payload T
|
||||
err := bson.Unmarshal(raw, &payload)
|
||||
return payload, err
|
||||
}
|
||||
|
||||
func unmarshalTypedPaymentData[T any](data json.RawMessage) (bson.Raw, bool, error) {
|
||||
var payload T
|
||||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
raw, err := bson.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
return raw, true, nil
|
||||
}
|
||||
|
||||
type PaymentStatus string
|
||||
|
||||
const (
|
||||
PaymentStatusUnspecified PaymentStatus = "unspecified"
|
||||
|
||||
// Intent exists, no funds touched yet.
|
||||
PaymentStatusCreated PaymentStatus = "created"
|
||||
|
||||
// Internal Sendico operations: holds, ledger, FX, fee calc.
|
||||
PaymentStatusAuthorizing PaymentStatus = "authorizing"
|
||||
|
||||
// Funds are outside Sendico (rail/gateway/blockchain/provider).
|
||||
// Observe lives ONLY in this state.
|
||||
PaymentStatusExecuting PaymentStatus = "executing"
|
||||
|
||||
// Final states.
|
||||
PaymentStatusSucceeded PaymentStatus = "success"
|
||||
PaymentStatusFailed PaymentStatus = "failed"
|
||||
PaymentStatusCancelled PaymentStatus = "cancelled"
|
||||
)
|
||||
Reference in new issue
Block a user