Fixed mntx discovery
All checks were successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/gateway_mntx Pipeline was successful
ci/woodpecker/push/gateway_tgsettle Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/gateway_chain Pipeline was successful
ci/woodpecker/push/gateway_tron Pipeline was successful
ci/woodpecker/push/billing_documents Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/callbacks Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/discovery Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/payments_methods Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/payments_quotation Pipeline was successful

Fixed mntx discovery
This commit was merged in pull request #610.
This commit is contained in:
2026-03-03 12:16:46 +00:00
25 changed files with 273 additions and 201 deletions

View File

@@ -391,7 +391,7 @@ func (s *Service) startDiscoveryAnnouncer() {
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "BILLING_DOCUMENTS", Service: mservice.BillingDocuments,
Operations: []string{discovery.OperationDocumentsBatchResolve, discovery.OperationDocumentsGet}, Operations: []string{discovery.OperationDocumentsBatchResolve, discovery.OperationDocumentsGet},
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,
Version: appversion.Create().Short(), Version: appversion.Create().Short(),

View File

@@ -564,7 +564,7 @@ func (s *Service) startDiscoveryAnnouncer() {
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "BILLING_FEES", Service: mservice.BillingFees,
Operations: []string{discovery.OperationFeeCalc}, Operations: []string{discovery.OperationFeeCalc},
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,
Version: appversion.Create().Short(), Version: appversion.Create().Short(),

View File

@@ -49,7 +49,7 @@ func (i *Imp) startDiscovery(cfg *config) error {
i.registrySvc = svc i.registrySvc = svc
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "DISCOVERY", Service: mservice.Discovery,
InstanceID: discovery.InstanceID(), InstanceID: discovery.InstanceID(),
Operations: []string{discovery.OperationDiscoveryLookup}, Operations: []string{discovery.OperationDiscoveryLookup},
Version: appversion.Create().Short(), Version: appversion.Create().Short(),

View File

@@ -17,6 +17,7 @@ import (
msg "github.com/tech/sendico/pkg/messaging" msg "github.com/tech/sendico/pkg/messaging"
msgproducer "github.com/tech/sendico/pkg/messaging/producer" msgproducer "github.com/tech/sendico/pkg/messaging/producer"
"github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/mservice"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -85,7 +86,7 @@ func (a *App) Run(ctx context.Context) error {
} else { } else {
producer := msgproducer.NewProducer(a.logger.Named("discovery_producer"), broker) producer := msgproducer.NewProducer(a.logger.Named("discovery_producer"), broker)
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "FX_INGESTOR", Service: mservice.FXIngestor,
Operations: []string{discovery.OperationFXIngest}, Operations: []string{discovery.OperationFXIngest},
Version: appversion.Create().Short(), Version: appversion.Create().Short(),
} }

View File

@@ -105,7 +105,7 @@ func (s *Service) startDiscoveryAnnouncer() {
return return
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "FX_ORACLE", Service: mservice.FXOracle,
Operations: []string{discovery.OperationFXQuote}, Operations: []string{discovery.OperationFXQuote},
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,
Version: appversion.Create().Short(), Version: appversion.Create().Short(),

View File

@@ -224,7 +224,7 @@ func (s *Service) startDiscoveryAnnouncers() {
announce := discovery.Announcement{ announce := discovery.Announcement{
ID: discovery.StableCryptoRailGatewayID(string(network.Name)), ID: discovery.StableCryptoRailGatewayID(string(network.Name)),
InstanceID: discovery.InstanceID(), InstanceID: discovery.InstanceID(),
Service: "CRYPTO_RAIL_GATEWAY", Service: mservice.ChainWallets,
Rail: discovery.RailCrypto, Rail: discovery.RailCrypto,
Operations: discovery.CryptoRailGatewayOperations(), Operations: discovery.CryptoRailGatewayOperations(),
Currencies: currencies, Currencies: currencies,

View File

@@ -151,7 +151,7 @@ func (s *Service) startDiscoveryAnnouncer() {
return return
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "CARD", Service: mservice.MntxGateway,
Rail: discovery.RailCardPayout, Rail: discovery.RailCardPayout,
Operations: discovery.CardPayoutRailGatewayOperations(), Operations: discovery.CardPayoutRailGatewayOperations(),
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,

View File

@@ -534,7 +534,7 @@ func (s *Service) startAnnouncer() {
announce := discovery.Announcement{ announce := discovery.Announcement{
ID: discovery.StablePaymentGatewayID(rail), ID: discovery.StablePaymentGatewayID(rail),
InstanceID: discovery.InstanceID(), InstanceID: discovery.InstanceID(),
Service: string(mservice.PaymentGateway), Service: mservice.TgSettle,
Rail: rail, Rail: rail,
Operations: caps, Operations: caps,
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,

View File

@@ -229,7 +229,7 @@ func (s *Service) startDiscoveryAnnouncers() {
announce := discovery.Announcement{ announce := discovery.Announcement{
ID: discovery.StableCryptoRailGatewayID(network.Name.String()), ID: discovery.StableCryptoRailGatewayID(network.Name.String()),
InstanceID: discovery.InstanceID(), InstanceID: discovery.InstanceID(),
Service: "CRYPTO_RAIL_GATEWAY", Service: mservice.TronGateway,
Rail: discovery.RailCrypto, Rail: discovery.RailCrypto,
Operations: discovery.CryptoRailGatewayOperations(), Operations: discovery.CryptoRailGatewayOperations(),
Currencies: currencies, Currencies: currencies,

View File

@@ -409,7 +409,7 @@ func (s *Service) startDiscoveryAnnouncer() {
return return
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "LEDGER", Service: mservice.Ledger,
Rail: discovery.RailLedger, Rail: discovery.RailLedger,
Operations: discovery.LedgerServiceOperations(), Operations: discovery.LedgerServiceOperations(),
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,

View File

@@ -119,7 +119,7 @@ func CreateAPI(a api.API) (*NotificationAPI, error) {
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "NOTIFICATIONS", Service: mservice.Notifications,
Operations: []string{discovery.OperationNotifySend}, Operations: []string{discovery.OperationNotifySend},
Version: appversion.Create().Short(), Version: appversion.Create().Short(),
} }

View File

@@ -6,6 +6,7 @@ import (
"github.com/tech/sendico/payments/methods/internal/appversion" "github.com/tech/sendico/payments/methods/internal/appversion"
"github.com/tech/sendico/pkg/discovery" "github.com/tech/sendico/pkg/discovery"
msg "github.com/tech/sendico/pkg/messaging" msg "github.com/tech/sendico/pkg/messaging"
"github.com/tech/sendico/pkg/mservice"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -51,7 +52,7 @@ func (i *Imp) startDiscoveryAnnouncer(cfg *config, producer msg.Producer) {
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "PAYMENTS_METHODS", Service: mservice.PaymentMethods,
Operations: []string{ Operations: []string{
discovery.OperationPaymentMethodsManage, discovery.OperationPaymentMethodsManage,
discovery.OperationPaymentMethodsRead, discovery.OperationPaymentMethodsRead,

View File

@@ -1,14 +1,12 @@
package serverimp package serverimp
import ( import (
mntxclient "github.com/tech/sendico/gateway/mntx/client"
ledgerclient "github.com/tech/sendico/ledger/client" ledgerclient "github.com/tech/sendico/ledger/client"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrator" "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrator"
) )
type orchestratorDeps struct { type orchestratorDeps struct {
ledgerClient ledgerclient.Client ledgerClient ledgerclient.Client
mntxClient mntxclient.Client
gatewayInvokeResolver orchestrator.GatewayInvokeResolver gatewayInvokeResolver orchestrator.GatewayInvokeResolver
} }
@@ -23,7 +21,6 @@ func (i *Imp) initDependencies(_ *config) *orchestratorDeps {
i.discoveryClients = newDiscoveryClientResolver(i.logger, i.discoveryReg) i.discoveryClients = newDiscoveryClientResolver(i.logger, i.discoveryReg)
deps.ledgerClient = &discoveryLedgerClient{resolver: i.discoveryClients} deps.ledgerClient = &discoveryLedgerClient{resolver: i.discoveryClients}
deps.mntxClient = &discoveryMntxClient{resolver: i.discoveryClients}
deps.gatewayInvokeResolver = discoveryGatewayInvokeResolver{resolver: i.discoveryClients} deps.gatewayInvokeResolver = discoveryGatewayInvokeResolver{resolver: i.discoveryClients}
return deps return deps
} }
@@ -36,9 +33,6 @@ func (i *Imp) buildServiceOptions(cfg *config, deps *orchestratorDeps) []orchest
if deps.ledgerClient != nil { if deps.ledgerClient != nil {
opts = append(opts, orchestrator.WithLedgerClient(deps.ledgerClient)) opts = append(opts, orchestrator.WithLedgerClient(deps.ledgerClient))
} }
if deps.mntxClient != nil {
opts = append(opts, orchestrator.WithMntxGateway(deps.mntxClient))
}
if deps.gatewayInvokeResolver != nil { if deps.gatewayInvokeResolver != nil {
opts = append(opts, orchestrator.WithGatewayInvokeResolver(deps.gatewayInvokeResolver)) opts = append(opts, orchestrator.WithGatewayInvokeResolver(deps.gatewayInvokeResolver))

View File

@@ -32,7 +32,7 @@ func (i *Imp) initDiscovery(cfg *config) {
i.logger.Info("Discovery registry watcher started") i.logger.Info("Discovery registry watcher started")
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "PAYMENTS_ORCHESTRATOR", Service: mservice.PaymentOrchestrator,
Operations: []string{discovery.OperationPaymentInitiate}, Operations: []string{discovery.OperationPaymentInitiate},
InvokeURI: cfg.GRPC.DiscoveryInvokeURI(), InvokeURI: cfg.GRPC.DiscoveryInvokeURI(),
Version: appversion.Create().Short(), Version: appversion.Create().Short(),

View File

@@ -12,7 +12,6 @@ import (
oracleclient "github.com/tech/sendico/fx/oracle/client" oracleclient "github.com/tech/sendico/fx/oracle/client"
chainclient "github.com/tech/sendico/gateway/chain/client" chainclient "github.com/tech/sendico/gateway/chain/client"
mntxclient "github.com/tech/sendico/gateway/mntx/client"
ledgerclient "github.com/tech/sendico/ledger/client" ledgerclient "github.com/tech/sendico/ledger/client"
"github.com/tech/sendico/pkg/discovery" "github.com/tech/sendico/pkg/discovery"
"github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/merrors"
@@ -28,15 +27,9 @@ import (
const discoveryLogThrottle = 30 * time.Second const discoveryLogThrottle = 30 * time.Second
var ( var (
feesServiceNames = []string{"BILLING_FEES", string(mservice.FeePlans)}
ledgerServiceNames = []string{"LEDGER", string(mservice.Ledger)}
oracleServiceNames = []string{"FX_ORACLE", string(mservice.FXOracle)}
mntxServiceNames = []string{"CARD_RAIL_GATEWAY", string(mservice.MntxGateway)}
feesRequiredOps = []string{discovery.OperationFeeCalc} feesRequiredOps = []string{discovery.OperationFeeCalc}
ledgerRequiredOps = discovery.LedgerServiceOperations() ledgerRequiredOps = discovery.LedgerServiceOperations()
oracleRequiredOps = []string{discovery.OperationFXQuote} oracleRequiredOps = []string{discovery.OperationFXQuote}
mntxRequiredOps = discovery.CardPayoutRailGatewayOperations()
) )
type discoveryEndpoint struct { type discoveryEndpoint struct {
@@ -64,9 +57,6 @@ type discoveryClientResolver struct {
oracleClient oracleclient.Client oracleClient oracleclient.Client
oracleEndpoint discoveryEndpoint oracleEndpoint discoveryEndpoint
mntxClient mntxclient.Client
mntxEndpoint discoveryEndpoint
chainClients map[string]chainclient.Client chainClients map[string]chainclient.Client
lastSelection map[string]string lastSelection map[string]string
@@ -101,10 +91,6 @@ func (r *discoveryClientResolver) Close() {
_ = r.oracleClient.Close() _ = r.oracleClient.Close()
r.oracleClient = nil r.oracleClient = nil
} }
if r.mntxClient != nil {
_ = r.mntxClient.Close()
r.mntxClient = nil
}
for key, client := range r.chainClients { for key, client := range r.chainClients {
if client != nil { if client != nil {
_ = client.Close() _ = client.Close()
@@ -114,27 +100,22 @@ func (r *discoveryClientResolver) Close() {
} }
func (r *discoveryClientResolver) FeesAvailable() bool { func (r *discoveryClientResolver) FeesAvailable() bool {
_, ok := r.findEntry("fees", feesServiceNames, "", "", feesRequiredOps) _, ok := r.findEntry(mservice.BillingFees, "", "", feesRequiredOps)
return ok return ok
} }
func (r *discoveryClientResolver) LedgerAvailable() bool { func (r *discoveryClientResolver) LedgerAvailable() bool {
_, ok := r.findEntry("ledger", ledgerServiceNames, "", "", ledgerRequiredOps) _, ok := r.findEntry(mservice.Ledger, "", "", ledgerRequiredOps)
return ok return ok
} }
func (r *discoveryClientResolver) OracleAvailable() bool { func (r *discoveryClientResolver) OracleAvailable() bool {
_, ok := r.findEntry("oracle", oracleServiceNames, "", "", oracleRequiredOps) _, ok := r.findEntry(mservice.FXOracle, "", "", oracleRequiredOps)
return ok
}
func (r *discoveryClientResolver) MntxAvailable() bool {
_, ok := r.findEntry("mntx", mntxServiceNames, "", "", mntxRequiredOps)
return ok return ok
} }
func (r *discoveryClientResolver) FeesClient(ctx context.Context) (feesv1.FeeEngineClient, error) { func (r *discoveryClientResolver) FeesClient(ctx context.Context) (feesv1.FeeEngineClient, error) {
entry, ok := r.findEntry("fees", feesServiceNames, "", "", feesRequiredOps) entry, ok := r.findEntry(mservice.BillingFees, "", "", feesRequiredOps)
if !ok { if !ok {
return nil, merrors.NoData("discovery: fees service unavailable") return nil, merrors.NoData("discovery: fees service unavailable")
} }
@@ -154,7 +135,7 @@ func (r *discoveryClientResolver) FeesClient(ctx context.Context) (feesv1.FeeEng
} }
conn, dialErr := dialGrpc(ctx, endpoint) conn, dialErr := dialGrpc(ctx, endpoint)
if dialErr != nil { if dialErr != nil {
r.logMissing("fees", "failed to dial fees service", endpoint.raw, dialErr) r.logMissing("fees", "Failed to dial fees service", endpoint.raw, dialErr)
return nil, dialErr return nil, dialErr
} }
r.feesConn = conn r.feesConn = conn
@@ -165,13 +146,13 @@ func (r *discoveryClientResolver) FeesClient(ctx context.Context) (feesv1.FeeEng
} }
func (r *discoveryClientResolver) LedgerClient(ctx context.Context) (ledgerclient.Client, error) { func (r *discoveryClientResolver) LedgerClient(ctx context.Context) (ledgerclient.Client, error) {
entry, ok := r.findEntry("ledger", ledgerServiceNames, "", "", ledgerRequiredOps) entry, ok := r.findEntry(mservice.Ledger, "", "", ledgerRequiredOps)
if !ok { if !ok {
return nil, merrors.NoData("discovery: ledger service unavailable") return nil, merrors.NoData("discovery: ledger service unavailable")
} }
endpoint, err := parseDiscoveryEndpoint(entry.InvokeURI) endpoint, err := parseDiscoveryEndpoint(entry.InvokeURI)
if err != nil { if err != nil {
r.logMissing("ledger", "invalid ledger invoke uri", entry.InvokeURI, err) r.logMissing("ledger", "Invalid ledger invoke uri", entry.InvokeURI, err)
return nil, err return nil, err
} }
@@ -188,7 +169,7 @@ func (r *discoveryClientResolver) LedgerClient(ctx context.Context) (ledgerclien
Insecure: endpoint.insecure, Insecure: endpoint.insecure,
}) })
if dialErr != nil { if dialErr != nil {
r.logMissing("ledger", "failed to dial ledger service", endpoint.raw, dialErr) r.logMissing("ledger", "Failed to dial ledger service", endpoint.raw, dialErr)
return nil, dialErr return nil, dialErr
} }
r.ledgerClient = client r.ledgerClient = client
@@ -199,13 +180,13 @@ func (r *discoveryClientResolver) LedgerClient(ctx context.Context) (ledgerclien
} }
func (r *discoveryClientResolver) OracleClient(ctx context.Context) (oracleclient.Client, error) { func (r *discoveryClientResolver) OracleClient(ctx context.Context) (oracleclient.Client, error) {
entry, ok := r.findEntry("oracle", oracleServiceNames, "", "", oracleRequiredOps) entry, ok := r.findEntry(mservice.FXOracle, "", "", oracleRequiredOps)
if !ok { if !ok {
return nil, merrors.NoData("discovery: oracle service unavailable") return nil, merrors.NoData("discovery: oracle service unavailable")
} }
endpoint, err := parseDiscoveryEndpoint(entry.InvokeURI) endpoint, err := parseDiscoveryEndpoint(entry.InvokeURI)
if err != nil { if err != nil {
r.logMissing("oracle", "invalid oracle invoke uri", entry.InvokeURI, err) r.logMissing("oracle", "Invalid oracle invoke uri", entry.InvokeURI, err)
return nil, err return nil, err
} }
@@ -222,7 +203,7 @@ func (r *discoveryClientResolver) OracleClient(ctx context.Context) (oracleclien
Insecure: endpoint.insecure, Insecure: endpoint.insecure,
}) })
if dialErr != nil { if dialErr != nil {
r.logMissing("oracle", "failed to dial oracle service", endpoint.raw, dialErr) r.logMissing("oracle", "Failed to dial oracle service", endpoint.raw, dialErr)
return nil, dialErr return nil, dialErr
} }
r.oracleClient = client r.oracleClient = client
@@ -232,47 +213,10 @@ func (r *discoveryClientResolver) OracleClient(ctx context.Context) (oracleclien
return r.oracleClient, nil return r.oracleClient, nil
} }
func (r *discoveryClientResolver) MntxClient(ctx context.Context) (mntxclient.Client, error) {
entry, ok := r.findEntry("mntx", mntxServiceNames, "", "", mntxRequiredOps)
if !ok {
return nil, merrors.NoData("discovery: mntx service unavailable")
}
endpoint, err := parseDiscoveryEndpoint(entry.InvokeURI)
if err != nil {
r.logMissing("mntx", "invalid mntx invoke uri", entry.InvokeURI, err)
return nil, err
}
r.mu.Lock()
defer r.mu.Unlock()
if r.mntxClient == nil || r.mntxEndpoint.key() != endpoint.key() || r.mntxEndpoint.address != endpoint.address {
if r.mntxClient != nil {
_ = r.mntxClient.Close()
r.mntxClient = nil
}
if !endpoint.insecure && r.logger != nil {
r.logger.Warn("Mntx gateway does not support TLS, falling back to insecure transport",
zap.String("invoke_uri", endpoint.raw))
}
client, dialErr := mntxclient.New(ctx, mntxclient.Config{
Address: endpoint.address,
})
if dialErr != nil {
r.logMissing("mntx", "failed to dial mntx service", endpoint.raw, dialErr)
return nil, dialErr
}
r.mntxClient = client
r.mntxEndpoint = endpoint
}
return r.mntxClient, nil
}
func (r *discoveryClientResolver) ChainClient(ctx context.Context, invokeURI string) (chainclient.Client, error) { func (r *discoveryClientResolver) ChainClient(ctx context.Context, invokeURI string) (chainclient.Client, error) {
endpoint, err := parseDiscoveryEndpoint(invokeURI) endpoint, err := parseDiscoveryEndpoint(invokeURI)
if err != nil { if err != nil {
r.logMissing("chain", "invalid chain gateway invoke uri", invokeURI, err) r.logMissing("chain", "Invalid chain gateway invoke uri", invokeURI, err)
return nil, err return nil, err
} }
@@ -288,7 +232,7 @@ func (r *discoveryClientResolver) ChainClient(ctx context.Context, invokeURI str
Insecure: endpoint.insecure, Insecure: endpoint.insecure,
}) })
if dialErr != nil { if dialErr != nil {
r.logMissing("chain", "failed to dial chain gateway", endpoint.raw, dialErr) r.logMissing("chain", "Failed to dial chain gateway", endpoint.raw, dialErr)
return nil, dialErr return nil, dialErr
} }
r.chainClients[endpoint.key()] = client r.chainClients[endpoint.key()] = client
@@ -298,7 +242,7 @@ func (r *discoveryClientResolver) ChainClient(ctx context.Context, invokeURI str
func (r *discoveryClientResolver) PaymentGatewayClient(ctx context.Context, invokeURI string) (chainclient.Client, error) { func (r *discoveryClientResolver) PaymentGatewayClient(ctx context.Context, invokeURI string) (chainclient.Client, error) {
endpoint, err := parseDiscoveryEndpoint(invokeURI) endpoint, err := parseDiscoveryEndpoint(invokeURI)
if err != nil { if err != nil {
r.logMissing("payment_gateway", "invalid payment gateway invoke uri", invokeURI, err) r.logMissing("payment_gateway", "Invalid payment gateway invoke uri", invokeURI, err)
return nil, err return nil, err
} }
@@ -314,16 +258,18 @@ func (r *discoveryClientResolver) PaymentGatewayClient(ctx context.Context, invo
Insecure: endpoint.insecure, Insecure: endpoint.insecure,
}) })
if dialErr != nil { if dialErr != nil {
r.logMissing("payment_gateway", "failed to dial payment gateway", endpoint.raw, dialErr) r.logMissing("payment_gateway", "Failed to dial payment gateway", endpoint.raw, dialErr)
return nil, dialErr return nil, dialErr
} }
r.chainClients[endpoint.key()] = client r.chainClients[endpoint.key()] = client
return client, nil return client, nil
} }
func (r *discoveryClientResolver) findEntry(key string, services []string, rail string, network string, requiredOps []string) (*discovery.RegistryEntry, bool) { func (r *discoveryClientResolver) findEntry(service mservice.Type, rail string, network string, requiredOps []string) (*discovery.RegistryEntry, bool) {
key := discoverySelectionKey(service, rail, network)
if r == nil || r.registry == nil { if r == nil || r.registry == nil {
r.logMissing(key, "discovery registry unavailable", "", nil) r.logMissing(key, "Discovery registry unavailable", "", nil)
return nil, false return nil, false
} }
@@ -335,7 +281,7 @@ func (r *discoveryClientResolver) findEntry(key string, services []string, rail
entries := r.registry.List(time.Now(), true) entries := r.registry.List(time.Now(), true)
matches := make([]discoveryMatch, 0) matches := make([]discoveryMatch, 0)
for _, entry := range entries { for _, entry := range entries {
if !matchesService(entry.Service, services) { if service != "" && !matchesService(entry.Service, service) {
continue continue
} }
if rail != "" && !strings.EqualFold(strings.TrimSpace(entry.Rail), rail) { if rail != "" && !strings.EqualFold(strings.TrimSpace(entry.Rail), rail) {
@@ -351,7 +297,7 @@ func (r *discoveryClientResolver) findEntry(key string, services []string, rail
} }
if len(matches) == 0 { if len(matches) == 0 {
r.logMissing(key, "discovery entry missing", "", nil) r.logMissing(key, "Discovery entry missing", "", nil)
return nil, false return nil, false
} }
@@ -374,6 +320,27 @@ func (r *discoveryClientResolver) findEntry(key string, services []string, rail
return &entry, true return &entry, true
} }
func discoverySelectionKey(service mservice.Type, rail, network string) string {
serviceName := strings.TrimSpace(string(service))
railName := strings.ToUpper(strings.TrimSpace(rail))
networkName := strings.ToUpper(strings.TrimSpace(network))
switch {
case serviceName != "" && railName != "" && networkName != "":
return fmt.Sprintf("%s|%s|%s", serviceName, railName, networkName)
case serviceName != "" && railName != "":
return fmt.Sprintf("%s|%s", serviceName, railName)
case serviceName != "":
return serviceName
case railName != "" && networkName != "":
return fmt.Sprintf("rail:%s|%s", railName, networkName)
case railName != "":
return "rail:" + railName
default:
return "discovery"
}
}
func (r *discoveryClientResolver) logSelection(key, entryKey string, entry discovery.RegistryEntry) { func (r *discoveryClientResolver) logSelection(key, entryKey string, entry discovery.RegistryEntry) {
r.mu.Lock() r.mu.Lock()
last := r.lastSelection[key] last := r.lastSelection[key]
@@ -423,17 +390,12 @@ func discoveryEntryKey(entry discovery.RegistryEntry) string {
strings.TrimSpace(entry.InvokeURI)) strings.TrimSpace(entry.InvokeURI))
} }
func matchesService(service string, candidates []string) bool { func matchesService(service string, candidate mservice.Type) bool {
service = strings.TrimSpace(service) service = strings.TrimSpace(service)
if service == "" || len(candidates) == 0 { if service == "" || strings.TrimSpace(string(candidate)) == "" {
return false return false
} }
for _, candidate := range candidates { return strings.EqualFold(service, strings.TrimSpace(string(candidate)))
if strings.EqualFold(service, strings.TrimSpace(candidate)) {
return true
}
}
return false
} }
func parseDiscoveryEndpoint(raw string) (discoveryEndpoint, error) { func parseDiscoveryEndpoint(raw string) (discoveryEndpoint, error) {

View File

@@ -11,7 +11,6 @@ import (
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" connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1"
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1" chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1" ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
@@ -247,60 +246,6 @@ func (c *discoveryOracleClient) Close() error {
return client.Close() return client.Close()
} }
type discoveryMntxClient struct {
resolver *discoveryClientResolver
}
func (c *discoveryMntxClient) Available() bool {
if c == nil || c.resolver == nil {
return false
}
return c.resolver.MntxAvailable()
}
func (c *discoveryMntxClient) CreateCardPayout(ctx context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) {
client, err := c.resolver.MntxClient(ctx)
if err != nil {
return nil, err
}
return client.CreateCardPayout(ctx, req)
}
func (c *discoveryMntxClient) CreateCardTokenPayout(ctx context.Context, req *mntxv1.CardTokenPayoutRequest) (*mntxv1.CardTokenPayoutResponse, error) {
client, err := c.resolver.MntxClient(ctx)
if err != nil {
return nil, err
}
return client.CreateCardTokenPayout(ctx, req)
}
func (c *discoveryMntxClient) GetCardPayoutStatus(ctx context.Context, req *mntxv1.GetCardPayoutStatusRequest) (*mntxv1.GetCardPayoutStatusResponse, error) {
client, err := c.resolver.MntxClient(ctx)
if err != nil {
return nil, err
}
return client.GetCardPayoutStatus(ctx, req)
}
func (c *discoveryMntxClient) ListGatewayInstances(ctx context.Context, req *mntxv1.ListGatewayInstancesRequest) (*mntxv1.ListGatewayInstancesResponse, error) {
client, err := c.resolver.MntxClient(ctx)
if err != nil {
return nil, err
}
return client.ListGatewayInstances(ctx, req)
}
func (c *discoveryMntxClient) Close() error {
if c == nil || c.resolver == nil {
return nil
}
client, err := c.resolver.MntxClient(context.Background())
if err != nil {
return nil
}
return client.Close()
}
type discoveryChainClient struct { type discoveryChainClient struct {
resolver *discoveryClientResolver resolver *discoveryClientResolver
invokeURI string invokeURI string

View File

@@ -3,8 +3,11 @@ package orchestrator
import ( import (
"context" "context"
"github.com/tech/sendico/pkg/discovery" "github.com/tech/sendico/pkg/discovery"
"net"
"net/url"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
mntxclient "github.com/tech/sendico/gateway/mntx/client" mntxclient "github.com/tech/sendico/gateway/mntx/client"
@@ -20,7 +23,12 @@ import (
) )
type gatewayCardPayoutExecutor struct { type gatewayCardPayoutExecutor struct {
mntxClient mntxclient.Client gatewayRegistry GatewayRegistry
mu sync.Mutex
clients map[string]mntxclient.Client
dialClient func(ctx context.Context, address string) (mntxclient.Client, error)
} }
type cardPayoutCustomer struct { type cardPayoutCustomer struct {
@@ -40,12 +48,20 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
if req.Payment == nil { if req.Payment == nil {
return nil, merrors.InvalidArgument("card payout send: payment is required") return nil, merrors.InvalidArgument("card payout send: payment is required")
} }
if e == nil || e.mntxClient == nil { if e == nil || e.gatewayRegistry == nil {
return nil, merrors.InvalidArgument("card payout send: mntx client is required") return nil, merrors.InvalidArgument("card payout send: gateway registry is required")
} }
if model.ParseRailOperation(string(req.Step.Action)) != discovery.RailOperationSend { if model.ParseRailOperation(string(req.Step.Action)) != discovery.RailOperationSend {
return nil, merrors.InvalidArgument("card payout send: unsupported action") return nil, merrors.InvalidArgument("card payout send: unsupported action")
} }
gateway, err := e.resolveGateway(ctx, req.Step)
if err != nil {
return nil, err
}
client, err := e.client(ctx, strings.TrimSpace(gateway.InvokeURI))
if err != nil {
return nil, err
}
card, err := payoutDestinationCard(req.Payment, req.Step.Metadata) card, err := payoutDestinationCard(req.Payment, req.Step.Metadata)
if err != nil { if err != nil {
@@ -68,7 +84,7 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
var responsePayout *mntxv1.CardPayoutState var responsePayout *mntxv1.CardPayoutState
if token := strings.TrimSpace(card.Token); token != "" { if token := strings.TrimSpace(card.Token); token != "" {
resp, createErr := e.mntxClient.CreateCardTokenPayout(ctx, &mntxv1.CardTokenPayoutRequest{ resp, createErr := client.CreateCardTokenPayout(ctx, &mntxv1.CardTokenPayoutRequest{
PayoutId: payoutRef, PayoutId: payoutRef,
ProjectId: projectID, ProjectId: projectID,
CustomerId: customer.id, CustomerId: customer.id,
@@ -106,7 +122,7 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
if card.ExpMonth == 0 || card.ExpYear == 0 { if card.ExpMonth == 0 || card.ExpYear == 0 {
return nil, merrors.InvalidArgument("card payout send: card expiry is required") return nil, merrors.InvalidArgument("card payout send: card expiry is required")
} }
resp, createErr := e.mntxClient.CreateCardPayout(ctx, &mntxv1.CardPayoutRequest{ resp, createErr := client.CreateCardPayout(ctx, &mntxv1.CardPayoutRequest{
PayoutId: payoutRef, PayoutId: payoutRef,
ProjectId: projectID, ProjectId: projectID,
CustomerId: customer.id, CustomerId: customer.id,
@@ -141,7 +157,12 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
resolvedPayoutRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetPayoutId()), payoutRef) resolvedPayoutRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetPayoutId()), payoutRef)
resolvedOperationRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetOperationRef()), operationRef) resolvedOperationRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetOperationRef()), operationRef)
gatewayInstanceID := firstNonEmpty(strings.TrimSpace(req.Step.InstanceID), strings.TrimSpace(req.Step.Gateway)) gatewayInstanceID := firstNonEmpty(
strings.TrimSpace(req.Step.InstanceID),
strings.TrimSpace(gateway.InstanceID),
strings.TrimSpace(req.Step.Gateway),
strings.TrimSpace(gateway.ID),
)
externalRefs, refsErr := cardPayoutExternalRefs(resolvedPayoutRef, resolvedOperationRef, gatewayInstanceID) externalRefs, refsErr := cardPayoutExternalRefs(resolvedPayoutRef, resolvedOperationRef, gatewayInstanceID)
if refsErr != nil { if refsErr != nil {
return nil, refsErr return nil, refsErr
@@ -155,6 +176,122 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
return &sexec.ExecuteOutput{StepExecution: step}, nil return &sexec.ExecuteOutput{StepExecution: step}, nil
} }
func (e *gatewayCardPayoutExecutor) resolveGateway(ctx context.Context, step xplan.Step) (*model.GatewayInstanceDescriptor, error) {
if e.gatewayRegistry == nil {
return nil, merrors.InvalidArgument("card payout send: gateway registry is required")
}
items, err := e.gatewayRegistry.List(ctx)
if err != nil {
return nil, err
}
stepGateway := strings.TrimSpace(step.Gateway)
stepInstance := strings.TrimSpace(step.InstanceID)
var byInstance *model.GatewayInstanceDescriptor
var byGateway *model.GatewayInstanceDescriptor
var single *model.GatewayInstanceDescriptor
cardCount := 0
for i := range items {
item := items[i]
if item == nil || model.ParseRail(string(item.Rail)) != discovery.RailCardPayout || !item.IsEnabled {
continue
}
cardCount++
single = item
if stepInstance != "" && (strings.EqualFold(strings.TrimSpace(item.InstanceID), stepInstance) || strings.EqualFold(strings.TrimSpace(item.ID), stepInstance)) {
byInstance = item
break
}
if stepGateway != "" && (strings.EqualFold(strings.TrimSpace(item.ID), stepGateway) || strings.EqualFold(strings.TrimSpace(item.InstanceID), stepGateway)) {
byGateway = item
}
}
switch {
case byInstance != nil:
if strings.TrimSpace(byInstance.InvokeURI) == "" {
return nil, merrors.InvalidArgument("card payout send: gateway invoke uri is missing")
}
return byInstance, nil
case byGateway != nil:
if strings.TrimSpace(byGateway.InvokeURI) == "" {
return nil, merrors.InvalidArgument("card payout send: gateway invoke uri is missing")
}
return byGateway, nil
case stepGateway == "" && stepInstance == "" && cardCount == 1:
if strings.TrimSpace(single.InvokeURI) == "" {
return nil, merrors.InvalidArgument("card payout send: gateway invoke uri is missing")
}
return single, nil
default:
return nil, merrors.InvalidArgument("card payout send: gateway instance not found")
}
}
func (e *gatewayCardPayoutExecutor) client(ctx context.Context, invokeURI string) (mntxclient.Client, error) {
address, err := parseGatewayAddress(invokeURI)
if err != nil {
return nil, err
}
e.mu.Lock()
defer e.mu.Unlock()
if e.clients == nil {
e.clients = map[string]mntxclient.Client{}
}
if c := e.clients[address]; c != nil {
return c, nil
}
dial := e.dialClient
if dial == nil {
dial = func(ctx context.Context, address string) (mntxclient.Client, error) {
return mntxclient.New(ctx, mntxclient.Config{Address: address})
}
}
client, dialErr := dial(ctx, address)
if dialErr != nil {
return nil, dialErr
}
e.clients[address] = client
return client, nil
}
func parseGatewayAddress(raw string) (string, error) {
raw = strings.TrimSpace(raw)
if raw == "" {
return "", merrors.InvalidArgument("card payout send: gateway invoke uri is required")
}
if !strings.Contains(raw, "://") {
if _, _, splitErr := net.SplitHostPort(raw); splitErr != nil {
return "", merrors.InvalidArgument("card payout send: gateway invoke uri must include host:port")
}
return raw, nil
}
parsed, err := url.Parse(raw)
if err != nil || parsed.Scheme == "" {
return "", merrors.InvalidArgument("card payout send: gateway invoke uri must include host:port")
}
switch strings.ToLower(strings.TrimSpace(parsed.Scheme)) {
case "grpc", "grpcs":
address := strings.TrimSpace(parsed.Host)
if _, _, splitErr := net.SplitHostPort(address); splitErr != nil {
return "", merrors.InvalidArgument("card payout send: gateway invoke uri must include host:port")
}
return address, nil
case "dns", "passthrough":
return raw, nil
default:
return "", merrors.InvalidArgument("card payout send: unsupported gateway invoke uri scheme")
}
}
func payoutDestinationCard(payment *agg.Payment, metadata map[string]string) (*model.CardEndpoint, error) { func payoutDestinationCard(payment *agg.Payment, metadata map[string]string) (*model.CardEndpoint, error) {
if card, ok := batchmeta.CardFromMetadata(metadata); ok && card != nil { if card, ok := batchmeta.CardFromMetadata(metadata); ok && card != nil {
return card, nil return card, nil

View File

@@ -23,8 +23,22 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin
orgID := bson.NewObjectID() orgID := bson.NewObjectID()
var payoutReq *mntxv1.CardPayoutRequest var payoutReq *mntxv1.CardPayoutRequest
var dialAddress string
executor := &gatewayCardPayoutExecutor{ executor := &gatewayCardPayoutExecutor{
mntxClient: &mntxclient.Fake{ gatewayRegistry: &fakeGatewayRegistry{
items: []*model.GatewayInstanceDescriptor{
{
ID: paymenttypes.DefaultCardsGatewayID,
InstanceID: paymenttypes.DefaultCardsGatewayID,
Rail: discovery.RailCardPayout,
InvokeURI: "grpc://mntx-gateway:50051",
IsEnabled: true,
},
},
},
dialClient: func(_ context.Context, address string) (mntxclient.Client, error) {
dialAddress = address
return &mntxclient.Fake{
CreateCardPayoutFn: func(_ context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) { CreateCardPayoutFn: func(_ context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) {
payoutReq = req payoutReq = req
return &mntxv1.CardPayoutResponse{ return &mntxv1.CardPayoutResponse{
@@ -33,6 +47,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin
}, },
}, nil }, nil
}, },
}, nil
}, },
} }
@@ -104,6 +119,9 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin
if payoutReq == nil { if payoutReq == nil {
t.Fatal("expected payout request to be submitted") t.Fatal("expected payout request to be submitted")
} }
if got, want := dialAddress, "mntx-gateway:50051"; got != want {
t.Fatalf("dial address mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetPayoutId(), "payment-1"; got != want { if got, want := payoutReq.GetPayoutId(), "payment-1"; got != want {
t.Fatalf("payout_id mismatch: got=%q want=%q", got, want) t.Fatalf("payout_id mismatch: got=%q want=%q", got, want)
} }
@@ -146,8 +164,22 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t
orgID := bson.NewObjectID() orgID := bson.NewObjectID()
var payoutReq *mntxv1.CardPayoutRequest var payoutReq *mntxv1.CardPayoutRequest
var dialAddress string
executor := &gatewayCardPayoutExecutor{ executor := &gatewayCardPayoutExecutor{
mntxClient: &mntxclient.Fake{ gatewayRegistry: &fakeGatewayRegistry{
items: []*model.GatewayInstanceDescriptor{
{
ID: paymenttypes.DefaultCardsGatewayID,
InstanceID: paymenttypes.DefaultCardsGatewayID,
Rail: discovery.RailCardPayout,
InvokeURI: "grpc://mntx-gateway:50051",
IsEnabled: true,
},
},
},
dialClient: func(_ context.Context, address string) (mntxclient.Client, error) {
dialAddress = address
return &mntxclient.Fake{
CreateCardPayoutFn: func(_ context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) { CreateCardPayoutFn: func(_ context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) {
payoutReq = req payoutReq = req
return &mntxv1.CardPayoutResponse{ return &mntxv1.CardPayoutResponse{
@@ -156,6 +188,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t
}, },
}, nil }, nil
}, },
}, nil
}, },
} }
@@ -221,6 +254,9 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t
if payoutReq == nil { if payoutReq == nil {
t.Fatal("expected payout request to be submitted") t.Fatal("expected payout request to be submitted")
} }
if got, want := dialAddress, "mntx-gateway:50051"; got != want {
t.Fatalf("dial address mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetAmountMinor(), int64(15000); got != want { if got, want := payoutReq.GetAmountMinor(), int64(15000); got != want {
t.Fatalf("amount_minor mismatch: got=%d want=%d", got, want) t.Fatalf("amount_minor mismatch: got=%d want=%d", got, want)
} }
@@ -235,7 +271,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t
} }
} }
func TestGatewayCardPayoutExecutor_ExecuteCardPayout_RequiresMntxClient(t *testing.T) { func TestGatewayCardPayoutExecutor_ExecuteCardPayout_RequiresGatewayRegistry(t *testing.T) {
orgID := bson.NewObjectID() orgID := bson.NewObjectID()
executor := &gatewayCardPayoutExecutor{} executor := &gatewayCardPayoutExecutor{}
@@ -270,7 +306,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_RequiresMntxClient(t *testi
if err == nil { if err == nil {
t.Fatal("expected error") t.Fatal("expected error")
} }
if !strings.Contains(err.Error(), "mntx client is required") { if !strings.Contains(err.Error(), "gateway registry is required") {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
} }

View File

@@ -6,7 +6,6 @@ import (
"time" "time"
chainclient "github.com/tech/sendico/gateway/chain/client" chainclient "github.com/tech/sendico/gateway/chain/client"
mntxclient "github.com/tech/sendico/gateway/mntx/client"
ledgerclient "github.com/tech/sendico/ledger/client" ledgerclient "github.com/tech/sendico/ledger/client"
"github.com/tech/sendico/payments/storage/model" "github.com/tech/sendico/payments/storage/model"
clockpkg "github.com/tech/sendico/pkg/clock" clockpkg "github.com/tech/sendico/pkg/clock"
@@ -54,16 +53,6 @@ func WithLedgerClient(client ledgerclient.Client) Option {
} }
} }
// WithMntxGateway configures card payout execution for card-bound steps.
func WithMntxGateway(client mntxclient.Client) Option {
return func(s *Service) {
if s == nil {
return
}
s.mntxClient = client
}
}
// WithPaymentGatewayBroker wires broker subscription for payment gateway execution events. // WithPaymentGatewayBroker wires broker subscription for payment gateway execution events.
func WithPaymentGatewayBroker(broker mb.Broker) Option { func WithPaymentGatewayBroker(broker mb.Broker) Option {
return func(s *Service) { return func(s *Service) {

View File

@@ -3,7 +3,6 @@ package orchestrator
import ( import (
"context" "context"
mntxclient "github.com/tech/sendico/gateway/mntx/client"
ledgerclient "github.com/tech/sendico/ledger/client" ledgerclient "github.com/tech/sendico/ledger/client"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/prepo" "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/prepo"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/psvc" "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/psvc"
@@ -26,7 +25,6 @@ type Service struct {
producer msg.Producer producer msg.Producer
ledgerClient ledgerclient.Client ledgerClient ledgerclient.Client
mntxClient mntxclient.Client
gatewayInvokeResolver GatewayInvokeResolver gatewayInvokeResolver GatewayInvokeResolver
gatewayRegistry GatewayRegistry gatewayRegistry GatewayRegistry
cardGatewayRoutes map[string]CardGatewayRoute cardGatewayRoutes map[string]CardGatewayRoute
@@ -56,7 +54,6 @@ func NewService(logger mlogger.Logger, repo storage.Repository, producer msg.Pro
var err error var err error
svc.v2, svc.paymentRepo, err = newOrchestrationV2Service(svc.logger, repo, v2RuntimeDeps{ svc.v2, svc.paymentRepo, err = newOrchestrationV2Service(svc.logger, repo, v2RuntimeDeps{
LedgerClient: svc.ledgerClient, LedgerClient: svc.ledgerClient,
MntxClient: svc.mntxClient,
GatewayInvokeResolver: svc.gatewayInvokeResolver, GatewayInvokeResolver: svc.gatewayInvokeResolver,
GatewayRegistry: svc.gatewayRegistry, GatewayRegistry: svc.gatewayRegistry,
CardGatewayRoutes: svc.cardGatewayRoutes, CardGatewayRoutes: svc.cardGatewayRoutes,

View File

@@ -3,7 +3,6 @@ package orchestrator
import ( import (
"context" "context"
mntxclient "github.com/tech/sendico/gateway/mntx/client"
ledgerclient "github.com/tech/sendico/ledger/client" ledgerclient "github.com/tech/sendico/ledger/client"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/oobs" "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/oobs"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/pquery" "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/pquery"
@@ -27,7 +26,6 @@ type v2MongoDBProvider interface {
type v2RuntimeDeps struct { type v2RuntimeDeps struct {
LedgerClient ledgerclient.Client LedgerClient ledgerclient.Client
MntxClient mntxclient.Client
GatewayInvokeResolver GatewayInvokeResolver GatewayInvokeResolver GatewayInvokeResolver
GatewayRegistry GatewayRegistry GatewayRegistry GatewayRegistry
CardGatewayRoutes map[string]CardGatewayRoute CardGatewayRoutes map[string]CardGatewayRoute
@@ -114,9 +112,9 @@ func buildOrchestrationV2Executors(logger mlogger.Logger, runtimeDeps v2RuntimeD
ledgerClient: runtimeDeps.LedgerClient, ledgerClient: runtimeDeps.LedgerClient,
} }
var cardPayoutExecutor sexec.CardPayoutExecutor var cardPayoutExecutor sexec.CardPayoutExecutor
if runtimeDeps.MntxClient != nil { if runtimeDeps.GatewayRegistry != nil {
cardPayoutExecutor = &gatewayCardPayoutExecutor{ cardPayoutExecutor = &gatewayCardPayoutExecutor{
mntxClient: runtimeDeps.MntxClient, gatewayRegistry: runtimeDeps.GatewayRegistry,
} }
} }
return psvc.NewDefaultExecutors(execLogger, sexec.Dependencies{ return psvc.NewDefaultExecutors(execLogger, sexec.Dependencies{

View File

@@ -6,6 +6,7 @@ import (
"github.com/tech/sendico/payments/quotation/internal/appversion" "github.com/tech/sendico/payments/quotation/internal/appversion"
"github.com/tech/sendico/pkg/discovery" "github.com/tech/sendico/pkg/discovery"
msg "github.com/tech/sendico/pkg/messaging" msg "github.com/tech/sendico/pkg/messaging"
"github.com/tech/sendico/pkg/mservice"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -51,7 +52,7 @@ func (i *Imp) startDiscoveryAnnouncer(cfg *config, producer msg.Producer) {
} }
announce := discovery.Announcement{ announce := discovery.Announcement{
Service: "PAYMENTS_QUOTATION", Service: mservice.PaymentQuotation,
Operations: []string{discovery.OperationPaymentQuote, discovery.OperationPaymentMultiQuote}, Operations: []string{discovery.OperationPaymentQuote, discovery.OperationPaymentMultiQuote},
InvokeURI: invokeURI, InvokeURI: invokeURI,
Version: appversion.Create().Short(), Version: appversion.Create().Short(),

View File

@@ -1,5 +1,7 @@
package discovery package discovery
import "github.com/tech/sendico/pkg/mservice"
type HealthParams struct { type HealthParams struct {
IntervalSec int `json:"intervalSec"` IntervalSec int `json:"intervalSec"`
TimeoutSec int `json:"timeoutSec"` TimeoutSec int `json:"timeoutSec"`
@@ -103,7 +105,7 @@ type CurrencyAnnouncement struct {
type Announcement struct { type Announcement struct {
ID string `json:"id"` ID string `json:"id"`
InstanceID string `bson:"instanceId" json:"instanceId"` InstanceID string `bson:"instanceId" json:"instanceId"`
Service string `json:"service"` Service mservice.Type `json:"service"`
Rail string `json:"rail,omitempty"` Rail string `json:"rail,omitempty"`
Operations []string `json:"operations,omitempty"` Operations []string `json:"operations,omitempty"`
Currencies []CurrencyAnnouncement `json:"currencies,omitempty"` Currencies []CurrencyAnnouncement `json:"currencies,omitempty"`

View File

@@ -16,8 +16,10 @@ const (
MntxGateway Type = "mntx_gateway" // Represents Monetix gateway microservice MntxGateway Type = "mntx_gateway" // Represents Monetix gateway microservice
PaymentGateway Type = "payment_gateway" // Represents payment gateway microservice PaymentGateway Type = "payment_gateway" // Represents payment gateway microservice
FXOracle Type = "fx_oracle" // Represents FX oracle microservice FXOracle Type = "fx_oracle" // Represents FX oracle microservice
FXIngestor Type = "fx_ingestor" // Represents FX ingestor microservice
FeePlans Type = "fee_plans" // Represents fee plans microservice FeePlans Type = "fee_plans" // Represents fee plans microservice
BillingDocuments Type = "billing_documents" // Represents billing documents microservice BillingDocuments Type = "billing_documents" // Represents billing documents microservice
BillingFees Type = "billing_fees" // Represents billing fees microservice
FilterProjects Type = "filter_projects" // Represents comments on tasks or other resources FilterProjects Type = "filter_projects" // Represents comments on tasks or other resources
Invitations Type = "invitations" // Represents invitations sent to users Invitations Type = "invitations" // Represents invitations sent to users
Invoices Type = "invoices" // Represents invoices Invoices Type = "invoices" // Represents invoices
@@ -30,6 +32,7 @@ const (
LedgerParties Type = "ledger_parties" // Represents ledger account owner parties microservice LedgerParties Type = "ledger_parties" // Represents ledger account owner parties microservice
LedgerPlines Type = "ledger_posting_lines" // Represents ledger journal posting lines microservice LedgerPlines Type = "ledger_posting_lines" // Represents ledger journal posting lines microservice
PaymentOrchestrator Type = "payment_orchestrator" // Represents payment orchestration microservice PaymentOrchestrator Type = "payment_orchestrator" // Represents payment orchestration microservice
PaymentQuotation Type = "payment_quotation" // Represents payment quotation microservice
ChainAssets Type = "chain_assets" // Represents managed chain assets ChainAssets Type = "chain_assets" // Represents managed chain assets
ChainWallets Type = "chain_wallets" // Represents managed chain wallets ChainWallets Type = "chain_wallets" // Represents managed chain wallets
ChainWalletBalances Type = "chain_wallet_balances" // Represents managed chain wallet balances ChainWalletBalances Type = "chain_wallet_balances" // Represents managed chain wallet balances
@@ -49,6 +52,7 @@ const (
Roles Type = "roles" // Represents roles in access control Roles Type = "roles" // Represents roles in access control
Storage Type = "storage" // Represents statuses of tasks or projects Storage Type = "storage" // Represents statuses of tasks or projects
TgSettle Type = "tgsettle_gateway" // Represents tg settlement gateway TgSettle Type = "tgsettle_gateway" // Represents tg settlement gateway
TronGateway Type = "tron_gateway" // Represents tron gateway microservice
Tenants Type = "tenants" // Represents tenants managed in the system Tenants Type = "tenants" // Represents tenants managed in the system
VerificationTokens Type = "verification_tokens" //Represents verification tokens managed in the system VerificationTokens Type = "verification_tokens" //Represents verification tokens managed in the system
Wallets Type = "wallets" // Represents workflows for tasks or projects Wallets Type = "wallets" // Represents workflows for tasks or projects

5
test.csv Normal file
View File

@@ -0,0 +1,5 @@
pan;first_name;last_name;exp_month;exp_year;amount
2204310159722456;Anastasiia;Limonova;06;2028;100
2204320167919754;Anastasiia;Limonova;10;2027;100
2200242558874568;Anastasiia;Limonova;07;2032;100
2203410113188371;Vladimir;Burmakin;02;2033;100
1 pan first_name last_name exp_month exp_year amount
2 2204310159722456 Anastasiia Limonova 06 2028 100
3 2204320167919754 Anastasiia Limonova 10 2027 100
4 2200242558874568 Anastasiia Limonova 07 2032 100
5 2203410113188371 Vladimir Burmakin 02 2033 100