package gateway import ( "context" "strings" "github.com/tech/sendico/gateway/mntx/internal/service/monetix" "github.com/tech/sendico/pkg/api/routers/gsresponse" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/mservice" mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1" "go.uber.org/zap" "google.golang.org/protobuf/proto" ) func (s *Service) CreateCardPayout(ctx context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) { return executeUnary(ctx, s, "CreateCardPayout", s.handleCreateCardPayout, req) } func (s *Service) handleCreateCardPayout(ctx context.Context, req *mntxv1.CardPayoutRequest) gsresponse.Responder[mntxv1.CardPayoutResponse] { log := s.logger.Named("card_payout") log.Info("Create card payout request received", zap.String("payout_id", strings.TrimSpace(req.GetPayoutId())), zap.String("customer_id", strings.TrimSpace(req.GetCustomerId())), zap.Int64("amount_minor", req.GetAmountMinor()), zap.String("currency", strings.ToUpper(strings.TrimSpace(req.GetCurrency()))), ) if s.card == nil { log.Warn("Card payout processor not initialised") return gsresponse.Internal[mntxv1.CardPayoutResponse](s.logger, mservice.MntxGateway, merrors.Internal("card payout processor not initialised")) } resp, err := s.card.Submit(ctx, req) if err != nil { log.Warn("Card payout submission failed", zap.Error(err)) return gsresponse.Auto[mntxv1.CardPayoutResponse](s.logger, mservice.MntxGateway, err) } log.Info("Card payout submission completed", zap.String("payout_id", resp.GetPayout().GetPayoutId()), zap.Bool("accepted", resp.GetAccepted())) return gsresponse.Success(resp) } func (s *Service) CreateCardTokenPayout(ctx context.Context, req *mntxv1.CardTokenPayoutRequest) (*mntxv1.CardTokenPayoutResponse, error) { return executeUnary(ctx, s, "CreateCardTokenPayout", s.handleCreateCardTokenPayout, req) } func (s *Service) handleCreateCardTokenPayout(ctx context.Context, req *mntxv1.CardTokenPayoutRequest) gsresponse.Responder[mntxv1.CardTokenPayoutResponse] { log := s.logger.Named("card_token_payout") log.Info("Create card token payout request received", zap.String("payout_id", strings.TrimSpace(req.GetPayoutId())), zap.String("customer_id", strings.TrimSpace(req.GetCustomerId())), zap.Int64("amount_minor", req.GetAmountMinor()), zap.String("currency", strings.ToUpper(strings.TrimSpace(req.GetCurrency()))), ) if s.card == nil { log.Warn("Card payout processor not initialised") return gsresponse.Internal[mntxv1.CardTokenPayoutResponse](s.logger, mservice.MntxGateway, merrors.Internal("card payout processor not initialised")) } resp, err := s.card.SubmitToken(ctx, req) if err != nil { log.Warn("Card token payout submission failed", zap.Error(err)) return gsresponse.Auto[mntxv1.CardTokenPayoutResponse](s.logger, mservice.MntxGateway, err) } log.Info("Card token payout submission completed", zap.String("payout_id", resp.GetPayout().GetPayoutId()), zap.Bool("accepted", resp.GetAccepted())) return gsresponse.Success(resp) } func (s *Service) CreateCardToken(ctx context.Context, req *mntxv1.CardTokenizeRequest) (*mntxv1.CardTokenizeResponse, error) { return executeUnary(ctx, s, "CreateCardToken", s.handleCreateCardToken, req) } func (s *Service) handleCreateCardToken(ctx context.Context, req *mntxv1.CardTokenizeRequest) gsresponse.Responder[mntxv1.CardTokenizeResponse] { log := s.logger.Named("card_tokenize") log.Info("Create card token request received", zap.String("request_id", strings.TrimSpace(req.GetRequestId())), zap.String("customer_id", strings.TrimSpace(req.GetCustomerId())), ) if s.card == nil { log.Warn("Card payout processor not initialised") return gsresponse.Internal[mntxv1.CardTokenizeResponse](s.logger, mservice.MntxGateway, merrors.Internal("card payout processor not initialised")) } resp, err := s.card.Tokenize(ctx, req) if err != nil { log.Warn("Card tokenization failed", zap.Error(err)) return gsresponse.Auto[mntxv1.CardTokenizeResponse](s.logger, mservice.MntxGateway, err) } log.Info("Card tokenization completed", zap.String("request_id", resp.GetRequestId()), zap.Bool("success", resp.GetSuccess())) return gsresponse.Success(resp) } func (s *Service) GetCardPayoutStatus(ctx context.Context, req *mntxv1.GetCardPayoutStatusRequest) (*mntxv1.GetCardPayoutStatusResponse, error) { return executeUnary(ctx, s, "GetCardPayoutStatus", s.handleGetCardPayoutStatus, req) } func (s *Service) handleGetCardPayoutStatus(_ context.Context, req *mntxv1.GetCardPayoutStatusRequest) gsresponse.Responder[mntxv1.GetCardPayoutStatusResponse] { log := s.logger.Named("card_payout_status") log.Info("Get card payout status request received", zap.String("payout_id", strings.TrimSpace(req.GetPayoutId()))) if s.card == nil { log.Warn("Card payout processor not initialised") return gsresponse.Internal[mntxv1.GetCardPayoutStatusResponse](s.logger, mservice.MntxGateway, merrors.Internal("card payout processor not initialised")) } state, err := s.card.Status(context.Background(), req.GetPayoutId()) if err != nil { log.Warn("Card payout status lookup failed", zap.Error(err)) return gsresponse.Auto[mntxv1.GetCardPayoutStatusResponse](s.logger, mservice.MntxGateway, err) } log.Info("Card payout status retrieved", zap.String("payout_id", state.GetPayoutId()), zap.String("status", state.GetStatus().String())) return gsresponse.Success(&mntxv1.GetCardPayoutStatusResponse{Payout: state}) } func sanitizeCardPayoutRequest(req *mntxv1.CardPayoutRequest) *mntxv1.CardPayoutRequest { if req == nil { return nil } clean := proto.Clone(req) r, ok := clean.(*mntxv1.CardPayoutRequest) if !ok { return req } r.PayoutId = strings.TrimSpace(r.GetPayoutId()) r.CustomerId = strings.TrimSpace(r.GetCustomerId()) r.CustomerFirstName = strings.TrimSpace(r.GetCustomerFirstName()) r.CustomerMiddleName = strings.TrimSpace(r.GetCustomerMiddleName()) r.CustomerLastName = strings.TrimSpace(r.GetCustomerLastName()) r.CustomerIp = strings.TrimSpace(r.GetCustomerIp()) r.CustomerZip = strings.TrimSpace(r.GetCustomerZip()) r.CustomerCountry = strings.TrimSpace(r.GetCustomerCountry()) r.CustomerState = strings.TrimSpace(r.GetCustomerState()) r.CustomerCity = strings.TrimSpace(r.GetCustomerCity()) r.CustomerAddress = strings.TrimSpace(r.GetCustomerAddress()) r.Currency = strings.ToUpper(strings.TrimSpace(r.GetCurrency())) r.CardPan = strings.TrimSpace(r.GetCardPan()) r.CardHolder = strings.TrimSpace(r.GetCardHolder()) return r } func sanitizeCardTokenPayoutRequest(req *mntxv1.CardTokenPayoutRequest) *mntxv1.CardTokenPayoutRequest { if req == nil { return nil } clean := proto.Clone(req) r, ok := clean.(*mntxv1.CardTokenPayoutRequest) if !ok { return req } r.PayoutId = strings.TrimSpace(r.GetPayoutId()) r.CustomerId = strings.TrimSpace(r.GetCustomerId()) r.CustomerFirstName = strings.TrimSpace(r.GetCustomerFirstName()) r.CustomerMiddleName = strings.TrimSpace(r.GetCustomerMiddleName()) r.CustomerLastName = strings.TrimSpace(r.GetCustomerLastName()) r.CustomerIp = strings.TrimSpace(r.GetCustomerIp()) r.CustomerZip = strings.TrimSpace(r.GetCustomerZip()) r.CustomerCountry = strings.TrimSpace(r.GetCustomerCountry()) r.CustomerState = strings.TrimSpace(r.GetCustomerState()) r.CustomerCity = strings.TrimSpace(r.GetCustomerCity()) r.CustomerAddress = strings.TrimSpace(r.GetCustomerAddress()) r.Currency = strings.ToUpper(strings.TrimSpace(r.GetCurrency())) r.CardToken = strings.TrimSpace(r.GetCardToken()) r.CardHolder = strings.TrimSpace(r.GetCardHolder()) r.MaskedPan = strings.TrimSpace(r.GetMaskedPan()) return r } func sanitizeCardTokenizeRequest(req *mntxv1.CardTokenizeRequest) *mntxv1.CardTokenizeRequest { if req == nil { return nil } clean := proto.Clone(req) r, ok := clean.(*mntxv1.CardTokenizeRequest) if !ok { return req } r.RequestId = strings.TrimSpace(r.GetRequestId()) r.CustomerId = strings.TrimSpace(r.GetCustomerId()) r.CustomerFirstName = strings.TrimSpace(r.GetCustomerFirstName()) r.CustomerMiddleName = strings.TrimSpace(r.GetCustomerMiddleName()) r.CustomerLastName = strings.TrimSpace(r.GetCustomerLastName()) r.CustomerIp = strings.TrimSpace(r.GetCustomerIp()) r.CustomerZip = strings.TrimSpace(r.GetCustomerZip()) r.CustomerCountry = strings.TrimSpace(r.GetCustomerCountry()) r.CustomerState = strings.TrimSpace(r.GetCustomerState()) r.CustomerCity = strings.TrimSpace(r.GetCustomerCity()) r.CustomerAddress = strings.TrimSpace(r.GetCustomerAddress()) r.CardPan = strings.TrimSpace(r.GetCardPan()) r.CardHolder = strings.TrimSpace(r.GetCardHolder()) r.CardCvv = strings.TrimSpace(r.GetCardCvv()) if card := r.GetCard(); card != nil { card.Pan = strings.TrimSpace(card.GetPan()) card.CardHolder = strings.TrimSpace(card.GetCardHolder()) card.Cvv = strings.TrimSpace(card.GetCvv()) r.Card = card } return r } func buildCardPayoutRequest(projectID int64, req *mntxv1.CardPayoutRequest) monetix.CardPayoutRequest { card := monetix.Card{ PAN: req.GetCardPan(), Year: int(req.GetCardExpYear()), Month: int(req.GetCardExpMonth()), CardHolder: req.GetCardHolder(), } return monetix.CardPayoutRequest{ General: monetix.General{ ProjectID: projectID, PaymentID: req.GetPayoutId(), }, Customer: monetix.Customer{ ID: req.GetCustomerId(), FirstName: req.GetCustomerFirstName(), Middle: req.GetCustomerMiddleName(), LastName: req.GetCustomerLastName(), IP: req.GetCustomerIp(), Zip: req.GetCustomerZip(), Country: req.GetCustomerCountry(), State: req.GetCustomerState(), City: req.GetCustomerCity(), Address: req.GetCustomerAddress(), }, Payment: monetix.Payment{ Amount: req.GetAmountMinor(), Currency: strings.ToUpper(strings.TrimSpace(req.GetCurrency())), }, Card: card, } } func buildCardTokenPayoutRequest(projectID int64, req *mntxv1.CardTokenPayoutRequest) monetix.CardTokenPayoutRequest { return monetix.CardTokenPayoutRequest{ General: monetix.General{ ProjectID: projectID, PaymentID: req.GetPayoutId(), }, Customer: monetix.Customer{ ID: req.GetCustomerId(), FirstName: req.GetCustomerFirstName(), Middle: req.GetCustomerMiddleName(), LastName: req.GetCustomerLastName(), IP: req.GetCustomerIp(), Zip: req.GetCustomerZip(), Country: req.GetCustomerCountry(), State: req.GetCustomerState(), City: req.GetCustomerCity(), Address: req.GetCustomerAddress(), }, Payment: monetix.Payment{ Amount: req.GetAmountMinor(), Currency: strings.ToUpper(strings.TrimSpace(req.GetCurrency())), }, Token: monetix.Token{ CardToken: req.GetCardToken(), CardHolder: req.GetCardHolder(), MaskedPAN: req.GetMaskedPan(), }, } } func buildCardTokenizeRequest(projectID int64, req *mntxv1.CardTokenizeRequest, card *tokenizeCardInput) monetix.CardTokenizeRequest { tokenizeCard := monetix.CardTokenize{ PAN: card.pan, Year: int(card.year), Month: int(card.month), CardHolder: card.holder, CVV: card.cvv, } return monetix.CardTokenizeRequest{ General: monetix.General{ ProjectID: projectID, PaymentID: req.GetRequestId(), }, Customer: monetix.Customer{ ID: req.GetCustomerId(), FirstName: req.GetCustomerFirstName(), Middle: req.GetCustomerMiddleName(), LastName: req.GetCustomerLastName(), IP: req.GetCustomerIp(), Zip: req.GetCustomerZip(), Country: req.GetCustomerCountry(), State: req.GetCustomerState(), City: req.GetCustomerCity(), Address: req.GetCustomerAddress(), }, Card: tokenizeCard, } }