Tutorial Pasukan Lucee MY

MyInvois: bina dan hantar dokumen UBL XML dari CFML

Bina dan hantar dokumen UBL 2.1 XML e-Invois MyInvois dari CFML: elemen wajib, kod jenis, versi 1.1, documentHash dan alternatif JSON yang lebih selamat.

MyInvois: bina dan hantar dokumen UBL XML dari CFML
0
Kandungan

MyInvois: bina dan hantar dokumen UBL XML dari CFML

MyInvois menerima e-Invois dalam standard UBL 2.1, sama ada sebagai dokumen XML atau perwakilan JSON alternatifnya. Dari Lucee, aliran kerjanya begini: bina dokumen XML sebagai rentetan, kira documentHash SHA-256 ke atasnya, bungkus dokumen dalam base64, kemudian hantar ke endpoint documentsubmissions menggunakan cfhttp. Jawapan pantas kepada soalan paling lazim: bahagian yang paling sukar bukan membina XML itu sendiri, tetapi menandatanganinya secara digital, kerana laluan XML memerlukan canonicalization xml-c14n11 yang amat cerewet. Artikel ini menunjukkan cara membina dokumen yang sah, menghantarnya, dan mengelak perangkap tandatangan dengan memilih laluan JSON yang lebih selamat.

Jenis dan versi dokumen UBL 2.1

MyInvois menyokong UBL 2.1 dalam dua bentuk: XML dan UBL 2.1 JSON Alternative Representation versi 2.0. Sebelum menulis sebarang elemen, anda mesti memilih jenis dan versi dokumen. Kod jenis e-Invois rasmi ialah 01 untuk Invoice, 02 Credit Note, 03 Debit Note, 04 Refund Note, dan 11 hingga 14 untuk varian self-billed bagi empat jenis itu. Versi dokumen diisi melalui atribut listVersionID pada cbc:InvoiceTypeCode: versi 1.0 tidak melalui validasi tandatangan, manakala versi 1.1 ke atas memerlukan tandatangan digital yang sah. Terdapat juga versi SVDP 1.2 tanpa tandatangan dan SVDP 1.3 dengan tandatangan untuk program khas. Untuk hantaran pengeluaran, sasarkan versi 1.1.

Elemen wajib minimum invois

Dokumentasi struktur data Invoice versi 1.1 menetapkan elemen wajib pada peringkat teras. Tanpa salah satu daripadanya, dokumen akan ditolak oleh validator struktur. Elemen wajib itu ialah cac:AccountingSupplierParty, cac:AccountingCustomerParty, cbc:InvoiceTypeCode dengan atribut listVersionID, cbc:ID yang terhad kepada 50 aksara, cbc:IssueDate dan cbc:IssueTime, cac:Signature, cbc:DocumentCurrencyCode dengan TaxCurrencyCode pilihan, cac:InvoiceLine, ketiga-tiga jumlah dalam LegalMonetaryTotal iaitu TaxExclusiveAmount, TaxInclusiveAmount dan PayableAmount, serta TaxTotal dengan TaxAmount dan pecahan TaxSubtotal mengikut kategori cukai. Jumlah ini mesti konsisten secara matematik antara satu sama lain.

Supplier, Buyer, Address dan Line Item

Blok Supplier dan Buyer membawa identiti setiap pihak. Supplier wajib menyertakan Name, TIN dengan schemeID bernilai TIN sepanjang 14 aksara, Registration atau Identification Number daripada jenis BRN, NRIC, PASSPORT atau ARMY, nombor SST yang diisi NA jika tidak berdaftar, Tourism Tax Number dengan peraturan sama, MSIC Code lima digit, Business Activity Description, Address dan Contact Number. Buyer memerlukan subset hampir sama kecuali MSIC dan Tourism Tax. Alamat wajib mengandungi Address Line sehingga 150 aksara, City Name sehingga 50 aksara, State dalam kod negeri rasmi, dan Country kod ISO 3166-1 tiga aksara. Setiap Line Item wajib ada Classification iaitu cbc:ItemClassificationCode dengan listID CLASS tiga aksara, Description, Unit Price dalam Price/PriceAmount, Tax Type, Tax Amount, Subtotal dan Total Excluding Tax.

Format TIN dan nombor rujukan yang betul

TIN individu menggunakan awalan IG, manakala TIN bukan individu dengan awalan C, CS, D dan lain-lain sentiasa berakhir dengan sifar dan sifar awal selepas awalan dibuang. Contohnya C01234567890 ditulis sebagai C1234567890. Nombor rujukan e-Invois dalam cbc:ID bebas daripada sekatan aksara khas tetapi terhad kepada 50 aksara. Untuk memadankan rekod dalaman, anda menghantar codeNumber anda sendiri bersama dokumen; MyInvois kemudian memulangkan uuid 26 aksara alfanumerik Latin yang boleh anda petakan semula kepada nombor rujukan dalaman anda.

Membina dokumen XML dari CFML

Pendekatan paling mudah dan boleh diramal ialah membina XML sebagai rentetan dengan penyambungan, bukannya bergelut dengan pembina XML yang mengubah susunan atribut. Contoh di bawah membina rangka awal dengan elemen teras; blok Supplier, Buyer, InvoiceLine dan jumlah ditambah mengikut corak yang sama:

// Rangka UBL 2.1 (fragmen, bukan dokumen lengkap).
// Lengkapkan Supplier, Buyer, InvoiceLine dan jumlah mengikut sampel rasmi.
invoiceCode = "INV-2026-0001";
issueDate = dateFormat(now(), "yyyy-mm-dd");
issueTime = "00:00:00Z";

xmlDoc = '<?xml version="1.0" encoding="UTF-8"?>' & chr(10)
  & '<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">' & chr(10)
  & '  <cbc:ID>' & invoiceCode & '</cbc:ID>' & chr(10)
  & '  <cbc:IssueDate>' & issueDate & '</cbc:IssueDate>' & chr(10)
  & '  <cbc:IssueTime>' & issueTime & '</cbc:IssueTime>' & chr(10)
  & '  <cbc:InvoiceTypeCode listVersionID="1.1">01</cbc:InvoiceTypeCode>' & chr(10)
  & '  <cbc:DocumentCurrencyCode>MYR</cbc:DocumentCurrencyCode>' & chr(10)
  & '</Invoice>';

Pastikan susunan elemen mengikut sampel XML rasmi; validator struktur menolak susunan yang salah tanpa kod ralat khusus.

Base64 dan documentHash sebelum hantar

Sebelum menghantar, dokumen mesti dibalut dalam base64 dan documentHash SHA-256 mesti dikira. Endpoint penghantaran ialah POST /api/v1.0/documentsubmissions/ pada API sistem. Permintaan mengandungi senarai documents, dan setiap dokumen membawa medan format sama ada XML atau JSON, document dalam base64, documentHash dan codeNumber. Jawapan yang berjaya ialah HTTP 202, bukan 200, kerana validasi belum selesai semasa respons dikembalikan; anda menerima submissionUID 26 aksara untuk menyemak status kemudian:

// Kira hash dan hantar dokumen ke MyInvois (sandbox)
binaryDoc = charsetDecode(xmlDoc, "utf-8");
docBase64 = binaryEncode(binaryDoc, "base64");
docHash = hash(binaryDoc, "SHA-256");

payload = {
  "documents" = [
    {
      "format" = "XML",
      "document" = docBase64,
      "documentHash" = docHash,
      "codeNumber" = invoiceCode
    }
  ]
};

cfhttp(method = "POST",
       url = "https://preprod-api.myinvois.hasil.gov.my/api/v1.0/documentsubmissions/",
       result = "resp") {
  cfhttpparam(type = "header", name = "Authorization", value = "Bearer " & accessToken);
  cfhttpparam(type = "header", name = "Content-Type", value = "application/json");
  cfhttpparam(type = "body", value = serializeJSON(payload));
}

// resp.statusCode sepatutnya 202; baca resp.filecontent untuk submissionUID

Sahkan perwakilan documentHash, sama ada hex atau base64, terhadap sampel rasmi sebelum go-live, dan semak status menggunakan submissionUID dengan selang 3 hingga 5 saat. Asas memanggil API luar dijelaskan dalam panduan cfhttp dan panggilan API luar.

Tandatangan XML: c14n11 ialah bahagian tersukar

Tandatangan digital MyInvois mengikut XAdES enveloped dengan hashing SHA-256 dan algoritma RSA. Kandungan yang ditandatangani ialah seluruh dokumen kecuali UBLExtensions dan elemen Signature. Di sinilah kesukarannya: laluan XML memerlukan canonicalization xml-c14n11 sebelum hashing. Susunan atribut, namespace dan ruang putih mesti tepat; sebarang perbezaan menghasilkan ralat DS322 iaitu document digest mismatch. Enjin Java yang menjalankan Lucee menyediakan komponen yang diperlukan secara prinsip, iaitu java.security.MessageDigest untuk SHA-256 dan java.security.Signature dengan SHA256withRSA, tetapi menyiapkan c14n11 yang betul-betul sama dengan jangkaan LHDN mesti diuji di sandbox dahulu. Jangan anggap ia mudah. Panduan penuh menandatangan dibincangkan dalam panduan tandatangan digital dan sijil LHDN.

Alternatif selamat: hantar JSON

Dokumentasi rasmi menyokong penghantaran dokumen dalam format JSON selain XML, dan ini laluan yang paling selamat untuk permulaan. Perwakilan JSON UBL 2.1 tidak memerlukan canonicalization XML; anda hanya meminimumkan JSON, mengira SHA-256 dan menandatanganinya. Corak atribut JSON ialah pasangan kunci garis bawah untuk nilai atribut, contohnya InvoiceTypeCode diwakili sebagai kunci underscore dengan nilai kod dan listVersionID. Memandangkan laluan JSON mengelak c14n11 sepenuhnya, mulakan di sini sebelum kembali ke XML jika keperluan perniagaan mendesak. Keseluruhan aliran OAuth dan penghantaran diterangkan dalam panduan integrasi MyInvois dari Lucee.

Medan yang paling kerap ditolak dan cara betulkan

Validator MyInvois memulangkan kod ralat khusus yang memudahkan pembetulan. Kod CF merujuk medan teras, contohnya CF345 dan CF346 untuk alamat melebihi 150 aksara, CF404 untuk bandar melebihi 50 aksara, CF405 untuk poskod, CF406 untuk SST tidak sah, dan CF408 hingga CF410 untuk nombor telefon yang mesti 8 hingga 20 aksara dengan hanya aksara tambah. Kod ERR merujuk data pembayar cukai, seperti ERR401 untuk TIN pembekal tidak sah dan ERR406 untuk TIN pembeli tidak sah. Kod CV merujuk kod rujukan seperti kod negeri; kod negeri 00 tidak lagi sah. Kod DC merujuk mata wang; jika TaxCurrencyCode wujud ia mesti sama dengan DocumentCurrencyCode atau MYR. Kod DV menandakan duplikat, dan kod DR menandakan rujukan dokumen tidak sah. Rujuk jadual rasmi untuk setiap kod.

Uji di sandbox sebelum go-live

Persekitaran sandbox wujud di preprod.myinvois.hasil.gov.my dengan API sistem di preprod-api.myinvois.hasil.gov.my. Daftar syarikat di portal pra-pengeluaran dan daftar sistem ERP anda untuk mendapat Client ID dan Secret sandbox, yang berbeza daripada nilai pengeluaran. Muat turun sampel rasmi seperti fail one-doc-signed.xml dan koleksi Postman, kemudian jalankan hantaran penuh dengan sijil ujian sebelum menyentuh persekitaran pengeluaran. Simpan kelayakan di luar kod sumber seperti dijelaskan dalam panduan menyimpan rahsia dalam pemboleh ubah persekitaran, dan cache token akses seperti dalam panduan caching dan prestasi.

Soalan Lazim (FAQ)

Adakah saya perlu hantar XML atau boleh guna JSON?

Kedua-duanya disokong. JSON lebih mudah kerana tidak memerlukan canonicalization xml-c14n11, jadi ia laluan paling selamat untuk permulaan.

Apakah versi dokumen yang perlu saya guna?

Guna versi 1.1 untuk dokumen yang perlu melalui validasi tandatangan digital. Versi 1.0 tidak divalidasi tandatangannya tetapi tidak sesuai untuk hantaran penuh.

Berapa besar dokumen yang boleh saya hantar?

Setiap e-Invois maksimum 300 KB, setiap submission maksimum 5 MB, dan setiap batch maksimum 100 e-Invois.

Kenapa saya mendapat ralat DS322?

DS322 bermaksud document digest mismatch, iaitu dokumen berubah selepas ditandatangani atau canonicalization tidak tepat. Jangan ubah dokumen selepas menandatanganinya.

Di mana saya boleh dapat sampel XML rasmi?

Halaman sampel rasmi menyediakan pelbagai fail contoh, termasuk fail invois bertandatangan; gunakan fail itu sebagai rujukan susunan elemen yang tepat.

Sumber

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk