mntx dev env

This commit is contained in:
Stephan D
2026-01-30 15:45:50 +01:00
parent 51f5b0804a
commit 0e7f6ac9b2
6 changed files with 162 additions and 41 deletions

View File

@@ -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

View File

@@ -1 +1,5 @@
/mntx-gateway /mntx-gateway
internal/generated
.gocache
tmp
app

View File

@@ -7,8 +7,9 @@ import (
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/tech/sendico/pkg/merrors" "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" 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" mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
"go.uber.org/zap" "go.uber.org/zap"
"google.golang.org/grpc" "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...) conn, err := grpc.DialContext(dialCtx, cfg.Address, dialOpts...)
if err != nil { if err != nil {
return nil, merrors.Internal("mntx: dial failed: "+err.Error()) return nil, merrors.Internal("mntx: dial failed: " + err.Error())
} }
return &gatewayClient{ return &gatewayClient{
@@ -148,12 +149,14 @@ func operationFromCardPayout(req *mntxv1.CardPayoutRequest) (*connectorv1.Operat
} }
params := payoutParamsFromCard(req) params := payoutParamsFromCard(req)
money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency()) money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency())
return &connectorv1.Operation{ op := &connectorv1.Operation{
Type: connectorv1.OperationType_PAYOUT, Type: connectorv1.OperationType_PAYOUT,
IdempotencyKey: strings.TrimSpace(req.GetPayoutId()), IdempotencyKey: strings.TrimSpace(req.GetPayoutId()),
Money: money, Money: money,
Params: structFromMap(params), Params: structFromMap(params),
}, nil }
setOperationRolesFromMetadata(op, req.GetMetadata())
return op, nil
} }
func operationFromTokenPayout(req *mntxv1.CardTokenPayoutRequest) (*connectorv1.Operation, error) { func operationFromTokenPayout(req *mntxv1.CardTokenPayoutRequest) (*connectorv1.Operation, error) {
@@ -162,34 +165,52 @@ func operationFromTokenPayout(req *mntxv1.CardTokenPayoutRequest) (*connectorv1.
} }
params := payoutParamsFromToken(req) params := payoutParamsFromToken(req)
money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency()) money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency())
return &connectorv1.Operation{ op := &connectorv1.Operation{
Type: connectorv1.OperationType_PAYOUT, Type: connectorv1.OperationType_PAYOUT,
IdempotencyKey: strings.TrimSpace(req.GetPayoutId()), IdempotencyKey: strings.TrimSpace(req.GetPayoutId()),
Money: money, Money: money,
Params: structFromMap(params), 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{} { func payoutParamsFromCard(req *mntxv1.CardPayoutRequest) map[string]interface{} {
params := map[string]interface{}{ params := map[string]interface{}{
"payout_id": strings.TrimSpace(req.GetPayoutId()), "payout_id": strings.TrimSpace(req.GetPayoutId()),
"project_id": req.GetProjectId(), "project_id": req.GetProjectId(),
"customer_id": strings.TrimSpace(req.GetCustomerId()), "customer_id": strings.TrimSpace(req.GetCustomerId()),
"customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()),
"customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()),
"customer_last_name": strings.TrimSpace(req.GetCustomerLastName()), "customer_last_name": strings.TrimSpace(req.GetCustomerLastName()),
"customer_ip": strings.TrimSpace(req.GetCustomerIp()), "customer_ip": strings.TrimSpace(req.GetCustomerIp()),
"customer_zip": strings.TrimSpace(req.GetCustomerZip()), "customer_zip": strings.TrimSpace(req.GetCustomerZip()),
"customer_country": strings.TrimSpace(req.GetCustomerCountry()), "customer_country": strings.TrimSpace(req.GetCustomerCountry()),
"customer_state": strings.TrimSpace(req.GetCustomerState()), "customer_state": strings.TrimSpace(req.GetCustomerState()),
"customer_city": strings.TrimSpace(req.GetCustomerCity()), "customer_city": strings.TrimSpace(req.GetCustomerCity()),
"customer_address": strings.TrimSpace(req.GetCustomerAddress()), "customer_address": strings.TrimSpace(req.GetCustomerAddress()),
"amount_minor": req.GetAmountMinor(), "amount_minor": req.GetAmountMinor(),
"currency": strings.TrimSpace(req.GetCurrency()), "currency": strings.TrimSpace(req.GetCurrency()),
"card_pan": strings.TrimSpace(req.GetCardPan()), "card_pan": strings.TrimSpace(req.GetCardPan()),
"card_exp_year": req.GetCardExpYear(), "card_exp_year": req.GetCardExpYear(),
"card_exp_month": req.GetCardExpMonth(), "card_exp_month": req.GetCardExpMonth(),
"card_holder": strings.TrimSpace(req.GetCardHolder()), "card_holder": strings.TrimSpace(req.GetCardHolder()),
} }
if len(req.GetMetadata()) > 0 { if len(req.GetMetadata()) > 0 {
params["metadata"] = mapStringToInterface(req.GetMetadata()) 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{} { func payoutParamsFromToken(req *mntxv1.CardTokenPayoutRequest) map[string]interface{} {
params := map[string]interface{}{ params := map[string]interface{}{
"payout_id": strings.TrimSpace(req.GetPayoutId()), "payout_id": strings.TrimSpace(req.GetPayoutId()),
"project_id": req.GetProjectId(), "project_id": req.GetProjectId(),
"customer_id": strings.TrimSpace(req.GetCustomerId()), "customer_id": strings.TrimSpace(req.GetCustomerId()),
"customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()),
"customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()),
"customer_last_name": strings.TrimSpace(req.GetCustomerLastName()), "customer_last_name": strings.TrimSpace(req.GetCustomerLastName()),
"customer_ip": strings.TrimSpace(req.GetCustomerIp()), "customer_ip": strings.TrimSpace(req.GetCustomerIp()),
"customer_zip": strings.TrimSpace(req.GetCustomerZip()), "customer_zip": strings.TrimSpace(req.GetCustomerZip()),
"customer_country": strings.TrimSpace(req.GetCustomerCountry()), "customer_country": strings.TrimSpace(req.GetCustomerCountry()),
"customer_state": strings.TrimSpace(req.GetCustomerState()), "customer_state": strings.TrimSpace(req.GetCustomerState()),
"customer_city": strings.TrimSpace(req.GetCustomerCity()), "customer_city": strings.TrimSpace(req.GetCustomerCity()),
"customer_address": strings.TrimSpace(req.GetCustomerAddress()), "customer_address": strings.TrimSpace(req.GetCustomerAddress()),
"amount_minor": req.GetAmountMinor(), "amount_minor": req.GetAmountMinor(),
"currency": strings.TrimSpace(req.GetCurrency()), "currency": strings.TrimSpace(req.GetCurrency()),
"card_token": strings.TrimSpace(req.GetCardToken()), "card_token": strings.TrimSpace(req.GetCardToken()),
"card_holder": strings.TrimSpace(req.GetCardHolder()), "card_holder": strings.TrimSpace(req.GetCardHolder()),
"masked_pan": strings.TrimSpace(req.GetMaskedPan()), "masked_pan": strings.TrimSpace(req.GetMaskedPan()),
} }
if len(req.GetMetadata()) > 0 { if len(req.GetMetadata()) > 0 {
params["metadata"] = mapStringToInterface(req.GetMetadata()) params["metadata"] = mapStringToInterface(req.GetMetadata())

View File

@@ -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

View File

@@ -1,6 +1,6 @@
module github.com/tech/sendico/gateway/mntx module github.com/tech/sendico/gateway/mntx
go 1.25.3 go 1.25.6
replace github.com/tech/sendico/pkg => ../../pkg replace github.com/tech/sendico/pkg => ../../pkg
@@ -50,5 +50,5 @@ require (
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.33.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
) )

View File

@@ -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= 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 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= 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-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
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/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= 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/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=