bysquare 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,22 +1,30 @@
1
1
  <h1 align="center">bysquare</h1>
2
2
 
3
3
  <p align="center">
4
- "PAY by square" is a national standard for QR code payments that was adopted
5
- by the Slovak Banking Association in 2013. It is incorporated into a variety
6
- of invoices, reminders and other payment regulations.
4
+ "PAY by square" is a national standard for QR code payments that was adopted by
5
+ the Slovak Banking Association in 2013. It is incorporated into a variety of
6
+ invoices, reminders and other payment regulations.
7
7
  </p>
8
8
 
9
- ## Why
10
-
11
- It's simple, I couldn't find any implementation of "PAY by square" standard for
12
- JavaScript, so I decided to create one and share it with the community to help
13
- individuals and businesses to create QR codes for their invoices.
9
+ <p align="center">
10
+ <a href="#features">Features</a> •
11
+ <a href="#installation">Installation</a>
12
+ <a href="#usage">Usage</a>
13
+ <a href="#cli">CLI</a>
14
+ <a href="#validation">Validation</a>
15
+ </p>
14
16
 
15
17
  ## Features
16
18
 
17
19
  - TypeScript support
20
+ - CLI tooling
18
21
  - Compatible with Slovak banking apps
19
- - Isomorphic Browser & Runtime-independent implementation
22
+ - Isomorphic Browser & Runtime-independent (Browser, Node.js, Bun, Deno)
23
+
24
+ > [!NOTE]
25
+ > Since v3, the implementation is considered stable and specification-complete.\
26
+ > No breaking changes are planned. Only minor improvements and bug fixes may be
27
+ > introduced.
20
28
 
21
29
  ## Installation
22
30
 
@@ -34,13 +42,11 @@ $ npm install bysquare
34
42
  </script>
35
43
  ```
36
44
 
37
- ## Quick start
45
+ ## Usage
38
46
 
39
47
  This library provides `encode` and `decode` functions to work with the data
40
48
  model directly, allowing you to create customized payment solutions.
41
49
 
42
- ### Guides
43
-
44
50
  ### HTML example
45
51
 
46
52
  This example shows how to generate a payment QR code and display it in a web
@@ -67,9 +73,8 @@ page:
67
73
  amount: 123.45,
68
74
  variableSymbol: "987654",
69
75
  currencyCode: CurrencyCode.EUR,
70
- bankAccounts: [
71
- { iban: "SK9611000000002918599669" }
72
- ],
76
+ beneficiary: { name: "John Doe" },
77
+ bankAccounts: [{ iban: "SK9611000000002918599669" }],
73
78
  },
74
79
  ],
75
80
  });
@@ -102,9 +107,8 @@ const qrstring = encode({
102
107
  amount: 50.75,
103
108
  variableSymbol: "123456",
104
109
  currencyCode: CurrencyCode.EUR, // "EUR"
105
- bankAccounts: [
106
- { iban: "SK9611000000002918599669" },
107
- ],
110
+ beneficiary: { name: "John Doe" },
111
+ bankAccounts: [{ iban: "SK9611000000002918599669" }],
108
112
  },
109
113
  ],
110
114
  });
@@ -120,9 +124,8 @@ const qrstring = encode({
120
124
  day: 15,
121
125
  month: Month.January, // Single month
122
126
  periodicity: Periodicity.Monthly, // "m"
123
- bankAccounts: [
124
- { iban: "SK9611000000002918599669" },
125
- ],
127
+ beneficiary: { name: "John Doe" },
128
+ bankAccounts: [{ iban: "SK9611000000002918599669" }],
126
129
  },
127
130
  ],
128
131
  });
@@ -135,9 +138,8 @@ const qrstring = encode({
135
138
  amount: 25.0,
136
139
  variableSymbol: "789012",
137
140
  currencyCode: CurrencyCode.EUR, // "EUR"
138
- bankAccounts: [
139
- { iban: "SK9611000000002918599669" },
140
- ],
141
+ beneficiary: { name: "John Doe" },
142
+ bankAccounts: [{ iban: "SK9611000000002918599669" }],
141
143
  },
142
144
  ],
143
145
  });
@@ -170,9 +172,8 @@ const qrstring = encode({
170
172
  month: Month.January | Month.July | Month.October, // Results in 577
171
173
  periodicity: Periodicity.Monthly,
172
174
  lastDate: "20251231",
173
- bankAccounts: [
174
- { iban: "SK9611000000002918599669" },
175
- ],
175
+ beneficiary: { name: "John Doe" },
176
+ bankAccounts: [{ iban: "SK9611000000002918599669" }],
176
177
  },
177
178
  ],
178
179
  });
@@ -192,9 +193,8 @@ const qrstring2 = encode({
192
193
  month: encodedMonths, // Same result: 577
193
194
  periodicity: Periodicity.Monthly,
194
195
  lastDate: "20251231",
195
- bankAccounts: [
196
- { iban: "SK9611000000002918599669" },
197
- ],
196
+ beneficiary: { name: "John Doe" },
197
+ bankAccounts: [{ iban: "SK9611000000002918599669" }],
198
198
  },
199
199
  ],
200
200
  });
@@ -235,6 +235,7 @@ const data = {
235
235
  amount: 100.0,
236
236
  variableSymbol: "123",
237
237
  paymentNote: "hello world",
238
+ beneficiary: { name: "John Doe" },
238
239
  bankAccounts: [
239
240
  { iban: "SK9611000000002918599669" },
240
241
  // ...more bank accounts
@@ -315,15 +316,16 @@ all XSD schema restrictions.
315
316
 
316
317
  ### Validation Behavior
317
318
 
318
- | Aspect | Behavior |
319
- | ------------- | --------------------------------------------------------------- |
320
- | IBAN | Validated (format + checksum via ISO 13616) |
321
- | BIC | Validated (format via ISO 9362) |
322
- | Currency | Validated (ISO 4217, case-insensitive, includes XXX) |
323
- | Date | Validated (ISO 8601 format) |
324
- | Symbols | Permissive (accepts letters, spaces - XSD pattern not enforced) |
325
- | Amounts | Permissive (accepts negative values) |
326
- | Field lengths | Not enforced |
319
+ | Aspect | Behavior |
320
+ | ---------------- | --------------------------------------------------------------- |
321
+ | IBAN | Validated (format + checksum via ISO 13616) |
322
+ | BIC | Validated (format via ISO 9362) |
323
+ | Currency | Validated (ISO 4217, case-insensitive, includes XXX) |
324
+ | Date | Validated (ISO 8601 format) |
325
+ | Beneficiary name | Required (per spec v1.2.0) |
326
+ | Symbols | Permissive (accepts letters, spaces - XSD pattern not enforced) |
327
+ | Amounts | Permissive (accepts negative values) |
328
+ | Field lengths | Not enforced |
327
329
 
328
330
  ### XSD Field Constraints Reference
329
331
 
package/lib/cli.js CHANGED
@@ -1,119 +1,192 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync, readFileSync, } from "node:fs";
2
+ import { existsSync, readFileSync, statSync, } from "node:fs";
3
3
  import process from "node:process";
4
4
  import { parseArgs } from "node:util";
5
5
  import { decode } from "./decode.js";
6
- import { encode } from "./encode.js";
7
- const args = parseArgs({
8
- allowPositionals: true,
9
- options: {
10
- decode: {
11
- type: "string",
12
- short: "d",
13
- },
14
- encode: {
15
- type: "boolean",
16
- short: "e",
17
- },
18
- validate: {
19
- type: "boolean",
20
- short: "v",
21
- },
22
- deburr: {
23
- type: "boolean",
24
- short: "b",
25
- },
26
- help: {
27
- type: "boolean",
28
- short: "h",
6
+ import { encode, } from "./encode.js";
7
+ import { Version } from "./types.js";
8
+ const version = "3.1.0";
9
+ const usage = `bysquare - Slovak PAY by square QR payment standard
10
+
11
+ USAGE:
12
+ bysquare encode [OPTIONS] <input.json>
13
+ bysquare decode <qr-string>
14
+ bysquare version
15
+
16
+ COMMANDS:
17
+ encode Encode JSON payment data to BySquare QR string
18
+ decode Decode BySquare QR string to JSON payment data
19
+ version Print version information
20
+
21
+ ENCODE OPTIONS:
22
+ -D, --no-deburr Keep diacritics (deburr enabled by default)
23
+ -V, --no-validate Skip validation (validation enabled by default)
24
+ -s, --spec-version VER Specification version: 1.0.0, 1.1.0, 1.2.0 (default: 1.2.0)
25
+
26
+ EXAMPLES:
27
+ # Encode with defaults (deburr=true, validate=true, version=1.2.0)
28
+ $ bysquare encode payment.json
29
+
30
+ # Encode with specific options
31
+ $ bysquare encode --no-deburr payment.json
32
+ $ bysquare encode --spec-version 1.1.0 payment.json
33
+ $ bysquare encode -s 1.0.0 --no-validate payment.json
34
+
35
+ # Encode from stdin
36
+ $ echo '{"payments":[...]}' | bysquare encode -
37
+
38
+ # Encode multiple files (including JSONL)
39
+ $ bysquare encode file1.json file2.jsonl
40
+
41
+ # Decode QR string
42
+ $ bysquare decode "00D80..."
43
+
44
+ # Decode from file
45
+ $ bysquare decode qr.txt
46
+
47
+ For more information, visit: https://github.com/xseman/bysquare
48
+ `;
49
+ function errorMessage(error) {
50
+ return error instanceof Error
51
+ ? error.message
52
+ : String(error);
53
+ }
54
+ async function readStdin() {
55
+ const chunks = [];
56
+ for await (const chunk of process.stdin) {
57
+ chunks.push(chunk);
58
+ }
59
+ return Buffer.concat(chunks).toString("utf8");
60
+ }
61
+ async function readInput(path) {
62
+ if (path === "-") {
63
+ return readStdin();
64
+ }
65
+ if (!existsSync(path)) {
66
+ throw new Error(`file ${path} doesn't exist`);
67
+ }
68
+ return readFileSync(path, "utf8");
69
+ }
70
+ async function cmdEncode(args) {
71
+ const parsed = parseArgs({
72
+ args,
73
+ allowPositionals: true,
74
+ options: {
75
+ "no-deburr": {
76
+ type: "boolean",
77
+ short: "D",
78
+ },
79
+ "no-validate": {
80
+ type: "boolean",
81
+ short: "V",
82
+ },
83
+ "spec-version": {
84
+ type: "string",
85
+ short: "s",
86
+ default: "1.2.0",
87
+ },
29
88
  },
30
- },
31
- });
32
- if (process.stdin.isTTY) {
33
- if (args.values.encode) {
34
- if (args.positionals.length === 0) {
35
- console.error("No files provided for encoding.");
89
+ });
90
+ if (parsed.positionals.length === 0) {
91
+ console.error("Error: missing input file argument");
92
+ process.exit(1);
93
+ }
94
+ const versionStr = parsed.values["spec-version"];
95
+ if (!(versionStr in Version)) {
96
+ console.error("Error: unsupported spec version:", parsed.values["spec-version"]);
97
+ process.exit(1);
98
+ }
99
+ const encodeOpts = {
100
+ validate: !parsed.values["no-validate"],
101
+ deburr: !parsed.values["no-deburr"],
102
+ version: Version[versionStr],
103
+ };
104
+ for (const inputFile of parsed.positionals) {
105
+ let input;
106
+ try {
107
+ input = await readInput(inputFile);
108
+ }
109
+ catch (error) {
110
+ console.error("Error:", errorMessage(error));
36
111
  process.exit(1);
37
112
  }
38
- for (const file of args.positionals) {
39
- if (existsSync(file) === false) {
40
- console.error(`File ${file} doesn't exist`);
41
- process.exit(1);
42
- }
43
- if (file.endsWith(".json") === false
44
- && file.endsWith(".jsonl") === false) {
45
- console.error(`Unsupported file format for ${file}`);
46
- process.exit(1);
113
+ if (inputFile.endsWith(".jsonl")) {
114
+ for (const line of input.split("\n")) {
115
+ if (!line.trim())
116
+ continue;
117
+ encodeAndPrint(line, encodeOpts);
47
118
  }
48
- const data = readFileSync(file, "utf8");
49
- if (file.endsWith(".jsonl")) {
50
- const lines = data.split("\n");
51
- for (const line of lines) {
52
- if (!line)
53
- continue;
54
- const json = JSON.parse(line);
55
- console.log(encode(json));
56
- }
57
- }
58
- if (file.endsWith(".json")) {
59
- console.log(encode(JSON.parse(data), {
60
- validate: Boolean(args.values.validate),
61
- deburr: Boolean(args.values.deburr),
62
- }));
63
- }
64
- process.exit(0);
119
+ continue;
65
120
  }
121
+ encodeAndPrint(input.trim(), encodeOpts);
66
122
  }
67
- if (args.values.decode) {
68
- const qrstring = args.values.decode;
69
- console.log(JSON.stringify(decode(qrstring), null, 4));
70
- process.exit(0);
123
+ }
124
+ function encodeAndPrint(jsonStr, opts) {
125
+ try {
126
+ const data = JSON.parse(jsonStr);
127
+ const result = encode(data, opts);
128
+ console.log(result);
71
129
  }
72
- if (args.values.help
73
- || Object.keys(args.values).length === 0) {
74
- console.log([
75
- "NAME",
76
- " bysquare - Simple Node.js library to generate and parse PAY bysquare standard",
77
- "",
78
- "SYNOPSIS",
79
- " bysquare [OPTIONS] [FILES...]",
80
- "",
81
- "DESCRIPTION",
82
- " bysquare is a command-line tool that provides a simple Node.js library to generate ",
83
- " and parse PAY bysquare standard. It offers functionality to encode JSON data into a ",
84
- " corresponding QR code and decode a QR code string to obtain the associated JSON data.",
85
- "",
86
- "OPTIONS",
87
- " -d, --decode <qrstring>",
88
- " Decode the specified QR code string and print the corresponding JSON data.",
89
- " The qrstring argument should be a valid QR code string.",
90
- "",
91
- " -e, --encode",
92
- " Encode JSON data from one or more files and print the corresponding QR code.",
93
- "",
94
- " -v, --validate",
95
- " Validate JSON data from one or more files before encoding.",
96
- "",
97
- " -b, --deburr",
98
- " Deburr JSON data from one or more files before encoding.",
99
- "",
100
- " -h, --help",
101
- " Display the help message and exit.",
102
- "",
103
- "USAGE",
104
- " Encoding JSON data from one or more files",
105
- "",
106
- ` ${process.argv[1]} --encode file1.json file2.json ...`,
107
- " The file1.json, file2.json, ... arguments should be the paths to the JSON or JSONL",
108
- " files you want to encode. The tool will read each file, generate a QR code representing",
109
- " the JSON data, and print them.",
110
- "",
111
- " Decoding a QR code string",
112
- "",
113
- ` ${process.argv[1]} --decode <qrstring>`,
114
- " Replace qrstring with the QR code string you want to decode.",
115
- " The program will parse the QR code string and print the resulting JSON data.",
116
- "",
117
- ].join("\n"));
130
+ catch (error) {
131
+ console.error("Error:", errorMessage(error));
132
+ process.exit(1);
118
133
  }
119
134
  }
135
+ async function cmdDecode(args) {
136
+ if (args.length === 0) {
137
+ console.error("Error: missing QR string argument");
138
+ process.exit(1);
139
+ }
140
+ const qrInput = args[0];
141
+ try {
142
+ let qr;
143
+ if (qrInput === "-") {
144
+ qr = await readStdin();
145
+ }
146
+ else if (existsSync(qrInput) && statSync(qrInput).isFile()) {
147
+ qr = readFileSync(qrInput, "utf8");
148
+ }
149
+ else {
150
+ qr = qrInput;
151
+ }
152
+ const model = decode(qr.trim());
153
+ console.log(JSON.stringify(model, null, 2));
154
+ }
155
+ catch (error) {
156
+ console.error("Error:", errorMessage(error));
157
+ process.exit(1);
158
+ }
159
+ }
160
+ async function main() {
161
+ if (process.argv.length < 3) {
162
+ console.error(usage);
163
+ process.exit(1);
164
+ }
165
+ const command = process.argv[2];
166
+ switch (command) {
167
+ case "encode":
168
+ await cmdEncode(process.argv.slice(3));
169
+ break;
170
+ case "decode":
171
+ await cmdDecode(process.argv.slice(3));
172
+ break;
173
+ case "version":
174
+ case "-v":
175
+ case "--version":
176
+ console.log(`bysquare version ${version}`);
177
+ break;
178
+ case "help":
179
+ case "-h":
180
+ case "--help":
181
+ console.log(usage);
182
+ break;
183
+ default:
184
+ console.error("Unknown command:", command);
185
+ console.error(usage);
186
+ process.exit(1);
187
+ }
188
+ }
189
+ main().catch((error) => {
190
+ console.error("Fatal error:", error);
191
+ process.exit(1);
192
+ });
package/lib/decode.js CHANGED
@@ -29,25 +29,6 @@ function decodeNumber(value) {
29
29
  function decodeString(value) {
30
30
  return value?.length ? value : undefined;
31
31
  }
32
- /**
33
- * Converts date from YYYYMMDD format to ISO 8601 format (YYYY-MM-DD)
34
- * per Pay by Square specification section 3.7.
35
- *
36
- * Note: This conversion is only used for paymentDueDate per specification.
37
- * lastDate remains in YYYYMMDD format.
38
- *
39
- * @param input - Date in YYYYMMDD format
40
- * @returns Date in ISO 8601 format (YYYY-MM-DD) | undefined
41
- */
42
- function deserializeDate(input) {
43
- if (!input || input.length !== 8) {
44
- return undefined;
45
- }
46
- const year = input.slice(0, 4);
47
- const month = input.slice(4, 6);
48
- const day = input.slice(6, 8);
49
- return year + "-" + month + "-" + day;
50
- }
51
32
  /**
52
33
  * Parse a tab-separated intermediate format into DataModel.
53
34
  *
@@ -123,12 +104,13 @@ export function deserialize(qr) {
123
104
  type: Number(paymentOptions),
124
105
  currencyCode: currency ?? CurrencyCode.EUR,
125
106
  amount: Number(ammount),
126
- paymentDueDate: deserializeDate(dueDate),
107
+ paymentDueDate: dueDate || undefined,
127
108
  variableSymbol: variableSymbol || undefined,
128
109
  constantSymbol: constantSymbol || undefined,
129
110
  specificSymbol: specificSymbol || undefined,
130
111
  originatorsReferenceInformation: originatorRefInfo || undefined,
131
112
  paymentNote: paymentNote || undefined,
113
+ beneficiary: { name: "" },
132
114
  bankAccounts: [],
133
115
  };
134
116
  const numberOfAccounts = Number(data.shift());
@@ -174,17 +156,15 @@ export function deserialize(qr) {
174
156
  output.payments.push(payment);
175
157
  }
176
158
  for (let i = 0; i < paymentslen; i++) {
177
- const name = data.shift();
178
- const addressLine1 = data.shift();
179
- const addressLine2 = data.shift();
180
- if (Boolean(name) || Boolean(addressLine1) || Boolean(addressLine2)) {
181
- const beneficiary = {
182
- name: name || undefined,
183
- street: addressLine1 || undefined,
184
- city: addressLine2 || undefined,
185
- };
186
- output.payments[i].beneficiary = beneficiary;
187
- }
159
+ const name = data.shift() ?? "";
160
+ const addressLine1 = data.shift() ?? "";
161
+ const addressLine2 = data.shift() ?? "";
162
+ const beneficiary = {
163
+ name: name,
164
+ street: addressLine1 || undefined,
165
+ city: addressLine2 || undefined,
166
+ };
167
+ output.payments[i].beneficiary = beneficiary;
188
168
  }
189
169
  return output;
190
170
  }
@@ -227,7 +207,7 @@ export function decode(qr) {
227
207
  const bytes = base32hex.decode(qr);
228
208
  const headerBytes = bytes.slice(0, 2);
229
209
  const headerData = bysquareHeaderDecoder(headerBytes);
230
- if ((headerData.version > Version["1.1.0"])) {
210
+ if ((headerData.version > Version["1.2.0"])) {
231
211
  throw new DecodeError(DecodeErrorMessage.UnsupportedVersion, {
232
212
  version: headerData.version,
233
213
  });
package/lib/encode.d.ts CHANGED
@@ -141,7 +141,7 @@ export declare function addChecksum(tabbedPayload: string): Uint8Array;
141
141
  */
142
142
  export declare function serialize(data: DataModel): string;
143
143
  export declare function removeDiacritics(model: DataModel): void;
144
- type Options = {
144
+ export type EncodeOptions = {
145
145
  /**
146
146
  * Many banking apps do not support diacritics, which results in errors when
147
147
  * serializing data from QR codes.
@@ -158,11 +158,10 @@ type Options = {
158
158
  /**
159
159
  * Version of the BySquare format to use.
160
160
  *
161
- * Note: Version 1.1.0 adds beneficiary name and address fields but is not
162
- * supported by all banking apps (e.g., TatraBanka). Use 1.0.0 for better
163
- * compatibility.
161
+ * Note: Version 1.2.0 requires beneficiary name. Earlier versions (1.0.0, 1.1.0)
162
+ * do not require it but may have limited banking app support for beneficiary fields.
164
163
  *
165
- * @default Version["1.0.0"]
164
+ * @default Version["1.2.0"]
166
165
  */
167
166
  version?: Version;
168
167
  };
@@ -200,5 +199,4 @@ type Options = {
200
199
  *
201
200
  * @see 3.16.
202
201
  */
203
- export declare function encode(model: DataModel, options?: Options): string;
204
- export {};
202
+ export declare function encode(model: DataModel, options?: EncodeOptions): string;
package/lib/encode.js CHANGED
@@ -4,22 +4,6 @@ import { crc32 } from "./crc32.js";
4
4
  import { deburr } from "./deburr.js";
5
5
  import { Month, PaymentOptions, Version, } from "./types.js";
6
6
  import { validateDataModel } from "./validations.js";
7
- /**
8
- * Converts date from ISO 8601 format (YYYY-MM-DD) to YYYYMMDD format
9
- * per Pay by Square specification section 3.7.
10
- *
11
- * Note: This conversion is only used for paymentDueDate per specification.
12
- * lastDate expects YYYYMMDD format directly.
13
- *
14
- * @param input - Date in ISO 8601 format (YYYY-MM-DD)
15
- * @returns Date in YYYYMMDD format | undefined
16
- */
17
- function serializeDate(input) {
18
- if (!input) {
19
- return undefined;
20
- }
21
- return input.split("-").join("");
22
- }
23
7
  export const EncodeErrorMessage = {
24
8
  /**
25
9
  * @description - find invalid value in extensions
@@ -206,7 +190,7 @@ export function serialize(data) {
206
190
  serialized.push(p.type.toString());
207
191
  serialized.push(p.amount?.toString());
208
192
  serialized.push(p.currencyCode);
209
- serialized.push(serializeDate(p.paymentDueDate));
193
+ serialized.push(p.paymentDueDate);
210
194
  serialized.push(p.variableSymbol);
211
195
  serialized.push(p.constantSymbol);
212
196
  serialized.push(p.specificSymbol);
@@ -345,7 +329,7 @@ export function encode(model, options = { deburr: true, validate: true }) {
345
329
  */
346
330
  const _lzmaHeader = payloadCompressed.subarray(0, 13);
347
331
  const lzmaBody = payloadCompressed.subarray(13);
348
- const version = options.version ?? Version["1.0.0"];
332
+ const version = options.version ?? Version["1.2.0"];
349
333
  const output = new Uint8Array([
350
334
  ...buildBysquareHeader([0x00, version, 0x00, 0x00]),
351
335
  ...buildPayloadLength(payloadChecked.byteLength),
package/lib/index.d.ts CHANGED
@@ -5,6 +5,6 @@
5
5
  */
6
6
  export { decodeOptions, encodeOptions } from "./classifier.js";
7
7
  export { decode } from "./decode.js";
8
- export { encode } from "./encode.js";
8
+ export { encode, type EncodeOptions } from "./encode.js";
9
9
  export { validateDataModel } from "./validations.js";
10
10
  export * from "./types.js";
package/lib/types.d.ts CHANGED
@@ -16,6 +16,12 @@ export declare const Version: {
16
16
  * **Released Date:** 2015-06-24
17
17
  */
18
18
  readonly "1.1.0": 1;
19
+ /**
20
+ * Beneficiary name is now a required field
21
+ *
22
+ * **Released Date:** 2025-04-01
23
+ */
24
+ readonly "1.2.0": 2;
19
25
  };
20
26
  export type Version = typeof Version[keyof typeof Version];
21
27
  /**
@@ -149,11 +155,11 @@ export declare const DirectDebitType: {
149
155
  export type DirectDebitType = typeof DirectDebitType[keyof typeof DirectDebitType];
150
156
  export type Beneficiary = {
151
157
  /**
152
- * Beneficiary name.
158
+ * Beneficiary name (required since v1.2.0).
153
159
  *
154
160
  * @maxLength 70
155
161
  */
156
- name?: string;
162
+ name: string;
157
163
  /**
158
164
  * Beneficiary street address.
159
165
  *
@@ -190,14 +196,13 @@ export type SimplePayment = {
190
196
  */
191
197
  currencyCode: string | keyof typeof CurrencyCode;
192
198
  /**
193
- * Payment due date.
199
+ * Payment due date in YYYYMMDD format per v1.2 specification section 3.7.
194
200
  *
195
201
  * For standing orders, this indicates the first payment date.
196
- * The date will be converted to YYYYMMDD format during encoding per specification section 3.7.
197
202
  *
198
203
  * @format date
199
- * @example "2024-12-31"
200
- * @pattern \d{4}-\d{2}-\d{2}
204
+ * @example "20241231"
205
+ * @pattern \d{8}
201
206
  */
202
207
  paymentDueDate?: string;
203
208
  /**
@@ -240,7 +245,10 @@ export type SimplePayment = {
240
245
  * @minItems 1
241
246
  */
242
247
  bankAccounts: BankAccount[];
243
- beneficiary?: Beneficiary;
248
+ /**
249
+ * Beneficiary information (required since v1.2.0).
250
+ */
251
+ beneficiary: Beneficiary;
244
252
  };
245
253
  export type PaymentOrder = SimplePayment & {
246
254
  type: typeof PaymentOptions.PaymentOrder;