@hypay/typescript-sdk 1.0.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 ADDED
@@ -0,0 +1,735 @@
1
+ # @hypay/typescript-sdk
2
+
3
+ A fully typed, production-ready TypeScript SDK for the [Hyp Pay](https://pay.hyp.co.il/) payment gateway API (Israel).
4
+
5
+ ## Features
6
+
7
+ - **Pay Protocol** — Generate signed payment page URLs with tamper-proof signatures
8
+ - **Signature Verification** — Verify transactions from success/failure redirect pages
9
+ - **Soft Protocol** — Server-side transactions with tokens, Apple Pay, and Google Pay
10
+ - **Token Management** — Obtain and reuse tokens for recurring charges (auto-parses Tokef)
11
+ - **J5 Transactions** — Reserve and later charge credit lines
12
+ - **Postpone Transactions** — Create delayed charges and commit them within 72 hours
13
+ - **Cancel & Refund** — Cancel same-day transactions or refund by transaction ID / token
14
+ - **Subscriptions (HK)** — Create standing orders with initial payments, terminate/activate
15
+ - **EzCount Invoices** — Generate signed invoice URLs, build item strings with validation
16
+ - **Offline Invoices** — Cash, Check, and Multi-check invoice creation
17
+ - **Error Handling** — Typed errors with full Hypay + Shva EMV error code mappings
18
+ - **Production Ready** — Timeouts, custom fetch, lifecycle hooks, Israeli ID validation
19
+ - **Tree-shakable** — ESM + CJS dual output, zero runtime dependencies
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @hypay/typescript-sdk
25
+ ```
26
+
27
+ **Requirements:** Node.js >= 18 (uses native `fetch`)
28
+
29
+ ## Quick Start
30
+
31
+ ```typescript
32
+ import { HypayClient, Coin, PageLang } from "@hypay/typescript-sdk";
33
+
34
+ const client = new HypayClient({
35
+ masof: "0010131918", // Terminal number (10 digits)
36
+ apiKey: "your-api-key", // API key from Settings > Terminal Settings
37
+ passP: "your-password", // PassP from terminal settings
38
+ });
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Pay Protocol — Payment Page
44
+
45
+ ### Step 1 + 2: Create a Signed Payment Page URL
46
+
47
+ ```typescript
48
+ const url = await client.createPaymentPageUrl({
49
+ Info: "Order #12345",
50
+ Amount: 100,
51
+ UserId: "203269535",
52
+ ClientName: "Israel",
53
+ ClientLName: "Israeli",
54
+ email: "customer@example.com",
55
+ phone: "098610338",
56
+ cell: "0505555555",
57
+ street: "Levanon 3",
58
+ city: "Netanya",
59
+ zip: "42361",
60
+ Tash: 2,
61
+ Coin: Coin.ILS,
62
+ PageLang: PageLang.HEB,
63
+ tmp: 1,
64
+ MoreData: true,
65
+ Sign: true,
66
+ UTF8: true,
67
+ UTF8out: true,
68
+ sendemail: true,
69
+ });
70
+
71
+ // Redirect the customer to `url`
72
+ ```
73
+
74
+ ### Step 1 only: Sign Parameters (for custom URL building)
75
+
76
+ ```typescript
77
+ const result = await client.sign({
78
+ Info: "Order #123",
79
+ Amount: 100,
80
+ // ...
81
+ });
82
+
83
+ console.log(result.signature); // The signature hash
84
+ console.log(result.raw); // Full signed query string
85
+
86
+ // Build the URL yourself
87
+ const paymentUrl = client.buildPaymentPageUrl(result.raw);
88
+ ```
89
+
90
+ ### Step 3: Handle Success Redirect
91
+
92
+ When the customer completes payment, they're redirected to your success page with transaction parameters in the URL.
93
+
94
+ ```typescript
95
+ import { parsePaymentPageResponse } from "@hypay/typescript-sdk";
96
+
97
+ // In your success page handler:
98
+ const response = parsePaymentPageResponse(req.url);
99
+ console.log(response.Id); // Transaction ID
100
+ console.log(response.CCode); // "0" = success
101
+ console.log(response.Amount); // Amount charged
102
+ console.log(response.ACode); // Confirmation code
103
+ console.log(response.L4digit); // Last 4 digits (when MoreData=True)
104
+ console.log(response.Bank); // Acquirer (when MoreData=True)
105
+ ```
106
+
107
+ ### Step 4: Verify Transaction Signature
108
+
109
+ ```typescript
110
+ // Option A: Verify from parsed parameters
111
+ import { parseRedirectUrl } from "@hypay/typescript-sdk";
112
+
113
+ const params = parseRedirectUrl(req.url);
114
+ const result = await client.verify(params);
115
+
116
+ if (result.verified) {
117
+ // Transaction is legitimate — process the order
118
+ } else {
119
+ // CCode=902 — verification failed, do NOT process
120
+ }
121
+
122
+ // Option B: Verify directly from URL
123
+ const result = await client.verifyRedirectUrl(req.url);
124
+ if (result.verified) { /* OK */ }
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Soft Protocol — Server-Side Transactions
130
+
131
+ ### Token-Based Transaction
132
+
133
+ ```typescript
134
+ const result = await client.soft({
135
+ CC: "1315872608557940000", // Token (19 digits)
136
+ Tmonth: "04",
137
+ Tyear: "2025",
138
+ Amount: 50,
139
+ Info: "Subscription renewal",
140
+ UserId: "203269535",
141
+ ClientName: "Israel",
142
+ ClientLName: "Israeli",
143
+ email: "customer@example.com",
144
+ Coin: Coin.ILS,
145
+ Token: true,
146
+ MoreData: true,
147
+ UTF8: true,
148
+ UTF8out: true,
149
+ sendemail: true,
150
+ });
151
+
152
+ console.log(result.Id); // Transaction ID
153
+ console.log(result.ACode); // Confirmation code
154
+ console.log(result.UID); // UID for J5 charge
155
+ // Access MoreData fields via result.params:
156
+ console.log(result.params.Bank); // Acquirer
157
+ console.log(result.params.Brand); // Card brand
158
+ console.log(result.params.L4digit); // Last 4 digits
159
+ ```
160
+
161
+ ### Apple Pay / Google Pay
162
+
163
+ ```typescript
164
+ const result = await client.soft({
165
+ WalletToken: walletTokenJsonString, // From Apple Pay / Google Pay SDK
166
+ Amount: 100,
167
+ Info: "Purchase",
168
+ UserId: "203269535",
169
+ ClientName: "Israel",
170
+ Coin: Coin.ILS,
171
+ MoreData: true,
172
+ UTF8: true,
173
+ UTF8out: true,
174
+ });
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Token Management
180
+
181
+ ### Get a Token
182
+
183
+ ```typescript
184
+ const token = await client.getToken({
185
+ TransId: "12788261",
186
+ Fild1: "customer-123", // Your reference (not saved in Hypay)
187
+ });
188
+
189
+ console.log(token.Token); // "1315872608557940000" (19 digits)
190
+ console.log(token.Tokef); // "2504" (YYMM format)
191
+ console.log(token.Tmonth); // "04" (auto-parsed)
192
+ console.log(token.Tyear); // "2025" (auto-parsed)
193
+
194
+ // Save token.Token, token.Tmonth, token.Tyear, and customer details
195
+ // (Hypay does NOT store user info or card validity with the token)
196
+ ```
197
+
198
+ ### Use Token in a Soft Transaction
199
+
200
+ ```typescript
201
+ await client.soft({
202
+ CC: token.Token,
203
+ Tmonth: token.Tmonth,
204
+ Tyear: token.Tyear,
205
+ Token: true,
206
+ Amount: 50,
207
+ Info: "Monthly charge",
208
+ UserId: savedUserId,
209
+ ClientName: savedName,
210
+ });
211
+ ```
212
+
213
+ ### Cross-Terminal Token Usage
214
+
215
+ ```typescript
216
+ await client.soft({
217
+ CC: token.Token,
218
+ Tmonth: token.Tmonth,
219
+ Tyear: token.Tyear,
220
+ Token: true,
221
+ tOwner: "0010020610", // Terminal that owns the token
222
+ Amount: 50,
223
+ Info: "Cross-terminal charge",
224
+ UserId: "203269535",
225
+ ClientName: "Israel",
226
+ });
227
+ ```
228
+
229
+ ### Manual Tokef Parsing
230
+
231
+ ```typescript
232
+ import { parseTokef } from "@hypay/typescript-sdk";
233
+
234
+ const { Tmonth, Tyear } = parseTokef("2504");
235
+ // Tmonth = "04", Tyear = "2025"
236
+ ```
237
+
238
+ ---
239
+
240
+ ## J5 Transaction — Credit Line Reservation
241
+
242
+ ### Reserve a Credit Line
243
+
244
+ ```typescript
245
+ const reservation = await client.soft({
246
+ CC: token.Token,
247
+ Tmonth: token.Tmonth,
248
+ Tyear: token.Tyear,
249
+ Token: true,
250
+ J5: true, // Reserve credit line
251
+ MoreData: true, // Required to get UID
252
+ Amount: 100,
253
+ Info: "Hotel reservation",
254
+ UserId: "203269535",
255
+ ClientName: "Israel",
256
+ });
257
+
258
+ // Save reservation.UID and reservation.ACode
259
+ ```
260
+
261
+ ### Charge the Reservation (amount <= original)
262
+
263
+ ```typescript
264
+ const charge = await client.chargeJ5(
265
+ {
266
+ CC: token.Token,
267
+ Tmonth: token.Tmonth,
268
+ Tyear: token.Tyear,
269
+ Token: true,
270
+ Amount: 80,
271
+ Info: "Hotel checkout",
272
+ UserId: "203269535",
273
+ ClientName: "Israel",
274
+ },
275
+ {
276
+ "inputObj.originalUid": reservation.UID!,
277
+ "inputObj.originalAmount": 8000, // 80 ILS in agorot
278
+ AuthNum: reservation.ACode,
279
+ "inputObj.authorizationCodeManpik": 7,
280
+ }
281
+ );
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Postpone Transaction
287
+
288
+ ### Create a Postponed Transaction
289
+
290
+ ```typescript
291
+ const postponed = await client.soft({
292
+ CC: token.Token,
293
+ Tmonth: token.Tmonth,
294
+ Tyear: token.Tyear,
295
+ Token: true,
296
+ Postpone: true,
297
+ Amount: 100,
298
+ Info: "Pending order verification",
299
+ UserId: "203269535",
300
+ ClientName: "Israel",
301
+ MoreData: true,
302
+ });
303
+
304
+ // postponed.CCode === "800" (valid postpone)
305
+ ```
306
+
307
+ ### Commit Within 72 Hours
308
+
309
+ ```typescript
310
+ const result = await client.commitTransaction({
311
+ TransId: postponed.Id,
312
+ SendHesh: true,
313
+ heshDesc: "Payment for order 1234",
314
+ UTF8: true,
315
+ UTF8out: true,
316
+ });
317
+
318
+ console.log(result.HeshASM); // Invoice number created
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Cancel & Refund
324
+
325
+ ### Cancel (Same Day, Before 23:20)
326
+
327
+ ```typescript
328
+ const result = await client.cancelTransaction({
329
+ TransId: "5890796",
330
+ });
331
+ ```
332
+
333
+ ### Refund by Transaction ID
334
+
335
+ ```typescript
336
+ const result = await client.refund({
337
+ TransId: "12290620",
338
+ Amount: 10,
339
+ Tash: 1,
340
+ SendHesh: true,
341
+ UTF8: true,
342
+ UTF8out: true,
343
+ });
344
+
345
+ console.log(result.Id); // New refund transaction ID
346
+ console.log(result.HeshASM); // Credit invoice number
347
+ ```
348
+
349
+ ### Refund by Token (PAYout)
350
+
351
+ ```typescript
352
+ const result = await client.refundByToken({
353
+ CC: "6907500685494032346",
354
+ Tmonth: "04",
355
+ Tyear: "2023",
356
+ Amount: 2,
357
+ Info: "Refund for order 123",
358
+ zPass: "1234", // Secret refund password (sent to terminal owner's phone)
359
+ Token: true,
360
+ UserId: "000000000",
361
+ ClientName: "Israel",
362
+ SendHesh: true,
363
+ sendemail: true,
364
+ UTF8: true,
365
+ UTF8out: true,
366
+ });
367
+ ```
368
+
369
+ ---
370
+
371
+ ## Subscriptions (HK Module)
372
+
373
+ ### Create a Subscription
374
+
375
+ ```typescript
376
+ const url = await client.createSubscriptionUrl({
377
+ Info: "Monthly subscription",
378
+ Amount: 120,
379
+ HK: true,
380
+ Tash: 999, // Unlimited payments
381
+ freq: 1, // Monthly
382
+ FirstDate: "2025-06-01",
383
+ OnlyOnApprove: true,
384
+ UserId: "203269535",
385
+ ClientName: "Israel",
386
+ email: "customer@example.com",
387
+ Coin: Coin.ILS,
388
+ UTF8: true,
389
+ UTF8out: true,
390
+ Sign: true,
391
+ MoreData: true,
392
+ sendemail: true,
393
+ SendHesh: true,
394
+ });
395
+
396
+ // The success redirect URL will include HKId (agreement number)
397
+ ```
398
+
399
+ ### Subscription with Initial Payment
400
+
401
+ ```typescript
402
+ const url = await client.createSubscriptionWithInitialPayment({
403
+ Info: "Plan with setup fee",
404
+ Amount: 120, // Monthly recurring amount
405
+ HK: true,
406
+ Tash: 999,
407
+ freq: 1,
408
+ TashFirstPayment: 50, // Setup fee amount
409
+ FirstPaymentTash: 3, // Charge setup fee for 3 months
410
+ FixTash: true,
411
+ OnlyOnApprove: true,
412
+ UserId: "203269535",
413
+ ClientName: "Israel",
414
+ Coin: Coin.ILS,
415
+ UTF8: true,
416
+ UTF8out: true,
417
+ Sign: true,
418
+ MoreData: true,
419
+ });
420
+ ```
421
+
422
+ ### Terminate / Activate an Agreement
423
+
424
+ ```typescript
425
+ import { HKNewStatus } from "@hypay/typescript-sdk";
426
+
427
+ // Terminate
428
+ await client.terminateSubscription("64239");
429
+ // or: await client.updateHKStatus({ HKId: "64239", NewStat: HKNewStatus.Terminate });
430
+
431
+ // Reactivate
432
+ await client.activateSubscription("64239");
433
+ // or: await client.updateHKStatus({ HKId: "64239", NewStat: HKNewStatus.Activate });
434
+ ```
435
+
436
+ ---
437
+
438
+ ## EzCount Invoices
439
+
440
+ ### Build Invoice Items
441
+
442
+ ```typescript
443
+ import { buildItemsString, calculateItemsTotal } from "@hypay/typescript-sdk";
444
+
445
+ const items = [
446
+ { code: "001", description: "Widget A", quantity: 2, price: 50 },
447
+ { code: "002", description: "Widget B", quantity: 1, price: 100 },
448
+ ];
449
+
450
+ const heshDesc = buildItemsString(items);
451
+ // "[001~Widget A~2~50][002~Widget B~1~100]"
452
+
453
+ const total = calculateItemsTotal(items);
454
+ // 200 (must match Amount parameter)
455
+ ```
456
+
457
+ ### Get a Signed Invoice URL
458
+
459
+ ```typescript
460
+ const invoiceUrl = await client.getInvoiceUrl({
461
+ TransId: "55373520",
462
+ type: "EZCOUNT",
463
+ });
464
+
465
+ // Or for old system:
466
+ const pdfUrl = await client.getInvoiceUrl({
467
+ TransId: "55373520",
468
+ type: "PDF",
469
+ HeshORCopy: true, // Authentic copy
470
+ });
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Offline Invoices
476
+
477
+ ### Cash Invoice
478
+
479
+ ```typescript
480
+ const result = await client.createOfflineInvoice({
481
+ TransType: "Cash",
482
+ Info: "Cash payment",
483
+ Amount: 200,
484
+ UserId: "203269535",
485
+ ClientName: "Israel",
486
+ email: "customer@example.com",
487
+ Pritim: true,
488
+ heshDesc: buildItemsString([
489
+ { code: "001", description: "Product A", quantity: 2, price: 50 },
490
+ { code: "002", description: "Product B", quantity: 1, price: 100 },
491
+ ]),
492
+ SendHesh: true,
493
+ UTF8: true,
494
+ UTF8out: true,
495
+ });
496
+ ```
497
+
498
+ ### Check Invoice
499
+
500
+ ```typescript
501
+ const result = await client.createOfflineInvoice({
502
+ TransType: "Check",
503
+ Info: "Check payment",
504
+ Amount: 200,
505
+ Bank: "10",
506
+ Snif: "912",
507
+ PAN: "1234456",
508
+ CheckNum: "11111111",
509
+ Date: "20250211",
510
+ UserId: "203269535",
511
+ ClientName: "Israel",
512
+ SendHesh: true,
513
+ UTF8: true,
514
+ UTF8out: true,
515
+ });
516
+ ```
517
+
518
+ ### Multi-Check Invoice
519
+
520
+ ```typescript
521
+ const result = await client.createOfflineInvoice({
522
+ TransType: "Multi",
523
+ Info: "Multi-check payment",
524
+ Amount: 200, // Total
525
+ Bank: "10,12,11",
526
+ Snif: "912,826,921",
527
+ PAN: "1234456,1111111,222222",
528
+ CheckNum: "11111111,112223,3554568",
529
+ Date: "20250211,20250911,20251012",
530
+ UserId: "203269535",
531
+ ClientName: "Israel",
532
+ SendHesh: true,
533
+ UTF8: true,
534
+ UTF8out: true,
535
+ });
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Error Handling
541
+
542
+ ### Typed Errors
543
+
544
+ ```typescript
545
+ import { HypayError, HypayNetworkError, HypayTimeoutError } from "@hypay/typescript-sdk";
546
+
547
+ try {
548
+ await client.soft({ /* ... */ });
549
+ } catch (error) {
550
+ if (error instanceof HypayError) {
551
+ console.error(`CCode: ${error.code}`); // e.g., "902"
552
+ console.error(`Message: ${error.message}`); // "Authentication error..."
553
+ console.error(`Raw: ${error.raw}`); // Full response string
554
+ console.error(`Params:`, error.params); // Parsed response
555
+ } else if (error instanceof HypayTimeoutError) {
556
+ console.error(`Timeout after ${error.timeoutMs}ms`);
557
+ } else if (error instanceof HypayNetworkError) {
558
+ console.error(`Network error: ${error.message}`);
559
+ console.error(`Cause:`, error.cause);
560
+ }
561
+ }
562
+ ```
563
+
564
+ ### Error Code Utilities
565
+
566
+ ```typescript
567
+ import {
568
+ isSuccessCode,
569
+ isShvaError,
570
+ isHypayError,
571
+ getErrorMessage,
572
+ ALL_ERROR_CODES,
573
+ } from "@hypay/typescript-sdk";
574
+
575
+ isSuccessCode("0"); // true — Approved
576
+ isSuccessCode("800"); // true — Postponed (valid)
577
+ isSuccessCode("902"); // false — Authentication error
578
+
579
+ isShvaError("6"); // true — Incorrect CVV (Shva)
580
+ isHypayError("902"); // true — Authentication error (Hypay)
581
+
582
+ getErrorMessage("902"); // "Authentication error — reference differs from configured method"
583
+ getErrorMessage("6"); // "Incorrect ID or CVV"
584
+ ```
585
+
586
+ ---
587
+
588
+ ## Validation Helpers
589
+
590
+ ```typescript
591
+ import {
592
+ isValidMasof,
593
+ isTestMasof,
594
+ isValidToken,
595
+ isValidEmail,
596
+ isValidIsraeliId,
597
+ } from "@hypay/typescript-sdk";
598
+
599
+ isValidMasof("0010131918"); // true (10 digits)
600
+ isTestMasof("0010131918"); // true (starts with 00100)
601
+ isTestMasof("1234567890"); // false
602
+
603
+ isValidToken("1315872608557940000"); // true (19 digits)
604
+ isValidEmail("test@example.com"); // true
605
+
606
+ isValidIsraeliId("203269535"); // true (valid Teudat Zehut)
607
+ isValidIsraeliId("000000000"); // true (special test value)
608
+ ```
609
+
610
+ ---
611
+
612
+ ## Advanced Configuration
613
+
614
+ ### Custom Timeout
615
+
616
+ ```typescript
617
+ const client = new HypayClient({
618
+ masof: "0010131918",
619
+ apiKey: "your-key",
620
+ timeout: 60_000, // 60 seconds
621
+ });
622
+ ```
623
+
624
+ ### Custom Fetch (Node.js < 18 or test mocks)
625
+
626
+ ```typescript
627
+ import nodeFetch from "node-fetch";
628
+
629
+ const client = new HypayClient({
630
+ masof: "0010131918",
631
+ apiKey: "your-key",
632
+ fetch: nodeFetch as unknown as typeof fetch,
633
+ });
634
+ ```
635
+
636
+ ### Lifecycle Hooks (Logging, Metrics)
637
+
638
+ ```typescript
639
+ const client = new HypayClient({
640
+ masof: "0010131918",
641
+ apiKey: "your-key",
642
+ hooks: {
643
+ onRequest: (ctx) => {
644
+ console.log(`[Hypay] ${ctx.method} ${ctx.action}`, ctx.params);
645
+ },
646
+ onResponse: (ctx) => {
647
+ console.log(`[Hypay] ${ctx.action} responded in ${ctx.durationMs}ms`, {
648
+ status: ctx.statusCode,
649
+ CCode: ctx.parsedParams.CCode,
650
+ });
651
+ },
652
+ onError: (error, ctx) => {
653
+ console.error(`[Hypay] ${ctx.action} failed: ${error.code} — ${error.message}`);
654
+ // Send to your error tracking (Sentry, Datadog, etc.)
655
+ },
656
+ },
657
+ });
658
+ ```
659
+
660
+ ---
661
+
662
+ ## Testing
663
+
664
+ Use a test terminal (Masof starting with `00100`) for development:
665
+
666
+ | Parameter | Test Value |
667
+ |-----------|-----------|
668
+ | Masof | `0010131918` |
669
+ | PassP | `yaad` |
670
+ | API Key | `7110eda4d09e062aa5e4a390b0a572ac0d2c0220` |
671
+
672
+ **Test Credit Card:**
673
+
674
+ | Field | Value |
675
+ |-------|-------|
676
+ | Number | `5326107300020772` |
677
+ | Expiry | `05/31` |
678
+ | CVV | `033` |
679
+ | ID | `890108558` or `000000000` |
680
+
681
+ Use low amounts (5-10 ILS) for testing. To simulate failures, use a real credit card on a test terminal.
682
+
683
+ ---
684
+
685
+ ## API Reference
686
+
687
+ ### Client Methods
688
+
689
+ | Method | Description |
690
+ |--------|-------------|
691
+ | `sign(params)` | Sign payment page parameters (APISign) |
692
+ | `buildPaymentPageUrl(qs)` | Build payment page URL from signed query string |
693
+ | `createPaymentPageUrl(params)` | Sign + build URL in one call |
694
+ | `verify(params)` | Verify transaction from success page params |
695
+ | `verifyRedirectUrl(url)` | Parse URL + verify in one call |
696
+ | `soft(params)` | Server-side transaction (token, wallet, card) |
697
+ | `getToken(params)` | Get reusable token from a transaction |
698
+ | `chargeJ5(tokenParams, j5Params)` | Charge a J5 credit line reservation |
699
+ | `commitTransaction(params)` | Commit a postponed (800) transaction |
700
+ | `cancelTransaction(params)` | Cancel a same-day transaction |
701
+ | `refund(params)` | Refund by transaction ID (zikoyAPI) |
702
+ | `refundByToken(params)` | Refund via token + zPass (PAYout) |
703
+ | `createSubscriptionUrl(params)` | Create HK subscription payment page |
704
+ | `createSubscriptionWithInitialPayment(params)` | Subscription with setup fee |
705
+ | `updateHKStatus(params)` | Change standing order status |
706
+ | `terminateSubscription(hkId)` | Terminate a standing order |
707
+ | `activateSubscription(hkId)` | Activate a standing order |
708
+ | `getInvoiceUrl(params)` | Get signed EzCount invoice URL |
709
+ | `createOfflineInvoice(params)` | Create Cash/Check/Multi invoice |
710
+
711
+ ### Helper Functions
712
+
713
+ | Function | Description |
714
+ |----------|-------------|
715
+ | `parseQueryString(qs)` | Parse URL query string to Record |
716
+ | `parseRedirectUrl(url)` | Parse success/failure redirect URL |
717
+ | `parsePaymentPageResponse(url)` | Parse redirect URL to typed response |
718
+ | `parseTokef(tokef)` | Parse YYMM token expiry to Tmonth/Tyear |
719
+ | `buildItemsString(items)` | Build heshDesc invoice items string |
720
+ | `calculateItemsTotal(items)` | Calculate total from invoice items |
721
+ | `isValidMasof(masof)` | Validate terminal number format |
722
+ | `isTestMasof(masof)` | Check if terminal is a test terminal |
723
+ | `isValidToken(token)` | Validate 19-digit token format |
724
+ | `isValidEmail(email)` | Basic email validation |
725
+ | `isValidIsraeliId(id)` | Validate Israeli ID (Teudat Zehut) |
726
+ | `isSuccessCode(ccode)` | Check if CCode is success (0/600/700/800) |
727
+ | `isShvaError(ccode)` | Check if CCode is Shva error (1-200) |
728
+ | `isHypayError(ccode)` | Check if CCode is Hypay error (201-999) |
729
+ | `getErrorMessage(ccode)` | Get human-readable error description |
730
+
731
+ ---
732
+
733
+ ## License
734
+
735
+ MIT