Payment Validation Pipeline
·
Interactive Form + Workflow
Card Preview
VISA
•••• •••• •••• ••••
CARDHOLDER
YOUR NAME
EXPIRES
MM/YY
Card Details
Card Number
Expiry
CVV
Cardholder Name
Validate Payment
Validation Pipeline
1
Raw Input
entry
User enters card number, expiry, CVV, and name. Input may contain spaces, dashes, formatting characters.
PAN
Expiry
CVV
Name
2
Sanitization
clean
Strip non-digits from PAN, normalize expiry format, trim whitespace from all fields.
Strip /\D/g
Normalize MM/YY
Trim whitespace
3
Field Validation
verify
Each field validated independently. Errors accumulate — not fail-fast.
Luhn mod-10
BIN detect
Length check
Month 01-12
Not expired
CVV digits
CVV length
Name valid
4
Cross-Validation
correlate
Card type determines CVV length: Amex → 4 digits, others → 3. All errors collected.
CVV ↔ Card Type
Accumulate all
5
Security Layer
protect
PAN never stored. Output masked. No network calls. Pure local validation.
🔒
PAN Storage
Never stored
🛡
Output
Masked only
⚠
Network
Zero calls
✔
PCI DSS
SAQ A-EP
6
Result Assembly
output
Returns { valid, fields, errors[], card }. Masked number + last4 only. Safe to log.
PaymentFormResult
Per-field results
•••• 4242
Sequence Diagram
Client
PaymentForm
CardValidator
Result
submitPayment({ card, expiry, cvv, name })
sanitizeCardNumber(raw)
"4242424242424242"
luhnCheck(digits)
true
detectCardType(digits)
{ visa, cvvLen: 3, lengths: [16] }
IIN/BIN prefix
detection (first 6)
validateExpiry("12/28")
{ valid: true, month: 12, year: 2028 }
CROSS-VALIDATION
validateCVV("123", cardType.cvvLen=3)
{ valid: true }
Amex → 4 digits
Others → 3 digits
validateCardholderName("John Doe")
{ valid: true }
RESULT ASSEMBLY
maskCardNumber(sanitized)
"•••• •••• •••• 4242"
{ valid, fields, errors, card }
PaymentFormResult
Client
PaymentForm
CardValidator
Result
Risk Vectors