diff --git a/components/fctl/cmd/payments/connectors/getconfig.go b/components/fctl/cmd/payments/connectors/getconfig.go index ab685eb562..afd74aba4f 100644 --- a/components/fctl/cmd/payments/connectors/getconfig.go +++ b/components/fctl/cmd/payments/connectors/getconfig.go @@ -62,6 +62,8 @@ func NewGetConfigCommand() *cobra.Command { err = displayCurrencyCloudConfig(cmd, response.ConnectorConfigResponse) case internal.WiseConnector: err = displayWiseConfig(cmd, response.ConnectorConfigResponse) + case internal.MangoPayConnector: + err = displayMangoPayConfig(cmd, response.ConnectorConfigResponse) default: pterm.Error.WithWriter(cmd.OutOrStderr()).Printfln("Connection unknown.") } @@ -176,3 +178,23 @@ func displayCurrencyCloudConfig(cmd *cobra.Command, connectorConfig *shared.Conn } return nil } + +func displayMangoPayConfig(cmd *cobra.Command, connectorConfig *shared.ConnectorConfigResponse) error { + config, ok := connectorConfig.Data.(*shared.MangoPayConfig) + if !ok { + return errors.New("invalid currency cloud connector config") + } + + tableData := pterm.TableData{} + tableData = append(tableData, []string{pterm.LightCyan("API key:"), config.APIKey}) + tableData = append(tableData, []string{pterm.LightCyan("Client ID:"), config.ClientID}) + tableData = append(tableData, []string{pterm.LightCyan("Endpoint:"), config.Endpoint}) + + if err := pterm.DefaultTable. + WithWriter(cmd.OutOrStdout()). + WithData(tableData). + Render(); err != nil { + return err + } + return nil +} diff --git a/components/fctl/cmd/payments/connectors/install/bankingcircle.go b/components/fctl/cmd/payments/connectors/install/bankingcircle.go index 8fb7f89e2a..020b2fdd3a 100644 --- a/components/fctl/cmd/payments/connectors/install/bankingcircle.go +++ b/components/fctl/cmd/payments/connectors/install/bankingcircle.go @@ -2,6 +2,7 @@ package install import ( "fmt" + "io/ioutil" "github.com/formancehq/fctl/cmd/payments/connectors/internal" fctl "github.com/formancehq/fctl/pkg" @@ -14,8 +15,10 @@ import ( func NewBankingCircleCommand() *cobra.Command { const ( - endpointFlag = "endpoint" - authorizationEndpointFlag = "authorization-endpoint" + endpointFlag = "endpoint" + authorizationEndpointFlag = "authorization-endpoint" + userCertificateFilePathFlag = "user-certificate" + userCertificateKeyFilePathFlag = "user-certificate-key" defaultEndpoint = "https://sandbox.bankingcircle.com" defaultAuthorizationEndpoint = "https://authorizationsandbox.bankingcircleconnect.com" @@ -25,6 +28,8 @@ func NewBankingCircleCommand() *cobra.Command { fctl.WithArgs(cobra.ExactArgs(2)), fctl.WithStringFlag(endpointFlag, defaultEndpoint, "API endpoint"), fctl.WithStringFlag(authorizationEndpointFlag, defaultAuthorizationEndpoint, "Authorization endpoint"), + fctl.WithStringFlag(userCertificateFilePathFlag, "", "User certificate"), + fctl.WithStringFlag(userCertificateKeyFilePathFlag, "", "User certificate key"), fctl.WithRunE(func(cmd *cobra.Command, args []string) error { cfg, err := fctl.GetConfig(cmd) if err != nil { @@ -50,6 +55,16 @@ func NewBankingCircleCommand() *cobra.Command { return err } + certificate, err := ioutil.ReadFile(fctl.GetString(cmd, userCertificateFilePathFlag)) + if err != nil { + return errors.Wrap(err, "reading user certificate") + } + + key, err := ioutil.ReadFile(fctl.GetString(cmd, userCertificateKeyFilePathFlag)) + if err != nil { + return errors.Wrap(err, "reading user certificate key") + } + request := operations.InstallConnectorRequest{ Connector: shared.ConnectorBankingCircle, RequestBody: shared.BankingCircleConfig{ @@ -57,6 +72,8 @@ func NewBankingCircleCommand() *cobra.Command { Password: args[1], Endpoint: fctl.GetString(cmd, endpointFlag), AuthorizationEndpoint: fctl.GetString(cmd, authorizationEndpointFlag), + UserCertificate: string(certificate), + UserCertificateKey: string(key), }, } response, err := paymentsClient.Payments.InstallConnector(cmd.Context(), request) diff --git a/components/fctl/cmd/payments/connectors/install/mangopay.go b/components/fctl/cmd/payments/connectors/install/mangopay.go new file mode 100644 index 0000000000..3ea6780622 --- /dev/null +++ b/components/fctl/cmd/payments/connectors/install/mangopay.go @@ -0,0 +1,72 @@ +package install + +import ( + "fmt" + + "github.com/formancehq/fctl/cmd/payments/connectors/internal" + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pkg/errors" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +func NewMangoPayCommand() *cobra.Command { + const ( + endpointFlag = "endpoint" + + defaultEndpoint = "https://api.sandbox.mangopay.com" + ) + return fctl.NewCommand(internal.MangoPayConnector+" ", + fctl.WithShortDescription("Install a MangoPay connector"), + fctl.WithArgs(cobra.ExactArgs(2)), + fctl.WithStringFlag(endpointFlag, defaultEndpoint, "API endpoint"), + fctl.WithRunE(func(cmd *cobra.Command, args []string) error { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return err + } + + organizationID, err := fctl.ResolveOrganizationID(cmd, cfg) + if err != nil { + return err + } + + stack, err := fctl.ResolveStack(cmd, cfg, organizationID) + if err != nil { + return err + } + + if !fctl.CheckStackApprobation(cmd, stack, "You are about to install connector '%s'", internal.MangoPayConnector) { + return fctl.ErrMissingApproval + } + + paymentsClient, err := fctl.NewStackClient(cmd, cfg, stack) + if err != nil { + return err + } + + request := operations.InstallConnectorRequest{ + Connector: shared.ConnectorMangopay, + RequestBody: shared.MangoPayConfig{ + ClientID: args[0], + APIKey: args[1], + Endpoint: fctl.GetString(cmd, endpointFlag), + }, + } + response, err := paymentsClient.Payments.InstallConnector(cmd.Context(), request) + if err != nil { + return errors.Wrap(err, "installing connector") + } + + if response.StatusCode >= 300 { + return fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Connector installed!") + + return nil + }), + ) +} diff --git a/components/fctl/cmd/payments/connectors/install/root.go b/components/fctl/cmd/payments/connectors/install/root.go index 08ea8fb2aa..e0420fbede 100644 --- a/components/fctl/cmd/payments/connectors/install/root.go +++ b/components/fctl/cmd/payments/connectors/install/root.go @@ -15,6 +15,7 @@ func NewInstallCommand() *cobra.Command { NewCurrencyCloudCommand(), NewModulrCommand(), NewWiseCommand(), + NewMangoPayCommand(), ), ) } diff --git a/components/fctl/cmd/payments/connectors/internal/connectors.go b/components/fctl/cmd/payments/connectors/internal/connectors.go index e0d22fe8ed..92f28a1bf5 100644 --- a/components/fctl/cmd/payments/connectors/internal/connectors.go +++ b/components/fctl/cmd/payments/connectors/internal/connectors.go @@ -6,6 +6,7 @@ const ( ModulrConnector = "modulr" StripeConnector = "stripe" WiseConnector = "wise" + MangoPayConnector = "mangopay" ) var AllConnectors = []string{ @@ -14,4 +15,5 @@ var AllConnectors = []string{ ModulrConnector, StripeConnector, WiseConnector, + MangoPayConnector, } diff --git a/components/payments/go.mod b/components/payments/go.mod index 0e047f3a07..dca775f830 100644 --- a/components/payments/go.mod +++ b/components/payments/go.mod @@ -30,6 +30,7 @@ require ( go.opentelemetry.io/otel/trace v1.14.0 go.uber.org/dig v1.16.1 go.uber.org/fx v1.19.1 + golang.org/x/oauth2 v0.6.0 golang.org/x/sync v0.1.0 ) @@ -50,7 +51,7 @@ require ( github.com/go-chi/render v1.0.2 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -107,10 +108,11 @@ require ( go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.6.0 // indirect + golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sys v0.7.0 // indirect golang.org/x/text v0.8.0 // indirect + google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148 // indirect google.golang.org/grpc v1.54.0 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/components/payments/go.sum b/components/payments/go.sum index 4e47d154f0..839def8a63 100644 --- a/components/payments/go.sum +++ b/components/payments/go.sum @@ -164,8 +164,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -458,8 +459,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -543,6 +544,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -699,6 +702,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= diff --git a/components/payments/internal/app/api/connectorconfigs.go b/components/payments/internal/app/api/connectorconfigs.go index d007fb0afe..1af27d27ae 100644 --- a/components/payments/internal/app/api/connectorconfigs.go +++ b/components/payments/internal/app/api/connectorconfigs.go @@ -10,6 +10,7 @@ import ( "github.com/formancehq/payments/internal/app/connectors/configtemplate" "github.com/formancehq/payments/internal/app/connectors/currencycloud" "github.com/formancehq/payments/internal/app/connectors/dummypay" + "github.com/formancehq/payments/internal/app/connectors/mangopay" "github.com/formancehq/payments/internal/app/connectors/modulr" "github.com/formancehq/payments/internal/app/connectors/stripe" "github.com/formancehq/payments/internal/app/connectors/wise" @@ -27,6 +28,7 @@ func connectorConfigsHandler() http.HandlerFunc { modulr.Config{}, stripe.Config{}, wise.Config{}, + mangopay.Config{}, ) err := json.NewEncoder(w).Encode(api.BaseResponse[configtemplate.Configs]{ diff --git a/components/payments/internal/app/api/module.go b/components/payments/internal/app/api/module.go index b390542016..045b251f78 100644 --- a/components/payments/internal/app/api/module.go +++ b/components/payments/internal/app/api/module.go @@ -13,6 +13,7 @@ import ( "github.com/formancehq/payments/internal/app/connectors/bankingcircle" "github.com/formancehq/payments/internal/app/connectors/currencycloud" + "github.com/formancehq/payments/internal/app/connectors/mangopay" "github.com/formancehq/payments/internal/app/connectors/dummypay" "github.com/formancehq/payments/internal/app/connectors/modulr" @@ -44,6 +45,7 @@ func HTTPModule(serviceInfo api.ServiceInfo, bind string) fx.Option { addConnector[wise.Config](wise.NewLoader()), addConnector[currencycloud.Config](currencycloud.NewLoader()), addConnector[bankingcircle.Config](bankingcircle.NewLoader()), + addConnector[mangopay.Config](mangopay.NewLoader()), ) } diff --git a/components/payments/internal/app/connectors/currency/currency.go b/components/payments/internal/app/connectors/currency/currency.go new file mode 100644 index 0000000000..ef062437aa --- /dev/null +++ b/components/payments/internal/app/connectors/currency/currency.go @@ -0,0 +1,136 @@ +package currency + +import ( + "fmt" + "strings" + + "github.com/formancehq/payments/internal/app/models" +) + +type currency struct { + decimals int +} + +func currencies() map[string]currency { + return map[string]currency{ + "AED": {2}, // UAE Dirham + "AMD": {2}, // Armenian Dram + "ANG": {2}, // Netherlands Antillian Guilder + "ARS": {2}, // Argentine Peso + "ATS": {2}, // Euro + "AUD": {2}, // Australian Dollar + "AWG": {2}, // Aruban Guilder + "BAM": {2}, // Bosnia and Herzegovina, Convertible Marks + "BDT": {2}, // Bangladesh, Taka + "BEF": {2}, // Euro + "BHD": {3}, // Bahraini Dinar + "BMD": {2}, // Bermudian Dollar + "BND": {2}, // Brunei Dollar + "BOB": {2}, // Bolivia, Boliviano + "BRL": {2}, // Brazilian Real + "BSD": {2}, // Bahamian Dollar + "BWP": {2}, // Botswana, Pula + "BZD": {2}, // Belize Dollar + "CAD": {2}, // Canadian Dollar + "CHF": {2}, // Swiss Franc + "CLP": {0}, // Chilean Peso + "CNY": {2}, // China Yuan Renminbi + "COP": {2}, // Colombian Peso + "CRC": {2}, // Costa Rican Colon + "CUC": {2}, // Cuban Convertible Peso + "CUP": {2}, // Cuban Peso + "CYP": {2}, // Cyprus Pound + "CZK": {2}, // Czech Koruna + "DEM": {2}, // Euro + "DKK": {2}, // Danish Krone + "DOP": {2}, // Dominican Peso + "EEK": {2}, // Euro + "EGP": {2}, // Egyptian Pound + "ESP": {2}, // Euro + "EUR": {2}, // Euro + "FIM": {2}, // Euro + "FRF": {2}, // Euro + "GBP": {2}, // Pound Sterling + "GHC": {2}, // Ghana, Cedi + "GIP": {2}, // Gibraltar Pound + "GRD": {2}, // Euro + "GTQ": {2}, // Guatemala, Quetzal + "HKD": {2}, // Hong Kong Dollar + "HNL": {2}, // Honduras, Lempira + "HRK": {2}, // Croatian Kuna + "HUF": {0}, // Hungary, Forint + "IDR": {2}, // Indonesia, Rupiah + "IEP": {2}, // Euro + "ILS": {2}, // New Israeli Shekel + "INR": {2}, // Indian Rupee + "IRR": {2}, // Iranian Rial + "ISK": {0}, // Iceland Krona + "ITL": {2}, // Euro + "JMD": {2}, // Jamaican Dollar + "JOD": {3}, // Jordanian Dinar + "JPY": {0}, // Japan, Yen + "KES": {2}, // Kenyan Shilling + "KRW": {0}, // South Korea, Won + "KWD": {3}, // Kuwaiti Dinar + "KYD": {2}, // Cayman Islands Dollar + "LBP": {0}, // Lebanese Pound + "LTL": {2}, // Lithuanian Litas + "LUF": {2}, // Euro + "LVL": {2}, // Latvian Lats + "MKD": {2}, // Macedonia, Denar + "MTL": {2}, // Maltese Lira + "MUR": {0}, // Mauritius Rupee + "MXN": {2}, // Mexican Peso + "MYR": {2}, // Malaysian Ringgit + "MZM": {2}, // Mozambique Metical + "NLG": {2}, // Euro + "NOK": {2}, // Norwegian Krone + "NPR": {2}, // Nepalese Rupee + "NZD": {2}, // New Zealand Dollar + "OMR": {3}, // Rial Omani + "PEN": {2}, // Peru, Nuevo Sol + "PHP": {2}, // Philippine Peso + "PKR": {2}, // Pakistan Rupee + "PLN": {2}, // Poland, Zloty + "PTE": {2}, // Euro + "ROL": {2}, // Romania, Old Leu + "RON": {2}, // Romania, New Leu + "RUB": {2}, // Russian Ruble + "SAR": {2}, // Saudi Riyal + "SEK": {2}, // Swedish Krona + "SGD": {2}, // Singapore Dollar + "SIT": {2}, // Slovenia, Tolar + "SKK": {2}, // Slovak Koruna + "SVC": {2}, // El Salvador Colon + "SZL": {2}, // Swaziland, Lilangeni + "THB": {2}, // Thailand, Baht + "TOP": {2}, // Tonga, Paanga + "TRY": {2}, // New Turkish Lira + "TZS": {2}, // Tanzanian Shilling + "UAH": {2}, // Ukraine, Hryvnia + "USD": {2}, // US Dollar + "UYU": {2}, // Peso Uruguayo + "VEB": {2}, // Venezuela, Bolivar + "VEF": {2}, // Venezuela Bolivares Fuertes + "VND": {0}, // Viet Nam, Dong + "VUV": {0}, // Vanuatu, Vatu + "XCD": {2}, // East Caribbean Dollar + "ZAR": {2}, // South Africa, Rand + "ZWD": {2}, // Zimbabwe Dollar + } +} + +func FormatAsset(cur string) models.PaymentAsset { + asset := strings.ToUpper(string(cur)) + + def, ok := currencies()[asset] + if !ok { + return models.PaymentAsset(asset) + } + + if def.decimals == 0 { + return models.PaymentAsset(asset) + } + + return models.PaymentAsset(fmt.Sprintf("%s/%d", asset, def.decimals)) +} diff --git a/components/payments/internal/app/connectors/mangopay/client/client.go b/components/payments/internal/app/connectors/mangopay/client/client.go new file mode 100644 index 0000000000..d87d53e99e --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/client/client.go @@ -0,0 +1,51 @@ +package client + +import ( + "context" + "net/http" + "strings" + "time" + + "github.com/formancehq/stack/libs/go-libs/logging" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" + "golang.org/x/oauth2/clientcredentials" +) + +type Client struct { + httpClient *http.Client + + clientID string + endpoint string + + logger logging.Logger +} + +func newHTTPClient(clientID, apiKey, endpoint string) *http.Client { + config := clientcredentials.Config{ + ClientID: clientID, + ClientSecret: apiKey, + TokenURL: endpoint + "/v2.01/oauth/token", + } + + httpClient := config.Client(context.Background()) + + return &http.Client{ + Timeout: 10 * time.Second, + Transport: otelhttp.NewTransport(httpClient.Transport), + } +} + +func NewClient(clientID, apiKey, endpoint string, logger logging.Logger) (*Client, error) { + endpoint = strings.TrimSuffix(endpoint, "/") + + c := &Client{ + httpClient: newHTTPClient(clientID, apiKey, endpoint), + + clientID: clientID, + endpoint: endpoint, + + logger: logger, + } + + return c, nil +} diff --git a/components/payments/internal/app/connectors/mangopay/client/transactions.go b/components/payments/internal/app/connectors/mangopay/client/transactions.go new file mode 100644 index 0000000000..4c3b29d4e4 --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/client/transactions.go @@ -0,0 +1,87 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +type payment struct { + Id string `json:"Id"` + Tag string `json:"Tag"` + CreationDate int64 `json:"CreationDate"` + AuthorId string `json:"AuthorId"` + CreditedUserId string `json:"CreditedUserId"` + DebitedFunds struct { + Currency string `json:"Currency"` + Amount int64 `json:"Amount"` + } `json:"DebitedFunds"` + CreditedFunds struct { + Currency string `json:"Currency"` + Amount int64 `json:"Amount"` + } `json:"CreditedFunds"` + Fees struct { + Currency string `json:"Currency"` + Amount int64 `json:"Amount"` + } `json:"Fees"` + Status string `json:"Status"` + ResultCode string `json:"ResultCode"` + ResultMessage string `json:"ResultMessage"` + ExecutionDate int64 `json:"ExecutionDate"` + Type string `json:"Type"` + Nature string `json:"Nature"` + CreditedWalletID string `json:"CreditedWalletId"` + DebitedWalletID string `json:"DebitedWalletId"` +} + +func (c *Client) GetAllTransactions(ctx context.Context, userID string) ([]*payment, error) { + var payments []*payment + + for page := 1; ; page++ { + pagedPayments, err := c.getTransactions(ctx, userID, page) + if err != nil { + return nil, err + } + + if len(pagedPayments) == 0 { + break + } + + payments = append(payments, pagedPayments...) + } + + return payments, nil +} + +func (c *Client) getTransactions(ctx context.Context, userID string, page int) ([]*payment, error) { + endpoint := fmt.Sprintf("%s/v2.01/%s/users/%s/transactions", c.endpoint, c.clientID, userID) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, http.NoBody) + if err != nil { + return nil, fmt.Errorf("failed to create login request: %w", err) + } + + q := req.URL.Query() + q.Add("per_page", "100") + q.Add("page", fmt.Sprint(page)) + req.URL.RawQuery = q.Encode() + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to login: %w", err) + } + + defer func() { + err = resp.Body.Close() + if err != nil { + c.logger.Error(err) + } + }() + + var payments []*payment + if err := json.NewDecoder(resp.Body).Decode(&payments); err != nil { + return nil, fmt.Errorf("failed to unmarshal login response body: %w", err) + } + + return payments, nil +} diff --git a/components/payments/internal/app/connectors/mangopay/client/users.go b/components/payments/internal/app/connectors/mangopay/client/users.go new file mode 100644 index 0000000000..42ef952755 --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/client/users.go @@ -0,0 +1,63 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +type user struct { + ID string `json:"Id"` +} + +func (c *Client) GetAllUsers(ctx context.Context) ([]*user, error) { + var users []*user + + for page := 1; ; page++ { + pagedUsers, err := c.getUsers(ctx, page) + if err != nil { + return nil, err + } + + if len(pagedUsers) == 0 { + break + } + + users = append(users, pagedUsers...) + } + + return users, nil +} + +func (c *Client) getUsers(ctx context.Context, page int) ([]*user, error) { + endpoint := fmt.Sprintf("%s/v2.01/%s/users", c.endpoint, c.clientID) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, http.NoBody) + if err != nil { + return nil, fmt.Errorf("failed to create login request: %w", err) + } + + q := req.URL.Query() + q.Add("per_page", "100") + q.Add("page", fmt.Sprint(page)) + req.URL.RawQuery = q.Encode() + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to login: %w", err) + } + + defer func() { + err = resp.Body.Close() + if err != nil { + c.logger.Error(err) + } + }() + + var users []*user + if err := json.NewDecoder(resp.Body).Decode(&users); err != nil { + return nil, fmt.Errorf("failed to unmarshal login response body: %w", err) + } + + return users, nil +} diff --git a/components/payments/internal/app/connectors/mangopay/config.go b/components/payments/internal/app/connectors/mangopay/config.go new file mode 100644 index 0000000000..7c97b776bf --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/config.go @@ -0,0 +1,48 @@ +package mangopay + +import ( + "encoding/json" + "fmt" + + "github.com/formancehq/payments/internal/app/connectors/configtemplate" +) + +type Config struct { + ClientID string `json:"clientID" yaml:"clientID" bson:"clientID"` + APIKey string `json:"apiKey" yaml:"apiKey" bson:"apiKey"` + Endpoint string `json:"endpoint" yaml:"endpoint" bson:"endpoint"` +} + +func (c Config) String() string { + return fmt.Sprintf("clientID=%s, apiKey=****", c.ClientID) +} + +func (c Config) Validate() error { + if c.ClientID == "" { + return ErrMissingClientID + } + + if c.APIKey == "" { + return ErrMissingAPIKey + } + + if c.Endpoint == "" { + return ErrMissingEndpoint + } + + return nil +} + +func (c Config) Marshal() ([]byte, error) { + return json.Marshal(c) +} + +func (c Config) BuildTemplate() (string, configtemplate.Config) { + cfg := configtemplate.NewConfig() + + cfg.AddParameter("clientID", configtemplate.TypeString, true) + cfg.AddParameter("apiKey", configtemplate.TypeString, true) + cfg.AddParameter("endpoint", configtemplate.TypeString, true) + + return Name.String(), cfg +} diff --git a/components/payments/internal/app/connectors/mangopay/connector.go b/components/payments/internal/app/connectors/mangopay/connector.go new file mode 100644 index 0000000000..900105bf1b --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/connector.go @@ -0,0 +1,58 @@ +package mangopay + +import ( + "context" + + "github.com/formancehq/payments/internal/app/integration" + "github.com/formancehq/payments/internal/app/models" + "github.com/formancehq/payments/internal/app/task" + "github.com/formancehq/stack/libs/go-libs/logging" +) + +const Name = models.ConnectorProviderMangopay + +type Connector struct { + logger logging.Logger + cfg Config +} + +func (c *Connector) InitiateTransfer(ctx task.ConnectorContext, transfer models.Transfer) error { + // TODO implement me + panic("implement me") +} + +func (c *Connector) Install(ctx task.ConnectorContext) error { + taskDescriptor, err := models.EncodeTaskDescriptor(TaskDescriptor{ + Name: "Fetch users from client", + Key: taskNameFetchUsers, + }) + if err != nil { + return err + } + + return ctx.Scheduler().Schedule(ctx.Context(), taskDescriptor, true) +} + +func (c *Connector) Uninstall(ctx context.Context) error { + return nil +} + +func (c *Connector) Resolve(descriptor models.TaskDescriptor) task.Task { + taskDescriptor, err := models.DecodeTaskDescriptor[TaskDescriptor](descriptor) + if err != nil { + panic(err) + } + + return resolveTasks(c.logger, c.cfg)(taskDescriptor) +} + +var _ integration.Connector = &Connector{} + +func newConnector(logger logging.Logger, cfg Config) *Connector { + return &Connector{ + logger: logger.WithFields(map[string]any{ + "component": "connector", + }), + cfg: cfg, + } +} diff --git a/components/payments/internal/app/connectors/mangopay/errors.go b/components/payments/internal/app/connectors/mangopay/errors.go new file mode 100644 index 0000000000..21e674b9aa --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/errors.go @@ -0,0 +1,17 @@ +package mangopay + +import "errors" + +var ( + // ErrMissingTask is returned when the task is missing. + ErrMissingTask = errors.New("task is not implemented") + + // ErrMissingClientID is returned when the clientID is missing. + ErrMissingClientID = errors.New("missing clientID from config") + + // ErrMissingAPIKey is returned when the apiKey is missing. + ErrMissingAPIKey = errors.New("missing apiKey from config") + + // ErrMissingEndpoint is returned when the endpoint is missing. + ErrMissingEndpoint = errors.New("missing endpoint from config") +) diff --git a/components/payments/internal/app/connectors/mangopay/loader.go b/components/payments/internal/app/connectors/mangopay/loader.go new file mode 100644 index 0000000000..91255128e2 --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/loader.go @@ -0,0 +1,32 @@ +package mangopay + +import ( + "github.com/formancehq/payments/internal/app/integration" + "github.com/formancehq/payments/internal/app/models" + "github.com/formancehq/stack/libs/go-libs/logging" +) + +type Loader struct{} + +const allowedTasks = 50 + +func (l *Loader) AllowTasks() int { + return allowedTasks +} + +func (l *Loader) Name() models.ConnectorProvider { + return Name +} + +func (l *Loader) Load(logger logging.Logger, config Config) integration.Connector { + return newConnector(logger, config) +} + +func (l *Loader) ApplyDefaults(cfg Config) Config { + return cfg +} + +// NewLoader creates a new loader. +func NewLoader() *Loader { + return &Loader{} +} diff --git a/components/payments/internal/app/connectors/mangopay/task_fetch_transactions.go b/components/payments/internal/app/connectors/mangopay/task_fetch_transactions.go new file mode 100644 index 0000000000..93e1245e33 --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/task_fetch_transactions.go @@ -0,0 +1,91 @@ +package mangopay + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "github.com/formancehq/payments/internal/app/connectors/currency" + "github.com/formancehq/payments/internal/app/connectors/mangopay/client" + "github.com/formancehq/payments/internal/app/ingestion" + "github.com/formancehq/payments/internal/app/models" + "github.com/formancehq/payments/internal/app/task" + "github.com/formancehq/stack/libs/go-libs/logging" +) + +func taskFetchTransactions(logger logging.Logger, client *client.Client, userID string) task.Task { + return func( + ctx context.Context, + ingester ingestion.Ingester, + ) error { + logger.Info("Fetching transactions for user", userID) + + transactions, err := client.GetAllTransactions(ctx, userID) + if err != nil { + return err + } + + batch := ingestion.PaymentBatch{} + for _, transaction := range transactions { + logger.Info(transaction) + + rawData, err := json.Marshal(transaction) + if err != nil { + return fmt.Errorf("failed to marshal transaction: %w", err) + } + + paymentType := matchPaymentType(transaction.Type) + + batchElement := ingestion.PaymentBatchElement{ + Payment: &models.Payment{ + ID: models.PaymentID{ + PaymentReference: models.PaymentReference{ + Reference: transaction.Id, + Type: paymentType, + }, + Provider: models.ConnectorProviderMangopay, + }, + CreatedAt: time.Unix(transaction.CreationDate, 0), + Reference: transaction.Id, + Amount: transaction.DebitedFunds.Amount, + Type: paymentType, + Status: matchPaymentStatus(transaction.Status), + Scheme: models.PaymentSchemeOther, + Asset: currency.FormatAsset(transaction.DebitedFunds.Currency), + RawData: rawData, + }, + } + + batch = append(batch, batchElement) + } + + return ingester.IngestPayments(ctx, batch, struct{}{}) + } +} + +func matchPaymentType(paymentType string) models.PaymentType { + switch paymentType { + case "PAYIN": + return models.PaymentTypePayIn + case "PAYOUT": + return models.PaymentTypePayOut + case "TRANSFER": + return models.PaymentTypeTransfer + } + + return models.PaymentTypeOther +} + +func matchPaymentStatus(paymentStatus string) models.PaymentStatus { + switch paymentStatus { + case "CREATED": + return models.PaymentStatusPending + case "SUCCEEDED": + return models.PaymentStatusSucceeded + case "FAILED": + return models.PaymentStatusFailed + } + + return models.PaymentStatusOther +} diff --git a/components/payments/internal/app/connectors/mangopay/task_fetch_users.go b/components/payments/internal/app/connectors/mangopay/task_fetch_users.go new file mode 100644 index 0000000000..437ce589f1 --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/task_fetch_users.go @@ -0,0 +1,44 @@ +package mangopay + +import ( + "context" + + "github.com/formancehq/payments/internal/app/connectors/mangopay/client" + "github.com/formancehq/payments/internal/app/models" + "github.com/formancehq/payments/internal/app/task" + "github.com/formancehq/stack/libs/go-libs/logging" +) + +func taskFetchUsers(logger logging.Logger, client *client.Client) task.Task { + return func( + ctx context.Context, + scheduler task.Scheduler, + ) error { + logger.Info(taskNameFetchUsers) + + users, err := client.GetAllUsers(ctx) + if err != nil { + return err + } + + for _, user := range users { + logger.Infof("scheduling fetch-transactions: %s", user.ID) + + transactionsTask, err := models.EncodeTaskDescriptor(TaskDescriptor{ + Name: "Fetch transactions from client by user", + Key: taskNameFetchTransactions, + UserID: user.ID, + }) + if err != nil { + return err + } + + err = scheduler.Schedule(ctx, transactionsTask, false) + if err != nil { + return err + } + } + + return nil + } +} diff --git a/components/payments/internal/app/connectors/mangopay/task_resolve.go b/components/payments/internal/app/connectors/mangopay/task_resolve.go new file mode 100644 index 0000000000..7f957df6fc --- /dev/null +++ b/components/payments/internal/app/connectors/mangopay/task_resolve.go @@ -0,0 +1,50 @@ +package mangopay + +import ( + "fmt" + + "github.com/formancehq/payments/internal/app/connectors/mangopay/client" + "github.com/formancehq/payments/internal/app/task" + "github.com/formancehq/stack/libs/go-libs/logging" +) + +const ( + taskNameFetchUsers = "fetch-users" + taskNameFetchTransactions = "fetch-transactions" +) + +// TaskDescriptor is the definition of a task. +type TaskDescriptor struct { + Name string `json:"name" yaml:"name" bson:"name"` + Key string `json:"key" yaml:"key" bson:"key"` + UserID string `json:"userID" yaml:"userID" bson:"userID"` +} + +// clientID, apiKey, endpoint string, logger logging +func resolveTasks(logger logging.Logger, config Config) func(taskDefinition TaskDescriptor) task.Task { + mangopayClient, err := client.NewClient( + config.ClientID, + config.APIKey, + config.Endpoint, + logger, + ) + if err != nil { + logger.Error(err) + + return nil + } + + return func(taskDescriptor TaskDescriptor) task.Task { + switch taskDescriptor.Key { + case taskNameFetchUsers: + return taskFetchUsers(logger, mangopayClient) + case taskNameFetchTransactions: + return taskFetchTransactions(logger, mangopayClient, taskDescriptor.UserID) + } + + // This should never happen. + return func() error { + return fmt.Errorf("key '%s': %w", taskDescriptor.Key, ErrMissingTask) + } + } +} diff --git a/components/payments/internal/app/connectors/stripe/translate.go b/components/payments/internal/app/connectors/stripe/translate.go index cedec5f566..fd07af2f4d 100644 --- a/components/payments/internal/app/connectors/stripe/translate.go +++ b/components/payments/internal/app/connectors/stripe/translate.go @@ -2,131 +2,17 @@ package stripe import ( "encoding/json" - "fmt" "log" "runtime/debug" - "strings" "time" "github.com/davecgh/go-spew/spew" + "github.com/formancehq/payments/internal/app/connectors/currency" "github.com/formancehq/payments/internal/app/ingestion" "github.com/formancehq/payments/internal/app/models" "github.com/stripe/stripe-go/v72" ) -type currency struct { - decimals int -} - -func currencies() map[string]currency { - return map[string]currency{ - "ARS": {2}, // Argentine Peso - "AMD": {2}, // Armenian Dram - "AWG": {2}, // Aruban Guilder - "AUD": {2}, // Australian Dollar - "BSD": {2}, // Bahamian Dollar - "BHD": {3}, // Bahraini Dinar - "BDT": {2}, // Bangladesh, Taka - "BZD": {2}, // Belize Dollar - "BMD": {2}, // Bermudian Dollar - "BOB": {2}, // Bolivia, Boliviano - "BAM": {2}, // Bosnia and Herzegovina, Convertible Marks - "BWP": {2}, // Botswana, Pula - "BRL": {2}, // Brazilian Real - "BND": {2}, // Brunei Dollar - "CAD": {2}, // Canadian Dollar - "KYD": {2}, // Cayman Islands Dollar - "CLP": {0}, // Chilean Peso - "CNY": {2}, // China Yuan Renminbi - "COP": {2}, // Colombian Peso - "CRC": {2}, // Costa Rican Colon - "HRK": {2}, // Croatian Kuna - "CUC": {2}, // Cuban Convertible Peso - "CUP": {2}, // Cuban Peso - "CYP": {2}, // Cyprus Pound - "CZK": {2}, // Czech Koruna - "DKK": {2}, // Danish Krone - "DOP": {2}, // Dominican Peso - "XCD": {2}, // East Caribbean Dollar - "EGP": {2}, // Egyptian Pound - "SVC": {2}, // El Salvador Colon - "ATS": {2}, // Euro - "BEF": {2}, // Euro - "DEM": {2}, // Euro - "EEK": {2}, // Euro - "ESP": {2}, // Euro - "EUR": {2}, // Euro - "FIM": {2}, // Euro - "FRF": {2}, // Euro - "GRD": {2}, // Euro - "IEP": {2}, // Euro - "ITL": {2}, // Euro - "LUF": {2}, // Euro - "NLG": {2}, // Euro - "PTE": {2}, // Euro - "GHC": {2}, // Ghana, Cedi - "GIP": {2}, // Gibraltar Pound - "GTQ": {2}, // Guatemala, Quetzal - "HNL": {2}, // Honduras, Lempira - "HKD": {2}, // Hong Kong Dollar - "HUF": {0}, // Hungary, Forint - "ISK": {0}, // Iceland Krona - "INR": {2}, // Indian Rupee - "IDR": {2}, // Indonesia, Rupiah - "IRR": {2}, // Iranian Rial - "JMD": {2}, // Jamaican Dollar - "JPY": {0}, // Japan, Yen - "JOD": {3}, // Jordanian Dinar - "KES": {2}, // Kenyan Shilling - "KWD": {3}, // Kuwaiti Dinar - "LVL": {2}, // Latvian Lats - "LBP": {0}, // Lebanese Pound - "LTL": {2}, // Lithuanian Litas - "MKD": {2}, // Macedonia, Denar - "MYR": {2}, // Malaysian Ringgit - "MTL": {2}, // Maltese Lira - "MUR": {0}, // Mauritius Rupee - "MXN": {2}, // Mexican Peso - "MZM": {2}, // Mozambique Metical - "NPR": {2}, // Nepalese Rupee - "ANG": {2}, // Netherlands Antillian Guilder - "ILS": {2}, // New Israeli Shekel - "TRY": {2}, // New Turkish Lira - "NZD": {2}, // New Zealand Dollar - "NOK": {2}, // Norwegian Krone - "PKR": {2}, // Pakistan Rupee - "PEN": {2}, // Peru, Nuevo Sol - "UYU": {2}, // Peso Uruguayo - "PHP": {2}, // Philippine Peso - "PLN": {2}, // Poland, Zloty - "GBP": {2}, // Pound Sterling - "OMR": {3}, // Rial Omani - "RON": {2}, // Romania, New Leu - "ROL": {2}, // Romania, Old Leu - "RUB": {2}, // Russian Ruble - "SAR": {2}, // Saudi Riyal - "SGD": {2}, // Singapore Dollar - "SKK": {2}, // Slovak Koruna - "SIT": {2}, // Slovenia, Tolar - "ZAR": {2}, // South Africa, Rand - "KRW": {0}, // South Korea, Won - "SZL": {2}, // Swaziland, Lilangeni - "SEK": {2}, // Swedish Krona - "CHF": {2}, // Swiss Franc - "TZS": {2}, // Tanzanian Shilling - "THB": {2}, // Thailand, Baht - "TOP": {2}, // Tonga, Paanga - "AED": {2}, // UAE Dirham - "UAH": {2}, // Ukraine, Hryvnia - "USD": {2}, // US Dollar - "VUV": {0}, // Vanuatu, Vatu - "VEF": {2}, // Venezuela Bolivares Fuertes - "VEB": {2}, // Venezuela, Bolivar - "VND": {0}, // Viet Nam, Dong - "ZWD": {2}, // Zimbabwe Dollar - } -} - func CreateBatchElement(balanceTransaction *stripe.BalanceTransaction, forward bool) (ingestion.PaymentBatchElement, bool) { var payment models.Payment // reference payments.Referenced // paymentData *payments.Data @@ -150,21 +36,6 @@ func CreateBatchElement(balanceTransaction *stripe.BalanceTransaction, forward b return ingestion.PaymentBatchElement{}, false } - formatAsset := func(cur stripe.Currency) models.PaymentAsset { - asset := strings.ToUpper(string(cur)) - - def, ok := currencies()[asset] - if !ok { - return models.PaymentAsset(asset) - } - - if def.decimals == 0 { - return models.PaymentAsset(asset) - } - - return models.PaymentAsset(fmt.Sprintf("%s/%d", asset, def.decimals)) - } - rawData, err := json.Marshal(balanceTransaction) if err != nil { return ingestion.PaymentBatchElement{}, false @@ -184,7 +55,7 @@ func CreateBatchElement(balanceTransaction *stripe.BalanceTransaction, forward b Type: models.PaymentTypePayIn, Status: models.PaymentStatusSucceeded, Amount: balanceTransaction.Source.Charge.Amount, - Asset: formatAsset(balanceTransaction.Source.Charge.Currency), + Asset: currency.FormatAsset(string(balanceTransaction.Source.Charge.Currency)), RawData: rawData, Scheme: models.PaymentScheme(balanceTransaction.Source.Charge.PaymentMethodDetails.Card.Brand), CreatedAt: time.Unix(balanceTransaction.Created, 0), @@ -203,7 +74,7 @@ func CreateBatchElement(balanceTransaction *stripe.BalanceTransaction, forward b Status: convertPayoutStatus(balanceTransaction.Source.Payout.Status), Amount: balanceTransaction.Source.Payout.Amount, RawData: rawData, - Asset: formatAsset(balanceTransaction.Source.Payout.Currency), + Asset: currency.FormatAsset(string(balanceTransaction.Source.Payout.Currency)), Scheme: func() models.PaymentScheme { switch balanceTransaction.Source.Payout.Type { case stripe.PayoutTypeBank: @@ -230,7 +101,7 @@ func CreateBatchElement(balanceTransaction *stripe.BalanceTransaction, forward b Status: models.PaymentStatusSucceeded, Amount: balanceTransaction.Source.Transfer.Amount, RawData: rawData, - Asset: formatAsset(balanceTransaction.Source.Transfer.Currency), + Asset: currency.FormatAsset(string(balanceTransaction.Source.Transfer.Currency)), Scheme: models.PaymentSchemeOther, CreatedAt: time.Unix(balanceTransaction.Created, 0), } @@ -269,7 +140,7 @@ func CreateBatchElement(balanceTransaction *stripe.BalanceTransaction, forward b Status: models.PaymentStatusSucceeded, Amount: balanceTransaction.Source.Charge.Amount, RawData: rawData, - Asset: formatAsset(balanceTransaction.Source.Charge.Currency), + Asset: currency.FormatAsset(string(balanceTransaction.Source.Charge.Currency)), Scheme: models.PaymentSchemeOther, CreatedAt: time.Unix(balanceTransaction.Created, 0), } diff --git a/components/payments/internal/app/models/connector.go b/components/payments/internal/app/models/connector.go index 510463985f..3ae964a8bd 100644 --- a/components/payments/internal/app/models/connector.go +++ b/components/payments/internal/app/models/connector.go @@ -47,6 +47,7 @@ const ( ConnectorProviderModulr ConnectorProvider = "MODULR" ConnectorProviderStripe ConnectorProvider = "STRIPE" ConnectorProviderWise ConnectorProvider = "WISE" + ConnectorProviderMangopay ConnectorProvider = "MANGOPAY" ) func (p ConnectorProvider) String() string { diff --git a/components/payments/internal/app/storage/migrations.go b/components/payments/internal/app/storage/migrations.go index caaf50e391..9f3326563e 100644 --- a/components/payments/internal/app/storage/migrations.go +++ b/components/payments/internal/app/storage/migrations.go @@ -308,6 +308,18 @@ func registerMigrations(migrator *migrations.Migrator) { return err } + return nil + }, + }, + migrations.Migration{ + Up: func(tx bun.Tx) error { + _, err := tx.Exec(` + ALTER TYPE connector_provider ADD VALUE 'MANGOPAY'; + `) + if err != nil { + return err + } + return nil }, }, diff --git a/components/payments/openapi.yaml b/components/payments/openapi.yaml index c30ff2e520..d4a21a2f1a 100644 --- a/components/payments/openapi.yaml +++ b/components/payments/openapi.yaml @@ -444,6 +444,7 @@ components: - $ref: '#/components/schemas/TaskDummyPay' - $ref: '#/components/schemas/TaskModulr' - $ref: '#/components/schemas/TaskBankingCircle' + - $ref: '#/components/schemas/TaskMangoPay' # ---------------------- RESPONSES ---------------------- ConnectorConfigResponse: @@ -513,6 +514,7 @@ components: - $ref: '#/components/schemas/TaskDummyPay' - $ref: '#/components/schemas/TaskModulr' - $ref: '#/components/schemas/TaskBankingCircle' + - $ref: '#/components/schemas/TaskMangoPay' TransferResponse: type: object properties: @@ -554,6 +556,7 @@ components: - MODULR - CURRENCY-CLOUD - BANKING-CIRCLE + - MANGOPAY ConnectorConfig: anyOf: - $ref: '#/components/schemas/StripeConfig' @@ -562,6 +565,7 @@ components: - $ref: '#/components/schemas/ModulrConfig' - $ref: '#/components/schemas/CurrencyCloudConfig' - $ref: '#/components/schemas/BankingCircleConfig' + - $ref: '#/components/schemas/MangoPayConfig' StripeConfig: type: object required: @@ -632,6 +636,8 @@ components: - password - endpoint - authorizationEndpoint + - userCertificate + - userCertificateKey properties: username: type: string @@ -645,6 +651,28 @@ components: authorizationEndpoint: type: string example: 'XXX' + userCertificate: + type: string + example: 'XXX' + userCertificateKey: + type: string + example: 'XXX' + MangoPayConfig: + type: object + required: + - clientID + - apiKey + - endpoint + properties: + clientID: + type: string + example: 'XXX' + apiKey: + type: string + example: 'XXX' + endpoint: + type: string + example: 'XXX' CurrencyCloudConfig: type: object required: @@ -918,6 +946,22 @@ components: type: string key: type: string + TaskMangoPay: + allOf: + - $ref: '#/components/schemas/TaskBase' + - type: object + required: + - descriptor + properties: + descriptor: + type: object + properties: + name: + type: string + key: + type: string + userID: + type: string TransferRequest: type: object required: diff --git a/openapi/build/generate.json b/openapi/build/generate.json index 03e77d873b..69aedc701a 100644 --- a/openapi/build/generate.json +++ b/openapi/build/generate.json @@ -12,7 +12,7 @@ "url": "https://avatars.githubusercontent.com/u/84325077?s=200&v=4", "altText": "Formance" }, - "version": "v1.0.20230614" + "version": "v1.0.20230630" }, "servers": [ { @@ -4917,6 +4917,9 @@ }, { "$ref": "#/components/schemas/TaskBankingCircle" + }, + { + "$ref": "#/components/schemas/TaskMangoPay" } ] } @@ -5036,6 +5039,9 @@ }, { "$ref": "#/components/schemas/TaskBankingCircle" + }, + { + "$ref": "#/components/schemas/TaskMangoPay" } ] } @@ -5096,7 +5102,8 @@ "WISE", "MODULR", "CURRENCY-CLOUD", - "BANKING-CIRCLE" + "BANKING-CIRCLE", + "MANGOPAY" ] }, "ConnectorConfig": { @@ -5118,6 +5125,9 @@ }, { "$ref": "#/components/schemas/BankingCircleConfig" + }, + { + "$ref": "#/components/schemas/MangoPayConfig" } ] }, @@ -5210,7 +5220,9 @@ "username", "password", "endpoint", - "authorizationEndpoint" + "authorizationEndpoint", + "userCertificate", + "userCertificateKey" ], "properties": { "username": { @@ -5228,6 +5240,36 @@ "authorizationEndpoint": { "type": "string", "example": "XXX" + }, + "userCertificate": { + "type": "string", + "example": "XXX" + }, + "userCertificateKey": { + "type": "string", + "example": "XXX" + } + } + }, + "MangoPayConfig": { + "type": "object", + "required": [ + "clientID", + "apiKey", + "endpoint" + ], + "properties": { + "clientID": { + "type": "string", + "example": "XXX" + }, + "apiKey": { + "type": "string", + "example": "XXX" + }, + "endpoint": { + "type": "string", + "example": "XXX" } } }, @@ -5636,6 +5678,35 @@ } ] }, + "TaskMangoPay": { + "allOf": [ + { + "$ref": "#/components/schemas/TaskBase" + }, + { + "type": "object", + "required": [ + "descriptor" + ], + "properties": { + "descriptor": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "userID": { + "type": "string" + } + } + } + } + } + ] + }, "TransferRequest": { "type": "object", "required": [ diff --git a/sdks/go/docs/payments/README.md b/sdks/go/docs/payments/README.md index 039d95ca8e..f90396ab19 100755 --- a/sdks/go/docs/payments/README.md +++ b/sdks/go/docs/payments/README.md @@ -94,7 +94,7 @@ func main() { Destination: "acct_1Gqj58KZcSIg2N2q", Source: formance.String("acct_1Gqj58KZcSIg2N2q"), }, - Connector: shared.ConnectorModulr, + Connector: shared.ConnectorCurrencyCloud, }) if err != nil { log.Fatal(err) @@ -132,7 +132,7 @@ func main() { ctx := context.Background() res, err := s.Payments.GetConnectorTask(ctx, operations.GetConnectorTaskRequest{ - Connector: shared.ConnectorBankingCircle, + Connector: shared.ConnectorMangopay, TaskID: "sint", }) if err != nil { @@ -213,7 +213,7 @@ func main() { FileGenerationPeriod: formance.String("60s"), FilePollingPeriod: formance.String("60s"), }, - Connector: shared.ConnectorBankingCircle, + Connector: shared.ConnectorMangopay, }) if err != nil { log.Fatal(err) @@ -319,7 +319,7 @@ func main() { ctx := context.Background() res, err := s.Payments.ListConnectorTasks(ctx, operations.ListConnectorTasksRequest{ - Connector: shared.ConnectorBankingCircle, + Connector: shared.ConnectorMangopay, Cursor: formance.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), PageSize: formance.Int64(680056), }) @@ -359,7 +359,7 @@ func main() { ctx := context.Background() res, err := s.Payments.ListConnectorsTransfers(ctx, operations.ListConnectorsTransfersRequest{ - Connector: shared.ConnectorWise, + Connector: shared.ConnectorModulr, }) if err != nil { log.Fatal(err) @@ -559,7 +559,7 @@ func main() { ctx := context.Background() res, err := s.Payments.ResetConnector(ctx, operations.ResetConnectorRequest{ - Connector: shared.ConnectorModulr, + Connector: shared.ConnectorCurrencyCloud, }) if err != nil { log.Fatal(err) @@ -597,7 +597,7 @@ func main() { ctx := context.Background() res, err := s.Payments.UninstallConnector(ctx, operations.UninstallConnectorRequest{ - Connector: shared.ConnectorDummyPay, + Connector: shared.ConnectorWise, }) if err != nil { log.Fatal(err) diff --git a/sdks/go/files.gen b/sdks/go/files.gen index 48f33ac2dc..75eea25779 100755 --- a/sdks/go/files.gen +++ b/sdks/go/files.gen @@ -226,6 +226,7 @@ pkg/models/shared/taskcurrencycloud.go pkg/models/shared/taskdummypay.go pkg/models/shared/taskmodulr.go pkg/models/shared/taskbankingcircle.go +pkg/models/shared/taskmangopay.go pkg/models/shared/paymentresponse.go pkg/models/shared/stripeconfig.go pkg/models/shared/dummypayconfig.go @@ -233,6 +234,7 @@ pkg/models/shared/wiseconfig.go pkg/models/shared/modulrconfig.go pkg/models/shared/currencycloudconfig.go pkg/models/shared/bankingcircleconfig.go +pkg/models/shared/mangopayconfig.go pkg/models/shared/connectorsresponse.go pkg/models/shared/connectorsconfigsresponse.go pkg/models/shared/taskscursor.go diff --git a/sdks/go/pkg/models/shared/bankingcircleconfig.go b/sdks/go/pkg/models/shared/bankingcircleconfig.go index 7e396b0b6f..6006f3e919 100755 --- a/sdks/go/pkg/models/shared/bankingcircleconfig.go +++ b/sdks/go/pkg/models/shared/bankingcircleconfig.go @@ -6,5 +6,7 @@ type BankingCircleConfig struct { AuthorizationEndpoint string `json:"authorizationEndpoint"` Endpoint string `json:"endpoint"` Password string `json:"password"` + UserCertificate string `json:"userCertificate"` + UserCertificateKey string `json:"userCertificateKey"` Username string `json:"username"` } diff --git a/sdks/go/pkg/models/shared/connector.go b/sdks/go/pkg/models/shared/connector.go index c552364551..01bbe9891f 100755 --- a/sdks/go/pkg/models/shared/connector.go +++ b/sdks/go/pkg/models/shared/connector.go @@ -17,6 +17,7 @@ const ( ConnectorModulr Connector = "MODULR" ConnectorCurrencyCloud Connector = "CURRENCY-CLOUD" ConnectorBankingCircle Connector = "BANKING-CIRCLE" + ConnectorMangopay Connector = "MANGOPAY" ) func (e Connector) ToPointer() *Connector { @@ -40,6 +41,8 @@ func (e *Connector) UnmarshalJSON(data []byte) error { case "CURRENCY-CLOUD": fallthrough case "BANKING-CIRCLE": + fallthrough + case "MANGOPAY": *e = Connector(v) return nil default: diff --git a/sdks/go/pkg/models/shared/mangopayconfig.go b/sdks/go/pkg/models/shared/mangopayconfig.go new file mode 100755 index 0000000000..937b287a8f --- /dev/null +++ b/sdks/go/pkg/models/shared/mangopayconfig.go @@ -0,0 +1,9 @@ +// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + +package shared + +type MangoPayConfig struct { + APIKey string `json:"apiKey"` + ClientID string `json:"clientID"` + Endpoint string `json:"endpoint"` +} diff --git a/sdks/go/pkg/models/shared/taskmangopay.go b/sdks/go/pkg/models/shared/taskmangopay.go new file mode 100755 index 0000000000..c2ef86328c --- /dev/null +++ b/sdks/go/pkg/models/shared/taskmangopay.go @@ -0,0 +1,24 @@ +// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + +package shared + +import ( + "time" +) + +type TaskMangoPayDescriptor struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + UserID *string `json:"userID,omitempty"` +} + +type TaskMangoPay struct { + ConnectorID string `json:"connectorId"` + CreatedAt time.Time `json:"createdAt"` + Descriptor TaskMangoPayDescriptor `json:"descriptor"` + Error *string `json:"error,omitempty"` + ID string `json:"id"` + State map[string]interface{} `json:"state"` + Status PaymentStatus `json:"status"` + UpdatedAt time.Time `json:"updatedAt"` +} diff --git a/sdks/go/pkg/models/shared/taskresponse.go b/sdks/go/pkg/models/shared/taskresponse.go index ffb946b075..4655e64110 100755 --- a/sdks/go/pkg/models/shared/taskresponse.go +++ b/sdks/go/pkg/models/shared/taskresponse.go @@ -17,6 +17,7 @@ const ( TaskResponseDataTypeTaskDummyPay TaskResponseDataType = "TaskDummyPay" TaskResponseDataTypeTaskModulr TaskResponseDataType = "TaskModulr" TaskResponseDataTypeTaskBankingCircle TaskResponseDataType = "TaskBankingCircle" + TaskResponseDataTypeTaskMangoPay TaskResponseDataType = "TaskMangoPay" ) type TaskResponseData struct { @@ -26,6 +27,7 @@ type TaskResponseData struct { TaskDummyPay *TaskDummyPay TaskModulr *TaskModulr TaskBankingCircle *TaskBankingCircle + TaskMangoPay *TaskMangoPay Type TaskResponseDataType } @@ -84,6 +86,15 @@ func CreateTaskResponseDataTaskBankingCircle(taskBankingCircle TaskBankingCircle } } +func CreateTaskResponseDataTaskMangoPay(taskMangoPay TaskMangoPay) TaskResponseData { + typ := TaskResponseDataTypeTaskMangoPay + + return TaskResponseData{ + TaskMangoPay: &taskMangoPay, + Type: typ, + } +} + func (u *TaskResponseData) UnmarshalJSON(data []byte) error { var d *json.Decoder @@ -141,6 +152,15 @@ func (u *TaskResponseData) UnmarshalJSON(data []byte) error { return nil } + taskMangoPay := new(TaskMangoPay) + d = json.NewDecoder(bytes.NewReader(data)) + d.DisallowUnknownFields() + if err := d.Decode(&taskMangoPay); err == nil { + u.TaskMangoPay = taskMangoPay + u.Type = TaskResponseDataTypeTaskMangoPay + return nil + } + return errors.New("could not unmarshal into supported union types") } @@ -169,6 +189,10 @@ func (u TaskResponseData) MarshalJSON() ([]byte, error) { return json.Marshal(u.TaskBankingCircle) } + if u.TaskMangoPay != nil { + return json.Marshal(u.TaskMangoPay) + } + return nil, nil } diff --git a/sdks/go/pkg/models/shared/taskscursor.go b/sdks/go/pkg/models/shared/taskscursor.go index 62d2070c75..c8e64d43bb 100755 --- a/sdks/go/pkg/models/shared/taskscursor.go +++ b/sdks/go/pkg/models/shared/taskscursor.go @@ -17,6 +17,7 @@ const ( TasksCursorCursorDataTypeTaskDummyPay TasksCursorCursorDataType = "TaskDummyPay" TasksCursorCursorDataTypeTaskModulr TasksCursorCursorDataType = "TaskModulr" TasksCursorCursorDataTypeTaskBankingCircle TasksCursorCursorDataType = "TaskBankingCircle" + TasksCursorCursorDataTypeTaskMangoPay TasksCursorCursorDataType = "TaskMangoPay" ) type TasksCursorCursorData struct { @@ -26,6 +27,7 @@ type TasksCursorCursorData struct { TaskDummyPay *TaskDummyPay TaskModulr *TaskModulr TaskBankingCircle *TaskBankingCircle + TaskMangoPay *TaskMangoPay Type TasksCursorCursorDataType } @@ -84,6 +86,15 @@ func CreateTasksCursorCursorDataTaskBankingCircle(taskBankingCircle TaskBankingC } } +func CreateTasksCursorCursorDataTaskMangoPay(taskMangoPay TaskMangoPay) TasksCursorCursorData { + typ := TasksCursorCursorDataTypeTaskMangoPay + + return TasksCursorCursorData{ + TaskMangoPay: &taskMangoPay, + Type: typ, + } +} + func (u *TasksCursorCursorData) UnmarshalJSON(data []byte) error { var d *json.Decoder @@ -141,6 +152,15 @@ func (u *TasksCursorCursorData) UnmarshalJSON(data []byte) error { return nil } + taskMangoPay := new(TaskMangoPay) + d = json.NewDecoder(bytes.NewReader(data)) + d.DisallowUnknownFields() + if err := d.Decode(&taskMangoPay); err == nil { + u.TaskMangoPay = taskMangoPay + u.Type = TasksCursorCursorDataTypeTaskMangoPay + return nil + } + return errors.New("could not unmarshal into supported union types") } @@ -169,6 +189,10 @@ func (u TasksCursorCursorData) MarshalJSON() ([]byte, error) { return json.Marshal(u.TaskBankingCircle) } + if u.TaskMangoPay != nil { + return json.Marshal(u.TaskMangoPay) + } + return nil, nil } diff --git a/sdks/java/docs/payments/README.md b/sdks/java/docs/payments/README.md index 8db3757b75..c6a8c7515c 100755 --- a/sdks/java/docs/payments/README.md +++ b/sdks/java/docs/payments/README.md @@ -91,7 +91,7 @@ public class Application { ConnectorsTransferRequest req = new ConnectorsTransferRequest( new TransferRequest(100L, "USD", "acct_1Gqj58KZcSIg2N2q") {{ source = "acct_1Gqj58KZcSIg2N2q"; - }};, Connector.MODULR); + }};, Connector.CURRENCY_CLOUD); ConnectorsTransferResponse res = sdk.payments.connectorsTransfer(req); @@ -196,6 +196,7 @@ import com.formance.formance_sdk.models.shared.BankingCircleConfig; import com.formance.formance_sdk.models.shared.Connector; import com.formance.formance_sdk.models.shared.CurrencyCloudConfig; import com.formance.formance_sdk.models.shared.DummyPayConfig; +import com.formance.formance_sdk.models.shared.MangoPayConfig; import com.formance.formance_sdk.models.shared.ModulrConfig; import com.formance.formance_sdk.models.shared.Security; import com.formance.formance_sdk.models.shared.StripeConfig; @@ -212,7 +213,7 @@ public class Application { InstallConnectorRequest req = new InstallConnectorRequest( new WiseConfig("XXX") {{ apiKey = "XXX"; - }}, Connector.MODULR); + }}, Connector.CURRENCY_CLOUD); InstallConnectorResponse res = sdk.payments.installConnector(req); @@ -318,7 +319,7 @@ public class Application { }}) .build(); - ListConnectorTasksRequest req = new ListConnectorTasksRequest(Connector.WISE) {{ + ListConnectorTasksRequest req = new ListConnectorTasksRequest(Connector.MODULR) {{ cursor = "aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="; pageSize = 301575L; }}; @@ -359,7 +360,7 @@ public class Application { }}) .build(); - ListConnectorsTransfersRequest req = new ListConnectorsTransfersRequest(Connector.MODULR); + ListConnectorsTransfersRequest req = new ListConnectorsTransfersRequest(Connector.CURRENCY_CLOUD); ListConnectorsTransfersResponse res = sdk.payments.listConnectorsTransfers(req); @@ -558,7 +559,7 @@ public class Application { }}) .build(); - ResetConnectorRequest req = new ResetConnectorRequest(Connector.MODULR); + ResetConnectorRequest req = new ResetConnectorRequest(Connector.CURRENCY_CLOUD); ResetConnectorResponse res = sdk.payments.resetConnector(req); @@ -596,7 +597,7 @@ public class Application { }}) .build(); - UninstallConnectorRequest req = new UninstallConnectorRequest(Connector.MODULR); + UninstallConnectorRequest req = new UninstallConnectorRequest(Connector.CURRENCY_CLOUD); UninstallConnectorResponse res = sdk.payments.uninstallConnector(req); diff --git a/sdks/java/files.gen b/sdks/java/files.gen index 86ba73cf89..29dc4479c6 100755 --- a/sdks/java/files.gen +++ b/sdks/java/files.gen @@ -330,6 +330,8 @@ lib/src/main/java/com/formance/formance_sdk/models/shared/TaskModulrDescriptor.j lib/src/main/java/com/formance/formance_sdk/models/shared/TaskModulr.java lib/src/main/java/com/formance/formance_sdk/models/shared/TaskBankingCircleDescriptor.java lib/src/main/java/com/formance/formance_sdk/models/shared/TaskBankingCircle.java +lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPayDescriptor.java +lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPay.java lib/src/main/java/com/formance/formance_sdk/models/shared/PaymentResponse.java lib/src/main/java/com/formance/formance_sdk/models/shared/StripeConfig.java lib/src/main/java/com/formance/formance_sdk/models/shared/DummyPayConfig.java @@ -337,6 +339,7 @@ lib/src/main/java/com/formance/formance_sdk/models/shared/WiseConfig.java lib/src/main/java/com/formance/formance_sdk/models/shared/ModulrConfig.java lib/src/main/java/com/formance/formance_sdk/models/shared/CurrencyCloudConfig.java lib/src/main/java/com/formance/formance_sdk/models/shared/BankingCircleConfig.java +lib/src/main/java/com/formance/formance_sdk/models/shared/MangoPayConfig.java lib/src/main/java/com/formance/formance_sdk/models/shared/ConnectorsResponseData.java lib/src/main/java/com/formance/formance_sdk/models/shared/ConnectorsResponse.java lib/src/main/java/com/formance/formance_sdk/models/shared/ConnectorsConfigsResponseDataConnectorKey.java diff --git a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/BankingCircleConfig.java b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/BankingCircleConfig.java index 4afc98e0d7..488467a69e 100755 --- a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/BankingCircleConfig.java +++ b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/BankingCircleConfig.java @@ -31,6 +31,22 @@ public BankingCircleConfig withPassword(String password) { return this; } + @JsonProperty("userCertificate") + public String userCertificate; + + public BankingCircleConfig withUserCertificate(String userCertificate) { + this.userCertificate = userCertificate; + return this; + } + + @JsonProperty("userCertificateKey") + public String userCertificateKey; + + public BankingCircleConfig withUserCertificateKey(String userCertificateKey) { + this.userCertificateKey = userCertificateKey; + return this; + } + @JsonProperty("username") public String username; @@ -39,8 +55,8 @@ public BankingCircleConfig withUsername(String username) { return this; } - public BankingCircleConfig(@JsonProperty("username") String username, @JsonProperty("password") String password, @JsonProperty("authorizationEndpoint") String authorizationEndpoint, @JsonProperty("endpoint") String endpoint) { - this.username = username; + public BankingCircleConfig(@JsonProperty("userCertificate") String userCertificate, @JsonProperty("password") String password, @JsonProperty("authorizationEndpoint") String authorizationEndpoint, @JsonProperty("endpoint") String endpoint) { + this.userCertificate = userCertificate; this.password = password; this.authorizationEndpoint = authorizationEndpoint; this.endpoint = endpoint; diff --git a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/Connector.java b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/Connector.java index ffcda0cf84..d70a6e91b6 100755 --- a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/Connector.java +++ b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/Connector.java @@ -15,7 +15,8 @@ public enum Connector { WISE("WISE"), MODULR("MODULR"), CURRENCY_CLOUD("CURRENCY-CLOUD"), - BANKING_CIRCLE("BANKING-CIRCLE"); + BANKING_CIRCLE("BANKING-CIRCLE"), + MANGOPAY("MANGOPAY"); @JsonValue public final String value; diff --git a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/MangoPayConfig.java b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/MangoPayConfig.java new file mode 100755 index 0000000000..314585309f --- /dev/null +++ b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/MangoPayConfig.java @@ -0,0 +1,39 @@ +/* + * Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + */ + +package com.formance.formance_sdk.models.shared; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MangoPayConfig { + @JsonProperty("apiKey") + public String apiKey; + + public MangoPayConfig withApiKey(String apiKey) { + this.apiKey = apiKey; + return this; + } + + @JsonProperty("clientID") + public String clientID; + + public MangoPayConfig withClientID(String clientID) { + this.clientID = clientID; + return this; + } + + @JsonProperty("endpoint") + public String endpoint; + + public MangoPayConfig withEndpoint(String endpoint) { + this.endpoint = endpoint; + return this; + } + + public MangoPayConfig(@JsonProperty("apiKey") String apiKey, @JsonProperty("clientID") String clientID, @JsonProperty("endpoint") String endpoint) { + this.apiKey = apiKey; + this.clientID = clientID; + this.endpoint = endpoint; + } +} diff --git a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPay.java b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPay.java new file mode 100755 index 0000000000..bc36472410 --- /dev/null +++ b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPay.java @@ -0,0 +1,95 @@ +/* + * Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + */ + +package com.formance.formance_sdk.models.shared; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.formance.formance_sdk.utils.DateTimeDeserializer; +import com.formance.formance_sdk.utils.DateTimeSerializer; +import java.time.OffsetDateTime; + +public class TaskMangoPay { + @JsonProperty("connectorId") + public String connectorId; + + public TaskMangoPay withConnectorId(String connectorId) { + this.connectorId = connectorId; + return this; + } + + @JsonSerialize(using = DateTimeSerializer.class) + @JsonDeserialize(using = DateTimeDeserializer.class) + @JsonProperty("createdAt") + public OffsetDateTime createdAt; + + public TaskMangoPay withCreatedAt(OffsetDateTime createdAt) { + this.createdAt = createdAt; + return this; + } + + @JsonProperty("descriptor") + public TaskMangoPayDescriptor descriptor; + + public TaskMangoPay withDescriptor(TaskMangoPayDescriptor descriptor) { + this.descriptor = descriptor; + return this; + } + + @JsonInclude(Include.NON_ABSENT) + @JsonProperty("error") + public String error; + + public TaskMangoPay withError(String error) { + this.error = error; + return this; + } + + @JsonProperty("id") + public String id; + + public TaskMangoPay withId(String id) { + this.id = id; + return this; + } + + @JsonProperty("state") + public java.util.Map state; + + public TaskMangoPay withState(java.util.Map state) { + this.state = state; + return this; + } + + @JsonProperty("status") + public PaymentStatus status; + + public TaskMangoPay withStatus(PaymentStatus status) { + this.status = status; + return this; + } + + @JsonSerialize(using = DateTimeSerializer.class) + @JsonDeserialize(using = DateTimeDeserializer.class) + @JsonProperty("updatedAt") + public OffsetDateTime updatedAt; + + public TaskMangoPay withUpdatedAt(OffsetDateTime updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public TaskMangoPay(@JsonProperty("connectorId") String connectorId, @JsonProperty("createdAt") OffsetDateTime createdAt, @JsonProperty("descriptor") TaskMangoPayDescriptor descriptor, @JsonProperty("id") String id, @JsonProperty("state") java.util.Map state, @JsonProperty("status") PaymentStatus status, @JsonProperty("updatedAt") OffsetDateTime updatedAt) { + this.connectorId = connectorId; + this.createdAt = createdAt; + this.descriptor = descriptor; + this.id = id; + this.state = state; + this.status = status; + this.updatedAt = updatedAt; + } +} diff --git a/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPayDescriptor.java b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPayDescriptor.java new file mode 100755 index 0000000000..d8fdd8dade --- /dev/null +++ b/sdks/java/lib/src/main/java/com/formance/formance_sdk/models/shared/TaskMangoPayDescriptor.java @@ -0,0 +1,40 @@ +/* + * Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + */ + +package com.formance.formance_sdk.models.shared; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TaskMangoPayDescriptor { + @JsonInclude(Include.NON_ABSENT) + @JsonProperty("key") + public String key; + + public TaskMangoPayDescriptor withKey(String key) { + this.key = key; + return this; + } + + @JsonInclude(Include.NON_ABSENT) + @JsonProperty("name") + public String name; + + public TaskMangoPayDescriptor withName(String name) { + this.name = name; + return this; + } + + @JsonInclude(Include.NON_ABSENT) + @JsonProperty("userID") + public String userID; + + public TaskMangoPayDescriptor withUserID(String userID) { + this.userID = userID; + return this; + } + + public TaskMangoPayDescriptor(){} +} diff --git a/sdks/php/docs/payments/README.md b/sdks/php/docs/payments/README.md index da9d7be5f4..dcdd1d0f7d 100755 --- a/sdks/php/docs/payments/README.md +++ b/sdks/php/docs/payments/README.md @@ -86,7 +86,7 @@ try { $request->transferRequest->asset = 'USD'; $request->transferRequest->destination = 'acct_1Gqj58KZcSIg2N2q'; $request->transferRequest->source = 'acct_1Gqj58KZcSIg2N2q'; - $request->connector = Connector::MODULR; + $request->connector = Connector::CURRENCY_CLOUD; $response = $sdk->payments->connectorsTransfer($request); @@ -120,7 +120,7 @@ $sdk = SDK::builder() try { $request = new GetConnectorTaskRequest(); - $request->connector = Connector::BANKING_CIRCLE; + $request->connector = Connector::MANGOPAY; $request->taskId = 'sint'; $response = $sdk->payments->getConnectorTask($request); @@ -192,7 +192,7 @@ try { $request->requestBody->directory = '/tmp/dummypay'; $request->requestBody->fileGenerationPeriod = '60s'; $request->requestBody->filePollingPeriod = '60s'; - $request->connector = Connector::BANKING_CIRCLE; + $request->connector = Connector::MANGOPAY; $response = $sdk->payments->installConnector($request); @@ -284,7 +284,7 @@ $sdk = SDK::builder() try { $request = new ListConnectorTasksRequest(); - $request->connector = Connector::BANKING_CIRCLE; + $request->connector = Connector::MANGOPAY; $request->cursor = 'aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=='; $request->pageSize = 680056; @@ -320,7 +320,7 @@ $sdk = SDK::builder() try { $request = new ListConnectorsTransfersRequest(); - $request->connector = Connector::WISE; + $request->connector = Connector::MODULR; $response = $sdk->payments->listConnectorsTransfers($request); @@ -499,7 +499,7 @@ $sdk = SDK::builder() try { $request = new ResetConnectorRequest(); - $request->connector = Connector::MODULR; + $request->connector = Connector::CURRENCY_CLOUD; $response = $sdk->payments->resetConnector($request); @@ -533,7 +533,7 @@ $sdk = SDK::builder() try { $request = new UninstallConnectorRequest(); - $request->connector = Connector::DUMMY_PAY; + $request->connector = Connector::WISE; $response = $sdk->payments->uninstallConnector($request); diff --git a/sdks/php/files.gen b/sdks/php/files.gen index 05b5dad742..5da8051bbb 100755 --- a/sdks/php/files.gen +++ b/sdks/php/files.gen @@ -319,6 +319,8 @@ src/Models/Shared/TaskModulrDescriptor.php src/Models/Shared/TaskModulr.php src/Models/Shared/TaskBankingCircleDescriptor.php src/Models/Shared/TaskBankingCircle.php +src/Models/Shared/TaskMangoPayDescriptor.php +src/Models/Shared/TaskMangoPay.php src/Models/Shared/PaymentResponse.php src/Models/Shared/StripeConfig.php src/Models/Shared/DummyPayConfig.php @@ -326,6 +328,7 @@ src/Models/Shared/WiseConfig.php src/Models/Shared/ModulrConfig.php src/Models/Shared/CurrencyCloudConfig.php src/Models/Shared/BankingCircleConfig.php +src/Models/Shared/MangoPayConfig.php src/Models/Shared/ConnectorsResponseData.php src/Models/Shared/ConnectorsResponse.php src/Models/Shared/ConnectorsConfigsResponseDataConnectorKey.php diff --git a/sdks/php/src/Models/Shared/BankingCircleConfig.php b/sdks/php/src/Models/Shared/BankingCircleConfig.php index 7dc54c1668..ce81db7f63 100755 --- a/sdks/php/src/Models/Shared/BankingCircleConfig.php +++ b/sdks/php/src/Models/Shared/BankingCircleConfig.php @@ -23,6 +23,14 @@ class BankingCircleConfig #[\JMS\Serializer\Annotation\Type('string')] public string $password; + #[\JMS\Serializer\Annotation\SerializedName('userCertificate')] + #[\JMS\Serializer\Annotation\Type('string')] + public string $userCertificate; + + #[\JMS\Serializer\Annotation\SerializedName('userCertificateKey')] + #[\JMS\Serializer\Annotation\Type('string')] + public string $userCertificateKey; + #[\JMS\Serializer\Annotation\SerializedName('username')] #[\JMS\Serializer\Annotation\Type('string')] public string $username; @@ -32,6 +40,8 @@ public function __construct() $this->authorizationEndpoint = ""; $this->endpoint = ""; $this->password = ""; + $this->userCertificate = ""; + $this->userCertificateKey = ""; $this->username = ""; } } diff --git a/sdks/php/src/Models/Shared/Connector.php b/sdks/php/src/Models/Shared/Connector.php index 85209642ed..f3a7c918df 100755 --- a/sdks/php/src/Models/Shared/Connector.php +++ b/sdks/php/src/Models/Shared/Connector.php @@ -18,4 +18,5 @@ enum Connector: string case MODULR = 'MODULR'; case CURRENCY_CLOUD = 'CURRENCY-CLOUD'; case BANKING_CIRCLE = 'BANKING-CIRCLE'; + case MANGOPAY = 'MANGOPAY'; } diff --git a/sdks/php/src/Models/Shared/MangoPayConfig.php b/sdks/php/src/Models/Shared/MangoPayConfig.php new file mode 100755 index 0000000000..6248cfb8af --- /dev/null +++ b/sdks/php/src/Models/Shared/MangoPayConfig.php @@ -0,0 +1,32 @@ +apiKey = ""; + $this->clientID = ""; + $this->endpoint = ""; + } +} diff --git a/sdks/php/src/Models/Shared/TaskMangoPay.php b/sdks/php/src/Models/Shared/TaskMangoPay.php new file mode 100755 index 0000000000..61dc376470 --- /dev/null +++ b/sdks/php/src/Models/Shared/TaskMangoPay.php @@ -0,0 +1,63 @@ +")] + public \DateTime $createdAt; + + #[\JMS\Serializer\Annotation\SerializedName('descriptor')] + #[\JMS\Serializer\Annotation\Type('formance\stack\Models\Shared\TaskMangoPayDescriptor')] + public TaskMangoPayDescriptor $descriptor; + + #[\JMS\Serializer\Annotation\SerializedName('error')] + #[\JMS\Serializer\Annotation\Type('string')] + #[\JMS\Serializer\Annotation\SkipWhenEmpty] + public ?string $error = null; + + #[\JMS\Serializer\Annotation\SerializedName('id')] + #[\JMS\Serializer\Annotation\Type('string')] + public string $id; + + /** + * $state + * + * @var array $state + */ + #[\JMS\Serializer\Annotation\SerializedName('state')] + #[\JMS\Serializer\Annotation\Type('array')] + public array $state; + + #[\JMS\Serializer\Annotation\SerializedName('status')] + #[\JMS\Serializer\Annotation\Type('enum')] + public PaymentStatus $status; + + #[\JMS\Serializer\Annotation\SerializedName('updatedAt')] + #[\JMS\Serializer\Annotation\Type("DateTime<'Y-m-d\TH:i:s.up'>")] + public \DateTime $updatedAt; + + public function __construct() + { + $this->connectorId = ""; + $this->createdAt = new \DateTime(); + $this->descriptor = new \formance\stack\Models\Shared\TaskMangoPayDescriptor(); + $this->error = null; + $this->id = ""; + $this->state = []; + $this->status = \formance\stack\Models\Shared\PaymentStatus::PENDING; + $this->updatedAt = new \DateTime(); + } +} diff --git a/sdks/php/src/Models/Shared/TaskMangoPayDescriptor.php b/sdks/php/src/Models/Shared/TaskMangoPayDescriptor.php new file mode 100755 index 0000000000..35fe24404c --- /dev/null +++ b/sdks/php/src/Models/Shared/TaskMangoPayDescriptor.php @@ -0,0 +1,35 @@ +key = null; + $this->name = null; + $this->userID = null; + } +} diff --git a/sdks/python/docs/payments/README.md b/sdks/python/docs/payments/README.md index 50254e1a9a..263abb6d15 100755 --- a/sdks/python/docs/payments/README.md +++ b/sdks/python/docs/payments/README.md @@ -74,7 +74,7 @@ req = operations.ConnectorsTransferRequest( destination='acct_1Gqj58KZcSIg2N2q', source='acct_1Gqj58KZcSIg2N2q', ), - connector=shared.Connector.MODULR, + connector=shared.Connector.CURRENCY_CLOUD, ) res = s.payments.connectors_transfer(req) @@ -100,7 +100,7 @@ s = sdk.SDK( ) req = operations.GetConnectorTaskRequest( - connector=shared.Connector.BANKING_CIRCLE, + connector=shared.Connector.MANGOPAY, task_id='sint', ) @@ -158,7 +158,7 @@ req = operations.InstallConnectorRequest( file_generation_period='60s', file_polling_period='60s', ), - connector=shared.Connector.BANKING_CIRCLE, + connector=shared.Connector.MANGOPAY, ) res = s.payments.install_connector(req) @@ -230,7 +230,7 @@ s = sdk.SDK( ) req = operations.ListConnectorTasksRequest( - connector=shared.Connector.BANKING_CIRCLE, + connector=shared.Connector.MANGOPAY, cursor='aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ==', page_size=680056, ) @@ -258,7 +258,7 @@ s = sdk.SDK( ) req = operations.ListConnectorsTransfersRequest( - connector=shared.Connector.WISE, + connector=shared.Connector.MODULR, ) res = s.payments.list_connectors_transfers(req) @@ -401,7 +401,7 @@ s = sdk.SDK( ) req = operations.ResetConnectorRequest( - connector=shared.Connector.MODULR, + connector=shared.Connector.CURRENCY_CLOUD, ) res = s.payments.reset_connector(req) @@ -427,7 +427,7 @@ s = sdk.SDK( ) req = operations.UninstallConnectorRequest( - connector=shared.Connector.DUMMY_PAY, + connector=shared.Connector.WISE, ) res = s.payments.uninstall_connector(req) diff --git a/sdks/python/files.gen b/sdks/python/files.gen index 786f891ce6..6b5f2a27ac 100755 --- a/sdks/python/files.gen +++ b/sdks/python/files.gen @@ -219,6 +219,7 @@ src/sdk/models/shared/taskcurrencycloud.py src/sdk/models/shared/taskdummypay.py src/sdk/models/shared/taskmodulr.py src/sdk/models/shared/taskbankingcircle.py +src/sdk/models/shared/taskmangopay.py src/sdk/models/shared/paymentresponse.py src/sdk/models/shared/stripeconfig.py src/sdk/models/shared/dummypayconfig.py @@ -226,6 +227,7 @@ src/sdk/models/shared/wiseconfig.py src/sdk/models/shared/modulrconfig.py src/sdk/models/shared/currencycloudconfig.py src/sdk/models/shared/bankingcircleconfig.py +src/sdk/models/shared/mangopayconfig.py src/sdk/models/shared/connectorsresponse.py src/sdk/models/shared/connectorsconfigsresponse.py src/sdk/models/shared/taskscursor.py diff --git a/sdks/python/src/sdk/models/shared/__init__.py b/sdks/python/src/sdk/models/shared/__init__.py index 21e2bbd8b5..f561ca2476 100755 --- a/sdks/python/src/sdk/models/shared/__init__.py +++ b/sdks/python/src/sdk/models/shared/__init__.py @@ -91,6 +91,7 @@ from .listworkflowsresponse import * from .log import * from .logscursorresponse import * +from .mangopayconfig import * from .migrationinfo import * from .modulrconfig import * from .monetary import * @@ -133,6 +134,7 @@ from .taskbankingcircle import * from .taskcurrencycloud import * from .taskdummypay import * +from .taskmangopay import * from .taskmodulr import * from .taskresponse import * from .taskscursor import * @@ -166,4 +168,4 @@ from .workflowinstancehistorystageinput import * from .workflowinstancehistorystageoutput import * -__all__ = ["Account","AccountResponse","AccountWithVolumesAndBalances","AccountsCursor","AccountsCursorCursor","AccountsCursorResponse","AccountsCursorResponseCursor","ActivityConfirmHold","ActivityCreateTransaction","ActivityCreateTransactionOutput","ActivityCreditWallet","ActivityDebitWallet","ActivityDebitWalletOutput","ActivityGetAccount","ActivityGetAccountOutput","ActivityGetPayment","ActivityGetPaymentOutput","ActivityGetWallet","ActivityGetWalletOutput","ActivityRevertTransaction","ActivityRevertTransactionOutput","ActivityStripeTransfer","ActivityVoidHold","AggregateBalancesResponse","AssetHolder","Attempt","AttemptResponse","Balance","BalanceWithAssets","BalancesCursorResponse","BalancesCursorResponseCursor","BankingCircleConfig","Client","ClientSecret","Config","ConfigChangeSecret","ConfigInfoResponse","ConfigResponse","ConfigUser","ConfigsResponse","ConfigsResponseCursor","ConfirmHoldRequest","Connector","ConnectorConfigResponse","ConnectorsConfigsResponse","ConnectorsConfigsResponseData","ConnectorsConfigsResponseDataConnector","ConnectorsConfigsResponseDataConnectorKey","ConnectorsResponse","ConnectorsResponseData","CreateBalanceRequest","CreateBalanceResponse","CreateClientRequest","CreateClientResponse","CreateScopeRequest","CreateScopeResponse","CreateSecretRequest","CreateSecretResponse","CreateTransactionResponse","CreateWalletRequest","CreateWalletResponse","CreateWorkflowRequest","CreateWorkflowResponse","CreditWalletRequest","CurrencyCloudConfig","DebitWalletRequest","DebitWalletResponse","DummyPayConfig","Error","ErrorErrorCode","ErrorResponse","ErrorsEnum","ExpandedDebitHold","ExpandedTransaction","GetBalanceResponse","GetHoldResponse","GetHoldsResponse","GetHoldsResponseCursor","GetTransactionResponse","GetTransactionsResponse","GetTransactionsResponseCursor","GetVersionsResponse","GetWalletResponse","GetWalletSummaryResponse","GetWorkflowInstanceHistoryResponse","GetWorkflowInstanceHistoryStageResponse","GetWorkflowInstanceResponse","GetWorkflowResponse","Hold","LedgerAccountSubject","LedgerInfo","LedgerInfoResponse","LedgerInfoStorage","LedgerStorage","ListBalancesResponse","ListBalancesResponseCursor","ListClientsResponse","ListRunsResponse","ListScopesResponse","ListUsersResponse","ListWalletsResponse","ListWalletsResponseCursor","ListWorkflowsResponse","Log","LogType","LogsCursorResponse","LogsCursorResponseCursor","MigrationInfo","MigrationInfoState","ModulrConfig","Monetary","Payment","PaymentAdjustment","PaymentMetadata","PaymentResponse","PaymentScheme","PaymentStatus","PaymentType","PaymentsAccount","PaymentsAccountType","PaymentsCursor","PaymentsCursorCursor","PostTransaction","PostTransactionScript","Posting","Query","ReadClientResponse","ReadScopeResponse","ReadUserResponse","Response","ResponseCursor","ResponseCursorTotal","RevertTransactionResponse","RunWorkflowResponse","Scope","Secret","Security","ServerInfo","StageDelay","StageSend","StageSendDestination","StageSendDestinationAccount","StageSendDestinationPayment","StageSendDestinationWallet","StageSendSource","StageSendSourceAccount","StageSendSourcePayment","StageSendSourceWallet","StageStatus","StageWaitEvent","Stats","StatsResponse","StripeConfig","StripeTransferRequest","TaskBankingCircle","TaskBankingCircleDescriptor","TaskCurrencyCloud","TaskCurrencyCloudDescriptor","TaskDummyPay","TaskDummyPayDescriptor","TaskModulr","TaskModulrDescriptor","TaskResponse","TaskStripe","TaskStripeDescriptor","TaskWise","TaskWiseDescriptor","TasksCursor","TasksCursorCursor","Transaction","TransactionsCursorResponse","TransactionsCursorResponseCursor","TransferRequest","TransferResponse","TransfersResponse","TransfersResponseData","UpdateClientRequest","UpdateClientResponse","UpdateScopeRequest","UpdateScopeResponse","User","Version","Volume","Wallet","WalletSubject","WalletWithBalances","WalletWithBalancesBalances","WalletsErrorResponse","WalletsErrorResponseErrorCode","WalletsTransaction","WalletsVolume","WebhooksConfig","WiseConfig","Workflow","WorkflowConfig","WorkflowInstance","WorkflowInstanceHistory","WorkflowInstanceHistoryStage","WorkflowInstanceHistoryStageInput","WorkflowInstanceHistoryStageOutput"] +__all__ = ["Account","AccountResponse","AccountWithVolumesAndBalances","AccountsCursor","AccountsCursorCursor","AccountsCursorResponse","AccountsCursorResponseCursor","ActivityConfirmHold","ActivityCreateTransaction","ActivityCreateTransactionOutput","ActivityCreditWallet","ActivityDebitWallet","ActivityDebitWalletOutput","ActivityGetAccount","ActivityGetAccountOutput","ActivityGetPayment","ActivityGetPaymentOutput","ActivityGetWallet","ActivityGetWalletOutput","ActivityRevertTransaction","ActivityRevertTransactionOutput","ActivityStripeTransfer","ActivityVoidHold","AggregateBalancesResponse","AssetHolder","Attempt","AttemptResponse","Balance","BalanceWithAssets","BalancesCursorResponse","BalancesCursorResponseCursor","BankingCircleConfig","Client","ClientSecret","Config","ConfigChangeSecret","ConfigInfoResponse","ConfigResponse","ConfigUser","ConfigsResponse","ConfigsResponseCursor","ConfirmHoldRequest","Connector","ConnectorConfigResponse","ConnectorsConfigsResponse","ConnectorsConfigsResponseData","ConnectorsConfigsResponseDataConnector","ConnectorsConfigsResponseDataConnectorKey","ConnectorsResponse","ConnectorsResponseData","CreateBalanceRequest","CreateBalanceResponse","CreateClientRequest","CreateClientResponse","CreateScopeRequest","CreateScopeResponse","CreateSecretRequest","CreateSecretResponse","CreateTransactionResponse","CreateWalletRequest","CreateWalletResponse","CreateWorkflowRequest","CreateWorkflowResponse","CreditWalletRequest","CurrencyCloudConfig","DebitWalletRequest","DebitWalletResponse","DummyPayConfig","Error","ErrorErrorCode","ErrorResponse","ErrorsEnum","ExpandedDebitHold","ExpandedTransaction","GetBalanceResponse","GetHoldResponse","GetHoldsResponse","GetHoldsResponseCursor","GetTransactionResponse","GetTransactionsResponse","GetTransactionsResponseCursor","GetVersionsResponse","GetWalletResponse","GetWalletSummaryResponse","GetWorkflowInstanceHistoryResponse","GetWorkflowInstanceHistoryStageResponse","GetWorkflowInstanceResponse","GetWorkflowResponse","Hold","LedgerAccountSubject","LedgerInfo","LedgerInfoResponse","LedgerInfoStorage","LedgerStorage","ListBalancesResponse","ListBalancesResponseCursor","ListClientsResponse","ListRunsResponse","ListScopesResponse","ListUsersResponse","ListWalletsResponse","ListWalletsResponseCursor","ListWorkflowsResponse","Log","LogType","LogsCursorResponse","LogsCursorResponseCursor","MangoPayConfig","MigrationInfo","MigrationInfoState","ModulrConfig","Monetary","Payment","PaymentAdjustment","PaymentMetadata","PaymentResponse","PaymentScheme","PaymentStatus","PaymentType","PaymentsAccount","PaymentsAccountType","PaymentsCursor","PaymentsCursorCursor","PostTransaction","PostTransactionScript","Posting","Query","ReadClientResponse","ReadScopeResponse","ReadUserResponse","Response","ResponseCursor","ResponseCursorTotal","RevertTransactionResponse","RunWorkflowResponse","Scope","Secret","Security","ServerInfo","StageDelay","StageSend","StageSendDestination","StageSendDestinationAccount","StageSendDestinationPayment","StageSendDestinationWallet","StageSendSource","StageSendSourceAccount","StageSendSourcePayment","StageSendSourceWallet","StageStatus","StageWaitEvent","Stats","StatsResponse","StripeConfig","StripeTransferRequest","TaskBankingCircle","TaskBankingCircleDescriptor","TaskCurrencyCloud","TaskCurrencyCloudDescriptor","TaskDummyPay","TaskDummyPayDescriptor","TaskMangoPay","TaskMangoPayDescriptor","TaskModulr","TaskModulrDescriptor","TaskResponse","TaskStripe","TaskStripeDescriptor","TaskWise","TaskWiseDescriptor","TasksCursor","TasksCursorCursor","Transaction","TransactionsCursorResponse","TransactionsCursorResponseCursor","TransferRequest","TransferResponse","TransfersResponse","TransfersResponseData","UpdateClientRequest","UpdateClientResponse","UpdateScopeRequest","UpdateScopeResponse","User","Version","Volume","Wallet","WalletSubject","WalletWithBalances","WalletWithBalancesBalances","WalletsErrorResponse","WalletsErrorResponseErrorCode","WalletsTransaction","WalletsVolume","WebhooksConfig","WiseConfig","Workflow","WorkflowConfig","WorkflowInstance","WorkflowInstanceHistory","WorkflowInstanceHistoryStage","WorkflowInstanceHistoryStageInput","WorkflowInstanceHistoryStageOutput"] diff --git a/sdks/python/src/sdk/models/shared/bankingcircleconfig.py b/sdks/python/src/sdk/models/shared/bankingcircleconfig.py index 2d057e80b0..49ac209bf5 100755 --- a/sdks/python/src/sdk/models/shared/bankingcircleconfig.py +++ b/sdks/python/src/sdk/models/shared/bankingcircleconfig.py @@ -13,5 +13,7 @@ class BankingCircleConfig: authorization_endpoint: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('authorizationEndpoint') }}) endpoint: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('endpoint') }}) password: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('password') }}) + user_certificate: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('userCertificate') }}) + user_certificate_key: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('userCertificateKey') }}) username: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('username') }}) \ No newline at end of file diff --git a/sdks/python/src/sdk/models/shared/connector.py b/sdks/python/src/sdk/models/shared/connector.py index 7140e6e509..8042866e0e 100755 --- a/sdks/python/src/sdk/models/shared/connector.py +++ b/sdks/python/src/sdk/models/shared/connector.py @@ -11,3 +11,4 @@ class Connector(str, Enum): MODULR = 'MODULR' CURRENCY_CLOUD = 'CURRENCY-CLOUD' BANKING_CIRCLE = 'BANKING-CIRCLE' + MANGOPAY = 'MANGOPAY' diff --git a/sdks/python/src/sdk/models/shared/mangopayconfig.py b/sdks/python/src/sdk/models/shared/mangopayconfig.py new file mode 100755 index 0000000000..7476fae10f --- /dev/null +++ b/sdks/python/src/sdk/models/shared/mangopayconfig.py @@ -0,0 +1,16 @@ +"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" + +from __future__ import annotations +import dataclasses +from dataclasses_json import Undefined, dataclass_json +from sdk import utils + + +@dataclass_json(undefined=Undefined.EXCLUDE) +@dataclasses.dataclass +class MangoPayConfig: + + api_key: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('apiKey') }}) + client_id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('clientID') }}) + endpoint: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('endpoint') }}) + \ No newline at end of file diff --git a/sdks/python/src/sdk/models/shared/taskmangopay.py b/sdks/python/src/sdk/models/shared/taskmangopay.py new file mode 100755 index 0000000000..207b18c216 --- /dev/null +++ b/sdks/python/src/sdk/models/shared/taskmangopay.py @@ -0,0 +1,35 @@ +"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" + +from __future__ import annotations +import dataclasses +import dateutil.parser +from ..shared import paymentstatus as shared_paymentstatus +from dataclasses_json import Undefined, dataclass_json +from datetime import datetime +from marshmallow import fields +from sdk import utils +from typing import Any, Optional + + +@dataclass_json(undefined=Undefined.EXCLUDE) +@dataclasses.dataclass +class TaskMangoPayDescriptor: + + key: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('key'), 'exclude': lambda f: f is None }}) + name: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('name'), 'exclude': lambda f: f is None }}) + user_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('userID'), 'exclude': lambda f: f is None }}) + + +@dataclass_json(undefined=Undefined.EXCLUDE) +@dataclasses.dataclass +class TaskMangoPay: + + connector_id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('connectorId') }}) + created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('createdAt'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) + descriptor: TaskMangoPayDescriptor = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('descriptor') }}) + id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('id') }}) + state: dict[str, Any] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('state') }}) + status: shared_paymentstatus.PaymentStatus = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('status') }}) + updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('updatedAt'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) + error: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('error'), 'exclude': lambda f: f is None }}) + \ No newline at end of file diff --git a/sdks/typescript/docs/payments/README.md b/sdks/typescript/docs/payments/README.md index 4971ac3aa8..92f8b97ba0 100755 --- a/sdks/typescript/docs/payments/README.md +++ b/sdks/typescript/docs/payments/README.md @@ -74,7 +74,7 @@ sdk.payments.connectorsTransfer({ destination: "acct_1Gqj58KZcSIg2N2q", source: "acct_1Gqj58KZcSIg2N2q", }, - connector: Connector.Modulr, + connector: Connector.CurrencyCloud, }).then((res: ConnectorsTransferResponse) => { if (res.statusCode == 200) { // handle response @@ -100,7 +100,7 @@ const sdk = new SDK({ }); sdk.payments.getConnectorTask({ - connector: Connector.BankingCircle, + connector: Connector.Mangopay, taskId: "sint", }).then((res: GetConnectorTaskResponse) => { if (res.statusCode == 200) { @@ -158,7 +158,7 @@ sdk.payments.installConnector({ fileGenerationPeriod: "60s", filePollingPeriod: "60s", }, - connector: Connector.BankingCircle, + connector: Connector.Mangopay, }).then((res: InstallConnectorResponse) => { if (res.statusCode == 200) { // handle response @@ -231,7 +231,7 @@ const sdk = new SDK({ }); sdk.payments.listConnectorTasks({ - connector: Connector.BankingCircle, + connector: Connector.Mangopay, cursor: "aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ==", pageSize: 680056, }).then((res: ListConnectorTasksResponse) => { @@ -259,7 +259,7 @@ const sdk = new SDK({ }); sdk.payments.listConnectorsTransfers({ - connector: Connector.Wise, + connector: Connector.Modulr, }).then((res: ListConnectorsTransfersResponse) => { if (res.statusCode == 200) { // handle response @@ -402,7 +402,7 @@ const sdk = new SDK({ }); sdk.payments.resetConnector({ - connector: Connector.Modulr, + connector: Connector.CurrencyCloud, }).then((res: ResetConnectorResponse) => { if (res.statusCode == 200) { // handle response @@ -428,7 +428,7 @@ const sdk = new SDK({ }); sdk.payments.uninstallConnector({ - connector: Connector.DummyPay, + connector: Connector.Wise, }).then((res: UninstallConnectorResponse) => { if (res.statusCode == 200) { // handle response diff --git a/sdks/typescript/files.gen b/sdks/typescript/files.gen index b00d4bb184..62add21e89 100755 --- a/sdks/typescript/files.gen +++ b/sdks/typescript/files.gen @@ -230,6 +230,7 @@ src/sdk/models/shared/taskcurrencycloud.ts src/sdk/models/shared/taskdummypay.ts src/sdk/models/shared/taskmodulr.ts src/sdk/models/shared/taskbankingcircle.ts +src/sdk/models/shared/taskmangopay.ts src/sdk/models/shared/paymentresponse.ts src/sdk/models/shared/stripeconfig.ts src/sdk/models/shared/dummypayconfig.ts @@ -237,6 +238,7 @@ src/sdk/models/shared/wiseconfig.ts src/sdk/models/shared/modulrconfig.ts src/sdk/models/shared/currencycloudconfig.ts src/sdk/models/shared/bankingcircleconfig.ts +src/sdk/models/shared/mangopayconfig.ts src/sdk/models/shared/connectorsresponse.ts src/sdk/models/shared/connectorsconfigsresponse.ts src/sdk/models/shared/taskscursor.ts diff --git a/sdks/typescript/src/sdk/models/shared/bankingcircleconfig.ts b/sdks/typescript/src/sdk/models/shared/bankingcircleconfig.ts index 1d6819bce2..23cf57a977 100755 --- a/sdks/typescript/src/sdk/models/shared/bankingcircleconfig.ts +++ b/sdks/typescript/src/sdk/models/shared/bankingcircleconfig.ts @@ -18,6 +18,14 @@ export class BankingCircleConfig extends SpeakeasyBase { @Expose({ name: "password" }) password: string; + @SpeakeasyMetadata() + @Expose({ name: "userCertificate" }) + userCertificate: string; + + @SpeakeasyMetadata() + @Expose({ name: "userCertificateKey" }) + userCertificateKey: string; + @SpeakeasyMetadata() @Expose({ name: "username" }) username: string; diff --git a/sdks/typescript/src/sdk/models/shared/connector.ts b/sdks/typescript/src/sdk/models/shared/connector.ts index ce17373d9a..0ea768ed9e 100755 --- a/sdks/typescript/src/sdk/models/shared/connector.ts +++ b/sdks/typescript/src/sdk/models/shared/connector.ts @@ -12,4 +12,5 @@ export enum Connector { Modulr = "MODULR", CurrencyCloud = "CURRENCY-CLOUD", BankingCircle = "BANKING-CIRCLE", + Mangopay = "MANGOPAY", } diff --git a/sdks/typescript/src/sdk/models/shared/index.ts b/sdks/typescript/src/sdk/models/shared/index.ts index ee0fb693fe..ea9b235ca6 100755 --- a/sdks/typescript/src/sdk/models/shared/index.ts +++ b/sdks/typescript/src/sdk/models/shared/index.ts @@ -93,6 +93,7 @@ export * from "./listwalletsresponse"; export * from "./listworkflowsresponse"; export * from "./log"; export * from "./logscursorresponse"; +export * from "./mangopayconfig"; export * from "./migrationinfo"; export * from "./modulrconfig"; export * from "./monetary"; @@ -135,6 +136,7 @@ export * from "./stripetransferrequest"; export * from "./taskbankingcircle"; export * from "./taskcurrencycloud"; export * from "./taskdummypay"; +export * from "./taskmangopay"; export * from "./taskmodulr"; export * from "./taskresponse"; export * from "./taskscursor"; diff --git a/sdks/typescript/src/sdk/models/shared/mangopayconfig.ts b/sdks/typescript/src/sdk/models/shared/mangopayconfig.ts new file mode 100755 index 0000000000..16d3a4d0e8 --- /dev/null +++ b/sdks/typescript/src/sdk/models/shared/mangopayconfig.ts @@ -0,0 +1,20 @@ +/* + * Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + */ + +import { SpeakeasyBase, SpeakeasyMetadata } from "../../../internal/utils"; +import { Expose } from "class-transformer"; + +export class MangoPayConfig extends SpeakeasyBase { + @SpeakeasyMetadata() + @Expose({ name: "apiKey" }) + apiKey: string; + + @SpeakeasyMetadata() + @Expose({ name: "clientID" }) + clientID: string; + + @SpeakeasyMetadata() + @Expose({ name: "endpoint" }) + endpoint: string; +} diff --git a/sdks/typescript/src/sdk/models/shared/taskmangopay.ts b/sdks/typescript/src/sdk/models/shared/taskmangopay.ts new file mode 100755 index 0000000000..3f4db21a4e --- /dev/null +++ b/sdks/typescript/src/sdk/models/shared/taskmangopay.ts @@ -0,0 +1,58 @@ +/* + * Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. + */ + +import { SpeakeasyBase, SpeakeasyMetadata } from "../../../internal/utils"; +import { PaymentStatus } from "./paymentstatus"; +import { Expose, Transform, Type } from "class-transformer"; + +export class TaskMangoPayDescriptor extends SpeakeasyBase { + @SpeakeasyMetadata() + @Expose({ name: "key" }) + key?: string; + + @SpeakeasyMetadata() + @Expose({ name: "name" }) + name?: string; + + @SpeakeasyMetadata() + @Expose({ name: "userID" }) + userID?: string; +} + +export class TaskMangoPay extends SpeakeasyBase { + @SpeakeasyMetadata() + @Expose({ name: "connectorId" }) + connectorId: string; + + @SpeakeasyMetadata() + @Expose({ name: "createdAt" }) + @Transform(({ value }) => new Date(value), { toClassOnly: true }) + createdAt: Date; + + @SpeakeasyMetadata() + @Expose({ name: "descriptor" }) + @Type(() => TaskMangoPayDescriptor) + descriptor: TaskMangoPayDescriptor; + + @SpeakeasyMetadata() + @Expose({ name: "error" }) + error?: string; + + @SpeakeasyMetadata() + @Expose({ name: "id" }) + id: string; + + @SpeakeasyMetadata() + @Expose({ name: "state" }) + state: Record; + + @SpeakeasyMetadata() + @Expose({ name: "status" }) + status: PaymentStatus; + + @SpeakeasyMetadata() + @Expose({ name: "updatedAt" }) + @Transform(({ value }) => new Date(value), { toClassOnly: true }) + updatedAt: Date; +}