removed intent_ref from frontend

This commit is contained in:
Stephan D
2026-02-26 22:20:54 +01:00
parent 4949c4ffe0
commit e8d763eb15
25 changed files with 174 additions and 750 deletions

View File

@@ -25,10 +25,9 @@ func (s *svc) ExecutePayment(ctx context.Context, req *orchestrationv2.ExecutePa
if req != nil && req.GetMeta() != nil {
orgRef = strings.TrimSpace(req.GetMeta().GetOrganizationRef())
}
logger.Debug("Starting Execute payment",
logger.Debug("Starting payment execution",
zap.String("organization_ref", orgRef),
zap.String("quotation_ref", strings.TrimSpace(req.GetQuotationRef())),
zap.String("intent_ref", strings.TrimSpace(req.GetIntentRef())),
zap.Bool("has_client_payment_ref", strings.TrimSpace(req.GetClientPaymentRef()) != ""),
)
defer func(start time.Time) {
@@ -44,9 +43,13 @@ func (s *svc) ExecutePayment(ctx context.Context, req *orchestrationv2.ExecutePa
logger.Warn("Failed to execute payment", append(fields, zap.Error(err))...)
return
}
logger.Debug("Completed Execute payment", fields...)
logger.Debug("Completed payment execution", fields...)
}(time.Now())
if req != nil && strings.TrimSpace(req.GetIntentRef()) != "" {
return nil, merrors.InvalidArgument("intent_ref is no longer supported for ExecutePayment")
}
requestCtx, fingerprint, err := s.prepareExecute(req)
if err != nil {
return nil, err
@@ -104,7 +107,6 @@ func (s *svc) prepareExecute(req *orchestrationv2.ExecutePaymentRequest) (*reqva
fingerprint, err := s.idempotency.Fingerprint(idem.FPInput{
OrganizationRef: requestCtx.OrganizationRef,
QuotationRef: requestCtx.QuotationRef,
IntentRef: requestCtx.IntentRef,
ClientPaymentRef: requestCtx.ClientPaymentRef,
})
if err != nil {
@@ -119,7 +121,6 @@ func mapExecuteReq(req *orchestrationv2.ExecutePaymentRequest) *reqval.Req {
}
out := &reqval.Req{
QuotationRef: req.GetQuotationRef(),
IntentRef: req.GetIntentRef(),
ClientPaymentRef: req.GetClientPaymentRef(),
}
meta := req.GetMeta()
@@ -148,7 +149,6 @@ func (s *svc) tryReuse(ctx context.Context, requestCtx *reqval.Ctx, requestFinge
existingFingerprint, err := s.idempotency.Fingerprint(idem.FPInput{
OrganizationRef: requestCtx.OrganizationRef,
QuotationRef: existing.QuotationRef,
IntentRef: existing.IntentSnapshot.Ref,
ClientPaymentRef: existing.ClientPaymentRef,
})
if err != nil {
@@ -202,7 +202,6 @@ func (s *svc) resolveAndPlan(ctx context.Context, requestCtx *reqval.Ctx) (*qsna
resolved, err := s.quote.Resolve(ctx, s.quoteStore, qsnap.Input{
OrganizationID: requestCtx.OrganizationID,
QuotationRef: requestCtx.QuotationRef,
IntentRef: requestCtx.IntentRef,
})
if err != nil {
return nil, nil, remapResolveError(err)
@@ -271,7 +270,7 @@ func remapIdempotencyError(err error) error {
func remapResolveError(err error) error {
switch {
case errors.Is(err, qsnap.ErrIntentRefRequired), errors.Is(err, qsnap.ErrIntentRefNotFound):
case errors.Is(err, qsnap.ErrBatchQuoteUnsupported):
return merrors.InvalidArgument(err.Error())
default:
return err
@@ -285,7 +284,6 @@ func mustFingerprint(idemSvc idem.Service, requestCtx *reqval.Ctx) string {
value, err := idemSvc.Fingerprint(idem.FPInput{
OrganizationRef: requestCtx.OrganizationRef,
QuotationRef: requestCtx.QuotationRef,
IntentRef: requestCtx.IntentRef,
ClientPaymentRef: requestCtx.ClientPaymentRef,
})
if err != nil {

View File

@@ -27,7 +27,7 @@ func (s *svc) ExecuteBatchPayment(ctx context.Context, req *orchestrationv2.Exec
if req != nil && req.GetMeta() != nil {
orgRef = strings.TrimSpace(req.GetMeta().GetOrganizationRef())
}
logger.Debug("Starting ExecuteBatchPayment",
logger.Debug("Starting batch payment execution",
zap.String("organization_ref", orgRef),
zap.String("quotation_ref", strings.TrimSpace(req.GetQuotationRef())),
zap.Bool("has_client_payment_ref", strings.TrimSpace(req.GetClientPaymentRef()) != ""),
@@ -41,7 +41,7 @@ func (s *svc) ExecuteBatchPayment(ctx context.Context, req *orchestrationv2.Exec
logger.Warn("Failed to execute batch payment", append(fields, zap.Error(err))...)
return
}
logger.Debug("Completed ExecuteBatchPayment", fields...)
logger.Debug("Completed batch payment execution", fields...)
}(time.Now())
requestCtx, err := s.prepareBatchExecute(req)

View File

@@ -41,7 +41,6 @@ func TestExecutePayment_EndToEndSyncSettled(t *testing.T) {
Meta: testMeta(env.orgID, "idem-sync"),
QuotationRef: "quote-sync",
ClientPaymentRef: "client-1",
IntentRef: "intent-sync",
})
if err != nil {
t.Fatalf("ExecutePayment returned error: %v", err)
@@ -89,7 +88,6 @@ func TestExecutePayment_IdempotencyMismatch(t *testing.T) {
Meta: testMeta(env.orgID, "idem-shared"),
QuotationRef: "quote-idem",
ClientPaymentRef: "client-a",
IntentRef: "intent-idem",
})
if err != nil {
t.Fatalf("first ExecutePayment returned error: %v", err)
@@ -99,14 +97,35 @@ func TestExecutePayment_IdempotencyMismatch(t *testing.T) {
Meta: testMeta(env.orgID, "idem-shared"),
QuotationRef: "quote-idem",
ClientPaymentRef: "client-b",
IntentRef: "intent-idem",
})
if !errors.Is(err, merrors.ErrInvalidArg) {
t.Fatalf("expected invalid argument for mismatch, got %v", err)
}
}
func TestExecutePayment_BatchQuoteRequiresIntentRef(t *testing.T) {
func TestExecutePayment_RejectsDeprecatedIntentRef(t *testing.T) {
env := newTestEnv(t, func(_ string, req sexec.StepRequest) (*sexec.ExecuteOutput, error) {
step := req.StepExecution
step.State = agg.StepStateCompleted
return &sexec.ExecuteOutput{StepExecution: step}, nil
})
env.quotes.Put(newExecutableQuote(env.orgID, "quote-sync", "intent-sync", buildLedgerRoute()))
_, err := env.svc.ExecutePayment(context.Background(), &orchestrationv2.ExecutePaymentRequest{
Meta: testMeta(env.orgID, "idem-intent-ref"),
QuotationRef: "quote-sync",
ClientPaymentRef: "client-1",
IntentRef: "intent-sync",
})
if !errors.Is(err, merrors.ErrInvalidArg) {
t.Fatalf("expected invalid argument for deprecated intent_ref, got %v", err)
}
if got := err.Error(); !strings.Contains(got, "intent_ref is no longer supported for ExecutePayment") {
t.Fatalf("unexpected error message: %q", got)
}
}
func TestExecutePayment_BatchQuoteRequiresBatchExecution(t *testing.T) {
env := newTestEnv(t, func(_ string, req sexec.StepRequest) (*sexec.ExecuteOutput, error) {
step := req.StepExecution
step.State = agg.StepStateCompleted
@@ -120,9 +139,9 @@ func TestExecutePayment_BatchQuoteRequiresIntentRef(t *testing.T) {
ClientPaymentRef: "client-batch",
})
if !errors.Is(err, merrors.ErrInvalidArg) {
t.Fatalf("expected invalid argument for missing intent_ref, got %v", err)
t.Fatalf("expected invalid argument for unsupported batch quote, got %v", err)
}
if got := err.Error(); !strings.Contains(got, "intent_ref is required for batch quotation") {
if got := err.Error(); !strings.Contains(got, "batch quotation is not supported for ExecutePayment; use ExecuteBatchPayment") {
t.Fatalf("unexpected error message: %q", got)
}
}
@@ -142,7 +161,6 @@ func TestExecutePayment_RetryThenSuccess(t *testing.T) {
Meta: testMeta(env.orgID, "idem-retry"),
QuotationRef: "quote-retry",
ClientPaymentRef: "client-retry",
IntentRef: "intent-retry",
})
if err != nil {
t.Fatalf("ExecutePayment returned error: %v", err)
@@ -186,7 +204,6 @@ func TestReconcileExternal_AdvancesAsyncPaymentToSettled(t *testing.T) {
Meta: testMeta(env.orgID, "idem-async"),
QuotationRef: "quote-async",
ClientPaymentRef: "client-async",
IntentRef: "intent-async",
})
if err != nil {
t.Fatalf("ExecutePayment returned error: %v", err)

View File

@@ -3,10 +3,9 @@ package qsnap
import "errors"
var (
ErrQuoteNotFound = errors.New("quotation_ref not found")
ErrQuoteExpired = errors.New("quotation_ref expired")
ErrQuoteNotExecutable = errors.New("quotation_ref is not executable")
ErrQuoteShapeMismatch = errors.New("quotation payload shape mismatch")
ErrIntentRefRequired = errors.New("intent_ref is required for batch quotation")
ErrIntentRefNotFound = errors.New("intent_ref not found in quotation")
ErrQuoteNotFound = errors.New("quotation_ref not found")
ErrQuoteExpired = errors.New("quotation_ref expired")
ErrQuoteNotExecutable = errors.New("quotation_ref is not executable")
ErrQuoteShapeMismatch = errors.New("quotation payload shape mismatch")
ErrBatchQuoteUnsupported = errors.New("batch quotation is not supported for ExecutePayment; use ExecuteBatchPayment")
)

View File

@@ -25,13 +25,11 @@ type Resolver interface {
type Input struct {
OrganizationID bson.ObjectID
QuotationRef string
IntentRef string
}
// Output contains extracted canonical snapshots for execution.
type Output struct {
QuotationRef string
IntentRef string
IntentSnapshot model.PaymentIntent
QuoteSnapshot *model.PaymentQuoteSnapshot
}

View File

@@ -142,7 +142,6 @@ func TestResolve_ShapeMismatch(t *testing.T) {
}, Input{
OrganizationID: bson.NewObjectID(),
QuotationRef: "quote-ref",
IntentRef: "intent-1",
})
if !errors.Is(err, ErrQuoteShapeMismatch) {
t.Fatalf("expected ErrQuoteShapeMismatch, got %v", err)

View File

@@ -45,7 +45,6 @@ func TestResolve_SingleShapeOK(t *testing.T) {
}, Input{
OrganizationID: orgID,
QuotationRef: "stored-quote-ref",
IntentRef: "intent-1",
})
if err != nil {
t.Fatalf("Resolve returned error: %v", err)
@@ -59,9 +58,6 @@ func TestResolve_SingleShapeOK(t *testing.T) {
if got, want := out.IntentSnapshot.Ref, "intent-1"; got != want {
t.Fatalf("intent.ref mismatch: got=%q want=%q", got, want)
}
if got, want := out.IntentRef, "intent-1"; got != want {
t.Fatalf("intent_ref mismatch: got=%q want=%q", got, want)
}
if out.QuoteSnapshot == nil {
t.Fatal("expected quote snapshot")
}
@@ -108,9 +104,6 @@ func TestResolve_ArrayShapeOK(t *testing.T) {
if out == nil {
t.Fatal("expected output")
}
if got, want := out.IntentRef, "intent-1"; got != want {
t.Fatalf("intent_ref mismatch: got=%q want=%q", got, want)
}
if got, want := out.IntentSnapshot.Ref, "intent-1"; got != want {
t.Fatalf("intent.ref mismatch: got=%q want=%q", got, want)
}
@@ -122,7 +115,7 @@ func TestResolve_ArrayShapeOK(t *testing.T) {
}
}
func TestResolve_MultiShapeSelectByIntentRef(t *testing.T) {
func TestResolve_MultiShapeRejectedForSingleExecution(t *testing.T) {
now := time.Date(2026, time.January, 2, 3, 4, 5, 0, time.UTC)
orgID := bson.NewObjectID()
@@ -153,91 +146,11 @@ func TestResolve_MultiShapeSelectByIntentRef(t *testing.T) {
}, Input{
OrganizationID: orgID,
QuotationRef: "batch-quote-ref",
IntentRef: "intent-b",
})
if err != nil {
t.Fatalf("Resolve returned error: %v", err)
if out != nil {
t.Fatalf("expected nil output, got %#v", out)
}
if out == nil {
t.Fatal("expected output")
}
if got, want := out.IntentSnapshot.Ref, "intent-b"; got != want {
t.Fatalf("intent.ref mismatch: got=%q want=%q", got, want)
}
if got, want := out.IntentRef, "intent-b"; got != want {
t.Fatalf("intent_ref mismatch: got=%q want=%q", got, want)
}
if out.QuoteSnapshot == nil || out.QuoteSnapshot.DebitAmount == nil {
t.Fatal("expected quote snapshot with debit amount")
}
if got, want := out.QuoteSnapshot.DebitAmount.Amount, "15"; got != want {
t.Fatalf("selected quote mismatch: got=%q want=%q", got, want)
}
}
func TestResolve_MultiShapeRequiresIntentRef(t *testing.T) {
now := time.Date(2026, time.January, 2, 3, 4, 5, 0, time.UTC)
resolver := New(Dependencies{Logger: zap.NewNop(), Now: func() time.Time { return now }})
_, err := resolver.Resolve(context.Background(), &fakeStore{
getByRefFn: func(context.Context, bson.ObjectID, string) (*model.PaymentQuoteRecord, error) {
return &model.PaymentQuoteRecord{
QuoteRef: "quote-ref",
RequestShape: model.QuoteRequestShapeBatch,
Items: []*model.PaymentQuoteItemV2{
{
Intent: &model.PaymentIntent{Ref: "intent-1", Kind: model.PaymentKindPayout},
Quote: &model.PaymentQuoteSnapshot{},
Status: &model.QuoteStatusV2{State: model.QuoteStateExecutable},
},
{
Intent: &model.PaymentIntent{Ref: "intent-2", Kind: model.PaymentKindPayout},
Quote: &model.PaymentQuoteSnapshot{},
Status: &model.QuoteStatusV2{State: model.QuoteStateExecutable},
},
},
ExpiresAt: now.Add(time.Minute),
}, nil
},
}, Input{
OrganizationID: bson.NewObjectID(),
QuotationRef: "quote-ref",
})
if !errors.Is(err, ErrIntentRefRequired) {
t.Fatalf("expected ErrIntentRefRequired, got %v", err)
}
}
func TestResolve_MultiShapeIntentRefNotFound(t *testing.T) {
now := time.Date(2026, time.January, 2, 3, 4, 5, 0, time.UTC)
resolver := New(Dependencies{Logger: zap.NewNop(), Now: func() time.Time { return now }})
_, err := resolver.Resolve(context.Background(), &fakeStore{
getByRefFn: func(context.Context, bson.ObjectID, string) (*model.PaymentQuoteRecord, error) {
return &model.PaymentQuoteRecord{
QuoteRef: "quote-ref",
RequestShape: model.QuoteRequestShapeBatch,
Items: []*model.PaymentQuoteItemV2{
{
Intent: &model.PaymentIntent{Ref: "intent-1", Kind: model.PaymentKindPayout},
Quote: &model.PaymentQuoteSnapshot{},
Status: &model.QuoteStatusV2{State: model.QuoteStateExecutable},
},
{
Intent: &model.PaymentIntent{Ref: "intent-2", Kind: model.PaymentKindPayout},
Quote: &model.PaymentQuoteSnapshot{},
Status: &model.QuoteStatusV2{State: model.QuoteStateExecutable},
},
},
ExpiresAt: now.Add(time.Minute),
}, nil
},
}, Input{
OrganizationID: bson.NewObjectID(),
QuotationRef: "quote-ref",
IntentRef: "intent-3",
})
if !errors.Is(err, ErrIntentRefNotFound) {
t.Fatalf("expected ErrIntentRefNotFound, got %v", err)
if !errors.Is(err, ErrBatchQuoteUnsupported) {
t.Fatalf("expected ErrBatchQuoteUnsupported, got %v", err)
}
}

View File

@@ -35,14 +35,12 @@ func (s *svc) Resolve(
logger.Debug("Starting Resolve",
zap.String("organization_ref", in.OrganizationID.Hex()),
zap.String("quotation_ref", strings.TrimSpace(in.QuotationRef)),
zap.String("intent_ref", strings.TrimSpace(in.IntentRef)),
)
defer func(start time.Time) {
fields := []zap.Field{zap.Int64("duration_ms", time.Since(start).Milliseconds())}
if out != nil {
fields = append(fields,
zap.String("quotation_ref", strings.TrimSpace(out.QuotationRef)),
zap.String("intent_ref", strings.TrimSpace(out.IntentRef)),
)
}
if err != nil {
@@ -63,7 +61,6 @@ func (s *svc) Resolve(
if quoteRef == "" {
return nil, merrors.InvalidArgument("quotation_ref is required")
}
intentRef := strings.TrimSpace(in.IntentRef)
record, err := store.GetByRef(ctx, in.OrganizationID, quoteRef)
if err != nil {
@@ -76,7 +73,7 @@ func (s *svc) Resolve(
return nil, ErrQuoteNotFound
}
item, err := resolveRecordItem(record, intentRef)
item, err := resolveRecordItem(record)
if err != nil {
return nil, err
}
@@ -95,7 +92,6 @@ func (s *svc) Resolve(
out = &Output{
QuotationRef: outputRef,
IntentRef: firstNonEmpty(strings.TrimSpace(item.Intent.Ref), intentRef),
IntentSnapshot: item.Intent,
QuoteSnapshot: item.Quote,
}
@@ -165,7 +161,7 @@ func (s *svc) ResolveAll(
if err := ensureExecutable(record, item.Status, s.now().UTC()); err != nil {
return nil, err
}
resolved, err := resolveItem(item, "")
resolved, err := resolveItem(item)
if err != nil {
return nil, xerr.Wrapf(err, "items[%d]", i)
}
@@ -225,7 +221,7 @@ func ensureExecutable(
}
}
func resolveRecordItem(record *model.PaymentQuoteRecord, intentRef string) (*resolvedQuoteItem, error) {
func resolveRecordItem(record *model.PaymentQuoteRecord) (*resolvedQuoteItem, error) {
if record == nil {
return nil, xerr.Wrapf(ErrQuoteShapeMismatch, "record is nil")
}
@@ -238,42 +234,18 @@ func resolveRecordItem(record *model.PaymentQuoteRecord, intentRef string) (*res
if len(record.Items) != 1 {
return nil, xerr.Wrapf(ErrQuoteShapeMismatch, "single shape requires exactly one item")
}
return resolveItem(record.Items[0], intentRef)
return resolveItem(record.Items[0])
case model.QuoteRequestShapeBatch:
index, err := resolveBatchItemIndex(record.Items, intentRef)
if err != nil {
return nil, err
if len(record.Items) != 1 {
return nil, ErrBatchQuoteUnsupported
}
return resolveItem(record.Items[index], intentRef)
return resolveItem(record.Items[0])
default:
return nil, xerr.Wrapf(ErrQuoteShapeMismatch, "request shape is invalid")
}
}
func resolveBatchItemIndex(items []*model.PaymentQuoteItemV2, intentRef string) (int, error) {
if len(items) == 1 {
if intentRef == "" {
return 0, nil
}
item := items[0]
if item == nil || item.Intent == nil || strings.TrimSpace(item.Intent.Ref) != intentRef {
return -1, xerr.Wrapf(ErrIntentRefNotFound, "%s", intentRef)
}
return 0, nil
}
if intentRef == "" {
return -1, ErrIntentRefRequired
}
index, found := findItemIndex(items, intentRef)
if !found {
return -1, xerr.Wrapf(ErrIntentRefNotFound, "%s", intentRef)
}
return index, nil
}
func resolveItem(item *model.PaymentQuoteItemV2, intentRef string) (*resolvedQuoteItem, error) {
func resolveItem(item *model.PaymentQuoteItemV2) (*resolvedQuoteItem, error) {
if item == nil {
return nil, xerr.Wrapf(ErrQuoteShapeMismatch, "item is nil")
}
@@ -286,9 +258,6 @@ func resolveItem(item *model.PaymentQuoteItemV2, intentRef string) (*resolvedQuo
if item.Status == nil {
return nil, xerr.Wrapf(ErrQuoteShapeMismatch, "status is nil")
}
if intentRef != "" && strings.TrimSpace(item.Intent.Ref) != intentRef {
return nil, xerr.Wrapf(ErrIntentRefNotFound, "%s", intentRef)
}
intentSnapshot, err := cloneIntentSnapshot(*item.Intent)
if err != nil {
@@ -310,32 +279,6 @@ func resolveItem(item *model.PaymentQuoteItemV2, intentRef string) (*resolvedQuo
}, nil
}
func findItemIndex(items []*model.PaymentQuoteItemV2, targetRef string) (int, bool) {
target := strings.TrimSpace(targetRef)
if target == "" {
return -1, false
}
for idx := range items {
item := items[idx]
if item == nil || item.Intent == nil {
continue
}
if strings.TrimSpace(item.Intent.Ref) == target {
return idx, true
}
}
return -1, false
}
func firstNonEmpty(values ...string) string {
for _, value := range values {
if trimmed := strings.TrimSpace(value); trimmed != "" {
return trimmed
}
}
return ""
}
func cloneIntentSnapshot(src model.PaymentIntent) (model.PaymentIntent, error) {
var dst model.PaymentIntent
if err := bsonClone(src, &dst); err != nil {

View File

@@ -16,7 +16,6 @@ type Validator interface {
type Req struct {
Meta *Meta
QuotationRef string
IntentRef string
ClientPaymentRef string
}
@@ -37,7 +36,6 @@ type Ctx struct {
OrganizationID bson.ObjectID
IdempotencyKey string
QuotationRef string
IntentRef string
ClientPaymentRef string
}

View File

@@ -14,7 +14,6 @@ import (
const (
maxIdempotencyKeyLen = 256
maxQuotationRefLen = 128
maxIntentRefLen = 128
maxClientRefLen = 128
)
@@ -33,7 +32,6 @@ func (s *svc) Validate(req *Req) (out *Ctx, err error) {
logger.Debug("Starting Validate",
zap.String("organization_ref", orgRefIn),
zap.String("quotation_ref", strings.TrimSpace(valueOrEmpty(req, func(v *Req) string { return v.QuotationRef }))),
zap.String("intent_ref", strings.TrimSpace(valueOrEmpty(req, func(v *Req) string { return v.IntentRef }))),
zap.Bool("has_idempotency_key", strings.TrimSpace(traceKey(req)) != ""),
)
defer func(start time.Time) {
@@ -42,7 +40,6 @@ func (s *svc) Validate(req *Req) (out *Ctx, err error) {
fields = append(fields,
zap.String("organization_ref", out.OrganizationRef),
zap.String("quotation_ref", out.QuotationRef),
zap.String("intent_ref", out.IntentRef),
zap.Bool("has_client_payment_ref", out.ClientPaymentRef != ""),
)
}
@@ -83,11 +80,6 @@ func (s *svc) Validate(req *Req) (out *Ctx, err error) {
return nil, err
}
intentRef, err := validateRefToken("intent_ref", req.IntentRef, maxIntentRefLen, false)
if err != nil {
return nil, err
}
clientPaymentRef, err := validateRefToken("client_payment_ref", req.ClientPaymentRef, maxClientRefLen, false)
if err != nil {
return nil, err
@@ -98,7 +90,6 @@ func (s *svc) Validate(req *Req) (out *Ctx, err error) {
OrganizationID: orgID,
IdempotencyKey: idempotencyKey,
QuotationRef: quotationRef,
IntentRef: intentRef,
ClientPaymentRef: clientPaymentRef,
}
return out, nil

View File

@@ -19,7 +19,6 @@ func TestValidate_OK(t *testing.T) {
},
},
QuotationRef: " quote-ref-1 ",
IntentRef: " intent-ref-1 ",
ClientPaymentRef: " client.ref-1 ",
})
if err != nil {
@@ -40,9 +39,6 @@ func TestValidate_OK(t *testing.T) {
if got, want := ctx.QuotationRef, "quote-ref-1"; got != want {
t.Fatalf("quotation_ref mismatch: got=%q want=%q", got, want)
}
if got, want := ctx.IntentRef, "intent-ref-1"; got != want {
t.Fatalf("intent_ref mismatch: got=%q want=%q", got, want)
}
if got, want := ctx.ClientPaymentRef, "client.ref-1"; got != want {
t.Fatalf("client_payment_ref mismatch: got=%q want=%q", got, want)
}
@@ -70,16 +66,12 @@ func TestValidate_ClientPaymentRefOptional(t *testing.T) {
if ctx.ClientPaymentRef != "" {
t.Fatalf("expected empty client_payment_ref, got %q", ctx.ClientPaymentRef)
}
if ctx.IntentRef != "" {
t.Fatalf("expected empty intent_ref, got %q", ctx.IntentRef)
}
}
func TestValidate_Errors(t *testing.T) {
orgID := bson.NewObjectID().Hex()
tooLongIdem := "x" + strings.Repeat("a", maxIdempotencyKeyLen)
tooLongQuote := "q" + strings.Repeat("a", maxQuotationRefLen)
tooLongIntent := "i" + strings.Repeat("a", maxIntentRefLen)
tooLongClient := "c" + strings.Repeat("a", maxClientRefLen)
tests := []struct {
@@ -193,28 +185,6 @@ func TestValidate_Errors(t *testing.T) {
ClientPaymentRef: tooLongClient,
},
},
{
name: "too long intent ref",
req: &Req{
Meta: &Meta{
OrganizationRef: orgID,
Trace: &Trace{IdempotencyKey: "idem-1"},
},
QuotationRef: "quote-1",
IntentRef: tooLongIntent,
},
},
{
name: "bad intent ref shape",
req: &Req{
Meta: &Meta{
OrganizationRef: orgID,
Trace: &Trace{IdempotencyKey: "idem-1"},
},
QuotationRef: "quote-1",
IntentRef: "intent ref",
},
},
{
name: "bad client payment ref shape",
req: &Req{

View File

@@ -15,7 +15,7 @@ import (
func TestV2GRPCServerExecutePayment_MapsInvalidArgument(t *testing.T) {
srv := newV2GRPCServer(fakeV2Service{
executeErr: merrors.InvalidArgument("intent_ref is required for batch quotation"),
executeErr: merrors.InvalidArgument("batch quotation is not supported for ExecutePayment; use ExecuteBatchPayment"),
}, zap.NewNop())
_, err := srv.ExecutePayment(context.Background(), &orchestrationv2.ExecutePaymentRequest{})
@@ -25,7 +25,7 @@ func TestV2GRPCServerExecutePayment_MapsInvalidArgument(t *testing.T) {
if got, want := status.Code(err), codes.InvalidArgument; got != want {
t.Fatalf("unexpected grpc status code: got=%s want=%s", got, want)
}
if got := status.Convert(err).Message(); !strings.Contains(got, "intent_ref is required for batch quotation") {
if got := status.Convert(err).Message(); !strings.Contains(got, "batch quotation is not supported for ExecutePayment; use ExecuteBatchPayment") {
t.Fatalf("unexpected grpc status message: %q", got)
}
}