fixed mntx payout sequence
This commit is contained in:
@@ -22,6 +22,7 @@ func (s *Service) handleCreateCardPayout(ctx context.Context, req *mntxv1.CardPa
|
||||
log.Info("Create card payout request received",
|
||||
zap.String("payout_id", strings.TrimSpace(req.GetPayoutId())),
|
||||
zap.String("operation_ref", strings.TrimSpace(req.GetOperationRef())),
|
||||
zap.String("parent_payment_ref", strings.TrimSpace(req.GetParentPaymentRef())),
|
||||
zap.String("customer_id", strings.TrimSpace(req.GetCustomerId())),
|
||||
zap.Int64("amount_minor", req.GetAmountMinor()),
|
||||
zap.String("currency", strings.ToUpper(strings.TrimSpace(req.GetCurrency()))),
|
||||
@@ -49,6 +50,7 @@ func (s *Service) handleCreateCardTokenPayout(ctx context.Context, req *mntxv1.C
|
||||
log.Info("Create card token payout request received",
|
||||
zap.String("payout_id", strings.TrimSpace(req.GetPayoutId())),
|
||||
zap.String("operation_ref", strings.TrimSpace(req.GetOperationRef())),
|
||||
zap.String("parent_payment_ref", strings.TrimSpace(req.GetParentPaymentRef())),
|
||||
zap.String("customer_id", strings.TrimSpace(req.GetCustomerId())),
|
||||
zap.Int64("amount_minor", req.GetAmountMinor()),
|
||||
zap.String("currency", strings.ToUpper(strings.TrimSpace(req.GetCurrency()))),
|
||||
@@ -122,6 +124,7 @@ func sanitizeCardPayoutRequest(req *mntxv1.CardPayoutRequest) *mntxv1.CardPayout
|
||||
return req
|
||||
}
|
||||
r.PayoutId = strings.TrimSpace(r.GetPayoutId())
|
||||
r.ParentPaymentRef = strings.TrimSpace(r.GetParentPaymentRef())
|
||||
r.CustomerId = strings.TrimSpace(r.GetCustomerId())
|
||||
r.CustomerFirstName = strings.TrimSpace(r.GetCustomerFirstName())
|
||||
r.CustomerMiddleName = strings.TrimSpace(r.GetCustomerMiddleName())
|
||||
@@ -151,6 +154,7 @@ func sanitizeCardTokenPayoutRequest(req *mntxv1.CardTokenPayoutRequest) *mntxv1.
|
||||
return req
|
||||
}
|
||||
r.PayoutId = strings.TrimSpace(r.GetPayoutId())
|
||||
r.ParentPaymentRef = strings.TrimSpace(r.GetParentPaymentRef())
|
||||
r.CustomerId = strings.TrimSpace(r.GetCustomerId())
|
||||
r.CustomerFirstName = strings.TrimSpace(r.GetCustomerFirstName())
|
||||
r.CustomerMiddleName = strings.TrimSpace(r.GetCustomerMiddleName())
|
||||
|
||||
@@ -17,6 +17,9 @@ func validateCardPayoutRequest(req *mntxv1.CardPayoutRequest, cfg monetix.Config
|
||||
if err := validateOperationIdentity(strings.TrimSpace(req.GetPayoutId()), strings.TrimSpace(req.GetOperationRef())); err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.TrimSpace(req.GetParentPaymentRef()) == "" {
|
||||
return newPayoutError("missing_parent_payment_ref", merrors.InvalidArgument("parent_payment_ref is required", "parent_payment_ref"))
|
||||
}
|
||||
if strings.TrimSpace(req.GetCustomerId()) == "" {
|
||||
return newPayoutError("missing_customer_id", merrors.InvalidArgument("customer_id is required", "customer_id"))
|
||||
}
|
||||
|
||||
@@ -28,6 +28,11 @@ func TestValidateCardPayoutRequest_Errors(t *testing.T) {
|
||||
mutate: func(r *mntxv1.CardPayoutRequest) { r.PayoutId = "" },
|
||||
expected: "missing_operation_ref",
|
||||
},
|
||||
{
|
||||
name: "missing_parent_payment_ref",
|
||||
mutate: func(r *mntxv1.CardPayoutRequest) { r.ParentPaymentRef = "" },
|
||||
expected: "missing_parent_payment_ref",
|
||||
},
|
||||
{
|
||||
name: "both_operation_and_payout_identity",
|
||||
mutate: func(r *mntxv1.CardPayoutRequest) {
|
||||
|
||||
@@ -39,8 +39,6 @@ type cardPayoutProcessor struct {
|
||||
perTxMinAmountMinorByCurrency map[string]int64
|
||||
}
|
||||
|
||||
const parentPaymentRefMetadataKey = "parent_payment_ref"
|
||||
|
||||
func mergePayoutStateWithExisting(state, existing *model.CardPayout) {
|
||||
if state == nil || existing == nil {
|
||||
return
|
||||
@@ -59,7 +57,7 @@ func mergePayoutStateWithExisting(state, existing *model.CardPayout) {
|
||||
if state.IntentRef == "" {
|
||||
state.IntentRef = existing.IntentRef
|
||||
}
|
||||
if state.PaymentRef == "" {
|
||||
if existing.PaymentRef != "" {
|
||||
state.PaymentRef = existing.PaymentRef
|
||||
}
|
||||
}
|
||||
@@ -72,47 +70,6 @@ func findOperationRef(operationRef, payoutID string) string {
|
||||
return strings.TrimSpace(payoutID)
|
||||
}
|
||||
|
||||
func parentPaymentRefFromOperationRef(operationRef string) string {
|
||||
ref := strings.TrimSpace(operationRef)
|
||||
if ref == "" {
|
||||
return ""
|
||||
}
|
||||
if idx := strings.Index(ref, ":hop_"); idx > 0 {
|
||||
return ref[:idx]
|
||||
}
|
||||
if idx := strings.Index(ref, ":"); idx > 0 {
|
||||
return ref[:idx]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func parentPaymentRefFromMetadata(metadata map[string]string) string {
|
||||
if len(metadata) == 0 {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(metadata[parentPaymentRefMetadataKey])
|
||||
}
|
||||
|
||||
func resolveParentPaymentRef(payoutID, operationRef string, metadata map[string]string) string {
|
||||
if parent := parentPaymentRefFromMetadata(metadata); parent != "" {
|
||||
return parent
|
||||
}
|
||||
payoutRef := strings.TrimSpace(payoutID)
|
||||
opRef := strings.TrimSpace(operationRef)
|
||||
|
||||
// Legacy callers may pass parent payment ref via payout_id and a distinct operation_ref.
|
||||
if payoutRef != "" && (opRef == "" || payoutRef != opRef) {
|
||||
return payoutRef
|
||||
}
|
||||
if parent := parentPaymentRefFromOperationRef(opRef); parent != "" {
|
||||
return parent
|
||||
}
|
||||
if payoutRef != "" {
|
||||
return payoutRef
|
||||
}
|
||||
return opRef
|
||||
}
|
||||
|
||||
func (p *cardPayoutProcessor) findExistingPayoutState(ctx context.Context, state *model.CardPayout) (*model.CardPayout, error) {
|
||||
if p == nil || state == nil {
|
||||
return nil, nil
|
||||
@@ -129,23 +86,6 @@ func (p *cardPayoutProcessor) findExistingPayoutState(ctx context.Context, state
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Legacy mode may still map operation ref to payout/payment ref.
|
||||
if paymentRef := strings.TrimSpace(state.PaymentRef); paymentRef == "" || paymentRef != opRef {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if paymentRef := strings.TrimSpace(state.PaymentRef); paymentRef != "" {
|
||||
existing, err := p.store.Payouts().FindByPaymentID(ctx, paymentRef)
|
||||
if err == nil {
|
||||
if existing != nil {
|
||||
return existing, nil
|
||||
}
|
||||
}
|
||||
if !errors.Is(err, merrors.ErrNoData) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -310,7 +250,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
|
||||
req = sanitizeCardPayoutRequest(req)
|
||||
operationRef := findOperationRef(req.GetOperationRef(), req.GetPayoutId())
|
||||
parentPaymentRef := resolveParentPaymentRef(req.GetPayoutId(), operationRef, req.GetMetadata())
|
||||
parentPaymentRef := strings.TrimSpace(req.GetParentPaymentRef())
|
||||
|
||||
p.logger.Info("Submitting card payout",
|
||||
zap.String("parent_payment_ref", parentPaymentRef),
|
||||
@@ -435,7 +375,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
||||
|
||||
req = sanitizeCardTokenPayoutRequest(req)
|
||||
operationRef := findOperationRef(req.GetOperationRef(), req.GetPayoutId())
|
||||
parentPaymentRef := resolveParentPaymentRef(req.GetPayoutId(), operationRef, req.GetMetadata())
|
||||
parentPaymentRef := strings.TrimSpace(req.GetParentPaymentRef())
|
||||
|
||||
p.logger.Info("Submitting card token payout",
|
||||
zap.String("parent_payment_ref", parentPaymentRef),
|
||||
@@ -609,7 +549,7 @@ func (p *cardPayoutProcessor) Status(ctx context.Context, payoutID string) (*mnt
|
||||
}
|
||||
|
||||
id := strings.TrimSpace(payoutID)
|
||||
p.logger.Info("Card payout status requested", zap.String("operation_or_payout_id", id))
|
||||
p.logger.Info("Card payout status requested", zap.String("operation_ref", id))
|
||||
|
||||
if id == "" {
|
||||
p.logger.Warn("Payout status requested with empty payout_id")
|
||||
@@ -622,11 +562,8 @@ func (p *cardPayoutProcessor) Status(ctx context.Context, payoutID string) (*mnt
|
||||
return nil, err
|
||||
}
|
||||
if state == nil || errors.Is(err, merrors.ErrNoData) {
|
||||
state, err = p.store.Payouts().FindByPaymentID(ctx, id)
|
||||
if err != nil || state == nil {
|
||||
p.logger.Warn("Payout status not found", zap.String("operation_or_payout_id", id), zap.Error(err))
|
||||
return nil, merrors.NoData("payout not found")
|
||||
}
|
||||
p.logger.Warn("Payout status not found", zap.String("operation_ref", id))
|
||||
return nil, merrors.NoData("payout not found")
|
||||
}
|
||||
|
||||
p.logger.Info("Card payout status resolved",
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
@@ -45,8 +46,9 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) {
|
||||
|
||||
repo := newMockRepository()
|
||||
repo.payouts.Save(&model.CardPayout{
|
||||
PaymentRef: "payout-1",
|
||||
CreatedAt: existingCreated,
|
||||
PaymentRef: "payment-parent-1",
|
||||
OperationRef: "payout-1",
|
||||
CreatedAt: existingCreated,
|
||||
})
|
||||
|
||||
httpClient := &http.Client{
|
||||
@@ -227,3 +229,173 @@ func TestCardPayoutProcessor_ProcessCallback(t *testing.T) {
|
||||
t.Fatalf("expected success status in model, got %v", state.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCardPayoutProcessor_Submit_SameParentDifferentOperationsStoredSeparately(t *testing.T) {
|
||||
cfg := monetix.Config{
|
||||
BaseURL: "https://monetix.test",
|
||||
SecretKey: "secret",
|
||||
ProjectID: 99,
|
||||
AllowedCurrencies: []string{"RUB"},
|
||||
}
|
||||
|
||||
repo := newMockRepository()
|
||||
var callN int
|
||||
httpClient := &http.Client{
|
||||
Transport: roundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||
callN++
|
||||
resp := monetix.APIResponse{}
|
||||
resp.Operation.RequestID = fmt.Sprintf("req-%d", callN)
|
||||
body, _ := json.Marshal(resp)
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(bytes.NewReader(body)),
|
||||
Header: http.Header{"Content-Type": []string{"application/json"}},
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
processor := newCardPayoutProcessor(
|
||||
zap.NewNop(),
|
||||
cfg,
|
||||
staticClock{now: time.Date(2026, 3, 4, 1, 2, 3, 0, time.UTC)},
|
||||
repo,
|
||||
httpClient,
|
||||
nil,
|
||||
)
|
||||
|
||||
parentPaymentRef := "payment-parent-1"
|
||||
op1 := parentPaymentRef + ":hop_4_card_payout_send"
|
||||
op2 := parentPaymentRef + ":hop_4_card_payout_send_2"
|
||||
|
||||
req1 := validCardPayoutRequest()
|
||||
req1.PayoutId = ""
|
||||
req1.OperationRef = op1
|
||||
req1.IdempotencyKey = "idem-1"
|
||||
req1.ParentPaymentRef = parentPaymentRef
|
||||
req1.CardPan = "2204310000002456"
|
||||
|
||||
req2 := validCardPayoutRequest()
|
||||
req2.PayoutId = ""
|
||||
req2.OperationRef = op2
|
||||
req2.IdempotencyKey = "idem-2"
|
||||
req2.ParentPaymentRef = parentPaymentRef
|
||||
req2.CardPan = "2204320000009754"
|
||||
|
||||
if _, err := processor.Submit(context.Background(), req1); err != nil {
|
||||
t.Fatalf("first submit failed: %v", err)
|
||||
}
|
||||
if _, err := processor.Submit(context.Background(), req2); err != nil {
|
||||
t.Fatalf("second submit failed: %v", err)
|
||||
}
|
||||
|
||||
first, err := repo.payouts.FindByOperationRef(context.Background(), op1)
|
||||
if err != nil || first == nil {
|
||||
t.Fatalf("expected first operation stored, err=%v", err)
|
||||
}
|
||||
second, err := repo.payouts.FindByOperationRef(context.Background(), op2)
|
||||
if err != nil || second == nil {
|
||||
t.Fatalf("expected second operation stored, err=%v", err)
|
||||
}
|
||||
|
||||
if got, want := first.PaymentRef, parentPaymentRef; got != want {
|
||||
t.Fatalf("first parent payment ref mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
if got, want := second.PaymentRef, parentPaymentRef; got != want {
|
||||
t.Fatalf("second parent payment ref mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
if got, want := first.OperationRef, op1; got != want {
|
||||
t.Fatalf("first operation ref mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
if got, want := second.OperationRef, op2; got != want {
|
||||
t.Fatalf("second operation ref mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
if first.ProviderPaymentID == "" || second.ProviderPaymentID == "" {
|
||||
t.Fatalf("expected provider payment ids for both operations")
|
||||
}
|
||||
if first.ProviderPaymentID == second.ProviderPaymentID {
|
||||
t.Fatalf("expected different provider payment ids, got=%q", first.ProviderPaymentID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCardPayoutProcessor_ProcessCallback_UpdatesMatchingOperationWithinSameParent(t *testing.T) {
|
||||
cfg := monetix.Config{
|
||||
SecretKey: "secret",
|
||||
StatusSuccess: "success",
|
||||
StatusProcessing: "processing",
|
||||
AllowedCurrencies: []string{"RUB"},
|
||||
}
|
||||
|
||||
parentPaymentRef := "payment-parent-1"
|
||||
op1 := parentPaymentRef + ":hop_4_card_payout_send"
|
||||
op2 := parentPaymentRef + ":hop_4_card_payout_send_2"
|
||||
now := time.Date(2026, 3, 4, 2, 3, 4, 0, time.UTC)
|
||||
|
||||
repo := newMockRepository()
|
||||
repo.payouts.Save(&model.CardPayout{
|
||||
PaymentRef: parentPaymentRef,
|
||||
OperationRef: op1,
|
||||
Status: model.PayoutStatusWaiting,
|
||||
CreatedAt: now.Add(-time.Minute),
|
||||
UpdatedAt: now.Add(-time.Minute),
|
||||
})
|
||||
repo.payouts.Save(&model.CardPayout{
|
||||
PaymentRef: parentPaymentRef,
|
||||
OperationRef: op2,
|
||||
Status: model.PayoutStatusWaiting,
|
||||
CreatedAt: now.Add(-time.Minute),
|
||||
UpdatedAt: now.Add(-time.Minute),
|
||||
})
|
||||
|
||||
processor := newCardPayoutProcessor(
|
||||
zap.NewNop(),
|
||||
cfg,
|
||||
staticClock{now: now},
|
||||
repo,
|
||||
&http.Client{},
|
||||
nil,
|
||||
)
|
||||
|
||||
cb := baseCallback()
|
||||
cb.Payment.ID = op2
|
||||
cb.Payment.Status = "success"
|
||||
cb.Operation.Status = "success"
|
||||
cb.Operation.Code = "0"
|
||||
cb.Operation.Provider.PaymentID = "provider-op-2"
|
||||
cb.Payment.Sum.Currency = "RUB"
|
||||
|
||||
sig, err := monetix.SignPayload(cb, cfg.SecretKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to sign callback: %v", err)
|
||||
}
|
||||
cb.Signature = sig
|
||||
payload, err := json.Marshal(cb)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal callback: %v", err)
|
||||
}
|
||||
|
||||
status, err := processor.ProcessCallback(context.Background(), payload)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
if status != http.StatusOK {
|
||||
t.Fatalf("expected status ok, got %d", status)
|
||||
}
|
||||
|
||||
first, err := repo.payouts.FindByOperationRef(context.Background(), op1)
|
||||
if err != nil || first == nil {
|
||||
t.Fatalf("expected first operation present, err=%v", err)
|
||||
}
|
||||
second, err := repo.payouts.FindByOperationRef(context.Background(), op2)
|
||||
if err != nil || second == nil {
|
||||
t.Fatalf("expected second operation present, err=%v", err)
|
||||
}
|
||||
|
||||
if got, want := first.Status, model.PayoutStatusWaiting; got != want {
|
||||
t.Fatalf("first operation status mismatch: got=%v want=%v", got, want)
|
||||
}
|
||||
if got, want := second.Status, model.PayoutStatusSuccess; got != want {
|
||||
t.Fatalf("second operation status mismatch: got=%v want=%v", got, want)
|
||||
}
|
||||
if got, want := second.PaymentRef, parentPaymentRef; got != want {
|
||||
t.Fatalf("second parent payment ref mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ func validateCardTokenPayoutRequest(req *mntxv1.CardTokenPayoutRequest, cfg mone
|
||||
if err := validateOperationIdentity(strings.TrimSpace(req.GetPayoutId()), strings.TrimSpace(req.GetOperationRef())); err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.TrimSpace(req.GetParentPaymentRef()) == "" {
|
||||
return newPayoutError("missing_parent_payment_ref", merrors.InvalidArgument("parent_payment_ref is required", "parent_payment_ref"))
|
||||
}
|
||||
if strings.TrimSpace(req.GetCustomerId()) == "" {
|
||||
return newPayoutError("missing_customer_id", merrors.InvalidArgument("customer_id is required", "customer_id"))
|
||||
}
|
||||
|
||||
@@ -28,6 +28,11 @@ func TestValidateCardTokenPayoutRequest_Errors(t *testing.T) {
|
||||
mutate: func(r *mntxv1.CardTokenPayoutRequest) { r.PayoutId = "" },
|
||||
expected: "missing_operation_ref",
|
||||
},
|
||||
{
|
||||
name: "missing_parent_payment_ref",
|
||||
mutate: func(r *mntxv1.CardTokenPayoutRequest) { r.ParentPaymentRef = "" },
|
||||
expected: "missing_parent_payment_ref",
|
||||
},
|
||||
{
|
||||
name: "both_operation_and_payout_identity",
|
||||
mutate: func(r *mntxv1.CardTokenPayoutRequest) {
|
||||
|
||||
@@ -69,18 +69,18 @@ func (s *Service) SubmitOperation(ctx context.Context, req *connectorv1.SubmitOp
|
||||
if err != nil {
|
||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, err.Error(), op, "")}}, nil
|
||||
}
|
||||
parentPaymentRef := strings.TrimSpace(reader.String("parent_payment_ref"))
|
||||
|
||||
payoutID := strings.TrimSpace(reader.String("payout_id"))
|
||||
payoutID = operationIDForRequest(payoutID, operationRef, idempotencyKey)
|
||||
payoutID := operationIDForRequest(operationRef)
|
||||
|
||||
if strings.TrimSpace(reader.String("card_token")) != "" {
|
||||
resp, err := s.CreateCardTokenPayout(ctx, buildCardTokenPayoutRequestFromParams(reader, payoutID, idempotencyKey, operationRef, intentRef, amountMinor, currency))
|
||||
resp, err := s.CreateCardTokenPayout(ctx, buildCardTokenPayoutRequestFromParams(reader, payoutID, parentPaymentRef, idempotencyKey, operationRef, intentRef, amountMinor, currency))
|
||||
if err != nil {
|
||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(mapErrorCode(err), err.Error(), op, "")}}, nil
|
||||
}
|
||||
return &connectorv1.SubmitOperationResponse{Receipt: payoutReceipt(resp.GetPayout())}, nil
|
||||
}
|
||||
cr := buildCardPayoutRequestFromParams(reader, payoutID, idempotencyKey, operationRef, intentRef, amountMinor, currency)
|
||||
cr := buildCardPayoutRequestFromParams(reader, payoutID, parentPaymentRef, idempotencyKey, operationRef, intentRef, amountMinor, currency)
|
||||
resp, err := s.CreateCardPayout(ctx, cr)
|
||||
if err != nil {
|
||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(mapErrorCode(err), err.Error(), op, "")}}, nil
|
||||
@@ -117,6 +117,7 @@ func mntxOperationParams() []*connectorv1.OperationParamSpec {
|
||||
{Key: "card_holder", Type: connectorv1.ParamType_STRING, Required: false},
|
||||
{Key: "amount_minor", Type: connectorv1.ParamType_INT, Required: false},
|
||||
{Key: "project_id", Type: connectorv1.ParamType_INT, Required: false},
|
||||
{Key: "parent_payment_ref", Type: connectorv1.ParamType_STRING, Required: true},
|
||||
{Key: "customer_middle_name", Type: connectorv1.ParamType_STRING, Required: false},
|
||||
{Key: "customer_country", Type: connectorv1.ParamType_STRING, Required: false},
|
||||
{Key: "customer_state", Type: connectorv1.ParamType_STRING, Required: false},
|
||||
@@ -167,24 +168,12 @@ func currencyFromOperation(op *connectorv1.Operation) string {
|
||||
return strings.ToUpper(currency)
|
||||
}
|
||||
|
||||
func operationIDForRequest(payoutID, operationRef, idempotencyKey string) string {
|
||||
if ref := strings.TrimSpace(operationRef); ref != "" {
|
||||
return ref
|
||||
}
|
||||
if ref := strings.TrimSpace(payoutID); ref != "" {
|
||||
return ref
|
||||
}
|
||||
return strings.TrimSpace(idempotencyKey)
|
||||
func operationIDForRequest(operationRef string) string {
|
||||
return strings.TrimSpace(operationRef)
|
||||
}
|
||||
|
||||
func metadataFromReader(reader params.Reader) map[string]string {
|
||||
metadata := reader.StringMap("metadata")
|
||||
if metadata == nil {
|
||||
metadata = map[string]string{}
|
||||
}
|
||||
if parentRef := strings.TrimSpace(reader.String("payout_id")); parentRef != "" && strings.TrimSpace(metadata[parentPaymentRefMetadataKey]) == "" {
|
||||
metadata[parentPaymentRefMetadataKey] = parentRef
|
||||
}
|
||||
if len(metadata) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -192,7 +181,7 @@ func metadataFromReader(reader params.Reader) map[string]string {
|
||||
}
|
||||
|
||||
func buildCardTokenPayoutRequestFromParams(reader params.Reader,
|
||||
payoutID, idempotencyKey, operationRef, intentRef string,
|
||||
payoutID, parentPaymentRef, idempotencyKey, operationRef, intentRef string,
|
||||
amountMinor int64, currency string) *mntxv1.CardTokenPayoutRequest {
|
||||
operationRef = strings.TrimSpace(operationRef)
|
||||
payoutID = strings.TrimSpace(payoutID)
|
||||
@@ -201,6 +190,7 @@ func buildCardTokenPayoutRequestFromParams(reader params.Reader,
|
||||
}
|
||||
req := &mntxv1.CardTokenPayoutRequest{
|
||||
PayoutId: payoutID,
|
||||
ParentPaymentRef: strings.TrimSpace(parentPaymentRef),
|
||||
ProjectId: readerInt64(reader, "project_id"),
|
||||
CustomerId: strings.TrimSpace(reader.String("customer_id")),
|
||||
CustomerFirstName: strings.TrimSpace(reader.String("customer_first_name")),
|
||||
@@ -226,7 +216,7 @@ func buildCardTokenPayoutRequestFromParams(reader params.Reader,
|
||||
}
|
||||
|
||||
func buildCardPayoutRequestFromParams(reader params.Reader,
|
||||
payoutID, idempotencyKey, operationRef, intentRef string,
|
||||
payoutID, parentPaymentRef, idempotencyKey, operationRef, intentRef string,
|
||||
amountMinor int64, currency string) *mntxv1.CardPayoutRequest {
|
||||
operationRef = strings.TrimSpace(operationRef)
|
||||
payoutID = strings.TrimSpace(payoutID)
|
||||
@@ -235,6 +225,7 @@ func buildCardPayoutRequestFromParams(reader params.Reader,
|
||||
}
|
||||
return &mntxv1.CardPayoutRequest{
|
||||
PayoutId: payoutID,
|
||||
ParentPaymentRef: strings.TrimSpace(parentPaymentRef),
|
||||
ProjectId: readerInt64(reader, "project_id"),
|
||||
CustomerId: strings.TrimSpace(reader.String("customer_id")),
|
||||
CustomerFirstName: strings.TrimSpace(reader.String("customer_first_name")),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tech/sendico/gateway/mntx/storage/model"
|
||||
@@ -22,7 +23,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *
|
||||
}
|
||||
|
||||
return &model.CardPayout{
|
||||
PaymentRef: p.PayoutId,
|
||||
PaymentRef: strings.TrimSpace(p.GetParentPaymentRef()),
|
||||
OperationRef: p.GetOperationRef(),
|
||||
IntentRef: p.GetIntentRef(),
|
||||
IdempotencyKey: p.GetIdempotencyKey(),
|
||||
@@ -42,6 +43,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *
|
||||
func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState {
|
||||
return &mntxv1.CardPayoutState{
|
||||
PayoutId: firstNonEmpty(m.OperationRef, m.PaymentRef),
|
||||
ParentPaymentRef: m.PaymentRef,
|
||||
ProjectId: m.ProjectID,
|
||||
CustomerId: m.CustomerID,
|
||||
AmountMinor: m.AmountMinor,
|
||||
|
||||
@@ -36,6 +36,7 @@ func testMonetixConfig() monetix.Config {
|
||||
func validCardPayoutRequest() *mntxv1.CardPayoutRequest {
|
||||
return &mntxv1.CardPayoutRequest{
|
||||
PayoutId: "payout-1",
|
||||
ParentPaymentRef: "payment-parent-1",
|
||||
CustomerId: "cust-1",
|
||||
CustomerFirstName: "Jane",
|
||||
CustomerLastName: "Doe",
|
||||
@@ -52,6 +53,7 @@ func validCardPayoutRequest() *mntxv1.CardPayoutRequest {
|
||||
func validCardTokenPayoutRequest() *mntxv1.CardTokenPayoutRequest {
|
||||
return &mntxv1.CardTokenPayoutRequest{
|
||||
PayoutId: "payout-1",
|
||||
ParentPaymentRef: "payment-parent-1",
|
||||
CustomerId: "cust-1",
|
||||
CustomerFirstName: "Jane",
|
||||
CustomerLastName: "Doe",
|
||||
|
||||
Reference in New Issue
Block a user