first version
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* EPC (SEPA Credit Transfer) QR code payload, a.k.a. GiroCode.
|
||||
* Specification: EPC069-12 v3.0.
|
||||
*
|
||||
* The payload is a fixed-order line-delimited block of fields that any SEPA
|
||||
* banking app can scan to pre-fill a transfer.
|
||||
*/
|
||||
|
||||
import QRCode from "qrcode";
|
||||
|
||||
export interface GiroCodeInput {
|
||||
beneficiaryName: string;
|
||||
iban: string;
|
||||
bic?: string;
|
||||
amount: number;
|
||||
currency?: string;
|
||||
/** Free-form remittance information (e.g. invoice number). Max 140 chars. */
|
||||
remittance: string;
|
||||
}
|
||||
|
||||
export function buildGiroCodePayload(input: GiroCodeInput): string {
|
||||
const currency = input.currency || "EUR";
|
||||
if (currency !== "EUR") {
|
||||
// EPC069-12 requires EUR; keep going but warn (most invoices are EUR).
|
||||
console.warn(`GiroCode: non-EUR currency ${currency} is non-standard.`);
|
||||
}
|
||||
|
||||
// Beneficiary name max 70 chars per spec.
|
||||
const name = input.beneficiaryName.slice(0, 70);
|
||||
const iban = input.iban.replace(/\s+/g, "").toUpperCase();
|
||||
const bic = (input.bic || "").replace(/\s+/g, "").toUpperCase();
|
||||
const amount = input.amount.toFixed(2);
|
||||
const remittance = input.remittance.slice(0, 140);
|
||||
|
||||
// Field order is fixed; trailing fields can be empty.
|
||||
// Service tag SCT = SEPA Credit Transfer.
|
||||
const lines = [
|
||||
"BCD",
|
||||
"002", // version
|
||||
"1", // character set 1 = UTF-8
|
||||
"SCT", // SEPA Credit Transfer
|
||||
bic, // BIC (optional in v002)
|
||||
name,
|
||||
iban,
|
||||
`EUR${amount}`,
|
||||
"", // purpose (optional)
|
||||
"", // structured remittance
|
||||
remittance, // unstructured remittance
|
||||
];
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
export async function buildGiroCodeDataUrl(
|
||||
input: GiroCodeInput,
|
||||
): Promise<string> {
|
||||
const payload = buildGiroCodePayload(input);
|
||||
// EPC requires error correction level M.
|
||||
return QRCode.toDataURL(payload, {
|
||||
errorCorrectionLevel: "M",
|
||||
margin: 1,
|
||||
width: 256,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user