This commit is contained in:
Stephan D
2026-03-10 12:31:09 +01:00
parent d87e709f43
commit e77d1ab793
287 changed files with 2089 additions and 1550 deletions

View File

@@ -69,7 +69,7 @@ func (a *PaymentAPI) getOperationDocument(r *http.Request, account *model.Accoun
op, err := a.fetchGatewayOperation(r.Context(), gateway.InvokeURI, operationRef)
if err != nil {
a.logger.Warn("Failed to fetch gateway operation for document generation", zap.Error(err), mzap.ObjRef("organization_ref", orgRef), zap.String("gateway_service", string(gatewayService)), zap.String("operation_ref", operationRef))
a.logger.Warn("Failed to fetch gateway operation for document generation", zap.Error(err), mzap.ObjRef("organization_ref", orgRef), zap.String("gateway_service", gatewayService), zap.String("operation_ref", operationRef))
return documentErrorResponse(a.logger, a.Name(), err)
}
@@ -77,7 +77,7 @@ func (a *PaymentAPI) getOperationDocument(r *http.Request, account *model.Accoun
docResp, err := a.fetchOperationDocument(r.Context(), service.InvokeURI, req)
if err != nil {
a.logger.Warn("Failed to fetch operation document", zap.Error(err), mzap.ObjRef("organization_ref", orgRef), zap.String("gateway_service", string(gatewayService)), zap.String("operation_ref", operationRef))
a.logger.Warn("Failed to fetch operation document", zap.Error(err), mzap.ObjRef("organization_ref", orgRef), zap.String("gateway_service", gatewayService), zap.String("operation_ref", operationRef))
return documentErrorResponse(a.logger, a.Name(), err)
}
@@ -154,6 +154,7 @@ func operationDocumentResponse(logger mlogger.Logger, source mservice.Type, docR
w.Header().Set("Content-Type", mimeType)
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filename))
w.WriteHeader(http.StatusOK)
//nolint:gosec // Binary payload is served as attachment with explicit content type.
if _, err := w.Write(docResp.GetContent()); err != nil {
logger.Warn("Failed to write document response", zap.Error(err))
}
@@ -167,15 +168,15 @@ func normalizeGatewayService(raw string) mservice.Type {
}
switch value {
case string(mservice.ChainGateway):
case mservice.ChainGateway:
return mservice.ChainGateway
case string(mservice.TronGateway):
case mservice.TronGateway:
return mservice.TronGateway
case string(mservice.MntxGateway):
case mservice.MntxGateway:
return mservice.MntxGateway
case string(mservice.PaymentGateway):
case mservice.PaymentGateway:
return mservice.PaymentGateway
case string(mservice.TgSettle):
case mservice.TgSettle:
return mservice.TgSettle
default:
return ""
@@ -219,7 +220,11 @@ func (a *PaymentAPI) fetchOperationDocument(ctx context.Context, invokeURI strin
if err != nil {
return nil, merrors.InternalWrap(err, "dial billing documents")
}
defer conn.Close()
defer func() {
if closeErr := conn.Close(); closeErr != nil {
a.logger.Warn("Failed to close billing documents connection", zap.Error(closeErr))
}
}()
client := documentsv1.NewDocumentServiceClient(conn)
@@ -234,7 +239,11 @@ func (a *PaymentAPI) fetchGatewayOperation(ctx context.Context, invokeURI, opera
if err != nil {
return nil, merrors.InternalWrap(err, "dial gateway connector")
}
defer conn.Close()
defer func() {
if closeErr := conn.Close(); closeErr != nil {
a.logger.Warn("Failed to close gateway connector connection", zap.Error(closeErr))
}
}()
client := connectorv1.NewConnectorServiceClient(conn)
@@ -307,7 +316,7 @@ func findGatewayForService(gateways []discovery.GatewaySummary, gatewayService m
func operationDocumentRequest(organizationRef string, gatewayService mservice.Type, requestedOperationRef string, op *connectorv1.Operation) *documentsv1.GetOperationDocumentRequest {
req := &documentsv1.GetOperationDocumentRequest{
OrganizationRef: strings.TrimSpace(organizationRef),
GatewayService: string(gatewayService),
GatewayService: gatewayService,
OperationRef: firstNonEmpty(strings.TrimSpace(op.GetOperationRef()), strings.TrimSpace(requestedOperationRef)),
OperationCode: strings.TrimSpace(op.GetType().String()),
OperationLabel: operationLabel(op.GetType()),

View File

@@ -103,6 +103,7 @@ func listPaymentsPage(r *http.Request) (*paginationv1.CursorPageRequest, error)
}
if cursor == "" && !hasLimit {
//nolint:nilnil // Absent pagination params mean no page request should be sent downstream.
return nil, nil
}
@@ -189,6 +190,7 @@ func firstNonEmpty(values ...string) string {
func parseRFC3339Timestamp(raw string, field string) (*timestamppb.Timestamp, error) {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
//nolint:nilnil // Empty timestamp filter is represented as (nil, nil).
return nil, nil
}
parsed, err := time.Parse(time.RFC3339, trimmed)

View File

@@ -102,7 +102,9 @@ func (a *PaymentAPI) initiatePayment(r *http.Request, account *model.Account, to
}
func decodeInitiatePayload(r *http.Request) (*srequest.InitiatePayment, error) {
defer r.Body.Close()
defer func() {
_ = r.Body.Close()
}()
payload := &srequest.InitiatePayment{}
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {

View File

@@ -68,7 +68,7 @@ func TestInitiateByQuote_RejectsMetadataIntentRef(t *testing.T) {
func invokeInitiateByQuote(t *testing.T, api *PaymentAPI, orgRef bson.ObjectID, body string) *httptest.ResponseRecorder {
t.Helper()
req := httptest.NewRequest(http.MethodPost, "/by-quote", bytes.NewBufferString(body))
req := httptest.NewRequestWithContext(context.Background(), http.MethodPost, "/by-quote", bytes.NewBufferString(body))
routeCtx := chi.NewRouteContext()
routeCtx.URLParams.Add("organizations_ref", orgRef.Hex())
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, routeCtx))

View File

@@ -63,7 +63,9 @@ func (a *PaymentAPI) initiatePaymentsByQuote(r *http.Request, account *model.Acc
}
func decodeInitiatePaymentsPayload(r *http.Request) (*srequest.InitiatePayments, error) {
defer r.Body.Close()
defer func() {
_ = r.Body.Close()
}()
payload := &srequest.InitiatePayments{}
decoder := json.NewDecoder(r.Body)

View File

@@ -10,7 +10,6 @@ import (
"github.com/go-chi/chi/v5"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
@@ -118,7 +117,7 @@ func TestInitiatePaymentsByQuote_RejectsDeprecatedIntentRefsField(t *testing.T)
func newBatchAPI(exec executionClient) *PaymentAPI {
return &PaymentAPI{
logger: mlogger.Logger(zap.NewNop()),
logger: zap.NewNop(),
execution: exec,
enf: fakeEnforcerForBatch{allowed: true},
oph: mutil.CreatePH(mservice.Organizations),
@@ -129,7 +128,7 @@ func newBatchAPI(exec executionClient) *PaymentAPI {
func invokeInitiatePaymentsByQuote(t *testing.T, api *PaymentAPI, orgRef bson.ObjectID, body string) *httptest.ResponseRecorder {
t.Helper()
req := httptest.NewRequest(http.MethodPost, "/by-multiquote", bytes.NewBufferString(body))
req := httptest.NewRequestWithContext(context.Background(), http.MethodPost, "/by-multiquote", bytes.NewBufferString(body))
routeCtx := chi.NewRouteContext()
routeCtx.URLParams.Add("organizations_ref", orgRef.Hex())
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, routeCtx))
@@ -177,6 +176,7 @@ func (f fakeEnforcerForBatch) Enforce(context.Context, bson.ObjectID, bson.Objec
}
func (fakeEnforcerForBatch) EnforceBatch(context.Context, []model.PermissionBoundStorable, bson.ObjectID, model.Action) (map[bson.ObjectID]bool, error) {
//nolint:nilnil // Test stub does not provide batch permissions map.
return nil, nil
}

View File

@@ -126,7 +126,9 @@ func (a *PaymentAPI) quotePayments(r *http.Request, account *model.Account, toke
}
func decodeQuotePayload(r *http.Request) (*srequest.QuotePayment, error) {
defer r.Body.Close()
defer func() {
_ = r.Body.Close()
}()
payload := &srequest.QuotePayment{}
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {
@@ -140,7 +142,9 @@ func decodeQuotePayload(r *http.Request) (*srequest.QuotePayment, error) {
}
func decodeQuotePaymentsPayload(r *http.Request) (*srequest.QuotePayments, error) {
defer r.Body.Close()
defer func() {
_ = r.Body.Close()
}()
payload := &srequest.QuotePayments{}
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {

View File

@@ -256,6 +256,7 @@ func (c *grpcQuotationClient) callContext(ctx context.Context) (context.Context,
if timeout <= 0 {
timeout = 3 * time.Second
}
//nolint:gosec // Caller receives cancel func and defers it in every call path.
return context.WithTimeout(ctx, timeout)
}
@@ -271,7 +272,7 @@ func (a *PaymentAPI) initDiscoveryClient(cfg *eapi.Config) error {
if err != nil {
return err
}
client, err := discovery.NewClient(a.logger, broker, nil, string(a.Name()))
client, err := discovery.NewClient(a.logger, broker, nil, a.Name())
if err != nil {
return err
}