Reason About and Validate Virtual Card Transactions
Capital OneSoftware Engineer · OnsiteLast updated
Implement a policy validation engine for encoded virtual card numbers against incoming transactions, handling rule parsing, Luhn checksum verification, and structured status reporting.
Problem Statement
Virtual card numbers (VCNs) allow customers to generate temporary card numbers with built-in spending controls. You are tasked with implementing a core transaction authorization rule engine that validates an incoming transaction against policy flags encoded directly into a 16-digit virtual card number.
Card Structure (1-based indices)
- Digits 1–4: Issuer prefix. Must be
"4147"or"5200". Any other prefix is considered an unrecognized card format. - Digit 5 (Usage Rule):
'1': Single-use card (only valid ifis_first_useisTrue).'2': Multi-use card (valid regardless ofis_first_use).
- Digit 6 (Channel Rule):
'0': Omnichannel (allowed for all transaction channels).'1': Online-only (channel must be"ONLINE").'2': In-store only (channel must be"IN_STORE").
- Digit 7 (Merchant Category Code / MCC Restriction):
'0': Unrestricted (all MCCs allowed).'1': Travel & Dining (MCCin range[3000, 3999]or[5812, 5814], inclusive).'2': Groceries & Retail (MCCin range[5300, 5499], inclusive).
- Digits 8–11: Spending limit per transaction in whole USD (e.g.,
"0050"means $50.00 = 5000 cents). - Digits 12–15: Random card identifier digits.
- Digit 16: Check digit using the standard Luhn algorithm.
Validation & Evaluation Order
Evaluate the transaction in the following exact order. Return upon the first failure encountered:
- Card Validity: The PAN must be exactly 16 decimal digits, start with a valid prefix, have valid policy codes (digit 5 in
'1'..'2', digit 6 in'0'..'2', digit 7 in'0'..'2'), and satisfy the Luhn algorithm. If any condition fails, return("INVALID", "MALFORMED_CARD"). - Channel Policy: If the transaction channel does not match digit 6, return
("DECLINED", "CHANNEL_NOT_ALLOWED"). - Usage Policy: If digit 5 is
'1'andis_first_useisFalse, return("DECLINED", "CARD_EXHAUSTED"). - Category Policy: If digit 7 restricts MCC and the transaction
mccis outside the permitted ranges, return("DECLINED", "CATEGORY_NOT_ALLOWED"). - Amount Limit: If
amount_cents > limit_dollars * 100, return("DECLINED", "EXCEEDS_LIMIT"). - Approval: If all checks pass, return
("APPROVED", "APPROVAL").
Function Signature
def validate_virtual_card_transaction(
pan: str,
amount_cents: int,
channel: str,
mcc: int,
is_first_use: bool
) -> tuple[str, str]:
pass
Examples
Example 1
# Digit breakdown:
# Prefix: 4147, Usage: 1 (single-use), Channel: 1 (online), Category: 0 (all), Limit: 0100 ($100), Random: 123, Check: 6
pan = "4147110010012346" # Assume valid Luhn check
status, reason = validate_virtual_card_transaction(
pan=pan,
amount_cents=5000,
channel="ONLINE",
mcc=5411,
is_first_use=True
)
# Output: ("APPROVED", "APPROVAL")
Example 2
# Same card, but attempted in-store
status, reason = validate_virtual_card_transaction(
pan="4147110010012346",
amount_cents=5000,
channel="IN_STORE",
mcc=5411,
is_first_use=True
)
# Output: ("DECLINED", "CHANNEL_NOT_ALLOWED")
Constraints
panis a string of arbitrary length and characters.amount_centsis an integer,1 <= amount_cents <= 10_000_000.channelis a string, typically"ONLINE"or"IN_STORE".mccis an integer,1000 <= mcc <= 9999.is_first_useis a boolean.
Hints
Hint 1
Verify string format and compute the Luhn check before attempting to slice rule parameters to prevent indexing errors or invalid state evaluation.
Hint 2
Be mindful of 1-based index descriptions versus 0-based slicing in code: digits 8–11 correspond to python slice `pan[7:11]`.
Hint 3
Implement the policy checks as an early-exit pipeline following the exact sequence defined in the requirements.
Follow-up questions
- How would you design the system to handle cumulative budget limits across multiple transactions instead of per-transaction limits?
- If business stakeholders frequently update MCC groupings or add new restriction categories, how would you refactor the rule engine to avoid hardcoding ranges?
- How would you protect against replay attacks and ensure concurrency safety if multiple authorizations for a single-use card arrive simultaneously?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.