121 lines
4.1 KiB
Go
121 lines
4.1 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
)
|
|
|
|
// Client exposes typed helpers around the payment orchestration and quotation gRPC APIs.
|
|
type Client interface {
|
|
ExecutePayment(ctx context.Context, req *orchestrationv2.ExecutePaymentRequest) (*orchestrationv2.ExecutePaymentResponse, error)
|
|
GetPayment(ctx context.Context, req *orchestrationv2.GetPaymentRequest) (*orchestrationv2.GetPaymentResponse, error)
|
|
ListPayments(ctx context.Context, req *orchestrationv2.ListPaymentsRequest) (*orchestrationv2.ListPaymentsResponse, error)
|
|
Close() error
|
|
}
|
|
|
|
type grpcOrchestratorClient interface {
|
|
ExecutePayment(ctx context.Context, in *orchestrationv2.ExecutePaymentRequest, opts ...grpc.CallOption) (*orchestrationv2.ExecutePaymentResponse, error)
|
|
GetPayment(ctx context.Context, in *orchestrationv2.GetPaymentRequest, opts ...grpc.CallOption) (*orchestrationv2.GetPaymentResponse, error)
|
|
ListPayments(ctx context.Context, in *orchestrationv2.ListPaymentsRequest, opts ...grpc.CallOption) (*orchestrationv2.ListPaymentsResponse, error)
|
|
}
|
|
|
|
type orchestratorClient struct {
|
|
cfg Config
|
|
conn *grpc.ClientConn
|
|
client grpcOrchestratorClient
|
|
}
|
|
|
|
// New dials the payment orchestrator endpoint and returns a ready client.
|
|
func New(ctx context.Context, cfg Config, opts ...grpc.DialOption) (Client, error) {
|
|
cfg.setDefaults()
|
|
if strings.TrimSpace(cfg.Address) == "" {
|
|
return nil, merrors.InvalidArgument("payment-orchestrator: address is required")
|
|
}
|
|
|
|
conn, err := dial(ctx, cfg, cfg.Address, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &orchestratorClient{
|
|
cfg: cfg,
|
|
conn: conn,
|
|
client: orchestrationv2.NewPaymentOrchestratorServiceClient(conn),
|
|
}, nil
|
|
}
|
|
|
|
func dial(ctx context.Context, cfg Config, address string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
|
|
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, address, dialOpts...)
|
|
if err != nil {
|
|
return nil, merrors.InternalWrap(err, fmt.Sprintf("payment-orchestrator: dial %s", address))
|
|
}
|
|
return conn, nil
|
|
}
|
|
|
|
// NewWithClient injects a pre-built orchestrator client (useful for tests).
|
|
func NewWithClient(cfg Config, oc grpcOrchestratorClient) Client {
|
|
cfg.setDefaults()
|
|
return &orchestratorClient{
|
|
cfg: cfg,
|
|
client: oc,
|
|
}
|
|
}
|
|
|
|
// NewWithClients injects pre-built orchestrator and quotation clients (useful for tests).
|
|
func NewWithClients(cfg Config, oc grpcOrchestratorClient) Client {
|
|
return NewWithClient(cfg, oc)
|
|
}
|
|
|
|
func (c *orchestratorClient) Close() error {
|
|
if c == nil || c.conn == nil {
|
|
return nil
|
|
}
|
|
return c.conn.Close()
|
|
}
|
|
|
|
func (c *orchestratorClient) ExecutePayment(ctx context.Context, req *orchestrationv2.ExecutePaymentRequest) (*orchestrationv2.ExecutePaymentResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.ExecutePayment(ctx, req)
|
|
}
|
|
|
|
func (c *orchestratorClient) GetPayment(ctx context.Context, req *orchestrationv2.GetPaymentRequest) (*orchestrationv2.GetPaymentResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.GetPayment(ctx, req)
|
|
}
|
|
|
|
func (c *orchestratorClient) ListPayments(ctx context.Context, req *orchestrationv2.ListPaymentsRequest) (*orchestrationv2.ListPaymentsResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.ListPayments(ctx, req)
|
|
}
|
|
|
|
func (c *orchestratorClient) callContext(ctx context.Context) (context.Context, context.CancelFunc) {
|
|
timeout := c.cfg.CallTimeout
|
|
if timeout <= 0 {
|
|
timeout = 3 * time.Second
|
|
}
|
|
return context.WithTimeout(ctx, timeout)
|
|
}
|