Chimera Settle service
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/tech/sendico/gateway/chsettle/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"
|
||||
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||
"github.com/tech/sendico/pkg/payments/rail"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func isFinalStatus(t *model.PaymentRecord) bool {
|
||||
switch t.Status {
|
||||
case model.PaymentStatusFailed, model.PaymentStatusSuccess, model.PaymentStatusCancelled:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func toOpStatus(t *model.PaymentRecord) (rail.OperationResult, error) {
|
||||
switch t.Status {
|
||||
case model.PaymentStatusFailed:
|
||||
return rail.OperationResultFailed, nil
|
||||
case model.PaymentStatusSuccess:
|
||||
return rail.OperationResultSuccess, nil
|
||||
case model.PaymentStatusCancelled:
|
||||
return rail.OperationResultCancelled, nil
|
||||
default:
|
||||
return rail.OperationResultFailed, merrors.InvalidArgument("unexpected transfer status", "payment.status")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) updateTransferStatus(ctx context.Context, record *model.PaymentRecord) error {
|
||||
if record == nil {
|
||||
return merrors.InvalidArgument("payment record is required", "record")
|
||||
}
|
||||
s.logger.Debug("Persisting transfer status",
|
||||
zap.String("idempotency_key", record.IdempotencyKey),
|
||||
zap.String("payment_ref", record.PaymentIntentID),
|
||||
zap.String("status", string(record.Status)),
|
||||
zap.Bool("is_final", isFinalStatus(record)))
|
||||
if !isFinalStatus(record) {
|
||||
if err := s.repo.Payments().Upsert(ctx, record); err != nil {
|
||||
s.logger.Warn("Failed to update transfer status", zap.String("payment_ref", record.PaymentIntentID), zap.String("status", string(record.Status)), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
s.logger.Debug("Transfer status persisted (non-final)",
|
||||
zap.String("idempotency_key", record.IdempotencyKey),
|
||||
zap.String("status", string(record.Status)))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := s.executeTransaction(ctx, func(txCtx context.Context) (any, error) {
|
||||
if upsertErr := s.repo.Payments().Upsert(txCtx, record); upsertErr != nil {
|
||||
return nil, upsertErr
|
||||
}
|
||||
if isFinalStatus(record) {
|
||||
if emitErr := s.emitTransferStatusEvent(txCtx, record); emitErr != nil {
|
||||
return nil, emitErr
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to update transfer status", zap.String("payment_ref", record.PaymentIntentID), zap.String("status", string(record.Status)), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
s.logger.Info("Transfer status persisted (final)",
|
||||
zap.String("idempotency_key", record.IdempotencyKey),
|
||||
zap.String("status", string(record.Status)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) emitTransferStatusEvent(ctx context.Context, record *model.PaymentRecord) error {
|
||||
if s == nil || record == nil {
|
||||
return nil
|
||||
}
|
||||
if s.producer == nil || s.outboxStore() == nil {
|
||||
return nil
|
||||
}
|
||||
status, err := toOpStatus(record)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to map transfer status for transfer status event", zap.Error(err), mzap.ObjRef("transfer_ref", record.ID))
|
||||
return err
|
||||
}
|
||||
|
||||
exec := pmodel.PaymentGatewayExecution{
|
||||
PaymentIntentID: record.PaymentIntentID,
|
||||
IdempotencyKey: record.IdempotencyKey,
|
||||
ExecutedMoney: record.ExecutedMoney,
|
||||
PaymentRef: record.PaymentRef,
|
||||
Status: status,
|
||||
OperationRef: record.OperationRef,
|
||||
Error: record.FailureReason,
|
||||
TransferRef: record.ID.Hex(),
|
||||
}
|
||||
env := paymentgateway.PaymentGatewayExecution(mservice.ChSettle, &exec)
|
||||
if sendErr := s.sendWithOutbox(ctx, env); sendErr != nil {
|
||||
s.logger.Warn("Failed to publish transfer status event", zap.Error(sendErr), mzap.ObjRef("transfer_ref", record.ID))
|
||||
return sendErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user