fixed bff compilation #473

Merged
tech merged 1 commits from po-473 into main 2026-02-11 17:53:50 +00:00
7 changed files with 155 additions and 30 deletions
Showing only changes of commit 3c0d709a82 - Show all commits

View File

@@ -11,6 +11,7 @@ import (
paginationv1 "github.com/tech/sendico/pkg/proto/common/pagination/v1" paginationv1 "github.com/tech/sendico/pkg/proto/common/pagination/v1"
oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1" oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestration/v1" orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestration/v1"
quotationv1 "github.com/tech/sendico/pkg/proto/payments/quotation/v1"
sharedv1 "github.com/tech/sendico/pkg/proto/payments/shared/v1" sharedv1 "github.com/tech/sendico/pkg/proto/payments/shared/v1"
) )
@@ -110,7 +111,7 @@ func PaymentQuotesResponse(logger mlogger.Logger, resp *quotationv1.QuotePayment
} }
// Payments wraps a list of payments with refreshed access token. // Payments wraps a list of payments with refreshed access token.
func PaymentsResponse(logger mlogger.Logger, payments []*orchestratorv1.Payment, token *TokenData) http.HandlerFunc { func PaymentsResponse(logger mlogger.Logger, payments []*sharedv1.Payment, token *TokenData) http.HandlerFunc {
return response.Ok(logger, paymentsResponse{ return response.Ok(logger, paymentsResponse{
Payments: toPayments(payments), Payments: toPayments(payments),
authResponse: authResponse{AccessToken: *token}, authResponse: authResponse{AccessToken: *token},
@@ -127,7 +128,7 @@ func PaymentsListResponse(logger mlogger.Logger, resp *orchestratorv1.ListPaymen
} }
// Payment wraps a payment with refreshed access token. // Payment wraps a payment with refreshed access token.
func PaymentResponse(logger mlogger.Logger, payment *orchestratorv1.Payment, token *TokenData) http.HandlerFunc { func PaymentResponse(logger mlogger.Logger, payment *sharedv1.Payment, token *TokenData) http.HandlerFunc {
return response.Ok(logger, paymentResponse{ return response.Ok(logger, paymentResponse{
Payment: toPayment(payment), Payment: toPayment(payment),
authResponse: authResponse{AccessToken: *token}, authResponse: authResponse{AccessToken: *token},
@@ -230,7 +231,7 @@ func toPaymentQuotes(resp *quotationv1.QuotePaymentsResponse) *PaymentQuotes {
} }
} }
func toPayments(items []*orchestratorv1.Payment) []Payment { func toPayments(items []*sharedv1.Payment) []Payment {
if len(items) == 0 { if len(items) == 0 {
return nil return nil
} }
@@ -246,7 +247,7 @@ func toPayments(items []*orchestratorv1.Payment) []Payment {
return result return result
} }
func toPayment(p *orchestratorv1.Payment) *Payment { func toPayment(p *sharedv1.Payment) *Payment {
if p == nil { if p == nil {
return nil return nil
} }

View File

@@ -62,7 +62,7 @@ func (a *PaymentAPI) listPayments(r *http.Request, account *model.Account, token
req.FilterStates = states req.FilterStates = states
} }
resp, err := a.client.ListPayments(ctx, req) resp, err := a.execution.ListPayments(ctx, req)
if err != nil { if err != nil {
a.logger.Warn("Failed to list payments", zap.Error(err), mzap.ObjRef("organization_ref", orgRef)) a.logger.Warn("Failed to list payments", zap.Error(err), mzap.ObjRef("organization_ref", orgRef))
return response.Auto(a.logger, a.Name(), err) return response.Auto(a.logger, a.Name(), err)

View File

@@ -77,7 +77,7 @@ func (a *PaymentAPI) initiatePayment(r *http.Request, account *model.Account, to
Metadata: payload.Metadata, Metadata: payload.Metadata,
} }
resp, err := a.client.InitiatePayment(ctx, req) resp, err := a.execution.InitiatePayment(ctx, req)
if err != nil { if err != nil {
a.logger.Warn("Failed to initiate payment", zap.Error(err), mzap.ObjRef("organization_ref", orgRef)) a.logger.Warn("Failed to initiate payment", zap.Error(err), mzap.ObjRef("organization_ref", orgRef))
return response.Auto(a.logger, a.Name(), err) return response.Auto(a.logger, a.Name(), err)

View File

@@ -49,7 +49,7 @@ func (a *PaymentAPI) initiatePaymentsByQuote(r *http.Request, account *model.Acc
Metadata: payload.Metadata, Metadata: payload.Metadata,
} }
resp, err := a.client.InitiatePayments(ctx, req) resp, err := a.execution.InitiatePayments(ctx, req)
if err != nil { if err != nil {
a.logger.Warn("Failed to initiate batch payments", zap.Error(err), zap.String("organization_ref", orgRef.Hex())) a.logger.Warn("Failed to initiate batch payments", zap.Error(err), zap.String("organization_ref", orgRef.Hex()))
return response.Auto(a.logger, a.Name(), err) return response.Auto(a.logger, a.Name(), err)

View File

@@ -8,6 +8,7 @@ import (
"github.com/tech/sendico/pkg/api/http/response" "github.com/tech/sendico/pkg/api/http/response"
"github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model" "github.com/tech/sendico/pkg/model"
quotationv1 "github.com/tech/sendico/pkg/proto/payments/quotation/v1"
sharedv1 "github.com/tech/sendico/pkg/proto/payments/shared/v1" sharedv1 "github.com/tech/sendico/pkg/proto/payments/shared/v1"
"github.com/tech/sendico/server/interface/api/srequest" "github.com/tech/sendico/server/interface/api/srequest"
"github.com/tech/sendico/server/interface/api/sresponse" "github.com/tech/sendico/server/interface/api/sresponse"
@@ -59,7 +60,7 @@ func (a *PaymentAPI) quotePayment(r *http.Request, account *model.Account, token
Intent: intent, Intent: intent,
} }
resp, err := a.client.QuotePayment(ctx, req) resp, err := a.quotation.QuotePayment(ctx, req)
if err != nil { if err != nil {
a.logger.Warn("Failed to quote payment", zap.Error(err), zap.String("organization_ref", orgRef.Hex())) a.logger.Warn("Failed to quote payment", zap.Error(err), zap.String("organization_ref", orgRef.Hex()))
return response.Auto(a.logger, a.Name(), err) return response.Auto(a.logger, a.Name(), err)
@@ -107,7 +108,7 @@ func (a *PaymentAPI) quotePayments(r *http.Request, account *model.Account, toke
intents = append(intents, intent) intents = append(intents, intent)
} }
req := &quotationv1.QuotePaymentResponse{ req := &quotationv1.QuotePaymentsRequest{
Meta: &sharedv1.RequestMeta{ Meta: &sharedv1.RequestMeta{
OrganizationRef: orgRef.Hex(), OrganizationRef: orgRef.Hex(),
}, },
@@ -116,7 +117,7 @@ func (a *PaymentAPI) quotePayments(r *http.Request, account *model.Account, toke
PreviewOnly: payload.PreviewOnly, PreviewOnly: payload.PreviewOnly,
} }
resp, err := a.client.QuotePayments(ctx, req) resp, err := a.quotation.QuotePayments(ctx, req)
if err != nil { if err != nil {
a.logger.Warn("Failed to quote payments", zap.Error(err), zap.String("organization_ref", orgRef.Hex())) a.logger.Warn("Failed to quote payments", zap.Error(err), zap.String("organization_ref", orgRef.Hex()))
return response.Auto(a.logger, a.Name(), err) return response.Auto(a.logger, a.Name(), err)

View File

@@ -2,6 +2,7 @@ package paymentapiimp
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@@ -18,24 +19,33 @@ import (
"github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/mservice" "github.com/tech/sendico/pkg/mservice"
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestration/v1" orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestration/v1"
quotationv1 "github.com/tech/sendico/pkg/proto/payments/quotation/v1"
eapi "github.com/tech/sendico/server/interface/api" eapi "github.com/tech/sendico/server/interface/api"
mutil "github.com/tech/sendico/server/internal/mutil/param" mutil "github.com/tech/sendico/server/internal/mutil/param"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap" "go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
) )
type paymentClient interface { type executionClient interface {
QuotePayment(ctx context.Context, req *quotationv1.QuotePaymentRequest) (*quotationv1.QuotePaymentResponse, error)
QuotePayments(ctx context.Context, req *quotationv1.QuotePaymentRequest) (*quotationv1.QuotePaymentsResponse, error)
InitiatePayments(ctx context.Context, req *orchestratorv1.InitiatePaymentsRequest) (*orchestratorv1.InitiatePaymentsResponse, error) InitiatePayments(ctx context.Context, req *orchestratorv1.InitiatePaymentsRequest) (*orchestratorv1.InitiatePaymentsResponse, error)
InitiatePayment(ctx context.Context, req *orchestratorv1.InitiatePaymentRequest) (*orchestratorv1.InitiatePaymentResponse, error) InitiatePayment(ctx context.Context, req *orchestratorv1.InitiatePaymentRequest) (*orchestratorv1.InitiatePaymentResponse, error)
ListPayments(ctx context.Context, req *orchestratorv1.ListPaymentsRequest) (*orchestratorv1.ListPaymentsResponse, error) ListPayments(ctx context.Context, req *orchestratorv1.ListPaymentsRequest) (*orchestratorv1.ListPaymentsResponse, error)
Close() error Close() error
} }
type quotationClient interface {
QuotePayment(ctx context.Context, req *quotationv1.QuotePaymentRequest) (*quotationv1.QuotePaymentResponse, error)
QuotePayments(ctx context.Context, req *quotationv1.QuotePaymentsRequest) (*quotationv1.QuotePaymentsResponse, error)
Close() error
}
type PaymentAPI struct { type PaymentAPI struct {
logger mlogger.Logger logger mlogger.Logger
client paymentClient execution executionClient
quotation quotationClient
enf auth.Enforcer enf auth.Enforcer
oph mutil.ParamHelper oph mutil.ParamHelper
discovery *discovery.Client discovery *discovery.Client
@@ -49,11 +59,16 @@ type PaymentAPI struct {
func (a *PaymentAPI) Name() mservice.Type { return mservice.Payments } func (a *PaymentAPI) Name() mservice.Type { return mservice.Payments }
func (a *PaymentAPI) Finish(ctx context.Context) error { func (a *PaymentAPI) Finish(ctx context.Context) error {
if a.client != nil { if a.execution != nil {
if err := a.client.Close(); err != nil { if err := a.execution.Close(); err != nil {
a.logger.Warn("Failed to close payment orchestrator client", zap.Error(err)) a.logger.Warn("Failed to close payment orchestrator client", zap.Error(err))
} }
} }
if a.quotation != nil {
if err := a.quotation.Close(); err != nil {
a.logger.Warn("Failed to close payment quotation client", zap.Error(err))
}
}
if a.discovery != nil { if a.discovery != nil {
a.discovery.Close() a.discovery.Close()
} }
@@ -103,15 +118,15 @@ func (a *PaymentAPI) initPaymentClient(cfg *eapi.PaymentOrchestratorConfig, quot
return merrors.InvalidArgument("payment orchestrator configuration is not provided") return merrors.InvalidArgument("payment orchestrator configuration is not provided")
} }
address := strings.TrimSpace(cfg.Address) address, err := resolveClientAddress("payment orchestrator", cfg)
if address == "" { if err != nil {
address = strings.TrimSpace(os.Getenv(cfg.AddressEnv)) return err
}
if address == "" {
return merrors.InvalidArgument(fmt.Sprintf("payment orchestrator address is not specified and address env %s is empty", cfg.AddressEnv))
} }
quoteAddress := address quoteAddress := address
quoteInsecure := cfg.Insecure
quoteDialTimeout := cfg.DialTimeoutSeconds
quoteCallTimeout := cfg.CallTimeoutSeconds
if quoteCfg != nil { if quoteCfg != nil {
if addr := strings.TrimSpace(quoteCfg.Address); addr != "" { if addr := strings.TrimSpace(quoteCfg.Address); addr != "" {
quoteAddress = addr quoteAddress = addr
@@ -120,25 +135,133 @@ func (a *PaymentAPI) initPaymentClient(cfg *eapi.PaymentOrchestratorConfig, quot
quoteAddress = resolved quoteAddress = resolved
} }
} }
quoteInsecure = quoteCfg.Insecure
quoteDialTimeout = quoteCfg.DialTimeoutSeconds
quoteCallTimeout = quoteCfg.CallTimeoutSeconds
} }
clientCfg := orchestratorclient.Config{ clientCfg := orchestratorclient.Config{
Address: address, Address: address,
QuoteAddress: quoteAddress, DialTimeout: time.Duration(cfg.DialTimeoutSeconds) * time.Second,
DialTimeout: time.Duration(cfg.DialTimeoutSeconds) * time.Second, CallTimeout: time.Duration(cfg.CallTimeoutSeconds) * time.Second,
CallTimeout: time.Duration(cfg.CallTimeoutSeconds) * time.Second, Insecure: cfg.Insecure,
Insecure: cfg.Insecure,
} }
client, err := orchestratorclient.New(context.Background(), clientCfg) execution, err := orchestratorclient.New(context.Background(), clientCfg)
if err != nil { if err != nil {
return err return err
} }
a.client = client quotation, err := newQuotationClient(context.Background(), quotationClientConfig{
Address: quoteAddress,
DialTimeout: time.Duration(quoteDialTimeout) * time.Second,
CallTimeout: time.Duration(quoteCallTimeout) * time.Second,
Insecure: quoteInsecure,
})
if err != nil {
_ = execution.Close()
return err
}
a.execution = execution
a.quotation = quotation
return nil return nil
} }
func resolveClientAddress(service string, cfg *eapi.PaymentOrchestratorConfig) (string, error) {
if cfg == nil {
return "", merrors.InvalidArgument(strings.TrimSpace(service) + " configuration is not provided")
}
address := strings.TrimSpace(cfg.Address)
if address != "" {
return address, nil
}
if env := strings.TrimSpace(cfg.AddressEnv); env != "" {
if resolved := strings.TrimSpace(os.Getenv(env)); resolved != "" {
return resolved, nil
}
return "", merrors.InvalidArgument(fmt.Sprintf("%s address is not specified and address env %s is empty", strings.TrimSpace(service), env))
}
return "", merrors.InvalidArgument(strings.TrimSpace(service) + " address is not specified")
}
type quotationClientConfig struct {
Address string
DialTimeout time.Duration
CallTimeout time.Duration
Insecure bool
}
func (c *quotationClientConfig) setDefaults() {
if c.DialTimeout <= 0 {
c.DialTimeout = 5 * time.Second
}
if c.CallTimeout <= 0 {
c.CallTimeout = 3 * time.Second
}
}
type grpcQuotationClient struct {
conn *grpc.ClientConn
client quotationv1.QuotationServiceClient
callTimeout time.Duration
}
func newQuotationClient(ctx context.Context, cfg quotationClientConfig, opts ...grpc.DialOption) (quotationClient, error) {
cfg.setDefaults()
if strings.TrimSpace(cfg.Address) == "" {
return nil, merrors.InvalidArgument("payment quotation: address is required")
}
dialCtx, cancel := context.WithTimeout(ctx, cfg.DialTimeout)
defer cancel()
dialOpts := make([]grpc.DialOption, 0, len(opts)+1)
dialOpts = append(dialOpts, opts...)
if cfg.Insecure {
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
} else {
dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
}
conn, err := grpc.DialContext(dialCtx, cfg.Address, dialOpts...)
if err != nil {
return nil, merrors.InternalWrap(err, fmt.Sprintf("payment-quotation: dial %s", cfg.Address))
}
return &grpcQuotationClient{
conn: conn,
client: quotationv1.NewQuotationServiceClient(conn),
callTimeout: cfg.CallTimeout,
}, nil
}
func (c *grpcQuotationClient) Close() error {
if c == nil || c.conn == nil {
return nil
}
return c.conn.Close()
}
func (c *grpcQuotationClient) QuotePayment(ctx context.Context, req *quotationv1.QuotePaymentRequest) (*quotationv1.QuotePaymentResponse, error) {
callCtx, cancel := c.callContext(ctx)
defer cancel()
return c.client.QuotePayment(callCtx, req)
}
func (c *grpcQuotationClient) QuotePayments(ctx context.Context, req *quotationv1.QuotePaymentsRequest) (*quotationv1.QuotePaymentsResponse, error) {
callCtx, cancel := c.callContext(ctx)
defer cancel()
return c.client.QuotePayments(callCtx, req)
}
func (c *grpcQuotationClient) callContext(ctx context.Context) (context.Context, context.CancelFunc) {
timeout := c.callTimeout
if timeout <= 0 {
timeout = 3 * time.Second
}
return context.WithTimeout(ctx, timeout)
}
func (a *PaymentAPI) initDiscoveryClient(cfg *eapi.Config) error { func (a *PaymentAPI) initDiscoveryClient(cfg *eapi.Config) error {
if cfg == nil || cfg.Mw == nil { if cfg == nil || cfg.Mw == nil {
return nil return nil

View File

@@ -25,7 +25,7 @@ tmp_dir = "tmp"
rerun = false rerun = false
rerun_delay = 500 rerun_delay = 500
send_interrupt = false send_interrupt = false
stop_on_error = false stop_on_error = true
[color] [color]
app = "" app = ""