👍🎉 First off, thanks for taking the time to contribute! 🎉👍
The following is a set of guidelines for contributing to Cardidy, which are hosted in the D-EDGE Organization on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
This project and everyone participating in it is governed by the D-EDGE Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to softwarecraft@d-edge.com.
Cardidy follows the Conventional commits specification. You can rely on commitizen to help format your commit message.
All C# code should follow the official C# Style rules.
Help and feedback is always welcome and pull requests get accepted.
Here is the contribution flow (more information on dataschool.io):
- Open or answer an issue to discuss the changes
- Fork the project after the change has been formally approved
- Create a feature branch
- Follow the code convention by examining existing code (mostly Microsoft's guidelines)
- Edit the code with the changes
- Add/modify unit tests as required
- Submit your PR against the main branch
PRs can only be approved and merged when all checks succeed (builds on Windows, MacOs and Linux)
In a library like Cardidy, one of the main way to contribute is by adding a new credit card. Below is a step-by-step guide:
- Select a card. Lets say Xxx.
- Clone the project and checkout the
main
branch - From
main
create a new branch namedfeat/addXxx
- Create a card for Xxx
- Open
src/DEdge.Cardidy/Model/Cards.cs
- Add a new record for you card
- Open
internal record Xxx : ALuhnCard
{
public Xxx() : base(CardType.Xxx, prefixes, lengths) { }
}
- Use
ALuhnCard
for a card check withLuhn or
ACard` otherwise. - Create a new
CardType
entry for the new card - Replace
prefixes
with an array ofPaddedRange
, an array ofint
or anint
. - Replace
lengths
with eitherSixteen
,From12To19
,From16To19
, or an array of lengths
For example:
Issuing network | IIN ranges | Active | Length | Validation |
---|---|---|---|---|
Maestro UK | 6759, 676770, 676774[11] | Yes | 12–19 | Luhn algorithm |
Verve | 506099–506198, 650002–650027, 507865-507964 | Yes | 16, 18, 19 | Luhn algorithm |
will be:
internal record MaestroUk : ALuhnCard
{
public MaestroUk() : base(CardType.MaestroUk, new[] { 6759, 676770, 676774 }, From12To19) { }
}
internal record Verve : ALuhnCard
{
public Verve() : base(CardType.Verve, new[] {
new PaddedRange(506099, 506198), new PaddedRange(650002, 650027), new PaddedRange(507865, 507964)
}, new[] { 16, 18, 19 })
{ }
}
-
Then, open
src/DEdge.Cardidy/Cardidy.cs
-
And add the new card to the array
knownCards
-
Test your code
- Open
src/Tests/IdentifyTests.cs
- Add a unit test for your generator:
- Open
[TestCase("676770-0000901089", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901089", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-000090", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-00009012", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-000090123", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901234", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-00009012345", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-000090123456", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901234567", ExpectedResult = CardType.MaestroUk)]
public CardType ShouldIdentifyAsMaestroUk(string cardNumber) => Cardidy.Identify(cardNumber, useCheck: false, ignoreNoise: true).First();
[TestCase("5060990000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("5061230000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("5061980000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500020000000001", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500100000000001", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500270000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500270000000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500020000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
[TestCase("6500100000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
[TestCase("6500270000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
[TestCase("65002700000000000", false, ExpectedResult = new[] { CardType.Discover })]
[TestCase("650027000000000000", false, ExpectedResult = new[] { CardType.Discover })]
[TestCase("6500270000000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
public IEnumerable<CardType> ShouldIdentifyAsVerve(string cardNumber, bool useCheck) => Cardidy.Identify(cardNumber, useCheck: useCheck).ToArray();
- Test your test with
dotnet test
- Push you branch to d-edge/Cardidy and open a Pull Request.
Thank you!
In a library like Cardidy, one of the main way to contribute is by updating a credit card. Below is a step-by-step guide:
- Select a card. Lets say Xxx.
- Clone the project and checkout the
main
branch - From
main
create a new branch namedfeat/updateXxx
- Update a card for Xxx
- Open
src/DEdge.Cardidy/Model/Cards.cs
- Find the existing record for you card
- Open
internal record Xxx : ALuhnCard
{
public Xxx() : base(CardType.Xxx, prefixes, lengths) { }
}
- Use
ALuhnCard
for a card check withLuhn or
ACard` otherwise. - Create a new
CardType
entry for the new card if there is a name change and remove the previous one - Replace
prefixes
with an array ofPaddedRange
, an array ofint
or anint
. - Replace
lengths
with eitherSixteen
,From12To19
,From16To19
, or an array of lengths
For example:
Issuing network | IIN ranges | Active | Length | Validation |
---|---|---|---|---|
Maestro UK | 6759, 676770, 676774 | Yes | 12–19 | Luhn algorithm |
Verve | 506099–506198, 650002–650027 | Yes | 16, 19 | Unknown |
will be:
internal record MaestroUk : ALuhnCard
{
public MaestroUk() : base(CardType.MaestroUk, new[] { 6759, 676770, 676774 }, From12To19) { }
}
internal record Verve : ACard
{
public Verve() : base(
CardType.Verve,
new[] { new PaddedRange(506099, 506198), new PaddedRange(650002, 650027) },
new[] { 16, 19 }) { }
}
-
Then, open
src/DEdge.Cardidy/Cardidy.cs
-
And rename if needed the card in the array
knownCards
-
Test your code
- Open
src/Tests/IdentifyTests.cs
- Update the unit tests of card:
- Open
[TestCase("676770-0000901089", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901089", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-000090", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-00009012", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-000090123", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901234", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-00009012345", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-000090123456", ExpectedResult = CardType.MaestroUk)]
[TestCase("676774-0000901234567", ExpectedResult = CardType.MaestroUk)]
public CardType ShouldIdentifyAsMaestroUk(string cardNumber) => Cardidy.Identify(cardNumber, useCheck: false, ignoreNoise: true).First();
[TestCase("5060990000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("5061230000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("5061980000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500020000000001", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500100000000001", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500270000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500270000000000000", true, ExpectedResult = new[] { CardType.Verve })]
[TestCase("6500020000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
[TestCase("6500100000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
[TestCase("6500270000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
[TestCase("65002700000000000", false, ExpectedResult = new[] { CardType.Discover })]
[TestCase("650027000000000000", false, ExpectedResult = new[] { CardType.Discover })]
[TestCase("6500270000000000000", false, ExpectedResult = new[] { CardType.Verve, CardType.Discover })]
public IEnumerable<CardType> ShouldIdentifyAsVerve(string cardNumber, bool useCheck) => Cardidy.Identify(cardNumber, useCheck: useCheck).ToArray();
- Test your test with
dotnet test
- Push you branch to d-edge/Cardidy and open a Pull Request.
Thank you!