PaymentCards.Net 0.1.0

dotnet add package PaymentCards.Net --version 0.1.0
                    
NuGet\Install-Package PaymentCards.Net -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PaymentCards.Net" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PaymentCards.Net" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="PaymentCards.Net" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PaymentCards.Net --version 0.1.0
                    
#r "nuget: PaymentCards.Net, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PaymentCards.Net@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PaymentCards.Net&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=PaymentCards.Net&version=0.1.0
                    
Install as a Cake Tool

PaymentCards.NET

Payment card validation and brand detection for .NET. Luhn check, scheme detection (Visa, Mastercard, American Express, Discover, Diners Club, JCB, UnionPay, Maestro, and Verve), expected PAN length and CVV length per scheme, expiry parsing with a past-due check, and a safe formatter that groups digits and masks everything but the last four. Zero external dependencies.

Every established .NET card-validation library on NuGet has gone stale since 2022, and none of them know about Verve, the Interswitch-operated scheme that a large share of Nigerian bank cards are issued on. If your checkout serves Nigerian customers and you route Verve traffic through a Mastercard code path, you get the brand icon wrong and, if you are keying CVV length off scheme, you get validation wrong too. PaymentCards.NET is a small, dependency-free library that treats Verve as a first-class scheme instead of an afterthought.

Install

dotnet add package PaymentCards.Net

Usage

Parse and validate a card in one call

using PaymentCards;

var card = PaymentCard.Parse("5061 8301 0000 1895");

Console.WriteLine(card.Scheme);        // Verve
Console.WriteLine(card.IsLuhnValid);   // True
Console.WriteLine(card.HasValidLength);// True
Console.WriteLine(card.IsValid);       // True
Console.WriteLine(card.MaskedNumber);  // **** **** **** 1895

Validate scheme, length, and CVV independently

using PaymentCards;

var scheme = CardSchemeDetector.Detect(pan);
var cvvIsRightLength = enteredCvv.Length == CardSchemeRules.GetCvvLength(scheme);
var panLengthIsRight = CardSchemeRules.IsValidLength(scheme, pan.Length);
var luhnPasses = LuhnChecksum.IsValid(pan);

Parse an expiry and reject an expired card

using PaymentCards;

var expiry = CardExpiry.Parse("07/26");

if (expiry.IsExpired())
{
    return CheckoutError.CardExpired;
}

Show a card number safely in a UI or a log line

using PaymentCards;

var card = PaymentCard.Parse(rawPan);
logger.LogInformation("Charging {Scheme} card {Masked}", card.Scheme, card.MaskedNumber);
// Charging AmericanExpress card **** ****** *0005

What "valid" means here

PaymentCard.IsValid is true only when all three of these hold:

  • IsLuhnValid: the PAN passes the Luhn checksum (ISO/IEC 7812-1)
  • HasValidLength: the digit count matches a length the detected scheme actually issues
  • the scheme is recognized (not CardScheme.Unknown)

PaymentCard.Parse and TryParse never throw or fail because a card is invalid in this sense. They only throw (Parse) or return false (TryParse) when the input is not structurally parseable at all, meaning it has no digits once spaces and hyphens are stripped. This mirrors how TryParse works across the rest of .NET: parseability and business validity are different questions, and you check IsValid for the second one.

Scheme coverage and the correctness bar

Detection is driven by a single table of published issuer identification number (IIN) ranges covering Visa, Mastercard (including the 2221-2720 second range), American Express, Discover, Diners Club, JCB, UnionPay, Maestro, and Verve (5060, 5061, 5078, and 6500). Verve's ranges are checked before Discover's and Maestro's broader ranges so a Verve PAN never gets misclassified as Mastercard or Discover just because it starts with a digit those schemes also use.

The test suite embeds the standard test card numbers published in Stripe's, Paystack's, and Interswitch's own sandbox documentation as fixtures and asserts exact scheme and Luhn results against them, not against hand-built numbers alone. It also asserts that corrupting a single digit of any of those numbers, at any position, to any other digit, always fails the Luhn check, and that every IIN range boundary resolves to the correct neighboring scheme rather than bleeding into it.

Known tradeoffs

  • Verve ranges are the spec-published blocks, not Interswitch's narrower live ranges. Verve's 5060/5061/5078/6500 prefixes are the ranges documented by the scheme itself. Interswitch's actual issuance is narrower (for example 506099-506198 and 650002-650027 within those blocks), so a genuine Discover PAN starting 6500, or a genuine Maestro PAN in the unassigned part of 5078xx, would misclassify as Verve. If you route real (non-Nigerian) traffic and need to disambiguate at that boundary, narrow CardSchemeCatalog's Verve ranges to your issuer's confirmed set.
  • Valid-length tables are pragmatic, not exhaustive. HasValidLength uses the lengths actually seen on the gateway test fixtures this library validates against: JCB is limited to 16 (JCB also issues up to 19), Discover to 16 and 19 (17 and 18 are omitted), and Diners Club to 14 and 16. A real card at one of the omitted lengths will pass IsLuhnValid but report HasValidLength: false.

Zero dependencies, AOT-friendly

No runtime NuGet dependencies. The library is plain arithmetic and string handling: no reflection, no System.Text.Json, nothing that needs a runtime source generator. It trims and publishes cleanly with Native AOT.

License

MIT. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 124 8/12/2026