Merge pull request 'improved storing' (#456) from mntx-452 into main
All checks were successful
ci/woodpecker/push/gateway_mntx Pipeline was successful
All checks were successful
ci/woodpecker/push/gateway_mntx Pipeline was successful
Reviewed-on: #456
This commit was merged in pull request #456.
This commit is contained in:
@@ -51,13 +51,13 @@ func (s *cardPayoutStore) FindByPaymentID(_ context.Context, id string) (*model.
|
||||
}
|
||||
|
||||
func (s *cardPayoutStore) Upsert(_ context.Context, record *model.CardPayout) error {
|
||||
s.data[record.PayoutID] = record
|
||||
s.data[record.PaymentRef] = record
|
||||
return nil
|
||||
}
|
||||
|
||||
// Save is a helper for tests to pre-populate data.
|
||||
func (s *cardPayoutStore) Save(state *model.CardPayout) {
|
||||
s.data[state.PayoutID] = state
|
||||
s.data[state.PaymentRef] = state
|
||||
}
|
||||
|
||||
// Get is a helper for tests to retrieve data.
|
||||
|
||||
@@ -92,7 +92,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
Base: storable.Base{
|
||||
ID: bson.NilObjectID,
|
||||
},
|
||||
PayoutID: strings.TrimSpace(req.GetPayoutId()),
|
||||
PaymentRef: strings.TrimSpace(req.GetPayoutId()),
|
||||
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
||||
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
||||
IntentRef: strings.TrimSpace(req.GetIntentRef()),
|
||||
@@ -106,7 +106,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
}
|
||||
|
||||
// Keep CreatedAt/refs if record already exists.
|
||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PayoutID); err == nil && existing != nil {
|
||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PaymentRef); err == nil && existing != nil {
|
||||
if !existing.CreatedAt.IsZero() {
|
||||
state.CreatedAt = existing.CreatedAt
|
||||
}
|
||||
@@ -130,7 +130,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
if e := p.updatePayoutStatus(ctx, state); e != nil {
|
||||
p.logger.Warn("Failed to update payout status",
|
||||
zap.Error(e),
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("customer_id", state.CustomerID),
|
||||
zap.String("operation_ref", state.OperationRef),
|
||||
zap.String("idempotency_key", state.IdempotencyKey),
|
||||
@@ -141,7 +141,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
|
||||
p.logger.Warn("Monetix payout submission failed",
|
||||
zap.Error(err),
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("customer_id", state.CustomerID),
|
||||
zap.String("operation_ref", state.OperationRef),
|
||||
zap.String("idempotency_key", state.IdempotencyKey),
|
||||
@@ -166,7 +166,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
if err := p.updatePayoutStatus(ctx, state); err != nil {
|
||||
p.logger.Warn("Failed to store payout",
|
||||
zap.Error(err),
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("customer_id", state.CustomerID),
|
||||
zap.String("operation_ref", state.OperationRef),
|
||||
zap.String("idempotency_key", state.IdempotencyKey),
|
||||
@@ -183,7 +183,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
||||
}
|
||||
|
||||
p.logger.Info("Card payout submission stored",
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("status", string(state.Status)),
|
||||
zap.Bool("accepted", result.Accepted),
|
||||
zap.String("provider_request_id", result.ProviderRequestID),
|
||||
@@ -233,7 +233,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
||||
|
||||
now := p.clock.Now()
|
||||
state := &model.CardPayout{
|
||||
PayoutID: strings.TrimSpace(req.GetPayoutId()),
|
||||
PaymentRef: strings.TrimSpace(req.GetPayoutId()),
|
||||
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
||||
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
||||
ProjectID: projectID,
|
||||
@@ -245,7 +245,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PayoutID); err == nil && existing != nil {
|
||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PaymentRef); err == nil && existing != nil {
|
||||
if !existing.CreatedAt.IsZero() {
|
||||
state.CreatedAt = existing.CreatedAt
|
||||
}
|
||||
@@ -269,7 +269,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
||||
_ = p.updatePayoutStatus(ctx, state)
|
||||
|
||||
p.logger.Warn("Monetix token payout submission failed",
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("customer_id", state.CustomerID),
|
||||
zap.Error(err),
|
||||
)
|
||||
@@ -301,7 +301,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
||||
}
|
||||
|
||||
p.logger.Info("Card token payout submission stored",
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("status", string(state.Status)),
|
||||
zap.Bool("accepted", result.Accepted),
|
||||
zap.String("provider_request_id", result.ProviderRequestID),
|
||||
@@ -396,7 +396,7 @@ func (p *cardPayoutProcessor) Status(ctx context.Context, payoutID string) (*mnt
|
||||
}
|
||||
|
||||
p.logger.Info("Card payout status resolved",
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("status", string(state.Status)),
|
||||
)
|
||||
|
||||
@@ -449,10 +449,10 @@ func (p *cardPayoutProcessor) ProcessCallback(ctx context.Context, payload []byt
|
||||
state := CardPayoutStateFromProto(p.clock, pbState)
|
||||
|
||||
// Preserve CreatedAt + internal keys from existing record if present.
|
||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PayoutID); err != nil {
|
||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PaymentRef); err != nil {
|
||||
p.logger.Warn("Failed to fetch payout state while processing callback",
|
||||
zap.Error(err),
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
)
|
||||
return http.StatusInternalServerError, err
|
||||
} else if existing != nil {
|
||||
@@ -477,7 +477,7 @@ func (p *cardPayoutProcessor) ProcessCallback(ctx context.Context, payload []byt
|
||||
monetix.ObserveCallback(statusLabel)
|
||||
|
||||
p.logger.Info("Monetix payout callback processed",
|
||||
zap.String("payout_id", state.PayoutID),
|
||||
zap.String("payment_ref", state.PaymentRef),
|
||||
zap.String("status", statusLabel),
|
||||
zap.String("provider_code", state.ProviderCode),
|
||||
zap.String("provider_message", state.ProviderMessage),
|
||||
|
||||
@@ -44,8 +44,8 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) {
|
||||
|
||||
repo := newMockRepository()
|
||||
repo.payouts.Save(&model.CardPayout{
|
||||
PayoutID: "payout-1",
|
||||
CreatedAt: existingCreated,
|
||||
PaymentRef: "payout-1",
|
||||
CreatedAt: existingCreated,
|
||||
})
|
||||
|
||||
httpClient := &http.Client{
|
||||
|
||||
@@ -22,7 +22,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *
|
||||
}
|
||||
|
||||
return &model.CardPayout{
|
||||
PayoutID: p.PayoutId,
|
||||
PaymentRef: p.PayoutId,
|
||||
OperationRef: p.GetOperationRef(),
|
||||
IntentRef: p.GetIntentRef(),
|
||||
IdempotencyKey: p.GetIdempotencyKey(),
|
||||
@@ -41,7 +41,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *
|
||||
|
||||
func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState {
|
||||
return &mntxv1.CardPayoutState{
|
||||
PayoutId: m.PayoutID,
|
||||
PayoutId: m.PaymentRef,
|
||||
ProjectId: m.ProjectID,
|
||||
CustomerId: m.CustomerID,
|
||||
AmountMinor: m.AmountMinor,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tech/sendico/gateway/mntx/storage/model"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
paymentgateway "github.com/tech/sendico/pkg/messaging/notifications/paymentgateway"
|
||||
pmodel "github.com/tech/sendico/pkg/model"
|
||||
"github.com/tech/sendico/pkg/mservice"
|
||||
@@ -23,23 +24,23 @@ func isFinalStatus(t *model.CardPayout) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func toOpStatus(t *model.CardPayout) rail.OperationResult {
|
||||
func toOpStatus(t *model.CardPayout) (rail.OperationResult, error) {
|
||||
switch t.Status {
|
||||
case model.PayoutStatusFailed:
|
||||
return rail.OperationResultFailed
|
||||
return rail.OperationResultFailed, nil
|
||||
case model.PayoutStatusSuccess:
|
||||
return rail.OperationResultSuccess
|
||||
return rail.OperationResultSuccess, nil
|
||||
case model.PayoutStatusCancelled:
|
||||
return rail.OperationResultCancelled
|
||||
return rail.OperationResultCancelled, nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected transfer status, %s", t.Status))
|
||||
return rail.OperationResultFailed, merrors.InvalidArgument(fmt.Sprintf("unexpected transfer status, %s", t.Status), "t.Status")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *cardPayoutProcessor) updatePayoutStatus(ctx context.Context, state *model.CardPayout) error {
|
||||
if err := p.store.Payouts().Upsert(ctx, state); err != nil {
|
||||
p.logger.Warn("Failed to update transfer status", zap.Error(err), mzap.ObjRef("payout_ref", state.ID),
|
||||
zap.String("transfer_ref", state.PayoutID), zap.String("status", string(state.Status)),
|
||||
zap.String("payment_ref", state.PaymentRef), zap.String("status", string(state.Status)),
|
||||
)
|
||||
}
|
||||
if isFinalStatus(state) {
|
||||
@@ -53,6 +54,13 @@ func (p *cardPayoutProcessor) emitTransferStatusEvent(payout *model.CardPayout)
|
||||
return
|
||||
}
|
||||
|
||||
status, err := toOpStatus(payout)
|
||||
if err != nil {
|
||||
p.logger.Warn("Failed to convert payout status to operation status for transfer status event", zap.Error(err),
|
||||
mzap.ObjRef("payout_ref", payout.ID), zap.String("payment_ref", payout.PaymentRef), zap.String("status", string(payout.Status)))
|
||||
return
|
||||
}
|
||||
|
||||
exec := pmodel.PaymentGatewayExecution{
|
||||
PaymentIntentID: payout.IntentRef,
|
||||
IdempotencyKey: payout.IdempotencyKey,
|
||||
@@ -61,7 +69,7 @@ func (p *cardPayoutProcessor) emitTransferStatusEvent(payout *model.CardPayout)
|
||||
Currency: payout.Currency,
|
||||
},
|
||||
PaymentRef: payout.PaymentRef,
|
||||
Status: toOpStatus(payout),
|
||||
Status: status,
|
||||
OperationRef: payout.OperationRef,
|
||||
Error: payout.FailureReason,
|
||||
TransferRef: payout.GetID().Hex(),
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
// CardPayout is a Mongo/JSON representation of proto CardPayout
|
||||
type CardPayout struct {
|
||||
storable.Base `bson:",inline" json:",inline"`
|
||||
PayoutID string `bson:"payoutId" json:"payout_id"`
|
||||
PaymentRef string `bson:"paymentRef" json:"payment_ref"`
|
||||
OperationRef string `bson:"operationRef" json:"operation_ref"`
|
||||
IdempotencyKey string `bson:"idempotencyKey" json:"idempotency_key"`
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
const (
|
||||
payoutsCollection = "card_payouts"
|
||||
payoutIdemField = "idempotencyKey"
|
||||
payoutIdField = "payoutId"
|
||||
payoutIdField = "paymentRef"
|
||||
)
|
||||
|
||||
type Payouts struct {
|
||||
@@ -74,7 +74,7 @@ func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error {
|
||||
}
|
||||
|
||||
record.OperationRef = strings.TrimSpace(record.OperationRef)
|
||||
record.PayoutID = strings.TrimSpace(record.PayoutID)
|
||||
record.PaymentRef = strings.TrimSpace(record.PaymentRef)
|
||||
record.CustomerID = strings.TrimSpace(record.CustomerID)
|
||||
record.ProviderCode = strings.TrimSpace(record.ProviderCode)
|
||||
record.ProviderPaymentID = strings.TrimSpace(record.ProviderPaymentID)
|
||||
@@ -86,7 +86,7 @@ func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error {
|
||||
|
||||
if err := p.repository.Upsert(ctx, record); err != nil {
|
||||
p.logger.Warn("Failed to upsert payout record", zap.Error(err), mzap.ObjRef("payout_ref", record.ID),
|
||||
zap.String("operation_ref", record.OperationRef), zap.String("payment_ref", record.PayoutID))
|
||||
zap.String("operation_ref", record.OperationRef), zap.String("payment_ref", record.PaymentRef))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user