diff --git a/QRCoder/PayloadGenerator.cs b/QRCoder/PayloadGenerator.cs index acc9d45d..ce465401 100644 --- a/QRCoder/PayloadGenerator.cs +++ b/QRCoder/PayloadGenerator.cs @@ -65,6 +65,18 @@ private static bool IsValidQRIban(string iban) private static bool IsValidBic(string bic) => Regex.IsMatch(bic.Replace(" ", ""), @"^([a-zA-Z]{4}[a-zA-Z]{2}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?)$"); + /// + /// Validates the structure of a BIC with optional requirement check. + /// + /// The BIC to validate. + /// Whether the BIC is required. If false, null/empty values are considered valid. + /// True if the BIC is valid; otherwise, false. + private static bool IsValidBic(string? bic, bool required) + { + if (string.IsNullOrEmpty(bic)) + return !required; + return IsValidBic(bic!); + } /// /// Converts a string to a specified encoding. diff --git a/QRCoder/PayloadGenerator/Girocode.cs b/QRCoder/PayloadGenerator/Girocode.cs index 66d4a7a7..54c06671 100644 --- a/QRCoder/PayloadGenerator/Girocode.cs +++ b/QRCoder/PayloadGenerator/Girocode.cs @@ -36,16 +36,16 @@ public class Girocode : Payload /// Girocode version. Either 001 or 002. Default: 001. /// Encoding of the Girocode payload. Default: ISO-8859-1 /// Thrown when the input values are not valid according to the Girocode specification. - public Girocode(string iban, string bic, string name, decimal amount, string remittanceInformation = "", TypeOfRemittance typeOfRemittance = TypeOfRemittance.Unstructured, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", GirocodeVersion version = GirocodeVersion.Version1, GirocodeEncoding encoding = GirocodeEncoding.ISO_8859_1) + public Girocode(string iban, string? bic, string name, decimal amount, string remittanceInformation = "", TypeOfRemittance typeOfRemittance = TypeOfRemittance.Unstructured, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", GirocodeVersion version = GirocodeVersion.Version1, GirocodeEncoding encoding = GirocodeEncoding.ISO_8859_1) { _version = version; _encoding = encoding; if (!IsValidIban(iban)) throw new GirocodeException("The IBAN entered isn't valid."); _iban = iban.Replace(" ", "").ToUpper(); - if (!IsValidBic(bic)) + if (!IsValidBic(bic, _version == GirocodeVersion.Version1)) throw new GirocodeException("The BIC entered isn't valid."); - _bic = bic.Replace(" ", "").ToUpper(); + _bic = bic?.Replace(" ", "").ToUpper() ?? string.Empty; if (name.Length > 70) throw new GirocodeException("(Payee-)Name must be shorter than 71 chars."); _name = name; diff --git a/QRCoderApiTests/net35+net40+net50+net50-windows+netstandard20+netstandard21/QRCoder.approved.txt b/QRCoderApiTests/net35+net40+net50+net50-windows+netstandard20+netstandard21/QRCoder.approved.txt index ef3ca5d7..a700b557 100644 --- a/QRCoderApiTests/net35+net40+net50+net50-windows+netstandard20+netstandard21/QRCoder.approved.txt +++ b/QRCoderApiTests/net35+net40+net50+net50-windows+netstandard20+netstandard21/QRCoder.approved.txt @@ -456,7 +456,7 @@ namespace QRCoder } public class Girocode : QRCoder.PayloadGenerator.Payload { - public Girocode(string iban, string bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } + public Girocode(string iban, string? bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } public override QRCoder.QRCodeGenerator.ECCLevel EccLevel { get; } public override string ToString() { } public enum GirocodeEncoding diff --git a/QRCoderApiTests/net60-windows/QRCoder.approved.txt b/QRCoderApiTests/net60-windows/QRCoder.approved.txt index 10d94672..d50a8826 100644 --- a/QRCoderApiTests/net60-windows/QRCoder.approved.txt +++ b/QRCoderApiTests/net60-windows/QRCoder.approved.txt @@ -461,7 +461,7 @@ namespace QRCoder } public class Girocode : QRCoder.PayloadGenerator.Payload { - public Girocode(string iban, string bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } + public Girocode(string iban, string? bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } public override QRCoder.QRCodeGenerator.ECCLevel EccLevel { get; } public override string ToString() { } public enum GirocodeEncoding diff --git a/QRCoderApiTests/net60/QRCoder.approved.txt b/QRCoderApiTests/net60/QRCoder.approved.txt index 76a2b1aa..1db2dc0a 100644 --- a/QRCoderApiTests/net60/QRCoder.approved.txt +++ b/QRCoderApiTests/net60/QRCoder.approved.txt @@ -419,7 +419,7 @@ namespace QRCoder } public class Girocode : QRCoder.PayloadGenerator.Payload { - public Girocode(string iban, string bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } + public Girocode(string iban, string? bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } public override QRCoder.QRCodeGenerator.ECCLevel EccLevel { get; } public override string ToString() { } public enum GirocodeEncoding diff --git a/QRCoderApiTests/netstandard13/QRCoder.approved.txt b/QRCoderApiTests/netstandard13/QRCoder.approved.txt index 5c13586a..d8a1d7e6 100644 --- a/QRCoderApiTests/netstandard13/QRCoder.approved.txt +++ b/QRCoderApiTests/netstandard13/QRCoder.approved.txt @@ -399,7 +399,7 @@ namespace QRCoder } public class Girocode : QRCoder.PayloadGenerator.Payload { - public Girocode(string iban, string bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } + public Girocode(string iban, string? bic, string name, decimal amount, string remittanceInformation = "", QRCoder.PayloadGenerator.Girocode.TypeOfRemittance typeOfRemittance = 1, string purposeOfCreditTransfer = "", string messageToGirocodeUser = "", QRCoder.PayloadGenerator.Girocode.GirocodeVersion version = 0, QRCoder.PayloadGenerator.Girocode.GirocodeEncoding encoding = 1) { } public override QRCoder.QRCodeGenerator.ECCLevel EccLevel { get; } public override string ToString() { } public enum GirocodeEncoding diff --git a/QRCoderTests/PayloadGeneratorTests/GirocodeTests.cs b/QRCoderTests/PayloadGeneratorTests/GirocodeTests.cs index 82df3eac..95d40c6d 100644 --- a/QRCoderTests/PayloadGeneratorTests/GirocodeTests.cs +++ b/QRCoderTests/PayloadGeneratorTests/GirocodeTests.cs @@ -321,4 +321,138 @@ public void girocode_generator_sets_encoding_parameters() payload.EciMode.ShouldBe(EciMode.Default); payload.Version.ShouldBe(-1); } + + [Fact] + public void girocode_generator_version2_with_null_bic_should_succeed() + { + var iban = "NL86INGB0002445588"; + var name = "a name"; + var remittanceInformation = "some info"; + var amount = 1337.99m; + + var payload = new PayloadGenerator.Girocode( + iban: iban, + bic: null, + name: name, + amount: amount, + remittanceInformation: remittanceInformation, + version: PayloadGenerator.Girocode.GirocodeVersion.Version2, + encoding: PayloadGenerator.Girocode.GirocodeEncoding.UTF_8); + + payload + .ToString() + .ShouldBe("BCD\n002\n1\nSCT\n\na name\nNL86INGB0002445588\nEUR1337.99\n\n\nsome info\n"); + } + + [Fact] + public void girocode_generator_version2_with_empty_bic_should_succeed() + { + var iban = "NL86INGB0002445588"; + var name = "a name"; + var remittanceInformation = "some info"; + var amount = 1337.99m; + + var payload = new PayloadGenerator.Girocode( + iban: iban, + bic: string.Empty, + name: name, + amount: amount, + remittanceInformation: remittanceInformation, + version: PayloadGenerator.Girocode.GirocodeVersion.Version2, + encoding: PayloadGenerator.Girocode.GirocodeEncoding.UTF_8); + + payload + .ToString() + .ShouldBe("BCD\n002\n1\nSCT\n\na name\nNL86INGB0002445588\nEUR1337.99\n\n\nsome info\n"); + } + + [Fact] + public void girocode_generator_version2_with_valid_bic_should_succeed() + { + var iban = "NL86INGB0002445588"; + var bic = "INGBNL2A"; + var name = "a name"; + var remittanceInformation = "some info"; + var amount = 1337.99m; + + var payload = new PayloadGenerator.Girocode( + iban: iban, + bic: bic, + name: name, + amount: amount, + remittanceInformation: remittanceInformation, + version: PayloadGenerator.Girocode.GirocodeVersion.Version2, + encoding: PayloadGenerator.Girocode.GirocodeEncoding.UTF_8); + + payload + .ToString() + .ShouldBe("BCD\n002\n1\nSCT\nINGBNL2A\na name\nNL86INGB0002445588\nEUR1337.99\n\n\nsome info\n"); + } + + [Fact] + public void girocode_generator_version2_with_invalid_bic_should_throw_exception() + { + var iban = "NL86INGB0002445588"; + var bic = "INVALID"; + var name = "a name"; + var remittanceInformation = "some info"; + var amount = 1337.99m; + + var exception = Record.Exception(() => new PayloadGenerator.Girocode( + iban: iban, + bic: bic, + name: name, + amount: amount, + remittanceInformation: remittanceInformation, + version: PayloadGenerator.Girocode.GirocodeVersion.Version2, + encoding: PayloadGenerator.Girocode.GirocodeEncoding.UTF_8)); + + Assert.NotNull(exception); + Assert.IsType(exception); + exception.Message.ShouldBe("The BIC entered isn't valid."); + } + + [Fact] + public void girocode_generator_version1_with_null_bic_should_throw_exception() + { + var iban = "NL86INGB0002445588"; + var name = "a name"; + var remittanceInformation = "some info"; + var amount = 1337.99m; + + var exception = Record.Exception(() => new PayloadGenerator.Girocode( + iban: iban, + bic: null, + name: name, + amount: amount, + remittanceInformation: remittanceInformation, + version: PayloadGenerator.Girocode.GirocodeVersion.Version1, + encoding: PayloadGenerator.Girocode.GirocodeEncoding.UTF_8)); + + Assert.NotNull(exception); + Assert.IsType(exception); + exception.Message.ShouldBe("The BIC entered isn't valid."); + } + + [Fact] + public void girocode_generator_version1_with_empty_bic_should_throw_exception() + { + var iban = "NL86INGB0002445588"; + var name = "a name"; + var remittanceInformation = "some info"; + var amount = 1337.99m; + + var exception = Record.Exception(() => new PayloadGenerator.Girocode( + iban: iban, + bic: string.Empty, + name: name, + amount: amount, + remittanceInformation: remittanceInformation, + version: PayloadGenerator.Girocode.GirocodeVersion.Version1, + encoding: PayloadGenerator.Girocode.GirocodeEncoding.UTF_8)); + + Assert.NotNull(exception); + Assert.IsType(exception); + exception.Message.ShouldBe("The BIC entered isn't valid."); + } }