package paymentapiimp import ( "context" "fmt" "os" "strings" "time" orchestratorclient "github.com/tech/sendico/payments/orchestrator/client" api "github.com/tech/sendico/pkg/api/http" "github.com/tech/sendico/pkg/auth" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/mservice" orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1" eapi "github.com/tech/sendico/server/interface/api" mutil "github.com/tech/sendico/server/internal/mutil/param" "go.mongodb.org/mongo-driver/bson/primitive" "go.uber.org/zap" ) type paymentClient interface { QuotePayment(ctx context.Context, req *orchestratorv1.QuotePaymentRequest) (*orchestratorv1.QuotePaymentResponse, error) InitiatePayment(ctx context.Context, req *orchestratorv1.InitiatePaymentRequest) (*orchestratorv1.InitiatePaymentResponse, error) Close() error } type PaymentAPI struct { logger mlogger.Logger client paymentClient enf auth.Enforcer oph mutil.ParamHelper permissionRef primitive.ObjectID } func (a *PaymentAPI) Name() mservice.Type { return mservice.Payments } func (a *PaymentAPI) Finish(ctx context.Context) error { if a.client != nil { if err := a.client.Close(); err != nil { a.logger.Warn("Failed to close payment orchestrator client", zap.Error(err)) } } return nil } func CreateAPI(apiCtx eapi.API) (*PaymentAPI, error) { p := &PaymentAPI{ logger: apiCtx.Logger().Named(mservice.Payments), enf: apiCtx.Permissions().Enforcer(), oph: mutil.CreatePH(mservice.Organizations), } desc, err := apiCtx.Permissions().GetPolicyDescription(context.Background(), mservice.Payments) if err != nil { p.logger.Warn("Failed to fetch payment orchestrator permission description", zap.Error(err)) return nil, err } p.permissionRef = desc.ID if err := p.initPaymentClient(apiCtx.Config().PaymentOrchestrator); err != nil { p.logger.Error("Failed to initialize payment orchestrator client", zap.Error(err)) return nil, err } apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/quote"), api.Post, p.quotePayment) apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/immediate"), api.Post, p.initiateImmediate) apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/by-quote"), api.Post, p.initiateByQuote) return p, nil } func (a *PaymentAPI) initPaymentClient(cfg *eapi.PaymentOrchestratorConfig) error { if cfg == nil { return merrors.InvalidArgument("payment orchestrator configuration is not provided") } address := strings.TrimSpace(cfg.Address) if address == "" { address = strings.TrimSpace(os.Getenv(cfg.AddressEnv)) } if address == "" { return merrors.InvalidArgument(fmt.Sprintf("payment orchestrator address is not specified and address env %s is empty", cfg.AddressEnv)) } clientCfg := orchestratorclient.Config{ Address: address, DialTimeout: time.Duration(cfg.DialTimeoutSeconds) * time.Second, CallTimeout: time.Duration(cfg.CallTimeoutSeconds) * time.Second, Insecure: cfg.Insecure, } client, err := orchestratorclient.New(context.Background(), clientCfg) if err != nil { return err } a.client = client return nil }