/* This file is part of GNU Taler (C) 2024 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 */ /** * Imports. */ import { Amounts } from "./index.js"; import { parsePaytoUri } from "./payto.js"; type EncodeResult = { type: "ok"; qrContent: string } | { type: "skip" }; /** * See "Schweizer Implementation Guidelines QR-Rechnung". */ function encodePaytoAsSwissQrBill(paytoUri: string): EncodeResult { const parsedPayto = parsePaytoUri(paytoUri); if (!parsedPayto) { throw Error("invalid payto URI"); } if (parsedPayto.targetType !== "iban") { return { type: "skip" }; } const amountStr = parsedPayto.params["amount"]; const iban = parsedPayto.targetPath; const countryCode = iban.slice(0, 2); const lines = [ "SPC", // QRType "0200", // Version "1", // Character set (1: UTF-8) iban, // Beneficiary IBAN // Group: Beneficiary "S", // Address type (S: structured) parsedPayto.params["receiver-name"], // Beneficiary name "", // street "", // apt. nr. "", // postal code "", // town countryCode, // Country // Group: Ultimate Debtor (not used in version 0200) "", // Ultimate Debtor Address type (S: structured) "", // Ultimate Debtor name "", // Ultimate Debtor street "", // Ultimate Debtor apt. nr "", // Ultimate Debtor postal code "", // Ultimate Debtor town "", // Ultimate Debtor country // Group: Amount Amounts.stringifyValue(amountStr, 2), // Amount Amounts.currencyOf(amountStr), // Currency // Group: Debtor "", // Address type (S: structured) "", // Debtor name "", // Debtor street "", // Debtor apt. nr "", // Debtor postal code "", // Debtor town "", // Debtor country // Group: Reference "NON", // reference type "", // Reference // Group: Additional Information parsedPayto.params["message"], // Unstructured data "EPD", // End of payment data ]; return { type: "ok", qrContent: lines.join("\n"), }; } /** * See "Quick Response Code - Guidelines to * Enable the Data Capture for the * Initiation of a SEPA Credit Transfer". */ function encodePaytoAsEpcQr(paytoUri: string): EncodeResult { const parsedPayto = parsePaytoUri(paytoUri); if (!parsedPayto) { throw Error("invalid payto URI"); } if (parsedPayto.targetType !== "iban") { return { type: "skip" }; } const amountStr = parsedPayto.params["amount"]; Amounts.stringifyValue; const lines = [ "BCD", // service tag "002", // version "1", // character set (1: UTF-8) "SCT", // Identification "", // optional BIC parsedPayto.params["receiver-name"], // Beneficiary name parsedPayto.targetPath, // Beneficiary IBAN `${Amounts.currencyOf(amountStr)}${Amounts.stringifyValue(amountStr, 2)}`, // Amount "", // AT-44 Purpose parsedPayto.params["message"], // AT-05 Unstructured remittance information ]; return { type: "ok", qrContent: lines.join("\n"), }; } /** * Specification of a QR code that includes payment information. */ export interface QrCodeSpec { /** * Type of the QR code. * * Depending on the type, different visual styles * might be applied. */ type: string; /** * Content of the QR code that should be rendered. */ qrContent: string; } /** * Get applicable QR code specifications for the given payto URI. */ export function getQrCodesForPayto(paytoUri: string): QrCodeSpec[] { const res: QrCodeSpec[] = []; { const qr = encodePaytoAsEpcQr(paytoUri); if (qr.type == "ok") { res.push({ type: "epc-qr", qrContent: qr.qrContent, }); } } { const qr = encodePaytoAsSwissQrBill(paytoUri); if (qr.type == "ok") { res.push({ type: "epc-qr", qrContent: qr.qrContent, }); } } return res; }