115 lines
3.1 KiB
Go
115 lines
3.1 KiB
Go
package quotation
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/tech/sendico/payments/storage"
|
|
"github.com/tech/sendico/pkg/api/routers"
|
|
clockpkg "github.com/tech/sendico/pkg/clock"
|
|
msg "github.com/tech/sendico/pkg/messaging"
|
|
mb "github.com/tech/sendico/pkg/messaging/broker"
|
|
"github.com/tech/sendico/pkg/mlogger"
|
|
orchestrationv1 "github.com/tech/sendico/pkg/proto/payments/orchestration/v1"
|
|
quotationv1 "github.com/tech/sendico/pkg/proto/payments/quotation/v1"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
type serviceError string
|
|
|
|
func (e serviceError) Error() string {
|
|
return string(e)
|
|
}
|
|
|
|
const (
|
|
defaultFeeQuoteTTLMillis int64 = 120000
|
|
defaultOracleTTLMillis int64 = 60000
|
|
)
|
|
|
|
var (
|
|
errStorageUnavailable = serviceError("payments.quotation: storage not initialised")
|
|
)
|
|
|
|
// Service handles payment quotation and read models.
|
|
type Service struct {
|
|
logger mlogger.Logger
|
|
storage storage.Repository
|
|
clock clockpkg.Clock
|
|
|
|
deps serviceDependencies
|
|
h handlerSet
|
|
|
|
gatewayBroker mb.Broker
|
|
gatewayConsumers []msg.Consumer
|
|
|
|
orchestrationv1.UnimplementedPaymentExecutionServiceServer
|
|
}
|
|
|
|
type serviceDependencies struct {
|
|
fees feesDependency
|
|
ledger ledgerDependency
|
|
gateway gatewayDependency
|
|
railGateways railGatewayDependency
|
|
providerGateway providerGatewayDependency
|
|
oracle oracleDependency
|
|
gatewayRegistry GatewayRegistry
|
|
gatewayInvokeResolver GatewayInvokeResolver
|
|
cardRoutes map[string]CardGatewayRoute
|
|
feeLedgerAccounts map[string]string
|
|
planBuilder PlanBuilder
|
|
}
|
|
|
|
type handlerSet struct {
|
|
commands *paymentCommandFactory
|
|
}
|
|
|
|
// NewService constructs the quotation service core.
|
|
func NewService(logger mlogger.Logger, repo storage.Repository, opts ...Option) *Service {
|
|
svc := &Service{
|
|
logger: logger.Named("payments.quotation"),
|
|
storage: repo,
|
|
clock: clockpkg.NewSystem(),
|
|
}
|
|
|
|
initMetrics()
|
|
|
|
for _, opt := range opts {
|
|
if opt != nil {
|
|
opt(svc)
|
|
}
|
|
}
|
|
|
|
if svc.clock == nil {
|
|
svc.clock = clockpkg.NewSystem()
|
|
}
|
|
|
|
engine := defaultPaymentEngine{svc: svc}
|
|
svc.h.commands = newPaymentCommandFactory(engine, svc.logger)
|
|
|
|
return svc
|
|
}
|
|
|
|
func (s *Service) ensureHandlers() {
|
|
if s.h.commands == nil {
|
|
s.h.commands = newPaymentCommandFactory(defaultPaymentEngine{svc: s}, s.logger)
|
|
}
|
|
}
|
|
|
|
// Register attaches the service to the supplied gRPC router.
|
|
func (s *Service) Register(router routers.GRPC) error {
|
|
return router.Register(func(reg grpc.ServiceRegistrar) {
|
|
orchestrationv1.RegisterPaymentExecutionServiceServer(reg, s)
|
|
})
|
|
}
|
|
|
|
// QuotePayment aggregates downstream quotes.
|
|
func (s *Service) QuotePayment(ctx context.Context, req *quotationv1.QuotePaymentRequest) (*quotationv1.QuotePaymentResponse, error) {
|
|
s.ensureHandlers()
|
|
return executeUnary(ctx, s, "QuotePayment", s.h.commands.QuotePayment().Execute, req)
|
|
}
|
|
|
|
// QuotePayments aggregates downstream quotes for multiple intents.
|
|
func (s *Service) QuotePayments(ctx context.Context, req *quotationv1.QuotePaymentsRequest) (*quotationv1.QuotePaymentsResponse, error) {
|
|
s.ensureHandlers()
|
|
return executeUnary(ctx, s, "QuotePayments", s.h.commands.QuotePayments().Execute, req)
|
|
}
|