fixed operations idempotency

This commit is contained in:
Stephan D
2026-03-04 02:27:12 +01:00
parent f06208348b
commit 8377b6b2af
16 changed files with 353 additions and 80 deletions

View File

@@ -74,7 +74,6 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
stepToken := cardPayoutStepToken(req.Step)
operationRef := cardPayoutOperationRef(req.Payment, stepToken)
payoutRef := cardPayoutRef(req.Payment)
idempotencyKey := cardPayoutIdempotencyKey(req.Payment, stepToken)
projectID := cardPayoutProjectID(req.Payment)
customer := cardPayoutCustomerFromPayment(req.Payment, card, req.Step.Metadata)
@@ -85,7 +84,6 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
var responsePayout *mntxv1.CardPayoutState
if token := strings.TrimSpace(card.Token); token != "" {
resp, createErr := client.CreateCardTokenPayout(ctx, &mntxv1.CardTokenPayoutRequest{
PayoutId: payoutRef,
ProjectId: projectID,
CustomerId: customer.id,
CustomerFirstName: customer.firstName,
@@ -123,7 +121,6 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
return nil, merrors.InvalidArgument("card payout send: card expiry is required")
}
resp, createErr := client.CreateCardPayout(ctx, &mntxv1.CardPayoutRequest{
PayoutId: payoutRef,
ProjectId: projectID,
CustomerId: customer.id,
CustomerFirstName: customer.firstName,
@@ -155,8 +152,8 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s
responsePayout = resp.GetPayout()
}
resolvedPayoutRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetPayoutId()), payoutRef)
resolvedOperationRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetOperationRef()), operationRef)
resolvedPayoutRef := firstNonEmpty(strings.TrimSpace(responsePayout.GetPayoutId()), resolvedOperationRef)
gatewayInstanceID := firstNonEmpty(
strings.TrimSpace(req.Step.InstanceID),
strings.TrimSpace(gateway.InstanceID),
@@ -356,14 +353,6 @@ func cardPayoutOperationRef(payment *agg.Payment, stepToken string) string {
return joinRef(base, stepToken)
}
func cardPayoutRef(payment *agg.Payment) string {
base := ""
if payment != nil {
base = firstNonEmpty(strings.TrimSpace(payment.PaymentRef), strings.TrimSpace(payment.IdempotencyKey), "card_payout")
}
return base
}
func cardPayoutIdempotencyKey(payment *agg.Payment, stepToken string) string {
base := ""
if payment != nil {
@@ -549,6 +538,9 @@ func cardPayoutMetadata(payment *agg.Payment, step xplan.Step) map[string]string
out = map[string]string{}
}
if payment != nil {
if parentPaymentRef := strings.TrimSpace(payment.PaymentRef); parentPaymentRef != "" {
out[settlementMetadataParentPaymentRef] = parentPaymentRef
}
if quoteRef := firstNonEmpty(
strings.TrimSpace(payment.QuotationRef),
strings.TrimSpace(quoteRefFromSnapshot(payment.QuoteSnapshot)),

View File

@@ -122,7 +122,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin
if got, want := dialAddress, "mntx-gateway:50051"; got != want {
t.Fatalf("dial address mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetPayoutId(), "payment-1"; got != want {
if got, want := payoutReq.GetPayoutId(), ""; got != want {
t.Fatalf("payout_id mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetOperationRef(), "payment-1:hop_4_card_payout_send"; got != want {
@@ -143,6 +143,9 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin
if got, want := payoutReq.GetMetadata()[settlementMetadataOutgoingLeg], string(discovery.RailCardPayout); got != want {
t.Fatalf("outgoing_leg metadata mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetMetadata()[settlementMetadataParentPaymentRef], "payment-1"; got != want {
t.Fatalf("parent_payment_ref metadata mismatch: got=%q want=%q", got, want)
}
if len(out.StepExecution.ExternalRefs) != 3 {
t.Fatalf("expected 3 external refs, got=%d", len(out.StepExecution.ExternalRefs))
}
@@ -263,12 +266,18 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t
if got, want := payoutReq.GetCurrency(), "RUB"; got != want {
t.Fatalf("currency mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetPayoutId(), ""; got != want {
t.Fatalf("payout_id mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetCardPan(), "2200700142860162"; got != want {
t.Fatalf("card pan mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetMetadata()[batchmeta.MetaPayoutTargetRef], "recipient-2"; got != want {
t.Fatalf("target_ref metadata mismatch: got=%q want=%q", got, want)
}
if got, want := payoutReq.GetMetadata()[settlementMetadataParentPaymentRef], "payment-2"; got != want {
t.Fatalf("parent_payment_ref metadata mismatch: got=%q want=%q", got, want)
}
}
func TestGatewayCardPayoutExecutor_ExecuteCardPayout_RequiresGatewayRegistry(t *testing.T) {

View File

@@ -15,8 +15,9 @@ import (
)
const (
settlementMetadataQuoteRef = "quote_ref"
settlementMetadataOutgoingLeg = "outgoing_leg"
settlementMetadataQuoteRef = "quote_ref"
settlementMetadataOutgoingLeg = "outgoing_leg"
settlementMetadataParentPaymentRef = "parent_payment_ref"
)
type gatewayProviderSettlementExecutor struct {