Merge pull request 'new payment by id method + shell scripts update + mntx removed' (#748) from bff-747 into main
Some checks failed
ci/woodpecker/push/callbacks Pipeline is pending
ci/woodpecker/push/discovery Pipeline is pending
ci/woodpecker/push/frontend Pipeline is pending
ci/woodpecker/push/fx_ingestor Pipeline is pending
ci/woodpecker/push/fx_oracle Pipeline is pending
ci/woodpecker/push/gateway_chain Pipeline is pending
ci/woodpecker/push/gateway_mntx Pipeline is pending
ci/woodpecker/push/gateway_tgsettle Pipeline is pending
ci/woodpecker/push/payments_methods Pipeline is pending
ci/woodpecker/push/payments_orchestrator Pipeline is pending
ci/woodpecker/push/gateway_tron Pipeline is pending
ci/woodpecker/push/ledger Pipeline is pending
ci/woodpecker/push/notification Pipeline is pending
ci/woodpecker/push/payments_quotation Pipeline is pending
ci/woodpecker/push/bff Pipeline failed
ci/woodpecker/push/billing_fees Pipeline failed
ci/woodpecker/push/billing_documents Pipeline failed

Reviewed-on: #748
This commit was merged in pull request #748.
This commit is contained in:
2026-03-16 14:44:00 +00:00
36 changed files with 348 additions and 26 deletions

View File

@@ -293,7 +293,7 @@ func TestToPaymentOperation_MapsOperationRefAndGateway(t *testing.T) {
if got, want := op.OperationRef, "op-123"; got != want {
t.Fatalf("operation_ref mismatch: got=%q want=%q", got, want)
}
if got, want := op.Gateway, "mntx_gateway"; got != want {
if got, want := op.Gateway, "mcards_gateway"; got != want {
t.Fatalf("gateway mismatch: got=%q want=%q", got, want)
}
}
@@ -331,7 +331,7 @@ func TestToPaymentOperation_DoesNotFallbackToCardPayoutRef(t *testing.T) {
if got := op.OperationRef; got != "" {
t.Fatalf("expected empty operation_ref, got=%q", got)
}
if got, want := op.Gateway, "mntx_gateway"; got != want {
if got, want := op.Gateway, "mcards_gateway"; got != want {
t.Fatalf("gateway mismatch: got=%q want=%q", got, want)
}
}

View File

@@ -0,0 +1,52 @@
package paymentapiimp
import (
"net/http"
"strings"
"github.com/tech/sendico/pkg/api/http/response"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
"github.com/tech/sendico/server/interface/api/sresponse"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
func (a *PaymentAPI) getPayment(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
paymentRef := strings.TrimSpace(a.pph.GetID(r))
if paymentRef == "" {
return response.BadReference(a.logger, a.Name(), a.pph.Name(), a.pph.GetID(r), merrors.InvalidArgument("payment reference is required"))
}
resp, err := a.execution.GetPayment(r.Context(), &orchestrationv2.GetPaymentRequest{
PaymentRef: paymentRef,
})
if err != nil {
a.logger.Warn("Failed to fetch payment", zap.Error(err), zap.String("payment_ref", paymentRef))
return grpcErrorResponse(a.logger, a.Name(), err)
}
if resp == nil || resp.GetPayment() == nil {
return response.Auto(a.logger, a.Name(), merrors.NoData("payment not found"))
}
orgRefRaw := strings.TrimSpace(resp.GetOrganizationRef())
orgRef, err := bson.ObjectIDFromHex(orgRefRaw)
if err != nil {
a.logger.Warn("Payment lookup returned invalid organization reference", zap.Error(err), zap.String("organization_ref", orgRefRaw), zap.String("payment_ref", paymentRef))
return response.Internal(a.logger, a.Name(), merrors.DataConflict("payment lookup returned invalid organization reference"))
}
allowed, err := a.enf.Enforce(r.Context(), a.permissionRef, account.ID, orgRef, bson.NilObjectID, model.ActionRead)
if err != nil {
a.logger.Warn("Failed to check payment access permissions", zap.Error(err), mzap.ObjRef("organization_ref", orgRef), zap.String("payment_ref", paymentRef))
return response.Auto(a.logger, a.Name(), err)
}
if !allowed {
a.logger.Debug("Payment access denied, hiding existence", mzap.ObjRef("organization_ref", orgRef), zap.String("payment_ref", paymentRef))
return response.NotFound(a.logger, a.Name(), "payment not found")
}
return sresponse.PaymentResponse(a.logger, resp.GetPayment(), token)
}

View File

@@ -0,0 +1,119 @@
package paymentapiimp
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/go-chi/chi/v5"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
"github.com/tech/sendico/server/interface/api/sresponse"
mutil "github.com/tech/sendico/server/internal/mutil/param"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
func TestGetPayment_FetchesByPaymentRefWithoutOrganizationPath(t *testing.T) {
orgRef := bson.NewObjectID()
paymentRef := "payment-123"
exec := &fakeExecutionClientForGet{
getPaymentResp: &orchestrationv2.GetPaymentResponse{
OrganizationRef: orgRef.Hex(),
Payment: &orchestrationv2.Payment{
PaymentRef: paymentRef,
},
},
}
enf := &capturingPaymentEnforcer{allowed: true}
api := &PaymentAPI{
logger: zap.NewNop(),
execution: exec,
enf: enf,
oph: mutil.CreatePH(mservice.Organizations),
pph: mutil.CreatePH(mservice.Payments),
permissionRef: bson.NewObjectID(),
}
req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/object/"+paymentRef, nil)
routeCtx := chi.NewRouteContext()
routeCtx.URLParams.Add("payments_ref", paymentRef)
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, routeCtx))
account := &model.Account{}
account.ID = bson.NewObjectID()
rr := httptest.NewRecorder()
handler := api.getPayment(req, account, &sresponse.TokenData{
Token: "token",
Expiration: time.Now().UTC().Add(time.Hour),
})
handler.ServeHTTP(rr, req)
if got, want := rr.Code, http.StatusOK; got != want {
t.Fatalf("status mismatch: got=%d want=%d body=%s", got, want, rr.Body.String())
}
if exec.getPaymentReq == nil {
t.Fatal("expected GetPayment request")
}
if got, want := exec.getPaymentReq.GetPaymentRef(), paymentRef; got != want {
t.Fatalf("payment_ref mismatch: got=%q want=%q", got, want)
}
if exec.getPaymentReq.GetMeta() != nil {
t.Fatalf("expected no organization metadata in request, got=%+v", exec.getPaymentReq.GetMeta())
}
if got, want := enf.organizationRef, orgRef; got != want {
t.Fatalf("permission organization_ref mismatch: got=%s want=%s", got.Hex(), want.Hex())
}
}
type fakeExecutionClientForGet struct {
getPaymentReq *orchestrationv2.GetPaymentRequest
getPaymentResp *orchestrationv2.GetPaymentResponse
}
func (*fakeExecutionClientForGet) ExecutePayment(context.Context, *orchestrationv2.ExecutePaymentRequest) (*orchestrationv2.ExecutePaymentResponse, error) {
return &orchestrationv2.ExecutePaymentResponse{}, nil
}
func (*fakeExecutionClientForGet) ExecuteBatchPayment(context.Context, *orchestrationv2.ExecuteBatchPaymentRequest) (*orchestrationv2.ExecuteBatchPaymentResponse, error) {
return &orchestrationv2.ExecuteBatchPaymentResponse{}, nil
}
func (f *fakeExecutionClientForGet) GetPayment(_ context.Context, req *orchestrationv2.GetPaymentRequest) (*orchestrationv2.GetPaymentResponse, error) {
f.getPaymentReq = req
return f.getPaymentResp, nil
}
func (*fakeExecutionClientForGet) ListPayments(context.Context, *orchestrationv2.ListPaymentsRequest) (*orchestrationv2.ListPaymentsResponse, error) {
return &orchestrationv2.ListPaymentsResponse{}, nil
}
func (*fakeExecutionClientForGet) Close() error { return nil }
type capturingPaymentEnforcer struct {
allowed bool
organizationRef bson.ObjectID
}
func (f *capturingPaymentEnforcer) Enforce(_ context.Context, _ bson.ObjectID, _ bson.ObjectID, organizationRef bson.ObjectID, _ bson.ObjectID, _ model.Action) (bool, error) {
f.organizationRef = organizationRef
return f.allowed, nil
}
func (*capturingPaymentEnforcer) EnforceBatch(context.Context, []model.PermissionBoundStorable, bson.ObjectID, model.Action) (map[bson.ObjectID]bool, error) {
return nil, nil
}
func (*capturingPaymentEnforcer) GetRoles(context.Context, bson.ObjectID, bson.ObjectID) ([]model.Role, error) {
return nil, nil
}
func (*capturingPaymentEnforcer) GetPermissions(context.Context, bson.ObjectID, bson.ObjectID) ([]model.Role, []model.Permission, error) {
return nil, nil, nil
}
var _ auth.Enforcer = (*capturingPaymentEnforcer)(nil)

View File

@@ -49,6 +49,7 @@ type PaymentAPI struct {
quotation quotationClient
enf auth.Enforcer
oph mutil.ParamHelper
pph mutil.ParamHelper
discovery *discovery.Client
refreshConsumer msg.Consumer
refreshMu sync.RWMutex
@@ -84,6 +85,7 @@ func CreateAPI(apiCtx eapi.API) (*PaymentAPI, error) {
logger: apiCtx.Logger().Named(mservice.Payments),
enf: apiCtx.Permissions().Enforcer(),
oph: mutil.CreatePH(mservice.Organizations),
pph: mutil.CreatePH(mservice.Payments),
}
desc, err := apiCtx.Permissions().GetPolicyDescription(context.Background(), mservice.Payments)
@@ -106,6 +108,7 @@ func CreateAPI(apiCtx eapi.API) (*PaymentAPI, error) {
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)
apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/by-multiquote"), api.Post, p.initiatePaymentsByQuote)
apiCtx.Register().AccountHandler(p.Name(), p.pph.AddRef("/by-ref"), api.Get, p.getPayment)
apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/"), api.Get, p.listPayments)
apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/documents/operation"), api.Get, p.getOperationDocument)
apiCtx.Register().AccountHandler(p.Name(), p.oph.AddRef("/registry"), api.Get, p.listDiscoveryRegistry)

View File

@@ -43,7 +43,7 @@ type gatewayClient struct {
func New(ctx context.Context, cfg Config, opts ...grpc.DialOption) (Client, error) {
cfg.setDefaults()
if strings.TrimSpace(cfg.Address) == "" {
return nil, merrors.InvalidArgument("mntx: address is required")
return nil, merrors.InvalidArgument("mcards: address is required")
}
dialOpts := make([]grpc.DialOption, 0, len(opts)+1)
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
@@ -51,7 +51,7 @@ func New(ctx context.Context, cfg Config, opts ...grpc.DialOption) (Client, erro
conn, err := grpc.NewClient(cfg.Address, dialOpts...)
if err != nil {
return nil, merrors.Internal("mntx: dial failed: " + err.Error())
return nil, merrors.Internal("mcards: dial failed: " + err.Error())
}
return &gatewayClient{
@@ -128,7 +128,7 @@ func (g *gatewayClient) GetCardPayoutStatus(ctx context.Context, req *mntxv1.Get
ctx, cancel := g.callContext(ctx, "GetCardPayoutStatus")
defer cancel()
if req == nil || strings.TrimSpace(req.GetPayoutId()) == "" {
return nil, merrors.InvalidArgument("mntx: payout_id is required")
return nil, merrors.InvalidArgument("mcards: payout_id is required")
}
resp, err := g.client.GetOperation(ctx, &connectorv1.GetOperationRequest{OperationId: strings.TrimSpace(req.GetPayoutId())})
if err != nil {
@@ -138,12 +138,12 @@ func (g *gatewayClient) GetCardPayoutStatus(ctx context.Context, req *mntxv1.Get
}
func (g *gatewayClient) ListGatewayInstances(ctx context.Context, req *mntxv1.ListGatewayInstancesRequest) (*mntxv1.ListGatewayInstancesResponse, error) {
return nil, merrors.NotImplemented("mntx: ListGatewayInstances not supported via connector")
return nil, merrors.NotImplemented("mcards: ListGatewayInstances not supported via connector")
}
func operationFromCardPayout(req *mntxv1.CardPayoutRequest) (*connectorv1.Operation, error) {
if req == nil {
return nil, merrors.InvalidArgument("mntx: request is required")
return nil, merrors.InvalidArgument("mcards: request is required")
}
params := payoutParamsFromCard(req)
money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency())
@@ -163,7 +163,7 @@ func operationFromCardPayout(req *mntxv1.CardPayoutRequest) (*connectorv1.Operat
func operationFromTokenPayout(req *mntxv1.CardTokenPayoutRequest) (*connectorv1.Operation, error) {
if req == nil {
return nil, merrors.InvalidArgument("mntx: request is required")
return nil, merrors.InvalidArgument("mcards: request is required")
}
params := payoutParamsFromToken(req)
money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency())

View File

@@ -21,7 +21,7 @@ func initMetrics() {
metricsOnce.Do(func() {
rpcLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "sendico",
Subsystem: "mntx_gateway",
Subsystem: "mcards_gateway",
Name: "rpc_latency_seconds",
Help: "Latency distribution for Monetix gateway RPC handlers.",
Buckets: prometheus.DefBuckets,
@@ -29,7 +29,7 @@ func initMetrics() {
rpcStatus = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "sendico",
Subsystem: "mntx_gateway",
Subsystem: "mcards_gateway",
Name: "rpc_requests_total",
Help: "Total number of RPC invocations grouped by method and status.",
}, []string{"method", "status"})

View File

@@ -21,21 +21,21 @@ func initMetrics() {
metricsOnce.Do(func() {
cardPayoutRequests = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "sendico",
Subsystem: "mntx_gateway",
Subsystem: "mcards_gateway",
Name: "card_payout_requests_total",
Help: "Monetix card payout submissions grouped by outcome.",
}, []string{"outcome"})
cardPayoutCallbacks = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "sendico",
Subsystem: "mntx_gateway",
Subsystem: "mcards_gateway",
Name: "card_payout_callbacks_total",
Help: "Monetix card payout callbacks grouped by provider status.",
}, []string{"status"})
cardPayoutLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "sendico",
Subsystem: "mntx_gateway",
Subsystem: "mcards_gateway",
Name: "card_payout_request_latency_seconds",
Help: "Latency distribution for outbound Monetix card payout requests.",
Buckets: prometheus.DefBuckets,

View File

@@ -80,13 +80,14 @@ func (s *svc) GetPayment(ctx context.Context, in GetPaymentInput) (payment *agg.
logger.Debug("Completed Get payment", fields...)
}(time.Now())
if in.OrganizationRef.IsZero() {
return nil, merrors.InvalidArgument("organization_ref is required")
}
paymentRef := strings.TrimSpace(in.PaymentRef)
if paymentRef == "" {
return nil, merrors.InvalidArgument("payment_ref is required")
}
if in.OrganizationRef.IsZero() {
payment, err = s.repo.GetByPaymentRefGlobal(ctx, paymentRef)
return payment, err
}
payment, err = s.repo.GetByPaymentRef(ctx, in.OrganizationRef, paymentRef)
return payment, err
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/pquery"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/prmap"
"github.com/tech/sendico/pkg/merrors"
paginationv1 "github.com/tech/sendico/pkg/proto/common/pagination/v1"
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
"go.uber.org/zap"
@@ -39,7 +40,10 @@ func (s *svc) GetPayment(ctx context.Context, req *orchestrationv2.GetPaymentReq
logger.Debug("Completed Get payment", fields...)
}(time.Now())
_, orgID, err := parseOrganization(req.GetMeta())
if req == nil {
return nil, merrors.InvalidArgument("request is required")
}
_, orgID, hasOrg, err := parseOptionalOrganization(req.GetMeta())
if err != nil {
return nil, err
}
@@ -48,10 +52,11 @@ func (s *svc) GetPayment(ctx context.Context, req *orchestrationv2.GetPaymentReq
return nil, err
}
payment, err := s.query.GetPayment(ctx, pquery.GetPaymentInput{
OrganizationRef: orgID,
PaymentRef: paymentRef,
})
queryInput := pquery.GetPaymentInput{PaymentRef: paymentRef}
if hasOrg {
queryInput.OrganizationRef = orgID
}
payment, err := s.query.GetPayment(ctx, queryInput)
if err != nil {
return nil, err
}
@@ -59,7 +64,10 @@ func (s *svc) GetPayment(ctx context.Context, req *orchestrationv2.GetPaymentReq
if err != nil {
return nil, err
}
resp = &orchestrationv2.GetPaymentResponse{Payment: protoPayment}
resp = &orchestrationv2.GetPaymentResponse{
Payment: protoPayment,
OrganizationRef: payment.OrganizationRef.Hex(),
}
return resp, nil
}

View File

@@ -35,6 +35,21 @@ func parseOrganization(meta *sharedv1.RequestMeta) (string, bson.ObjectID, error
return orgRef, orgID, nil
}
func parseOptionalOrganization(meta *sharedv1.RequestMeta) (string, bson.ObjectID, bool, error) {
if meta == nil {
return "", bson.NilObjectID, false, nil
}
orgRef := strings.TrimSpace(meta.GetOrganizationRef())
if orgRef == "" {
return "", bson.NilObjectID, false, nil
}
orgID, err := bson.ObjectIDFromHex(orgRef)
if err != nil {
return "", bson.NilObjectID, false, merrors.InvalidArgument("meta.organization_ref must be a valid objectID")
}
return orgRef, orgID, true, nil
}
func parsePaymentRef(value string) (string, error) {
ref := strings.TrimSpace(value)
if ref == "" {

View File

@@ -67,6 +67,25 @@ func TestExecutePayment_EndToEndSyncSettled(t *testing.T) {
if got, want := getResp.GetPayment().GetPaymentRef(), resp.GetPayment().GetPaymentRef(); got != want {
t.Fatalf("payment_ref mismatch: got=%q want=%q", got, want)
}
if got, want := getResp.GetOrganizationRef(), env.orgID.Hex(); got != want {
t.Fatalf("organization_ref mismatch: got=%q want=%q", got, want)
}
getRespGlobal, err := env.svc.GetPayment(context.Background(), &orchestrationv2.GetPaymentRequest{
PaymentRef: resp.GetPayment().GetPaymentRef(),
})
if err != nil {
t.Fatalf("GetPayment(global) returned error: %v", err)
}
if getRespGlobal.GetPayment() == nil {
t.Fatal("expected payment from global GetPayment")
}
if got, want := getRespGlobal.GetPayment().GetPaymentRef(), resp.GetPayment().GetPaymentRef(); got != want {
t.Fatalf("global payment_ref mismatch: got=%q want=%q", got, want)
}
if got, want := getRespGlobal.GetOrganizationRef(), env.orgID.Hex(); got != want {
t.Fatalf("global organization_ref mismatch: got=%q want=%q", got, want)
}
timeline, err := env.observer.PaymentTimeline(context.Background(), oobs.PaymentTimelineInput{
PaymentRef: resp.GetPayment().GetPaymentRef(),

View File

@@ -13,7 +13,7 @@ const (
Changes Type = "changes" // Tracks changes made to resources
Clients Type = "clients" // Represents client information
ChainGateway Type = "chain_gateway" // Represents chain gateway microservice
MntxGateway Type = "mntx_gateway" // Represents Monetix gateway microservice
MntxGateway Type = "mcards_gateway" // Represents Monetix gateway microservice
PaymentGateway Type = "payment_gateway" // Represents payment gateway microservice
FXOracle Type = "fx_oracle" // Represents FX oracle microservice
FXIngestor Type = "fx_ingestor" // Represents FX ingestor microservice

View File

@@ -72,6 +72,10 @@ message ExecuteBatchPaymentResponse {
}
// GetPaymentRequest fetches one payment by payment_ref.
//
// If meta.organization_ref is provided, the lookup is scoped to that
// organization. If it is omitted, the service resolves the payment globally by
// payment_ref and returns the resolved organization_ref in the response.
message GetPaymentRequest {
payments.shared.v1.RequestMeta meta = 1;
string payment_ref = 2;
@@ -80,6 +84,7 @@ message GetPaymentRequest {
// GetPaymentResponse returns one orchestration payment aggregate.
message GetPaymentResponse {
Payment payment = 1;
string organization_ref = 2;
}
// ListPaymentsRequest lists payments within the caller organization scope.

View File

@@ -1,9 +1,9 @@
# Overrides for the shared prod-style runtime when deploying main to the dev server.
AMPLI_ENVIRONMENT=development
API_PROTOCOL=http
SERVICE_HOST=178.57.67.136
WS_PROTOCOL=ws
API_PROTOCOL=https
SERVICE_HOST=dev.sendico.io
WS_PROTOCOL=wss
SSH_HOST=178.57.67.136
SSH_USER=cloud

View File

@@ -14,6 +14,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then
SSH_OPTS+=(-vv)

View File

@@ -57,6 +57,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -61,6 +61,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -51,6 +51,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -55,6 +55,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -61,6 +61,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -23,6 +23,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -47,6 +47,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -26,6 +26,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -77,6 +77,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -51,6 +51,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -55,6 +55,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -19,6 +19,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -62,6 +62,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -51,6 +51,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -51,6 +51,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -51,6 +51,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -51,6 +51,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -63,6 +63,9 @@ SSH_OPTS=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR
-o BatchMode=yes
-o PreferredAuthentications=publickey
-o ConnectTimeout=10
-q
)
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then

View File

@@ -93,6 +93,8 @@ paths:
$ref: ./api/payments/by_quote.yaml
/payments/by-multiquote/{organizations_ref}:
$ref: ./api/payments/by_multiquote.yaml
/payments/object/{payments_ref}:
$ref: ./api/payments/object.yaml
/payments/{organizations_ref}:
$ref: ./api/payments/list.yaml
/payments/documents/operation/{organizations_ref}:

View File

@@ -0,0 +1,10 @@
components:
parameters:
PaymentsRef:
name: payments_ref
in: path
required: true
description: Stable payment reference.
schema:
type: string
minLength: 1

View File

@@ -0,0 +1,31 @@
get:
tags: [Payments]
summary: Get payment by reference
description: Returns a single payment by `payments_ref`.
operationId: paymentsGet
security:
- bearerAuth: []
parameters:
- $ref: ../parameters/payments_ref.yaml#/components/parameters/PaymentsRef
responses:
'200':
description: Payment data
content:
application/json:
schema:
allOf:
- $ref: ../response/response.yaml#/components/schemas/BaseResponse
- type: object
properties:
data:
$ref: ./response/payment.yaml#/components/schemas/PaymentData
'400':
$ref: ../response/operation.yaml#/components/responses/BadRequest
'401':
$ref: ../response/operation.yaml#/components/responses/Unauthorized
'403':
$ref: ../response/operation.yaml#/components/responses/Forbidden
'404':
$ref: ../response/operation.yaml#/components/responses/NotFound
'500':
$ref: ../response/operation.yaml#/components/responses/InternalServerError