@ripwords/myinvois-client 0.1.0 → 0.1.3
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/CHANGELOG.md +111 -0
- package/README.md +128 -4
- package/bun.lock +59 -0
- package/dist/{0X-Yw7mZEro.d.cts → 0X-CTIq3y3a.d.ts} +1 -2
- package/dist/{0X-C4IRh_fJ.d.ts → 0X-Cr3M7hci.d.cts} +1 -1
- package/dist/{1X-D_aUVsuM.d.cts → 1X-Bu4oiv8D.d.ts} +1 -2
- package/dist/{1X-C-_KHV-Q.d.ts → 1X-BywXCqtn.d.ts} +1 -2
- package/dist/{1X-Brnls9Jh.d.ts → 1X-CWwmfCzo.d.cts} +1 -1
- package/dist/{1X-BwpSoT3o.d.cts → 1X-ClnJ79HH.d.cts} +1 -1
- package/dist/{2X-DkS1BoE5.d.ts → 2X-3fSEGIuE.d.ts} +1 -2
- package/dist/{2X-Bb6elyzV.d.cts → 2X-CV9eYhog.d.cts} +1 -1
- package/dist/{2X-UdQcQW24.d.ts → 2X-DNtkJ0tj.d.cts} +1 -1
- package/dist/{2X-hClUyw26.d.cts → 2X-DnG3FY1f.d.ts} +1 -2
- package/dist/{3X-C7VFD-n-.d.cts → 3X--VWVsC84.d.cts} +1 -1
- package/dist/{3X-CLMESDvz.d.cts → 3X-BOxfatu3.d.cts} +1 -1
- package/dist/{3X-DVDyspgb.d.ts → 3X-CLdmoel1.d.ts} +1 -2
- package/dist/{3X-DFI-4RQQ.d.ts → 3X-Ynjfgoll.d.ts} +1 -2
- package/dist/{4X-DIfvpU6V.d.cts → 4X-B5ePdMky.d.ts} +1 -2
- package/dist/{4X-CvScPJTf.d.cts → 4X-BTG6o1Gn.d.ts} +1 -2
- package/dist/{4X-CIJ2JJ2w.d.ts → 4X-By9PzHaY.d.cts} +1 -1
- package/dist/{4X-CUR8jlaZ.d.ts → 4X-C7fzDWJ_.d.cts} +1 -1
- package/dist/{5X-BOUxhadJ.d.cts → 5X-B5M0Cv_K.d.cts} +1 -1
- package/dist/{5X-C6db432h.d.ts → 5X-CNAFsDm2.d.cts} +1 -1
- package/dist/{5X-CkLu7Vyd.d.cts → 5X-CjSz1zxJ.d.ts} +1 -2
- package/dist/{5X-COsZHUaQ.d.ts → 5X-dhP6fyou.d.ts} +1 -2
- package/dist/{6X-Mf32k1d0.d.cts → 6X-B9KP_vEn.d.ts} +1 -2
- package/dist/{6X-DE7RJeV6.d.cts → 6X-BHaY0TCf.d.ts} +1 -2
- package/dist/{6X-ClZDKOTC.d.ts → 6X-C3elgd-n.d.cts} +1 -1
- package/dist/{6X-C_fFIcJC.d.ts → 6X-uObUP4VG.d.cts} +1 -1
- package/dist/{7X-DoCUcp-J.d.cts → 7X-BifJnY24.d.cts} +1 -1
- package/dist/{7X-Chtd6B66.d.cts → 7X-C4eX_tAk.d.ts} +1 -2
- package/dist/{7X-BZyesooz.d.ts → 7X-D3idQBl9.d.cts} +1 -1
- package/dist/{7X-kot_VccM.d.ts → 7X-DtkQutx2.d.ts} +1 -2
- package/dist/{8X-Dr9RunRw.d.cts → 8X-5n9seY3z.d.ts} +1 -2
- package/dist/{8X-DkuKAkHz.d.ts → 8X-C6UMFvQW.d.cts} +1 -1
- package/dist/{8X-DqZyMvyV.d.cts → 8X-D6HTLShY.d.ts} +1 -2
- package/dist/{8X-Df4DOBOe.d.ts → 8X-DioBXCJ0.d.cts} +1 -1
- package/dist/{9X-BaoZtjWF.d.cts → 9X-BjffnXuq.d.cts} +1 -1
- package/dist/{9X-BDgifncF.d.ts → 9X-CHZKsIdD.d.ts} +1 -2
- package/dist/{9X-BcAb6Uso.d.cts → 9X-CJjPJgIG.d.cts} +1 -1
- package/dist/{9X-BhBWlgxG.d.ts → 9X-Cpb6V4JC.d.ts} +1 -2
- package/dist/{AX-D6XHWdrY.d.ts → AX-C0w_r3PA.d.ts} +1 -2
- package/dist/{AX-BY72FohC.d.cts → AX-DrEd2Ov6.d.cts} +1 -1
- package/dist/{BX-D_0C8Qbd.d.ts → BX-C5jc6myN.d.cts} +1 -1
- package/dist/{BX-CA0OmrUZ.d.cts → BX-RadlZ-6m.d.ts} +1 -2
- package/dist/{CX-glpQSL8x.d.cts → CX-CT1Zzb9D.d.ts} +1 -2
- package/dist/{CX-HH4cSZRX.d.ts → CX-oSgvmn3h.d.cts} +1 -1
- package/dist/{DX-Dx22ax_I.d.ts → DX-CtUeTKMM.d.ts} +1 -2
- package/dist/{DX-DimL1MDM.d.cts → DX-ZIG0enmK.d.cts} +1 -1
- package/dist/{EX-BRWh1wFc.d.ts → EX-084Yu7Wt.d.ts} +1 -2
- package/dist/{EX-Cx87Ruxl.d.cts → EX-BpWZ5ADq.d.cts} +1 -1
- package/dist/{FX-RmjwAr40.d.ts → FX-BrbQM0CW.d.ts} +1 -2
- package/dist/{FX-D81UlxNN.d.cts → FX-CvYBEc51.d.cts} +1 -1
- package/dist/{GX-CJyo7oDp.d.ts → GX-CU8PZy0G.d.cts} +1 -1
- package/dist/{GX-9i7piP9G.d.cts → GX-gKj8iAAh.d.ts} +1 -2
- package/dist/{HX-XALBTdLA.d.ts → HX-9D-ZXTy5.d.ts} +1 -2
- package/dist/{HX-20GVJAvl.d.cts → HX-DoEErDeE.d.cts} +1 -1
- package/dist/{IX-D54NGPsc.d.cts → IX-DR4Fc92A.d.ts} +1 -2
- package/dist/{IX-6SZ55QKb.d.ts → IX-jLAUHe8i.d.cts} +1 -1
- package/dist/{JX-hQ1XRmLp.d.ts → JX-DIKa9ma-.d.ts} +1 -2
- package/dist/{JX-C1RYcwQX.d.cts → JX-DX8BjYQC.d.cts} +1 -1
- package/dist/{KX-BNwunEfn.d.ts → KX-DpsJ_unT.d.ts} +1 -2
- package/dist/{KX-gQHCIgtQ.d.cts → KX-fZb4_vhw.d.cts} +1 -1
- package/dist/{LX-CHYX3X3J.d.ts → LX-D_mI1bk-.d.cts} +1 -1
- package/dist/{LX-CPurJGIh.d.cts → LX-DeXPPWUX.d.ts} +1 -2
- package/dist/{MX-BnyW5eHf.d.cts → MX-CKMjg_zK.d.ts} +1 -2
- package/dist/{MX-BPGLWSUz.d.ts → MX-DlYZhpkT.d.cts} +1 -1
- package/dist/{NX-B11fQuco.d.cts → NX-DELEEbad.d.cts} +1 -1
- package/dist/{NX-RulN5Ml3.d.ts → NX-oYdb4NDo.d.ts} +1 -2
- package/dist/{OX-T-ydRXQS.d.cts → OX-Bid9es3D.d.ts} +1 -2
- package/dist/{OX-DgKVSp7I.d.ts → OX-CKPyrIFf.d.cts} +1 -1
- package/dist/{PX-DA4A2kEv.d.ts → PX-D7jy9CFk.d.ts} +1 -2
- package/dist/{PX-p0n1SzvU.d.cts → PX-SP6NxBtG.d.cts} +1 -1
- package/dist/{QX-DrFqsMEs.d.ts → QX-BFWOR4g3.d.ts} +1 -2
- package/dist/{QX-CI1NccIB.d.cts → QX-QZA7E2O-.d.cts} +1 -1
- package/dist/{RX-Cm7vFcFN.d.ts → RX-DBcgbdeE.d.cts} +1 -1
- package/dist/{RX-DnNKol22.d.cts → RX-XHgCyMV1.d.ts} +1 -2
- package/dist/{SX-CsPPTu-W.d.ts → SX-Cl8RN8oH.d.ts} +1 -2
- package/dist/{SX-BUjiWQYz.d.cts → SX-DmiJeCMN.d.cts} +1 -1
- package/dist/{TX-DCY25MdR.d.ts → TX-C1SoDobK.d.cts} +1 -1
- package/dist/{TX-DOEpsf05.d.cts → TX-ZymoIbtr.d.ts} +1 -2
- package/dist/{UX-DgUOnTFK.d.cts → UX-D-Ndd1ov.d.ts} +1 -2
- package/dist/{UX-DauyagHy.d.ts → UX-DFVynFhQ.d.cts} +1 -1
- package/dist/{VX-kUX6LM-3.d.cts → VX-B-1b34r7.d.ts} +1 -2
- package/dist/{VX-DD4scgCe.d.ts → VX-DsRum5k3.d.cts} +1 -1
- package/dist/{WX-DPfyPFFh.d.cts → WX-0GuMjPNZ.d.ts} +1 -2
- package/dist/{WX-CjkoppdY.d.ts → WX-VReU5R5M.d.cts} +1 -1
- package/dist/{XX-C4C1gQZH.d.cts → XX-CF2NANsy.d.ts} +1 -2
- package/dist/{XX-sbsIUOnA.d.ts → XX-ChAviUMj.d.cts} +1 -1
- package/dist/{YX-DUdO8mRC.d.ts → YX-B51BbNSg.d.ts} +1 -2
- package/dist/{YX-BeT-LsiA.d.cts → YX-QfzeMEKx.d.cts} +1 -1
- package/dist/{ZX-DwfcSA-D.d.ts → ZX-BMJS1iAv.d.ts} +1 -2
- package/dist/{ZX-BuVTTq-D.d.cts → ZX-Ca2E726a.d.cts} +1 -1
- package/dist/api/platform/platformLogin.d.ts +58 -60
- package/dist/api/platform/platformLogin.js +1 -1
- package/dist/certificate-DFK-788s.cjs +62 -0
- package/dist/certificate-DFK-788s.cjs.map +1 -0
- package/dist/certificate-aooIRf9A.js +49 -0
- package/dist/{classification-codes-C2X4xW5-.d.ts → classification-codes-BKxV-rO9.d.ts} +1 -2
- package/dist/{country-code-DsI8Mbzx.d.ts → country-code-CQuaiQm2.d.ts} +1 -2
- package/dist/{currencies-DKuDflOO.d.ts → currencies-BYJK-m6v.d.ts} +1 -2
- package/dist/document-CARHiGdp.cjs +472 -0
- package/dist/document-CARHiGdp.cjs.map +1 -0
- package/dist/document-D6VKMAtx.js +405 -0
- package/dist/documents-CJ8hqIGH.d.ts +858 -0
- package/dist/documents-MGs0EvXh.d.cts +859 -0
- package/dist/{e-invoice-C2TxhyrK.d.ts → e-invoice-CmbLQkHw.d.ts} +1 -2
- package/dist/{getBaseUrl-Dx6RDC8I.js → getBaseUrl-R3IdgCu3.js} +1 -2
- package/dist/{index-B1DSs-wd.d.cts → index-0-EvC6Nv.d.ts} +1 -2
- package/dist/{index-FTgB2nM6.d.ts → index-D2_HVwCz.d.cts} +1 -1
- package/dist/index.cjs +308 -12
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +233 -60
- package/dist/index.js +306 -11
- package/dist/index10.cjs +0 -34
- package/dist/index11.cjs +25 -15
- package/dist/index11.cjs.map +1 -1
- package/dist/index12.cjs +24 -0
- package/dist/index12.cjs.map +1 -0
- package/dist/index13.cjs +0 -13
- package/dist/index15.cjs +3 -2
- package/dist/index16.cjs +12 -16
- package/dist/index17.cjs +2 -2
- package/dist/index18.cjs +336 -204
- package/dist/index18.cjs.map +1 -1
- package/dist/index19.cjs +325 -105
- package/dist/index19.cjs.map +1 -1
- package/dist/index20.cjs +136 -133
- package/dist/index20.cjs.map +1 -1
- package/dist/index21.cjs +203 -59
- package/dist/index21.cjs.map +1 -1
- package/dist/index22.cjs +104 -262
- package/dist/index22.cjs.map +1 -1
- package/dist/index23.cjs +132 -74
- package/dist/index23.cjs.map +1 -1
- package/dist/index24.cjs +59 -102
- package/dist/index24.cjs.map +1 -1
- package/dist/index25.cjs +262 -68
- package/dist/index25.cjs.map +1 -1
- package/dist/index26.cjs +74 -107
- package/dist/index26.cjs.map +1 -1
- package/dist/index27.cjs +102 -95
- package/dist/index27.cjs.map +1 -1
- package/dist/index28.cjs +68 -13
- package/dist/index28.cjs.map +1 -1
- package/dist/index29.cjs +107 -33
- package/dist/index29.cjs.map +1 -1
- package/dist/index30.cjs +95 -14
- package/dist/index30.cjs.map +1 -1
- package/dist/index31.cjs +11 -22
- package/dist/index31.cjs.map +1 -1
- package/dist/index32.cjs +31 -13
- package/dist/index32.cjs.map +1 -1
- package/dist/index33.cjs +12 -7
- package/dist/index33.cjs.map +1 -1
- package/dist/index34.cjs +22 -7
- package/dist/index34.cjs.map +1 -1
- package/dist/index35.cjs +13 -10
- package/dist/index35.cjs.map +1 -1
- package/dist/index36.cjs +7 -6
- package/dist/index36.cjs.map +1 -1
- package/dist/index37.cjs +7 -101
- package/dist/index37.cjs.map +1 -1
- package/dist/index38.cjs +10 -106
- package/dist/index38.cjs.map +1 -1
- package/dist/index39.cjs +6 -119
- package/dist/index39.cjs.map +1 -1
- package/dist/index40.cjs +101 -106
- package/dist/index40.cjs.map +1 -1
- package/dist/index41.cjs +106 -98
- package/dist/index41.cjs.map +1 -1
- package/dist/index42.cjs +119 -118
- package/dist/index42.cjs.map +1 -1
- package/dist/index43.cjs +106 -127
- package/dist/index43.cjs.map +1 -1
- package/dist/index44.cjs +98 -117
- package/dist/index44.cjs.map +1 -1
- package/dist/index45.cjs +118 -14
- package/dist/index45.cjs.map +1 -1
- package/dist/index46.cjs +127 -95
- package/dist/index46.cjs.map +1 -1
- package/dist/index47.cjs +117 -142
- package/dist/index47.cjs.map +1 -1
- package/dist/index48.cjs +14 -114
- package/dist/index48.cjs.map +1 -1
- package/dist/index49.cjs +95 -144
- package/dist/index49.cjs.map +1 -1
- package/dist/index5.cjs +0 -25
- package/dist/index50.cjs +142 -113
- package/dist/index50.cjs.map +1 -1
- package/dist/index51.cjs +114 -17
- package/dist/index51.cjs.map +1 -1
- package/dist/index52.cjs +144 -112
- package/dist/index52.cjs.map +1 -1
- package/dist/index53.cjs +113 -47
- package/dist/index53.cjs.map +1 -1
- package/dist/index54.cjs +17 -14
- package/dist/index54.cjs.map +1 -1
- package/dist/index55.cjs +112 -28
- package/dist/index55.cjs.map +1 -1
- package/dist/index56.cjs +47 -22
- package/dist/index56.cjs.map +1 -1
- package/dist/index57.cjs +14 -9
- package/dist/index57.cjs.map +1 -1
- package/dist/index58.cjs +28 -8
- package/dist/index58.cjs.map +1 -1
- package/dist/index58.cts.map +1 -0
- package/dist/index59.cjs +22 -17
- package/dist/index59.cjs.map +1 -1
- package/dist/index59.cts.map +1 -1
- package/dist/index6.cjs +25 -0
- package/dist/{index5.cjs.map → index6.cjs.map} +1 -1
- package/dist/index60.cjs +9 -412
- package/dist/index60.cjs.map +1 -1
- package/dist/index60.cts.map +1 -0
- package/dist/index61.cjs +8 -8
- package/dist/index61.cjs.map +1 -1
- package/dist/index61.cts.map +1 -0
- package/dist/index62.cjs +17 -9
- package/dist/index62.cjs.map +1 -1
- package/dist/index62.cts.map +1 -1
- package/dist/index63.cjs +419 -0
- package/dist/index63.cjs.map +1 -0
- package/dist/index63.cts.map +1 -1
- package/dist/index64.cjs +15 -0
- package/dist/index64.cjs.map +1 -0
- package/dist/index64.cts.map +1 -1
- package/dist/index65.cjs +10 -116
- package/dist/index65.cjs.map +1 -1
- package/dist/index65.cts.map +1 -1
- package/dist/index66.cjs +2 -228
- package/dist/index66.cts.map +1 -1
- package/dist/index8.cjs +0 -25
- package/dist/index9.cjs +25 -0
- package/dist/{index8.cjs.map → index9.cjs.map} +1 -1
- package/dist/msic-codes-C8PJVOaA.d.ts +25 -0
- package/dist/{msic-codes-B_1W6lZF.d.cts → msic-codes-CIKdPqag.d.cts} +11 -11
- package/dist/{payment-modes-DHihrywe.d.cts → payment-modes-BOTSRC_X.d.ts} +1 -2
- package/dist/{payment-modes-B8dNy3SM.d.ts → payment-modes-ghFEXnUl.d.cts} +1 -1
- package/dist/platformLogin-PGzMhw1X.cjs.map +1 -1
- package/dist/{platformLogin-DsxWWUXr.js → platformLogin-f0bNAoZI.js} +1 -2
- package/dist/{signatures-C9QPZTQd.d.ts → signatures-W-_brwdb.d.ts} +1 -2
- package/dist/{signatures-BKi9DP2K.d.cts → signatures-hFbt_std.d.cts} +1 -1
- package/dist/{state-codes-DXSWtE6a.d.cts → state-codes-BlILGZ9d.d.cts} +1 -1
- package/dist/{state-codes-CxG1S9YY.d.ts → state-codes-oeFKlwXZ.d.ts} +1 -2
- package/dist/{tax-types-CgwxONDS.d.cts → tax-types-B5sQ8UyN.d.cts} +1 -1
- package/dist/{tax-types-CEpfSh5P.d.ts → tax-types-CsQ76JMf.d.ts} +1 -2
- package/dist/types/classification-codes.d.ts +1 -1
- package/dist/types/country-code.d.ts +1 -1
- package/dist/types/currencies.d.ts +1 -1
- package/dist/types/documents.d.ts +18 -0
- package/dist/types/e-invoice.d.ts +1 -1
- package/dist/types/index.d.ts +58 -59
- package/dist/types/msic/0X.d.ts +1 -1
- package/dist/types/msic/1X.d.ts +1 -1
- package/dist/types/msic/2X.d.ts +1 -1
- package/dist/types/msic/3X.d.ts +1 -1
- package/dist/types/msic/4X.d.ts +1 -1
- package/dist/types/msic/5X.d.ts +1 -1
- package/dist/types/msic/6X.d.ts +1 -1
- package/dist/types/msic/7X.d.ts +1 -1
- package/dist/types/msic/8X.d.ts +1 -1
- package/dist/types/msic/9X.d.ts +1 -1
- package/dist/types/msic-codes.d.ts +11 -11
- package/dist/types/payment-modes.d.ts +1 -1
- package/dist/types/signatures.d.ts +1 -1
- package/dist/types/state-codes.d.ts +1 -1
- package/dist/types/tax-types.d.ts +1 -1
- package/dist/types/unit/1X.d.ts +1 -1
- package/dist/types/unit/2X.d.ts +1 -1
- package/dist/types/unit/3X.d.ts +1 -1
- package/dist/types/unit/4X.d.ts +1 -1
- package/dist/types/unit/5X.d.ts +1 -1
- package/dist/types/unit/6X.d.ts +1 -1
- package/dist/types/unit/7X.d.ts +1 -1
- package/dist/types/unit/8X.d.ts +1 -1
- package/dist/types/unit/9X.d.ts +1 -1
- package/dist/types/unit/AX.d.ts +1 -1
- package/dist/types/unit/BX.d.ts +1 -1
- package/dist/types/unit/CX.d.ts +1 -1
- package/dist/types/unit/DX.d.ts +1 -1
- package/dist/types/unit/EX.d.ts +1 -1
- package/dist/types/unit/FX.d.ts +1 -1
- package/dist/types/unit/GX.d.ts +1 -1
- package/dist/types/unit/HX.d.ts +1 -1
- package/dist/types/unit/IX.d.ts +1 -1
- package/dist/types/unit/JX.d.ts +1 -1
- package/dist/types/unit/KX.d.ts +1 -1
- package/dist/types/unit/LX.d.ts +1 -1
- package/dist/types/unit/MX.d.ts +1 -1
- package/dist/types/unit/NX.d.ts +1 -1
- package/dist/types/unit/OX.d.ts +1 -1
- package/dist/types/unit/PX.d.ts +1 -1
- package/dist/types/unit/QX.d.ts +1 -1
- package/dist/types/unit/RX.d.ts +1 -1
- package/dist/types/unit/SX.d.ts +1 -1
- package/dist/types/unit/TX.d.ts +1 -1
- package/dist/types/unit/UX.d.ts +1 -1
- package/dist/types/unit/VX.d.ts +1 -1
- package/dist/types/unit/WX.d.ts +1 -1
- package/dist/types/unit/XX.d.ts +1 -1
- package/dist/types/unit/YX.d.ts +1 -1
- package/dist/types/unit/ZX.d.ts +1 -1
- package/dist/types/unit-types.d.ts +36 -36
- package/dist/unit-types-B41YFOLT.d.ts +55 -0
- package/dist/unit-types-CjWNk2wS.d.cts +56 -0
- package/dist/utils/base64.d.ts +1 -2
- package/dist/utils/base64.js +1 -2
- package/dist/utils/certificate.d.ts +22 -0
- package/dist/utils/certificate.js +3 -0
- package/dist/utils/document.d.ts +135 -0
- package/dist/utils/document.js +3 -0
- package/dist/utils/getBaseUrl.d.ts +1 -2
- package/dist/utils/getBaseUrl.js +1 -1
- package/dist/utils/helpers.d.ts +271 -0
- package/dist/utils/helpers.js +330 -0
- package/dist/utils/signature-diagnostics.d.ts +93 -0
- package/dist/utils/signature-diagnostics.js +326 -0
- package/dist/utils/validation.d.ts +46 -0
- package/dist/utils/validation.js +134 -0
- package/myinvois-cert.conf.template +23 -0
- package/package.json +9 -3
- package/scripts/gen-cert.sh +159 -0
- package/src/api/platform/platformLogin.ts +1 -1
- package/src/index.ts +528 -1
- package/src/types/documents.d.ts +870 -0
- package/src/types/index.d.ts +1 -1
- package/src/utils/certificate.ts +60 -0
- package/src/utils/document.ts +852 -0
- package/src/utils/helpers.ts +552 -0
- package/src/utils/signature-diagnostics.ts +583 -0
- package/src/utils/validation.ts +268 -0
- package/test/MyInvoiClientWithRealData.test.ts +9 -1
- package/test/MyInvoisClient.test.ts +7 -1
- package/test/dynamicInvoiceFeatures.test.ts +451 -0
- package/test/signAndSubmitInvoice.test.ts +271 -734
- package/test/signature-diagnostics.test.ts +130 -0
- package/tsconfig.json +0 -3
- package/dist/0X-C4IRh_fJ.d.ts.map +0 -1
- package/dist/0X-Yw7mZEro.d.cts.map +0 -1
- package/dist/1X-Brnls9Jh.d.ts.map +0 -1
- package/dist/1X-BwpSoT3o.d.cts.map +0 -1
- package/dist/1X-C-_KHV-Q.d.ts.map +0 -1
- package/dist/1X-D_aUVsuM.d.cts.map +0 -1
- package/dist/2X-Bb6elyzV.d.cts.map +0 -1
- package/dist/2X-DkS1BoE5.d.ts.map +0 -1
- package/dist/2X-UdQcQW24.d.ts.map +0 -1
- package/dist/2X-hClUyw26.d.cts.map +0 -1
- package/dist/3X-C7VFD-n-.d.cts.map +0 -1
- package/dist/3X-CLMESDvz.d.cts.map +0 -1
- package/dist/3X-DFI-4RQQ.d.ts.map +0 -1
- package/dist/3X-DVDyspgb.d.ts.map +0 -1
- package/dist/4X-CIJ2JJ2w.d.ts.map +0 -1
- package/dist/4X-CUR8jlaZ.d.ts.map +0 -1
- package/dist/4X-CvScPJTf.d.cts.map +0 -1
- package/dist/4X-DIfvpU6V.d.cts.map +0 -1
- package/dist/5X-BOUxhadJ.d.cts.map +0 -1
- package/dist/5X-C6db432h.d.ts.map +0 -1
- package/dist/5X-COsZHUaQ.d.ts.map +0 -1
- package/dist/5X-CkLu7Vyd.d.cts.map +0 -1
- package/dist/6X-C_fFIcJC.d.ts.map +0 -1
- package/dist/6X-ClZDKOTC.d.ts.map +0 -1
- package/dist/6X-DE7RJeV6.d.cts.map +0 -1
- package/dist/6X-Mf32k1d0.d.cts.map +0 -1
- package/dist/7X-BZyesooz.d.ts.map +0 -1
- package/dist/7X-Chtd6B66.d.cts.map +0 -1
- package/dist/7X-DoCUcp-J.d.cts.map +0 -1
- package/dist/7X-kot_VccM.d.ts.map +0 -1
- package/dist/8X-Df4DOBOe.d.ts.map +0 -1
- package/dist/8X-DkuKAkHz.d.ts.map +0 -1
- package/dist/8X-DqZyMvyV.d.cts.map +0 -1
- package/dist/8X-Dr9RunRw.d.cts.map +0 -1
- package/dist/9X-BDgifncF.d.ts.map +0 -1
- package/dist/9X-BaoZtjWF.d.cts.map +0 -1
- package/dist/9X-BcAb6Uso.d.cts.map +0 -1
- package/dist/9X-BhBWlgxG.d.ts.map +0 -1
- package/dist/AX-BY72FohC.d.cts.map +0 -1
- package/dist/AX-D6XHWdrY.d.ts.map +0 -1
- package/dist/BX-CA0OmrUZ.d.cts.map +0 -1
- package/dist/BX-D_0C8Qbd.d.ts.map +0 -1
- package/dist/CX-HH4cSZRX.d.ts.map +0 -1
- package/dist/CX-glpQSL8x.d.cts.map +0 -1
- package/dist/DX-DimL1MDM.d.cts.map +0 -1
- package/dist/DX-Dx22ax_I.d.ts.map +0 -1
- package/dist/EX-BRWh1wFc.d.ts.map +0 -1
- package/dist/EX-Cx87Ruxl.d.cts.map +0 -1
- package/dist/FX-D81UlxNN.d.cts.map +0 -1
- package/dist/FX-RmjwAr40.d.ts.map +0 -1
- package/dist/GX-9i7piP9G.d.cts.map +0 -1
- package/dist/GX-CJyo7oDp.d.ts.map +0 -1
- package/dist/HX-20GVJAvl.d.cts.map +0 -1
- package/dist/HX-XALBTdLA.d.ts.map +0 -1
- package/dist/IX-6SZ55QKb.d.ts.map +0 -1
- package/dist/IX-D54NGPsc.d.cts.map +0 -1
- package/dist/JX-C1RYcwQX.d.cts.map +0 -1
- package/dist/JX-hQ1XRmLp.d.ts.map +0 -1
- package/dist/KX-BNwunEfn.d.ts.map +0 -1
- package/dist/KX-gQHCIgtQ.d.cts.map +0 -1
- package/dist/LX-CHYX3X3J.d.ts.map +0 -1
- package/dist/LX-CPurJGIh.d.cts.map +0 -1
- package/dist/MX-BPGLWSUz.d.ts.map +0 -1
- package/dist/MX-BnyW5eHf.d.cts.map +0 -1
- package/dist/MyInvoisClient-BrNyMjS-.d.cts +0 -178
- package/dist/MyInvoisClient-BrNyMjS-.d.cts.map +0 -1
- package/dist/MyInvoisClient-CXu4pdl-.d.ts +0 -178
- package/dist/MyInvoisClient-CXu4pdl-.d.ts.map +0 -1
- package/dist/MyInvoisClient-Cnvb5iUC.js +0 -299
- package/dist/MyInvoisClient-Cnvb5iUC.js.map +0 -1
- package/dist/MyInvoisClient-DO1dJfQq.cjs +0 -304
- package/dist/MyInvoisClient-DO1dJfQq.cjs.map +0 -1
- package/dist/NX-B11fQuco.d.cts.map +0 -1
- package/dist/NX-RulN5Ml3.d.ts.map +0 -1
- package/dist/OX-DgKVSp7I.d.ts.map +0 -1
- package/dist/OX-T-ydRXQS.d.cts.map +0 -1
- package/dist/PX-DA4A2kEv.d.ts.map +0 -1
- package/dist/PX-p0n1SzvU.d.cts.map +0 -1
- package/dist/QX-CI1NccIB.d.cts.map +0 -1
- package/dist/QX-DrFqsMEs.d.ts.map +0 -1
- package/dist/RX-Cm7vFcFN.d.ts.map +0 -1
- package/dist/RX-DnNKol22.d.cts.map +0 -1
- package/dist/SX-BUjiWQYz.d.cts.map +0 -1
- package/dist/SX-CsPPTu-W.d.ts.map +0 -1
- package/dist/TX-DCY25MdR.d.ts.map +0 -1
- package/dist/TX-DOEpsf05.d.cts.map +0 -1
- package/dist/UX-DauyagHy.d.ts.map +0 -1
- package/dist/UX-DgUOnTFK.d.cts.map +0 -1
- package/dist/VX-DD4scgCe.d.ts.map +0 -1
- package/dist/VX-kUX6LM-3.d.cts.map +0 -1
- package/dist/WX-CjkoppdY.d.ts.map +0 -1
- package/dist/WX-DPfyPFFh.d.cts.map +0 -1
- package/dist/XX-C4C1gQZH.d.cts.map +0 -1
- package/dist/XX-sbsIUOnA.d.ts.map +0 -1
- package/dist/YX-BeT-LsiA.d.cts.map +0 -1
- package/dist/YX-DUdO8mRC.d.ts.map +0 -1
- package/dist/ZX-BuVTTq-D.d.cts.map +0 -1
- package/dist/ZX-DwfcSA-D.d.ts.map +0 -1
- package/dist/api/platform/platformLogin.d.ts.map +0 -1
- package/dist/canonicalize-C_fNNpYr.cjs +0 -80
- package/dist/canonicalize-C_fNNpYr.cjs.map +0 -1
- package/dist/canonicalize-DNUrCGad.js +0 -68
- package/dist/canonicalize-DNUrCGad.js.map +0 -1
- package/dist/classification-codes-B15PbWxz.d.cts.map +0 -1
- package/dist/classification-codes-C2X4xW5-.d.ts.map +0 -1
- package/dist/country-code-DPeNFMMi.d.cts.map +0 -1
- package/dist/country-code-DsI8Mbzx.d.ts.map +0 -1
- package/dist/currencies-DKuDflOO.d.ts.map +0 -1
- package/dist/currencies-S5g1gzBU.d.cts.map +0 -1
- package/dist/e-invoice-BuwtFnlI.d.cts.map +0 -1
- package/dist/e-invoice-C2TxhyrK.d.ts.map +0 -1
- package/dist/getBaseUrl-Dx6RDC8I.js.map +0 -1
- package/dist/hashCert-Bol7lIh2.js +0 -62
- package/dist/hashCert-Bol7lIh2.js.map +0 -1
- package/dist/hashCert-mlYEuYex.cjs +0 -68
- package/dist/hashCert-mlYEuYex.cjs.map +0 -1
- package/dist/hashSignedProperties-9vj5wlYR.js +0 -83
- package/dist/hashSignedProperties-9vj5wlYR.js.map +0 -1
- package/dist/hashSignedProperties-CU_ZqqmY.cjs +0 -95
- package/dist/hashSignedProperties-CU_ZqqmY.cjs.map +0 -1
- package/dist/index-B1DSs-wd.d.cts.map +0 -1
- package/dist/index-CJNLQVjx.d.ts +0 -1
- package/dist/index-FTgB2nM6.d.ts.map +0 -1
- package/dist/index-Wy1ONBjV.d.cts +0 -1
- package/dist/index10.cjs.map +0 -1
- package/dist/index66.cjs.map +0 -1
- package/dist/index67.cjs +0 -4
- package/dist/index67.cts.map +0 -1
- package/dist/index68.cjs +0 -3
- package/dist/index68.cts.map +0 -1
- package/dist/index69.cjs +0 -4
- package/dist/index69.cts.map +0 -1
- package/dist/index70.cjs +0 -3
- package/dist/index70.cts.map +0 -1
- package/dist/index71.cjs +0 -3
- package/dist/index71.cts.map +0 -1
- package/dist/index72.cjs +0 -3
- package/dist/index72.cts.map +0 -1
- package/dist/index73.cjs +0 -3
- package/dist/index73.cts.map +0 -1
- package/dist/invoice-1_1-BJVcw-oE.d.ts +0 -432
- package/dist/invoice-1_1-BJVcw-oE.d.ts.map +0 -1
- package/dist/invoice-1_1-DWdNPRzr.d.cts +0 -432
- package/dist/invoice-1_1-DWdNPRzr.d.cts.map +0 -1
- package/dist/invoice1-1-8S-QQn7P.cjs +0 -547
- package/dist/invoice1-1-8S-QQn7P.cjs.map +0 -1
- package/dist/invoice1-1-CHuLpkFz.js +0 -504
- package/dist/invoice1-1-CHuLpkFz.js.map +0 -1
- package/dist/msic-codes-B_1W6lZF.d.cts.map +0 -1
- package/dist/msic-codes-bs0lTfSZ.d.ts +0 -26
- package/dist/msic-codes-bs0lTfSZ.d.ts.map +0 -1
- package/dist/payment-modes-B8dNy3SM.d.ts.map +0 -1
- package/dist/payment-modes-DHihrywe.d.cts.map +0 -1
- package/dist/platformLogin-DsxWWUXr.js.map +0 -1
- package/dist/populateFinalDocument-BdyYzz5Y.cjs +0 -96
- package/dist/populateFinalDocument-BdyYzz5Y.cjs.map +0 -1
- package/dist/populateFinalDocument-BpLXmgLv.js +0 -90
- package/dist/populateFinalDocument-BpLXmgLv.js.map +0 -1
- package/dist/populateSignedProperties-BJMcBQ6S.cjs +0 -58
- package/dist/populateSignedProperties-BJMcBQ6S.cjs.map +0 -1
- package/dist/populateSignedProperties-BvGN-YZH.js +0 -52
- package/dist/populateSignedProperties-BvGN-YZH.js.map +0 -1
- package/dist/sign-B61Cy3gO.cjs +0 -40
- package/dist/sign-B61Cy3gO.cjs.map +0 -1
- package/dist/sign-DzHK7UhR.js +0 -34
- package/dist/sign-DzHK7UhR.js.map +0 -1
- package/dist/signatures-BKi9DP2K.d.cts.map +0 -1
- package/dist/signatures-C9QPZTQd.d.ts.map +0 -1
- package/dist/state-codes-CxG1S9YY.d.ts.map +0 -1
- package/dist/state-codes-DXSWtE6a.d.cts.map +0 -1
- package/dist/tax-types-CEpfSh5P.d.ts.map +0 -1
- package/dist/tax-types-CgwxONDS.d.cts.map +0 -1
- package/dist/transform-BLz0S687.cjs +0 -72
- package/dist/transform-BLz0S687.cjs.map +0 -1
- package/dist/transform-D1q-U6Zj.js +0 -66
- package/dist/transform-D1q-U6Zj.js.map +0 -1
- package/dist/types/documents/index.d.ts +0 -57
- package/dist/types/documents/invoice-1_1.d.ts +0 -56
- package/dist/unit-types-1bF0KhIp.d.ts +0 -56
- package/dist/unit-types-1bF0KhIp.d.ts.map +0 -1
- package/dist/unit-types-CsrkvgfG.d.cts +0 -56
- package/dist/unit-types-CsrkvgfG.d.cts.map +0 -1
- package/dist/utils/MyInvoisClient.d.ts +0 -60
- package/dist/utils/MyInvoisClient.js +0 -13
- package/dist/utils/base64.d.ts.map +0 -1
- package/dist/utils/base64.js.map +0 -1
- package/dist/utils/debug/debug-document-hash.d.ts +0 -100
- package/dist/utils/debug/debug-document-hash.d.ts.map +0 -1
- package/dist/utils/debug/debug-document-hash.js +0 -120
- package/dist/utils/debug/debug-document-hash.js.map +0 -1
- package/dist/utils/debug/debug-invoice-submission.d.ts +0 -152
- package/dist/utils/debug/debug-invoice-submission.d.ts.map +0 -1
- package/dist/utils/debug/debug-invoice-submission.js +0 -226
- package/dist/utils/debug/debug-invoice-submission.js.map +0 -1
- package/dist/utils/getBaseUrl.d.ts.map +0 -1
- package/dist/utils/invoice1-1.d.ts +0 -117
- package/dist/utils/invoice1-1.d.ts.map +0 -1
- package/dist/utils/invoice1-1.js +0 -10
- package/dist/utils/signature/canonicalize.d.ts +0 -26
- package/dist/utils/signature/canonicalize.d.ts.map +0 -1
- package/dist/utils/signature/canonicalize.js +0 -3
- package/dist/utils/signature/hashCert.d.ts +0 -15
- package/dist/utils/signature/hashCert.d.ts.map +0 -1
- package/dist/utils/signature/hashCert.js +0 -3
- package/dist/utils/signature/hashSignedProperties.d.ts +0 -25
- package/dist/utils/signature/hashSignedProperties.d.ts.map +0 -1
- package/dist/utils/signature/hashSignedProperties.js +0 -3
- package/dist/utils/signature/populateFinalDocument.d.ts +0 -23
- package/dist/utils/signature/populateFinalDocument.d.ts.map +0 -1
- package/dist/utils/signature/populateFinalDocument.js +0 -3
- package/dist/utils/signature/populateSignedProperties.d.ts +0 -23
- package/dist/utils/signature/populateSignedProperties.d.ts.map +0 -1
- package/dist/utils/signature/populateSignedProperties.js +0 -3
- package/dist/utils/signature/sign.d.ts +0 -16
- package/dist/utils/signature/sign.d.ts.map +0 -1
- package/dist/utils/signature/sign.js +0 -3
- package/dist/utils/signature/transform.d.ts +0 -16
- package/dist/utils/signature/transform.d.ts.map +0 -1
- package/dist/utils/signature/transform.js +0 -3
- package/src/types/documents/index.d.ts +0 -1
- package/src/types/documents/invoice-1_1.d.ts +0 -439
- package/src/utils/MyInvoisClient.ts +0 -501
- package/src/utils/debug/debug-document-hash.ts +0 -249
- package/src/utils/debug/debug-invoice-submission.ts +0 -355
- package/src/utils/invoice1-1.ts +0 -671
- package/src/utils/signature/canonicalize.ts +0 -104
- package/src/utils/signature/hashCert.ts +0 -115
- package/src/utils/signature/hashSignedProperties.ts +0 -155
- package/src/utils/signature/populateFinalDocument.ts +0 -187
- package/src/utils/signature/populateSignedProperties.ts +0 -87
- package/src/utils/signature/sign.ts +0 -51
- package/src/utils/signature/transform.ts +0 -99
- package/test/canonicalize.test.ts +0 -110
- package/test/hashCert.test.ts +0 -95
- package/test/hashSignedProperties.test.ts +0 -140
- package/test/populateFinalDocument.test.ts +0 -218
- package/test/populateSignedProperties.test.ts +0 -155
- package/test/sign.test.ts +0 -70
- package/test/transform.test.ts +0 -158
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'crypto'
|
|
2
|
-
import c14nFactory from 'xml-c14n'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Canonicalizes the XML document using the best available canonicalization algorithm,
|
|
6
|
-
* hashes it using SHA-256, and returns the Base64 encoded digest.
|
|
7
|
-
*
|
|
8
|
-
* Corresponds to Step 3 in the MyInvois Signature Creation guide:
|
|
9
|
-
* https://sdk.myinvois.hasil.gov.my/signature-creation/#step-3-canonicalize-the-document-and-generate-the-document-hash-digest
|
|
10
|
-
*
|
|
11
|
-
* Note: MyInvois documentation specifies C14N 1.1, but due to limited Node.js library support,
|
|
12
|
-
* this implementation uses Exclusive C14N which is widely supported and should be compatible
|
|
13
|
-
* in most cases. If signature validation fails, this may need to be updated.
|
|
14
|
-
*
|
|
15
|
-
* @param doc The XML Document object (from xmldom-ts) after transformations (Step 2).
|
|
16
|
-
* @param algorithm Optional canonicalization algorithm URI. Defaults to Exclusive C14N.
|
|
17
|
-
* @returns A Promise resolving to the Base64 encoded SHA-256 hash (DocDigest).
|
|
18
|
-
* @throws {Error} If canonicalization or hashing fails.
|
|
19
|
-
*/
|
|
20
|
-
export function canonicalizeAndHashDocument(
|
|
21
|
-
doc: Document,
|
|
22
|
-
algorithm: string = 'http://www.w3.org/2001/10/xml-exc-c14n#',
|
|
23
|
-
): Promise<string> {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
try {
|
|
26
|
-
// Get the canonicalization factory instance
|
|
27
|
-
const c14n = c14nFactory()
|
|
28
|
-
|
|
29
|
-
// Create a canonicaliser instance for the desired algorithm
|
|
30
|
-
// Try C14N 1.1 first, fallback to Exclusive C14N
|
|
31
|
-
let algorithmUri = algorithm
|
|
32
|
-
|
|
33
|
-
// If C14N 1.1 is requested but not available, use Exclusive C14N
|
|
34
|
-
if (algorithm === 'https://www.w3.org/TR/xml-c14n11') {
|
|
35
|
-
console.warn(
|
|
36
|
-
'C14N 1.1 requested but may not be supported, falling back to Exclusive C14N',
|
|
37
|
-
)
|
|
38
|
-
algorithmUri = 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const canonicaliser = c14n.createCanonicaliser(algorithmUri)
|
|
42
|
-
|
|
43
|
-
// Canonicalize the document using the callback pattern
|
|
44
|
-
canonicaliser.canonicalise(doc, (error, canonicalXml) => {
|
|
45
|
-
if (error) {
|
|
46
|
-
console.error('Error during canonicalization:', error)
|
|
47
|
-
return reject(
|
|
48
|
-
new Error(`Canonicalization failed: ${error.message || error}`),
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (typeof canonicalXml !== 'string') {
|
|
53
|
-
return reject(
|
|
54
|
-
new Error('Canonicalization did not return a string result.'),
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
// Hash the canonicalized document using SHA-256
|
|
60
|
-
const hash = crypto.createHash('sha256')
|
|
61
|
-
hash.update(canonicalXml, 'utf8')
|
|
62
|
-
|
|
63
|
-
// Encode the hash digest to Base64
|
|
64
|
-
const base64Digest = hash.digest('base64')
|
|
65
|
-
|
|
66
|
-
resolve(base64Digest)
|
|
67
|
-
} catch (hashError: any) {
|
|
68
|
-
console.error('Error during hashing:', hashError)
|
|
69
|
-
reject(new Error(`Hashing failed: ${hashError.message || hashError}`))
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
} catch (setupError: any) {
|
|
73
|
-
console.error('Error setting up canonicalizer:', setupError)
|
|
74
|
-
reject(
|
|
75
|
-
new Error(
|
|
76
|
-
`Canonicalizer setup failed: ${setupError.message || setupError}`,
|
|
77
|
-
),
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Attempts to use C14N 1.1 if available, otherwise falls back to Exclusive C14N.
|
|
85
|
-
* This function provides a way to try the MyInvois-specified algorithm first.
|
|
86
|
-
*/
|
|
87
|
-
export async function canonicalizeAndHashDocumentWithC14N11Fallback(
|
|
88
|
-
doc: Document,
|
|
89
|
-
): Promise<string> {
|
|
90
|
-
try {
|
|
91
|
-
// Try C14N 1.1 first (may not be supported by xml-c14n library)
|
|
92
|
-
return await canonicalizeAndHashDocument(
|
|
93
|
-
doc,
|
|
94
|
-
'http://www.w3.org/2006/12/xml-c14n11',
|
|
95
|
-
)
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.warn('C14N 1.1 failed, falling back to Exclusive C14N:', error)
|
|
98
|
-
// Fallback to Exclusive C14N
|
|
99
|
-
return await canonicalizeAndHashDocument(
|
|
100
|
-
doc,
|
|
101
|
-
'http://www.w3.org/2001/10/xml-exc-c14n#',
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'crypto'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Extracts the Base64 encoded DER certificate from a PEM string.
|
|
5
|
-
* Removes headers/footers and newlines.
|
|
6
|
-
*
|
|
7
|
-
* @param pemCert The certificate in PEM format (string).
|
|
8
|
-
* @returns The Base64 encoded DER certificate string.
|
|
9
|
-
* @throws {Error} If the PEM format is invalid or content is not found.
|
|
10
|
-
*/
|
|
11
|
-
function extractBase64FromPem(pemCert: string): string {
|
|
12
|
-
const beginMarker = '-----BEGIN CERTIFICATE-----'
|
|
13
|
-
const endMarker = '-----END CERTIFICATE-----'
|
|
14
|
-
|
|
15
|
-
let startIndex = pemCert.indexOf(beginMarker)
|
|
16
|
-
let endIndex = pemCert.indexOf(endMarker)
|
|
17
|
-
let currentBeginMarker = beginMarker
|
|
18
|
-
|
|
19
|
-
// Check for primary markers
|
|
20
|
-
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
|
|
21
|
-
// Try finding other common markers if the primary one fails
|
|
22
|
-
const altBeginMarker = '-----BEGIN PUBLIC KEY-----'
|
|
23
|
-
const altEndMarker = '-----END PUBLIC KEY-----'
|
|
24
|
-
startIndex = pemCert.indexOf(altBeginMarker)
|
|
25
|
-
endIndex = pemCert.indexOf(altEndMarker)
|
|
26
|
-
currentBeginMarker = altBeginMarker
|
|
27
|
-
|
|
28
|
-
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
|
|
29
|
-
throw new Error(
|
|
30
|
-
'Invalid PEM format: Missing or misplaced BEGIN/END markers (CERTIFICATE or other expected type).',
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Extract the raw content between markers (including newlines, etc.)
|
|
36
|
-
const content = pemCert.substring(
|
|
37
|
-
startIndex + currentBeginMarker.length,
|
|
38
|
-
endIndex,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
// Validate the raw content *before* cleaning - check for invalid chars within the block
|
|
42
|
-
// This regex checks if there's anything *other than* whitespace or Base64 characters.
|
|
43
|
-
const invalidCharRegex = /[^A-Za-z0-9+/=\s]/
|
|
44
|
-
if (invalidCharRegex.test(content)) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
'Invalid non-Base64, non-whitespace characters detected in PEM content block.',
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Clean the extracted content: remove only whitespace (newlines, spaces)
|
|
51
|
-
const base64Der = content.replace(/\s/g, '')
|
|
52
|
-
|
|
53
|
-
// Final check: ensure the cleaned string is valid Base64 format (e.g., correct padding)
|
|
54
|
-
const base64FormatRegex = /^[A-Za-z0-9+/]*={0,2}$/
|
|
55
|
-
if (!base64FormatRegex.test(base64Der)) {
|
|
56
|
-
// This might catch incorrect padding or other structural issues post-cleaning
|
|
57
|
-
throw new Error(
|
|
58
|
-
'Invalid Base64 structure (e.g., padding) after cleaning PEM content.',
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (base64Der.length === 0) {
|
|
63
|
-
throw new Error(
|
|
64
|
-
'Invalid PEM format: No Base64 content found between markers after cleaning.',
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return base64Der
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Hashes the signing certificate using SHA-256 and encodes the hash in Base64.
|
|
73
|
-
*
|
|
74
|
-
* Corresponds to Step 5 in the MyInvois Signature Creation guide:
|
|
75
|
-
* https://sdk.myinvois.hasil.gov.my/signature-creation/#step-5-generate-the-certificate-hash
|
|
76
|
-
*
|
|
77
|
-
* @param certificatePem The signing certificate in PEM format (string).
|
|
78
|
-
* @returns The Base64 encoded SHA-256 hash of the certificate (CertDigest).
|
|
79
|
-
* @throws {Error} If hashing fails or PEM is invalid.
|
|
80
|
-
*/
|
|
81
|
-
export function hashCertificate(certificatePem: string): string {
|
|
82
|
-
try {
|
|
83
|
-
// 1. Extract *and validate* Base64 DER content from PEM
|
|
84
|
-
const base64Der = extractBase64FromPem(certificatePem)
|
|
85
|
-
|
|
86
|
-
// Base64 validation is now done inside extractBase64FromPem
|
|
87
|
-
// const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
88
|
-
// if (base64Der.length > 0 && !base64Regex.test(base64Der)) {
|
|
89
|
-
// throw new Error('Invalid Base64 characters detected in PEM certificate content.')
|
|
90
|
-
// }
|
|
91
|
-
|
|
92
|
-
// 2. Decode Base64 to get the raw DER bytes
|
|
93
|
-
const rawDer = Buffer.from(base64Der, 'base64')
|
|
94
|
-
|
|
95
|
-
// The check below might be redundant now with the improved extraction/validation,
|
|
96
|
-
// but kept as a fallback safety measure.
|
|
97
|
-
if (base64Der.length > 0 && rawDer.length === 0) {
|
|
98
|
-
throw new Error(
|
|
99
|
-
'Invalid Base64 content characters in PEM certificate (Buffer decoding check).',
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// 3. Hash the raw DER certificate using SHA-256
|
|
104
|
-
const hash = crypto.createHash('sha256')
|
|
105
|
-
hash.update(rawDer)
|
|
106
|
-
|
|
107
|
-
// 4. Encode the hash digest to Base64
|
|
108
|
-
const base64CertDigest = hash.digest('base64')
|
|
109
|
-
|
|
110
|
-
return base64CertDigest
|
|
111
|
-
} catch (error: any) {
|
|
112
|
-
console.error('Error hashing certificate:', error)
|
|
113
|
-
throw new Error(`Failed to hash certificate: ${error.message || error}`)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'crypto'
|
|
2
|
-
import * as xpath from 'xpath-ts'
|
|
3
|
-
import c14nFactory from 'xml-c14n'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Selects the SignedProperties element, canonicalizes it using the best available
|
|
7
|
-
* canonicalization algorithm, hashes it using SHA-256, and returns the Base64 encoded digest.
|
|
8
|
-
*
|
|
9
|
-
* Corresponds to Step 7 in the MyInvois Signature Creation guide:
|
|
10
|
-
* https://sdk.myinvois.hasil.gov.my/signature-creation/#step-7-generate-signed-properties-hash
|
|
11
|
-
*
|
|
12
|
-
* Note: MyInvois documentation specifies C14N 1.1, but due to limited Node.js library support,
|
|
13
|
-
* this implementation uses Exclusive C14N which is widely supported and should be compatible
|
|
14
|
-
* in most cases. If signature validation fails, this may need to be updated.
|
|
15
|
-
*
|
|
16
|
-
* @param doc The XML Document object (from xmldom-ts) after SignedProperties population (Step 6).
|
|
17
|
-
* @param algorithm Optional canonicalization algorithm URI. Defaults to Exclusive C14N.
|
|
18
|
-
* @returns A Promise resolving to the Base64 encoded SHA-256 hash (PropsDigest).
|
|
19
|
-
* @throws {Error} If the SignedProperties element cannot be found or canonicalization/hashing fails.
|
|
20
|
-
*/
|
|
21
|
-
export function hashSignedProperties(
|
|
22
|
-
doc: Document,
|
|
23
|
-
algorithm: string = 'http://www.w3.org/2001/10/xml-exc-c14n#',
|
|
24
|
-
): Promise<string> {
|
|
25
|
-
return new Promise((resolve, reject) => {
|
|
26
|
-
try {
|
|
27
|
-
// Define namespaces, including the default namespace for Invoice
|
|
28
|
-
const ns = {
|
|
29
|
-
inv: 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2',
|
|
30
|
-
ext: 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
|
|
31
|
-
sig: 'urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2',
|
|
32
|
-
sac: 'urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2',
|
|
33
|
-
ds: 'http://www.w3.org/2000/09/xmldsig#',
|
|
34
|
-
xades: 'http://uri.etsi.org/01903/v1.3.2#',
|
|
35
|
-
}
|
|
36
|
-
const select = xpath.useNamespaces(ns)
|
|
37
|
-
|
|
38
|
-
// 1. Get the SignedProperties element using XPath
|
|
39
|
-
const signedPropertiesXPath =
|
|
40
|
-
'/inv:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sig:UBLDocumentSignatures/sac:SignatureInformation/ds:Signature/ds:Object/xades:QualifyingProperties/xades:SignedProperties'
|
|
41
|
-
const nodes = select(signedPropertiesXPath, doc)
|
|
42
|
-
|
|
43
|
-
if (!Array.isArray(nodes) || nodes.length === 0) {
|
|
44
|
-
throw new Error(
|
|
45
|
-
`SignedProperties element not found for XPath: ${signedPropertiesXPath}`,
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
if (nodes.length > 1) {
|
|
49
|
-
throw new Error(
|
|
50
|
-
`Multiple SignedProperties elements found (expected 1): ${signedPropertiesXPath}`,
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
const signedPropertiesNode = nodes[0] as Node
|
|
54
|
-
|
|
55
|
-
if (!signedPropertiesNode) {
|
|
56
|
-
throw new Error('Selected SignedProperties node is invalid or null.')
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// 2. Canonicalize the SignedProperties node
|
|
60
|
-
const c14n = c14nFactory()
|
|
61
|
-
|
|
62
|
-
// Try C14N 1.1 first, fallback to Exclusive C14N
|
|
63
|
-
let algorithmUri = algorithm
|
|
64
|
-
|
|
65
|
-
// If C14N 1.1 is requested but not available, use Exclusive C14N
|
|
66
|
-
if (algorithm === 'https://www.w3.org/TR/xml-c14n11') {
|
|
67
|
-
console.warn(
|
|
68
|
-
'C14N 1.1 requested for SignedProperties but may not be supported, falling back to Exclusive C14N',
|
|
69
|
-
)
|
|
70
|
-
algorithmUri = 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const canonicaliser = c14n.createCanonicaliser(algorithmUri)
|
|
74
|
-
|
|
75
|
-
// Canonicalize the SignedProperties node using the callback pattern
|
|
76
|
-
canonicaliser.canonicalise(
|
|
77
|
-
signedPropertiesNode,
|
|
78
|
-
(error, canonicalXml) => {
|
|
79
|
-
if (error) {
|
|
80
|
-
console.error(
|
|
81
|
-
'Error during SignedProperties canonicalization:',
|
|
82
|
-
error,
|
|
83
|
-
)
|
|
84
|
-
return reject(
|
|
85
|
-
new Error(
|
|
86
|
-
`SignedProperties canonicalization failed: ${error.message || error}`,
|
|
87
|
-
),
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (typeof canonicalXml !== 'string') {
|
|
92
|
-
return reject(
|
|
93
|
-
new Error(
|
|
94
|
-
'SignedProperties canonicalization did not return a string result.',
|
|
95
|
-
),
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
// 3. Hash the canonicalized property tag using SHA-256
|
|
101
|
-
const hash = crypto.createHash('sha256')
|
|
102
|
-
hash.update(canonicalXml, 'utf8')
|
|
103
|
-
|
|
104
|
-
// 4. Encode the hashed property tag using Base64 Encoder
|
|
105
|
-
const base64PropsDigest = hash.digest('base64')
|
|
106
|
-
|
|
107
|
-
resolve(base64PropsDigest)
|
|
108
|
-
} catch (hashError: any) {
|
|
109
|
-
console.error('Error during SignedProperties hashing:', hashError)
|
|
110
|
-
reject(
|
|
111
|
-
new Error(
|
|
112
|
-
`SignedProperties hashing failed: ${hashError.message || hashError}`,
|
|
113
|
-
),
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
)
|
|
118
|
-
} catch (setupError: any) {
|
|
119
|
-
console.error(
|
|
120
|
-
'Error setting up or selecting SignedProperties:',
|
|
121
|
-
setupError,
|
|
122
|
-
)
|
|
123
|
-
reject(
|
|
124
|
-
new Error(
|
|
125
|
-
`SignedProperties processing setup failed: ${setupError.message || setupError}`,
|
|
126
|
-
),
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Attempts to use C14N 1.1 for SignedProperties if available, otherwise falls back to Exclusive C14N.
|
|
134
|
-
*/
|
|
135
|
-
export async function hashSignedPropertiesWithC14N11Fallback(
|
|
136
|
-
doc: Document,
|
|
137
|
-
): Promise<string> {
|
|
138
|
-
try {
|
|
139
|
-
// Try C14N 1.1 first (may not be supported by xml-c14n library)
|
|
140
|
-
return await hashSignedProperties(
|
|
141
|
-
doc,
|
|
142
|
-
'http://www.w3.org/2006/12/xml-c14n11',
|
|
143
|
-
)
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.warn(
|
|
146
|
-
'C14N 1.1 failed for SignedProperties, falling back to Exclusive C14N:',
|
|
147
|
-
error,
|
|
148
|
-
)
|
|
149
|
-
// Fallback to Exclusive C14N
|
|
150
|
-
return await hashSignedProperties(
|
|
151
|
-
doc,
|
|
152
|
-
'http://www.w3.org/2001/10/xml-exc-c14n#',
|
|
153
|
-
)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import * as xpath from 'xpath-ts'
|
|
2
|
-
|
|
3
|
-
export interface FinalDocumentData {
|
|
4
|
-
signatureValue: string // Base64 encoded RSA signature (Sig from Step 4)
|
|
5
|
-
propsDigest: string // Base64 encoded hash of SignedProperties (PropsDigest from Step 7)
|
|
6
|
-
docDigest: string // Base64 encoded hash of Canonicalized Document (DocDigest from Step 3)
|
|
7
|
-
certificatePem: string // Signing certificate in PEM format
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Extracts the Base64 encoded DER certificate content from a PEM string,
|
|
12
|
-
* removing headers, footers, and newlines.
|
|
13
|
-
* @param pemCert The certificate in PEM format.
|
|
14
|
-
* @returns The cleaned Base64 DER string.
|
|
15
|
-
*/
|
|
16
|
-
function cleanCertificatePem(pemCert: string): string {
|
|
17
|
-
const beginMarker = '-----BEGIN CERTIFICATE-----'
|
|
18
|
-
const endMarker = '-----END CERTIFICATE-----'
|
|
19
|
-
let content = pemCert
|
|
20
|
-
|
|
21
|
-
const startIndex = pemCert.indexOf(beginMarker)
|
|
22
|
-
const endIndex = pemCert.indexOf(endMarker)
|
|
23
|
-
|
|
24
|
-
if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
|
|
25
|
-
content = pemCert.substring(startIndex + beginMarker.length, endIndex)
|
|
26
|
-
} // else: Assume it might be just the Base64 part already, or another PEM type
|
|
27
|
-
|
|
28
|
-
// Remove any remaining non-Base64 characters (newlines, etc.)
|
|
29
|
-
return content.replace(/[^A-Za-z0-9+/=]/g, '')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Populates the final signature information fields within the UBL document's signature structure.
|
|
34
|
-
*
|
|
35
|
-
* Corresponds to Step 8 in the MyInvois Signature Creation guide:
|
|
36
|
-
* https://sdk.myinvois.hasil.gov.my/signature-creation/#step-8-populate-the-information-in-the-document-to-create-the-signed-document
|
|
37
|
-
*
|
|
38
|
-
* Modifies the passed Document object in place.
|
|
39
|
-
*
|
|
40
|
-
* @param doc The XML Document object (from xmldom-ts) containing the signature structure.
|
|
41
|
-
* @param finalData An object containing the final signature data to populate.
|
|
42
|
-
* @throws {Error} If any target element cannot be found or if multiple are found.
|
|
43
|
-
*/
|
|
44
|
-
export function populateFinalDocument(
|
|
45
|
-
doc: Document,
|
|
46
|
-
finalData: FinalDocumentData,
|
|
47
|
-
): void {
|
|
48
|
-
const ns = {
|
|
49
|
-
inv: 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2',
|
|
50
|
-
ext: 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
|
|
51
|
-
sig: 'urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2',
|
|
52
|
-
sac: 'urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2',
|
|
53
|
-
ds: 'http://www.w3.org/2000/09/xmldsig#',
|
|
54
|
-
// No xades needed here, but cac might be needed if populating /Invoice/cac:Signature
|
|
55
|
-
// cac: 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'
|
|
56
|
-
cac: 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
|
|
57
|
-
cbc: 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
|
|
58
|
-
}
|
|
59
|
-
const select = xpath.useNamespaces(ns)
|
|
60
|
-
|
|
61
|
-
// Helper function to find a single node and set its text content
|
|
62
|
-
const setElementValue = (xpathExpr: string, value: string) => {
|
|
63
|
-
try {
|
|
64
|
-
const selectionResult = select(xpathExpr, doc) // Store the result first
|
|
65
|
-
|
|
66
|
-
// Check 0: Explicitly check for null/undefined before array check
|
|
67
|
-
if (selectionResult == null) {
|
|
68
|
-
// Use == to catch both null and undefined
|
|
69
|
-
throw new Error(
|
|
70
|
-
`XPath selection returned null or undefined for: ${xpathExpr}`,
|
|
71
|
-
)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Check 1: Ensure it's an array (xpath.select can return other types)
|
|
75
|
-
if (!Array.isArray(selectionResult)) {
|
|
76
|
-
throw new Error(
|
|
77
|
-
`XPath selection did not return an array for: ${xpathExpr}. Result: ${typeof selectionResult}`,
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Check 2: Ensure exactly one node was found
|
|
82
|
-
if (selectionResult.length === 0) {
|
|
83
|
-
throw new Error(`Element not found for XPath: ${xpathExpr}`)
|
|
84
|
-
}
|
|
85
|
-
if (selectionResult.length > 1) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
`Multiple elements found for XPath (expected 1): ${xpathExpr}`,
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Check 3: Ensure the found item is a Node and specifically an Element node (type 1)
|
|
92
|
-
const node = selectionResult[0] as Node // Assert as Node for type checking
|
|
93
|
-
// Node.ELEMENT_NODE is typically 1
|
|
94
|
-
if (
|
|
95
|
-
!node ||
|
|
96
|
-
typeof node !== 'object' ||
|
|
97
|
-
!('nodeType' in node) ||
|
|
98
|
-
node.nodeType !== 1
|
|
99
|
-
) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Selected item is not an Element Node for XPath: ${xpathExpr}. Node details: ${JSON.stringify(node)}`,
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Check 4: Ensure textContent can be set (should be true for element nodes)
|
|
106
|
-
if ('textContent' in node) {
|
|
107
|
-
// Ensure the property is writable (though typically it is for elements)
|
|
108
|
-
node.textContent = value
|
|
109
|
-
} else {
|
|
110
|
-
// This case should technically be impossible if nodeType is 1
|
|
111
|
-
throw new Error(
|
|
112
|
-
`Selected Element Node does not have textContent property for XPath: ${xpathExpr}`,
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
} catch (error: any) {
|
|
116
|
-
console.error(`Error setting value for XPath ${xpathExpr}:`, error)
|
|
117
|
-
// Keep the wrapping error message format consistent with tests
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Failed to set value for XPath ${xpathExpr}: ${error.message}`,
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Helper function to check if *at least one* node exists for an XPath
|
|
125
|
-
const checkElementExists = (xpathExpr: string): boolean => {
|
|
126
|
-
try {
|
|
127
|
-
const selectionResult = select(xpathExpr, doc)
|
|
128
|
-
// Check if it's an array and has at least one element
|
|
129
|
-
return Array.isArray(selectionResult) && selectionResult.length > 0
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.error(`Error checking existence for XPath ${xpathExpr}:`, error)
|
|
132
|
-
return false // Treat errors during check as non-existent
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Define XPaths based on UBL documentation for Step 8
|
|
137
|
-
const basePath =
|
|
138
|
-
'/inv:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sig:UBLDocumentSignatures/sac:SignatureInformation/ds:Signature'
|
|
139
|
-
|
|
140
|
-
// Define XPaths for the parent Reference elements
|
|
141
|
-
const propsRefPath = `${basePath}/ds:SignedInfo/ds:Reference[@URI='#id-xades-signed-props']`
|
|
142
|
-
const docRefPath = `${basePath}/ds:SignedInfo/ds:Reference[@Id='id-doc-signed-data']`
|
|
143
|
-
|
|
144
|
-
// Define XPaths for the target elements
|
|
145
|
-
const signatureValuePath = `${basePath}/ds:SignatureValue`
|
|
146
|
-
const x509CertPath = `${basePath}/ds:KeyInfo/ds:X509Data/ds:X509Certificate`
|
|
147
|
-
const propsDigestPath = `${propsRefPath}/ds:DigestValue`
|
|
148
|
-
const docDigestPath = `${docRefPath}/ds:DigestValue`
|
|
149
|
-
|
|
150
|
-
// Populate the values, adding existence checks for Reference parents
|
|
151
|
-
setElementValue(signatureValuePath, finalData.signatureValue)
|
|
152
|
-
setElementValue(x509CertPath, cleanCertificatePem(finalData.certificatePem))
|
|
153
|
-
|
|
154
|
-
// Check propsDigest parent before setting value
|
|
155
|
-
if (!checkElementExists(propsRefPath)) {
|
|
156
|
-
// Throw using the child path to match original test intent
|
|
157
|
-
throw new Error(
|
|
158
|
-
`Failed to set value for XPath ${propsDigestPath}: Element not found for XPath: ${propsDigestPath}`,
|
|
159
|
-
)
|
|
160
|
-
}
|
|
161
|
-
setElementValue(propsDigestPath, finalData.propsDigest)
|
|
162
|
-
|
|
163
|
-
// Check docDigest parent before setting value
|
|
164
|
-
if (!checkElementExists(docRefPath)) {
|
|
165
|
-
// Throw using the child path to match original test intent
|
|
166
|
-
throw new Error(
|
|
167
|
-
`Failed to set value for XPath ${docDigestPath}: Element not found for XPath: ${docDigestPath}`,
|
|
168
|
-
)
|
|
169
|
-
}
|
|
170
|
-
setElementValue(docDigestPath, finalData.docDigest)
|
|
171
|
-
|
|
172
|
-
// Populate the /Invoice/cac:Signature elements
|
|
173
|
-
const cacSignatureIdPath = '/inv:Invoice/cac:Signature/cbc:ID'
|
|
174
|
-
const cacSignatureMethodPath =
|
|
175
|
-
'/inv:Invoice/cac:Signature/cbc:SignatureMethod'
|
|
176
|
-
|
|
177
|
-
// Static values based on the user's example XML
|
|
178
|
-
const cacSignatureIdValue =
|
|
179
|
-
'urn:oasis:names:specification:ubl:signature:Invoice'
|
|
180
|
-
const cacSignatureMethodValue =
|
|
181
|
-
'urn:oasis:names:specification:ubl:dsig:enveloped:xades'
|
|
182
|
-
|
|
183
|
-
setElementValue(cacSignatureIdPath, cacSignatureIdValue)
|
|
184
|
-
setElementValue(cacSignatureMethodPath, cacSignatureMethodValue)
|
|
185
|
-
|
|
186
|
-
// Document `doc` is modified in place.
|
|
187
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import * as xpath from 'xpath-ts'
|
|
2
|
-
|
|
3
|
-
export interface SignedPropertiesData {
|
|
4
|
-
certDigest: string // Base64 encoded SHA-256 hash of certificate (Step 5)
|
|
5
|
-
signingTime: string // ISO 8601 UTC timestamp string (e.g., 2023-10-26T10:30:00Z)
|
|
6
|
-
issuerName: string // Certificate Issuer Name
|
|
7
|
-
serialNumber: string // Certificate Serial Number
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Populates the SignedProperties section within the UBL document's signature structure.
|
|
12
|
-
*
|
|
13
|
-
* Corresponds to Step 6 in the MyInvois Signature Creation guide:
|
|
14
|
-
* https://sdk.myinvois.hasil.gov.my/signature-creation/#step-6-populate-the-signed-properties-section
|
|
15
|
-
*
|
|
16
|
-
* Modifies the passed Document object in place.
|
|
17
|
-
*
|
|
18
|
-
* @param doc The XML Document object (from xmldom-ts) containing the signature structure.
|
|
19
|
-
* @param properties An object containing the data to populate.
|
|
20
|
-
* @throws {Error} If any target element cannot be found or if multiple are found.
|
|
21
|
-
*/
|
|
22
|
-
export function populateSignedProperties(
|
|
23
|
-
doc: Document,
|
|
24
|
-
properties: SignedPropertiesData,
|
|
25
|
-
): void {
|
|
26
|
-
// Define namespaces used in the XPaths
|
|
27
|
-
const ns = {
|
|
28
|
-
inv: 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', // Define prefix for default NS
|
|
29
|
-
ext: 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
|
|
30
|
-
sig: 'urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2',
|
|
31
|
-
sac: 'urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2',
|
|
32
|
-
ds: 'http://www.w3.org/2000/09/xmldsig#',
|
|
33
|
-
xades: 'http://uri.etsi.org/01903/v1.3.2#', // Common XAdES namespace
|
|
34
|
-
}
|
|
35
|
-
const select = xpath.useNamespaces(ns)
|
|
36
|
-
|
|
37
|
-
// Helper function to find a single node and set its text content
|
|
38
|
-
const setElementValue = (xpathExpr: string, value: string) => {
|
|
39
|
-
try {
|
|
40
|
-
const nodes = select(xpathExpr, doc)
|
|
41
|
-
|
|
42
|
-
// Refine check: Explicitly look for an empty array result
|
|
43
|
-
if (!Array.isArray(nodes) || nodes.length === 0) {
|
|
44
|
-
throw new Error(`Element not found for XPath: ${xpathExpr}`)
|
|
45
|
-
}
|
|
46
|
-
if (nodes.length > 1) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`Multiple elements found for XPath (expected 1): ${xpathExpr}`,
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const node = nodes[0]
|
|
53
|
-
|
|
54
|
-
// Ensure it's a valid Node (like Element or Attr) before setting textContent
|
|
55
|
-
if (node && typeof node === 'object' && 'textContent' in node) {
|
|
56
|
-
// Type assertion might be needed if TS struggles with union type from select
|
|
57
|
-
;(node as Node).textContent = value
|
|
58
|
-
} else {
|
|
59
|
-
throw new Error(
|
|
60
|
-
`Selected item is not a valid Node for XPath: ${xpathExpr}`,
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
} catch (error: any) {
|
|
64
|
-
console.error(`Error setting value for XPath ${xpathExpr}:`, error)
|
|
65
|
-
// Re-throw to indicate failure to populate
|
|
66
|
-
throw new Error(
|
|
67
|
-
`Failed to set value for XPath ${xpathExpr}: ${error.message}`,
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Define XPaths based on UBL documentation
|
|
73
|
-
// Use the defined prefix 'inv' for the root Invoice element
|
|
74
|
-
const basePath =
|
|
75
|
-
'/inv:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sig:UBLDocumentSignatures/sac:SignatureInformation/ds:Signature/ds:Object/xades:QualifyingProperties/xades:SignedProperties/xades:SignedSignatureProperties'
|
|
76
|
-
|
|
77
|
-
const certDigestPath = `${basePath}/xades:SigningCertificate/xades:Cert/xades:CertDigest/ds:DigestValue`
|
|
78
|
-
const signingTimePath = `${basePath}/xades:SigningTime`
|
|
79
|
-
const issuerNamePath = `${basePath}/xades:SigningCertificate/xades:Cert/xades:IssuerSerial/ds:X509IssuerName`
|
|
80
|
-
const serialNumberPath = `${basePath}/xades:SigningCertificate/xades:Cert/xades:IssuerSerial/ds:X509SerialNumber`
|
|
81
|
-
|
|
82
|
-
// Populate the values
|
|
83
|
-
setElementValue(certDigestPath, properties.certDigest)
|
|
84
|
-
setElementValue(signingTimePath, properties.signingTime)
|
|
85
|
-
setElementValue(issuerNamePath, properties.issuerName)
|
|
86
|
-
setElementValue(serialNumberPath, properties.serialNumber)
|
|
87
|
-
}
|