From 0e7f6ac9b2d814bebff01a3c9f988b536c5c1227 Mon Sep 17 00:00:00 2001 From: Stephan D Date: Fri, 30 Jan 2026 15:45:50 +0100 Subject: [PATCH] mntx dev env --- api/gateway/mntx/.air.toml | 46 +++++++++++++++ api/gateway/mntx/.gitignore | 4 ++ api/gateway/mntx/client/client.go | 95 +++++++++++++++++++------------ api/gateway/mntx/config.dev.yml | 50 ++++++++++++++++ api/gateway/mntx/go.mod | 4 +- api/gateway/mntx/go.sum | 4 +- 6 files changed, 162 insertions(+), 41 deletions(-) create mode 100644 api/gateway/mntx/.air.toml create mode 100644 api/gateway/mntx/config.dev.yml diff --git a/api/gateway/mntx/.air.toml b/api/gateway/mntx/.air.toml new file mode 100644 index 00000000..16f8c34b --- /dev/null +++ b/api/gateway/mntx/.air.toml @@ -0,0 +1,46 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = [] + entrypoint = "./tmp/main" + cmd = "go build -o ./tmp/main ." + delay = 1000 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] + exclude_file = [] + exclude_regex = ["_test.go", "_templ.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "html"] + include_file = [] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + post_cmd = [] + pre_cmd = [] + rerun = false + rerun_delay = 500 + send_interrupt = false + stop_on_error = false + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = false + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/api/gateway/mntx/.gitignore b/api/gateway/mntx/.gitignore index 4cb3c7e6..67db59ee 100644 --- a/api/gateway/mntx/.gitignore +++ b/api/gateway/mntx/.gitignore @@ -1 +1,5 @@ /mntx-gateway +internal/generated +.gocache +tmp +app diff --git a/api/gateway/mntx/client/client.go b/api/gateway/mntx/client/client.go index 9bc0e29f..978c4608 100644 --- a/api/gateway/mntx/client/client.go +++ b/api/gateway/mntx/client/client.go @@ -7,8 +7,9 @@ import ( "github.com/shopspring/decimal" "github.com/tech/sendico/pkg/merrors" - connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1" + pmodel "github.com/tech/sendico/pkg/model" moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" + connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1" mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1" "go.uber.org/zap" "google.golang.org/grpc" @@ -52,7 +53,7 @@ func New(ctx context.Context, cfg Config, opts ...grpc.DialOption) (Client, erro conn, err := grpc.DialContext(dialCtx, cfg.Address, dialOpts...) if err != nil { - return nil, merrors.Internal("mntx: dial failed: "+err.Error()) + return nil, merrors.Internal("mntx: dial failed: " + err.Error()) } return &gatewayClient{ @@ -148,12 +149,14 @@ func operationFromCardPayout(req *mntxv1.CardPayoutRequest) (*connectorv1.Operat } params := payoutParamsFromCard(req) money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency()) - return &connectorv1.Operation{ + op := &connectorv1.Operation{ Type: connectorv1.OperationType_PAYOUT, IdempotencyKey: strings.TrimSpace(req.GetPayoutId()), Money: money, Params: structFromMap(params), - }, nil + } + setOperationRolesFromMetadata(op, req.GetMetadata()) + return op, nil } func operationFromTokenPayout(req *mntxv1.CardTokenPayoutRequest) (*connectorv1.Operation, error) { @@ -162,34 +165,52 @@ func operationFromTokenPayout(req *mntxv1.CardTokenPayoutRequest) (*connectorv1. } params := payoutParamsFromToken(req) money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency()) - return &connectorv1.Operation{ + op := &connectorv1.Operation{ Type: connectorv1.OperationType_PAYOUT, IdempotencyKey: strings.TrimSpace(req.GetPayoutId()), Money: money, Params: structFromMap(params), - }, nil + } + setOperationRolesFromMetadata(op, req.GetMetadata()) + return op, nil +} + +func setOperationRolesFromMetadata(op *connectorv1.Operation, metadata map[string]string) { + if op == nil || len(metadata) == 0 { + return + } + if raw := strings.TrimSpace(metadata[pmodel.MetadataKeyFromRole]); raw != "" { + if role, ok := pmodel.Parse(raw); ok && role != "" { + op.FromRole = pmodel.ToProto(role) + } + } + if raw := strings.TrimSpace(metadata[pmodel.MetadataKeyToRole]); raw != "" { + if role, ok := pmodel.Parse(raw); ok && role != "" { + op.ToRole = pmodel.ToProto(role) + } + } } func payoutParamsFromCard(req *mntxv1.CardPayoutRequest) map[string]interface{} { params := map[string]interface{}{ - "payout_id": strings.TrimSpace(req.GetPayoutId()), - "project_id": req.GetProjectId(), - "customer_id": strings.TrimSpace(req.GetCustomerId()), - "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), + "payout_id": strings.TrimSpace(req.GetPayoutId()), + "project_id": req.GetProjectId(), + "customer_id": strings.TrimSpace(req.GetCustomerId()), + "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), - "customer_last_name": strings.TrimSpace(req.GetCustomerLastName()), - "customer_ip": strings.TrimSpace(req.GetCustomerIp()), - "customer_zip": strings.TrimSpace(req.GetCustomerZip()), - "customer_country": strings.TrimSpace(req.GetCustomerCountry()), - "customer_state": strings.TrimSpace(req.GetCustomerState()), - "customer_city": strings.TrimSpace(req.GetCustomerCity()), - "customer_address": strings.TrimSpace(req.GetCustomerAddress()), - "amount_minor": req.GetAmountMinor(), - "currency": strings.TrimSpace(req.GetCurrency()), - "card_pan": strings.TrimSpace(req.GetCardPan()), + "customer_last_name": strings.TrimSpace(req.GetCustomerLastName()), + "customer_ip": strings.TrimSpace(req.GetCustomerIp()), + "customer_zip": strings.TrimSpace(req.GetCustomerZip()), + "customer_country": strings.TrimSpace(req.GetCustomerCountry()), + "customer_state": strings.TrimSpace(req.GetCustomerState()), + "customer_city": strings.TrimSpace(req.GetCustomerCity()), + "customer_address": strings.TrimSpace(req.GetCustomerAddress()), + "amount_minor": req.GetAmountMinor(), + "currency": strings.TrimSpace(req.GetCurrency()), + "card_pan": strings.TrimSpace(req.GetCardPan()), "card_exp_year": req.GetCardExpYear(), "card_exp_month": req.GetCardExpMonth(), - "card_holder": strings.TrimSpace(req.GetCardHolder()), + "card_holder": strings.TrimSpace(req.GetCardHolder()), } if len(req.GetMetadata()) > 0 { params["metadata"] = mapStringToInterface(req.GetMetadata()) @@ -199,23 +220,23 @@ func payoutParamsFromCard(req *mntxv1.CardPayoutRequest) map[string]interface{} func payoutParamsFromToken(req *mntxv1.CardTokenPayoutRequest) map[string]interface{} { params := map[string]interface{}{ - "payout_id": strings.TrimSpace(req.GetPayoutId()), - "project_id": req.GetProjectId(), - "customer_id": strings.TrimSpace(req.GetCustomerId()), - "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), + "payout_id": strings.TrimSpace(req.GetPayoutId()), + "project_id": req.GetProjectId(), + "customer_id": strings.TrimSpace(req.GetCustomerId()), + "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), - "customer_last_name": strings.TrimSpace(req.GetCustomerLastName()), - "customer_ip": strings.TrimSpace(req.GetCustomerIp()), - "customer_zip": strings.TrimSpace(req.GetCustomerZip()), - "customer_country": strings.TrimSpace(req.GetCustomerCountry()), - "customer_state": strings.TrimSpace(req.GetCustomerState()), - "customer_city": strings.TrimSpace(req.GetCustomerCity()), - "customer_address": strings.TrimSpace(req.GetCustomerAddress()), - "amount_minor": req.GetAmountMinor(), - "currency": strings.TrimSpace(req.GetCurrency()), - "card_token": strings.TrimSpace(req.GetCardToken()), - "card_holder": strings.TrimSpace(req.GetCardHolder()), - "masked_pan": strings.TrimSpace(req.GetMaskedPan()), + "customer_last_name": strings.TrimSpace(req.GetCustomerLastName()), + "customer_ip": strings.TrimSpace(req.GetCustomerIp()), + "customer_zip": strings.TrimSpace(req.GetCustomerZip()), + "customer_country": strings.TrimSpace(req.GetCustomerCountry()), + "customer_state": strings.TrimSpace(req.GetCustomerState()), + "customer_city": strings.TrimSpace(req.GetCustomerCity()), + "customer_address": strings.TrimSpace(req.GetCustomerAddress()), + "amount_minor": req.GetAmountMinor(), + "currency": strings.TrimSpace(req.GetCurrency()), + "card_token": strings.TrimSpace(req.GetCardToken()), + "card_holder": strings.TrimSpace(req.GetCardHolder()), + "masked_pan": strings.TrimSpace(req.GetMaskedPan()), } if len(req.GetMetadata()) > 0 { params["metadata"] = mapStringToInterface(req.GetMetadata()) diff --git a/api/gateway/mntx/config.dev.yml b/api/gateway/mntx/config.dev.yml new file mode 100644 index 00000000..eed8596c --- /dev/null +++ b/api/gateway/mntx/config.dev.yml @@ -0,0 +1,50 @@ +runtime: + shutdown_timeout_seconds: 15 + +grpc: + network: tcp + address: ":50075" + advertise_host: "dev-mntx-gateway" + enable_reflection: true + enable_health: true + +metrics: + address: ":9404" + +messaging: + driver: NATS + settings: + url_env: NATS_URL + host_env: NATS_HOST + port_env: NATS_PORT + username_env: NATS_USER + password_env: NATS_PASSWORD + broker_name: Monetix Gateway Service + max_reconnects: 10 + reconnect_wait: 5 + buffer_size: 1024 + +monetix: + base_url_env: MONETIX_BASE_URL + project_id_env: MONETIX_PROJECT_ID + secret_key_env: MONETIX_SECRET_KEY + allowed_currencies: ["RUB"] + require_customer_address: false + request_timeout_seconds: 15 + status_success: "success" + status_processing: "processing" + +gateway: + id: "monetix" + is_enabled: true + network: "VISA_DIRECT" + currencies: ["RUB"] + limits: + min_amount: "0" + +http: + callback: + address: ":8084" + path: "/monetix/callback" + allowed_cidrs: [] + max_body_bytes: 1048576 diff --git a/api/gateway/mntx/go.mod b/api/gateway/mntx/go.mod index 449c6c33..fc4960e5 100644 --- a/api/gateway/mntx/go.mod +++ b/api/gateway/mntx/go.mod @@ -1,6 +1,6 @@ module github.com/tech/sendico/gateway/mntx -go 1.25.3 +go 1.25.6 replace github.com/tech/sendico/pkg => ../../pkg @@ -50,5 +50,5 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect ) diff --git a/api/gateway/mntx/go.sum b/api/gateway/mntx/go.sum index 15cc004a..2a66f12c 100644 --- a/api/gateway/mntx/go.sum +++ b/api/gateway/mntx/go.sum @@ -214,8 +214,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -- 2.49.1