Skip to content

Commit 8742e07

Browse files
authored
Merge pull request #498 from codebude/feature/392-fix-and-improve-payment-payload-generator-validation
Feature/392 fix and improve payment payload generator validation
2 parents efc73cf + 25455b8 commit 8742e07

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

QRCoder/PayloadGenerator.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,13 @@ public override string ToString()
25122512

25132513
public byte[] ToBytes()
25142514
{
2515+
//Setup byte encoder
2516+
//Encode return string as byte[] with correct CharacterSet
2517+
#if !NET35_OR_GREATER
2518+
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
2519+
#endif
2520+
var cp = this.characterSet.ToString().Replace("_", "-");
2521+
25152522
//Calculate the seperator
25162523
separator = DetermineSeparator();
25172524

@@ -2523,21 +2530,19 @@ public byte[] ToBytes()
25232530
$"{separator}BIC={mFields.BIC}" +
25242531
$"{separator}CorrespAcc={mFields.CorrespAcc}";
25252532

2533+
//Check length of mandatory field block (-8 => Removing service data block bytes from ret length)
2534+
int bytesMandatoryLen = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(cp), Encoding.UTF8.GetBytes(ret)).Length - 8;
2535+
if (bytesMandatoryLen > 300)
2536+
throw new RussiaPaymentOrderException($"Data too long. Mandatory data must not exceed 300 bytes, but actually is {bytesMandatoryLen} bytes long. Remove additional data fields or shorten strings/values.");
2537+
2538+
25262539
//Add optional fields, if filled
25272540
var optionalFieldsList = GetOptionalFieldsAsList();
25282541
if (optionalFieldsList.Count > 0)
25292542
ret += $"|{string.Join("|", optionalFieldsList.ToArray())}";
25302543
ret += separator;
25312544

2532-
//Encode return string as byte[] with correct CharacterSet
2533-
#if !NET35_OR_GREATER
2534-
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
2535-
#endif
2536-
var cp = this.characterSet.ToString().Replace("_", "-");
2537-
byte[] bytesOut = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(cp), Encoding.UTF8.GetBytes(ret));
2538-
if (bytesOut.Length > 300)
2539-
throw new RussiaPaymentOrderException($"Data too long. Payload must not exceed 300 bytes, but actually is {bytesOut.Length} bytes long. Remove additional data fields or shorten strings/values.");
2540-
return bytesOut;
2545+
return Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(cp), Encoding.UTF8.GetBytes(ret));
25412546
}
25422547

25432548

QRCoderTests/PayloadGeneratorTests.cs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,24 +3280,44 @@ public void russiapayment_generator_should_throw_no_separator_exception()
32803280
[Fact]
32813281
[Category("PayloadGenerator/RussiaPaymentOrder")]
32823282
public void russiapayment_generator_should_throw_data_too_long_exception()
3283+
{
3284+
var account = "40702810138250123017";
3285+
var bic = "044525225";
3286+
var bankName = "A very very very very very long bank name";
3287+
// We use € symbol for the test case, because it needs 2-bytes. Otherwise we couldn't generate more than 300 bytes
3288+
// of mandatory data to trigger the test case and stay at the same time within the 160 chars field validation limit
3289+
var name = "A very €€€€ €€€€ €€€€ €€€€ very very very very very very very very very very very very very very very very very very very very very very very very ver long name";
3290+
var correspAcc = "30101810400000000225";
3291+
var generator = new PayloadGenerator.RussiaPaymentOrder(name, account, bankName, bic, correspAcc);
3292+
3293+
var exception = Record.Exception(() => generator.ToString());
3294+
Assert.NotNull(exception);
3295+
Assert.IsType<PayloadGenerator.RussiaPaymentOrder.RussiaPaymentOrderException>(exception);
3296+
exception.Message.ShouldStartWith("Data too long");
3297+
}
3298+
3299+
[Fact]
3300+
[Category("PayloadGenerator/RussiaPaymentOrder")]
3301+
public void russiapayment_generator_should_throw_no_data_too_long_exception()
32833302
{
32843303
var account = "40702810138250123017";
32853304
var bic = "044525225";
32863305
var bankName = "ОАО | \"БАНК\"";
3287-
var name = "A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long name";
3306+
var name = "A name";
32883307
var correspAcc = "30101810400000000225";
32893308
var optionalFields = new PayloadGenerator.RussiaPaymentOrder.OptionalFields()
32903309
{
32913310
FirstName = "Another long long long long long long long long long long long long long long firstname",
32923311
LastName = "Another long long long long long long long long long long long long long long lastname",
3312+
Category = "A pretty long long long long long long long long long long long long long category",
32933313
Sum = "125000"
32943314
};
32953315
var generator = new PayloadGenerator.RussiaPaymentOrder(name, account, bankName, bic, correspAcc, optionalFields);
32963316

3317+
// Should throw no exception as the 300 byte limit applies only to the mandatory fields
3318+
// See https://github.com/codebude/QRCoder/issues/392
32973319
var exception = Record.Exception(() => generator.ToString());
3298-
Assert.NotNull(exception);
3299-
Assert.IsType<PayloadGenerator.RussiaPaymentOrder.RussiaPaymentOrderException>(exception);
3300-
exception.Message.ShouldStartWith("Data too long");
3320+
Assert.Null(exception);
33013321
}
33023322

33033323
[Fact]

0 commit comments

Comments
 (0)