commit 0989504aa59c5e6911a7f4b862782e8635ba2b8c
parent 195c58648cc736ffe9e4be0dcfd235d96b2a5e66
Author: Florian Dold <dold@taler.net>
Date: Tue, 21 Jul 2026 11:05:53 +0200
util: test the field layout of the generated payment QR codes
Diffstat:
1 file changed, 65 insertions(+), 0 deletions(-)
diff --git a/packages/taler-util/src/qr.test.ts b/packages/taler-util/src/qr.test.ts
@@ -0,0 +1,65 @@
+/*
+ This file is part of GNU Taler
+ (C) 2026 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import assert from "node:assert";
+import { test } from "node:test";
+import { getQrCodesForPayto, QrCodeSpec } from "./qr.js";
+
+function contentOf(codes: QrCodeSpec[], type: string) {
+ const found = codes.find((c) => c.type === type);
+ assert.ok(found, `no ${type} code generated`);
+ return found.qrContent;
+}
+
+test("EPC QR keeps the beneficiary IBAN in its own field", (t) => {
+ // The record is newline delimited: line 6 is the beneficiary name and line 7
+ // the beneficiary IBAN. A payto parameter carrying a line break would
+ // otherwise let whoever supplied the URI choose the account being paid.
+ const codes = getQrCodesForPayto(
+ "payto://iban/DE75512108001245126199" +
+ "?receiver-name=Alice%0ADE89370400440532013000%0AEUR999.99" +
+ "&amount=EUR:10",
+ );
+ const lines = contentOf(codes, "epc-qr").split("\n");
+ assert.strictEqual(lines[6], "DE75512108001245126199");
+ assert.strictEqual(lines[7], "EUR10.00");
+});
+
+test("Swiss QR bill keeps its field layout", (t) => {
+ const codes = getQrCodesForPayto(
+ "payto://iban/CH9300762011623852957" +
+ "?receiver-name=Alice%0AS%0AMallory" +
+ "&amount=CHF:10",
+ );
+ const lines = contentOf(codes, "spc").split("\n");
+ assert.strictEqual(lines[0], "SPC");
+ assert.strictEqual(lines[3], "CH9300762011623852957");
+ assert.strictEqual(lines[4], "S");
+ // Address lines follow the beneficiary name and must stay empty.
+ assert.strictEqual(lines[6], "");
+ assert.strictEqual(lines[7], "");
+});
+
+test("a well-formed payto still produces a usable EPC record", (t) => {
+ const codes = getQrCodesForPayto(
+ "payto://iban/DE75512108001245126199?receiver-name=Alice&amount=EUR:10",
+ );
+ const lines = contentOf(codes, "epc-qr").split("\n");
+ assert.strictEqual(lines[0], "BCD");
+ assert.strictEqual(lines[5], "Alice");
+ assert.strictEqual(lines[6], "DE75512108001245126199");
+ assert.strictEqual(lines[7], "EUR10.00");
+});