109 lines
4.0 KiB
Go
109 lines
4.0 KiB
Go
package gateway
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/gateway/mntx/internal/service/monetix"
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
|
|
)
|
|
|
|
type tokenizeCardInput struct {
|
|
pan string
|
|
month uint32
|
|
year uint32
|
|
holder string
|
|
cvv string
|
|
}
|
|
|
|
func validateCardTokenizeRequest(req *mntxv1.CardTokenizeRequest, cfg monetix.Config) (*tokenizeCardInput, error) {
|
|
if req == nil {
|
|
return nil, newPayoutError("invalid_request", merrors.InvalidArgument("request cannot be empty"))
|
|
}
|
|
if strings.TrimSpace(req.GetRequestId()) == "" {
|
|
return nil, newPayoutError("missing_request_id", merrors.InvalidArgument("request_id is required", "request_id"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerId()) == "" {
|
|
return nil, newPayoutError("missing_customer_id", merrors.InvalidArgument("customer_id is required", "customer_id"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerFirstName()) == "" {
|
|
return nil, newPayoutError("missing_customer_first_name", merrors.InvalidArgument("customer_first_name is required", "customer_first_name"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerLastName()) == "" {
|
|
return nil, newPayoutError("missing_customer_last_name", merrors.InvalidArgument("customer_last_name is required", "customer_last_name"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerIp()) == "" {
|
|
return nil, newPayoutError("missing_customer_ip", merrors.InvalidArgument("customer_ip is required", "customer_ip"))
|
|
}
|
|
|
|
card := extractTokenizeCard(req)
|
|
if card.pan == "" {
|
|
return nil, newPayoutError("missing_card_pan", merrors.InvalidArgument("card_pan is required", "card.pan"))
|
|
}
|
|
if card.holder == "" {
|
|
return nil, newPayoutError("missing_card_holder", merrors.InvalidArgument("card_holder is required", "card.holder"))
|
|
}
|
|
if card.month == 0 || card.month > 12 {
|
|
return nil, newPayoutError("invalid_expiry_month", merrors.InvalidArgument("card_exp_month must be between 1 and 12", "card.exp_month"))
|
|
}
|
|
if card.year == 0 {
|
|
return nil, newPayoutError("invalid_expiry_year", merrors.InvalidArgument("card_exp_year must be provided", "card.exp_year"))
|
|
}
|
|
if card.cvv == "" {
|
|
return nil, newPayoutError("missing_cvv", merrors.InvalidArgument("card_cvv is required", "card.cvv"))
|
|
}
|
|
if expired(card.month, card.year) {
|
|
return nil, newPayoutError("expired_card", merrors.InvalidArgument("card expiry is in the past", "card.expiry"))
|
|
}
|
|
|
|
if cfg.RequireCustomerAddress {
|
|
if strings.TrimSpace(req.GetCustomerCountry()) == "" {
|
|
return nil, newPayoutError("missing_customer_country", merrors.InvalidArgument("customer_country is required", "customer_country"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerCity()) == "" {
|
|
return nil, newPayoutError("missing_customer_city", merrors.InvalidArgument("customer_city is required", "customer_city"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerAddress()) == "" {
|
|
return nil, newPayoutError("missing_customer_address", merrors.InvalidArgument("customer_address is required", "customer_address"))
|
|
}
|
|
if strings.TrimSpace(req.GetCustomerZip()) == "" {
|
|
return nil, newPayoutError("missing_customer_zip", merrors.InvalidArgument("customer_zip is required", "customer_zip"))
|
|
}
|
|
}
|
|
|
|
return card, nil
|
|
}
|
|
|
|
func extractTokenizeCard(req *mntxv1.CardTokenizeRequest) *tokenizeCardInput {
|
|
card := req.GetCard()
|
|
if card != nil {
|
|
return &tokenizeCardInput{
|
|
pan: strings.TrimSpace(card.GetPan()),
|
|
month: card.GetExpMonth(),
|
|
year: card.GetExpYear(),
|
|
holder: strings.TrimSpace(card.GetCardHolder()),
|
|
cvv: strings.TrimSpace(card.GetCvv()),
|
|
}
|
|
}
|
|
return &tokenizeCardInput{
|
|
pan: strings.TrimSpace(req.GetCardPan()),
|
|
month: req.GetCardExpMonth(),
|
|
year: req.GetCardExpYear(),
|
|
holder: strings.TrimSpace(req.GetCardHolder()),
|
|
cvv: strings.TrimSpace(req.GetCardCvv()),
|
|
}
|
|
}
|
|
|
|
func expired(month uint32, year uint32) bool {
|
|
now := time.Now()
|
|
y := int(year)
|
|
m := time.Month(month)
|
|
// Normalize 2-digit years: assume 2000-2099.
|
|
if y < 100 {
|
|
y += 2000
|
|
}
|
|
expiry := time.Date(y, m, 1, 0, 0, 0, 0, time.UTC).AddDate(0, 1, -1)
|
|
return now.After(expiry)
|
|
}
|