Panduan Pasukan Lucee MY

DuitNow QR dari Lucee: jana dan terima pembayaran QR

Jana kod DuitNow QR dari CFML: bina muatan EMVCo tag 00 hingga 63, kira CRC16-CCITT 0x1021 yang wajib betul, dan fahami had akaun peniaga untuk terima bayaran.

DuitNow QR dari Lucee: jana dan terima pembayaran QR
0
Kandungan

DuitNow QR ialah kod QR pembayaran Malaysia yang dibina di atas spesifikasi EMVCo Merchant Presented Mode (MPM). Isinya bukan gambar, tetapi satu rentetan teks dalam format Tag-Length-Value (TLV) yang ditutup dengan checksum CRC16-CCITT. Anda boleh membina muatan itu sepenuhnya daripada CFML tanpa pustaka luar, tetapi menerima wang sebenar memerlukan akaun peniaga yang didaftarkan dengan bank atau penyedia DuitNow. Artikel ini menunjukkan cara menjana muatan yang sah, dan had antara menjana kod dengan menerima bayaran.

Apa itu DuitNow QR dan dari mana formatnya datang

DuitNow QR ialah lapisan QR pembayaran yang diselenggara oleh PayNet, mematuhi spesifikasi EMV QRCPS dalam mod merchant-presented, sama asas dengan QRIS di Indonesia dan PromptPay di Thailand. Apabila aplikasi perbankan mengimbasnya, ia membaca rentetan teks, menghuraikan setiap medan mengikut tag, mengesahkan checksum, lalu menunjukkan nama peniaga dan jumlah.

Format ini bebas daripada bahasa pengaturcaraan: rentetan yang dihasilkan oleh CFML, PHP atau Python sama sahaja selagi strukturnya betul. Yang menentukan sama ada kod diterima bank ialah susunan medan yang tepat dan CRC16-CCITT yang betul. Salah satu, dan aplikasi menolak kod tanpa membuka halaman pembayaran.

Struktur muatan: tag, panjang, nilai

Setiap medan ditulis sebagai tiga bahagian yang disambung tanpa pemisah: dua digit tag, dua digit panjang, kemudian nilai. Tag 00 dengan nilai 02 ditulis 000202. Medan seterusnya bermula sebaik sahaja medan sebelumnya tamat, jadi keseluruhan muatan ialah satu baris panjang tanpa ruang.

TagMedanContoh nilaiWajib
00Payload Format Indicator02Ya
01Point of Initiation Method11 atau 12Ya
26Merchant Account InformationTLV bersarangYa
52Merchant Category Code (MCC)5812 atau 0000Ya
53Transaction Currency458 (MYR)Ya
54Transaction Amount10.00Tidak
58Country CodeMYYa
59Merchant NameKedai Kopi AliYa
60Merchant CityKuala LumpurYa
63CRC4 aksara heksadesimalYa

Dua perkara yang selalu mengejutkan pembangun kali pertama: Payload Format Indicator ialah 02 (bukan 01, mengikut dokumen PayNet), dan kod mata wang ialah 458 dengan kod negara MY, bukan MYR, mengikut ISO 4217 dan ISO 3166.

Tag 26: maklumat akaun peniaga

Tag 26 ialah satu-satunya medan yang mengandungi TLV bersarang. Nilainya ialah rantai tag-panjang-nilai yang membawa identiti peniaga. Tiga sub-medan wajib di dalamnya ialah:

  • Sub-tag 00, Application Identifier (AID), sentiasa A0000006150001, pengenal skema DuitNow Malaysia sepanjang 14 aksara.
  • Sub-tag 01, Acquirer ID, sehingga 6 aksara, dikeluarkan oleh bank atau penyedia pemeroleh kepada peniaga.
  • Sub-tag 02, QR ID, sehingga 28 aksara, nombor pengenalan peniaga yang ditetapkan pemeroleh.

Sub-tag 03 (Merchant Descriptor) dan 04 (Mobile Number) adalah pilihan, dan JomPAY QR memakai sub-tag 02 untuk kod bil. Intinya: AID boleh ditulis sendiri kerana nilai awam, manakala Acquirer ID dan QR ID mesti datang daripada pemeroleh; tanpanya kod tidak menunjuk kepada mana-mana akaun sebenar.

Tiga jenis kod QR dan bila menggunakannya

DuitNow QR terbahagi kepada tiga bentuk berdasarkan nilai tag 01 dan kehadiran tag 54.

Jenis kodTag 01Tag 54 (jumlah)Bila guna
QR statik peniaga11TiadaKod tercetak di kaunter, diguna semula; pelanggan masukkan jumlah sendiri
QR dinamik satu transaksi12Wajib adaDijana setiap transaksi seperti checkout, sah untuk satu bayaran
QR dengan jumlah terkunci11AdaStatik tetapi jumlah ditetapkan, sesuai untuk tiket atau parkir

QR statik tanpa jumlah ialah kod yang anda cetak sekali dan tampal. QR dinamik ialah kod yang pelayan jana setiap kali pelanggan mahu bayar, dengan jumlah dimasukkan dalam kod itu sendiri. Kedua-duanya menggunakan fungsi yang sama; hanya nilai tag 01 dan kehadiran tag 54 yang berbeza.

CRC16-CCITT: nadi yang bank semak

CRC ialah empat aksara heksadesimal di hujung muatan yang membolehkan aplikasi mengesan satu aksara rosak semasa imbasan. DuitNow QR menggunakan CRC16-CCITT dengan polinomial 0x1021 dan nilai awal 0xFFFF, tanpa pantulan bit, iaitu varian CRC-16/CCITT-FALSE. Menyalin fungsi CRC dari sumber lain tanpa menyemak variannya ialah cara paling cepat menghasilkan kod yang ditolak bank.

CRC dikira ke atas semua aksara dari awal muatan sehingga dan termasuk 6304, iaitu tag dan panjang medan CRC itu sendiri. Nilai CRC empat aksara tidak termasuk dalam pengiraan. Rentetan semak terkenal untuk varian ini ialah 123456789 yang mesti menghasilkan 29B1; kalau fungsi anda mengeluarkan nilai lain, ia varian yang salah.

Membina muatan dari CFML

Fungsi tlv menulis tag, panjang dua digit, kemudian nilai. Dari situ, fungsi pembina menyusun medan mengikut tertib spesifikasi: tag 00, 01, 26, 52, 53, 54 (jika ada), 58, 59, 60, dan akhirnya 6304 sebelum CRC dikira.

<cfscript>
function tlv(tag, value) {
    return tag & right("00" & len(value), 2) & value;
}

function binaDuitNowQR(s) {
    var akaun = tlv("00", s.aid) & tlv("01", s.acquirer) & tlv("02", s.qrId);
    var qr = tlv("00", "02") & tlv("01", s.initiation) & tlv("26", akaun) & tlv("52", s.mcc) & tlv("53", s.currency);
    if (structKeyExists(s, "jumlah") && len(s.jumlah) > 0) {
        qr &= tlv("54", s.jumlah);
    }
    qr &= tlv("58", s.country) & tlv("59", s.nama) & tlv("60", s.bandar) & "6304";
    return qr & hitungCRC(qr);
}
</cfscript>

Fungsi ini memulangkan muatan penuh termasuk CRC. s.aid ialah A0000006150001, manakala s.acquirer dan s.qrId ialah nilai yang diberikan pemeroleh. Contoh di bawah memakai nilai contoh rasmi PayNet, jadi ia sah dari segi struktur tetapi tidak menunjuk kepada akaun sebenar.

Mengira CRC16-CCITT dari CFML

CRC dikira bit demi bit dengan operasi bitwise terbina dalam CFML, tanpa pustaka luar. hitungCRC memproses setiap aksara, XOR dengan lapan bit tertinggi, kemudian mengalihkan 16 bit sebanyak lapan pusingan sambil XOR dengan 0x1021 (4129 perpuluhan) apabila bit tertinggi ialah satu.

<cfscript>
function keHex4(n) {
    var digit = "0123456789ABCDEF";
    var out = "";
    var i = 3;
    for (i = 3; i >= 0; i--) {
        out &= mid(digit, bitAnd(bitShrn(n, i * 4), 15) + 1, 1);
    }
    return out;
}

function hitungCRC(payload) {
    var crc = 65535;
    var n = len(payload);
    var i = 1;
    var j = 1;
    var ch = 0;
    for (i = 1; i <= n; i++) {
        ch = asc(mid(payload, i, 1));
        crc = bitAnd(bitXor(crc, bitShln(ch, 8)), 65535);
        for (j = 1; j <= 8; j++) {
            if (bitAnd(crc, 32768) != 0) {
                crc = bitAnd(bitXor(bitShln(crc, 1), 4129), 65535);
            } else {
                crc = bitAnd(bitShln(crc, 1), 65535);
            }
        }
    }
    return keHex4(crc);
}
</cfscript>

keHex4 menukar integer CRC kepada empat aksara heksadesimal huruf besar kerana Lucee tidak membawa formatBaseN, dengan membaca setiap empat bit melalui bitShrn dan bitAnd.

Menjana imej QR daripada muatan

Muatan teks yang betul ialah bahagian yang sukar, tetapi ia belum menjadi imej yang boleh diimbas. Lucee teras tidak membawa penjana imej QR, jadi anda perlu masukkan pustaka Java ZXing ke dalam classpath, atau menghantar muatan kepada perkhidmatan janaan QR. Jangan hantar muatan kepada perkhidmatan awam tanpa berfikir, kerana ia membawa identiti peniaga dan jumlah transaksi.

Penjanaan imej ialah langkah paparan semata-mata: ia tidak mengubah muatan, tidak menghubungi PayNet, dan tidak memindahkan wang. Ia hanya menukar rentetan TLV kepada corak hitam putih.

Menjana sendiri lawan menerima bayaran

Di sinilah ramai pembangun tersilap. Menjana muatan QR yang sah dari segi struktur tidak sama dengan menerima bayaran. DuitNow QR bukan API terbuka yang membenarkan sesiapa memintas wang terus ke akaun. Untuk menerima dana, peniaga mesti melalui proses onboarding dengan bank atau penyedia pemeroleh berdaftar PayNet, dan proses itu memberikan Acquirer ID serta QR ID yang diikat kepada akaun peniaga sebenar.

Maksud praktikalnya: binaDuitNowQR menjana kod yang dihuraikan dengan betul oleh aplikasi perbankan, tetapi wang hanya berpindah jika s.acquirer dan s.qrId ialah nilai sebenar yang dikeluarkan kepada anda. Menjana QR ialah kerja perisian yang boleh anda lakukan hari ini; menerima bayaran ialah kerja pendaftaran dengan institusi kewangan.

Bukti sebenar dari rig

Semua keluaran di bawah dijalankan pada pelayan Lucee 7.1, bukan dibaca daripada dokumentasi. Fungsi CRC diuji dengan dua rentetan semak dahulu, kemudian muatan contoh rasmi PayNet dibina dan CRCnya dibandingkan dengan nilai rujukan.

CRC('123456789') = 29B1   jangka 29B1
CRC('abc')        = 514A   jangka 514A

QR statik:
00020201021126410014A0000006150001010650166402091234567895204999953034585802MY5909QRCSDNBHD6005BANGI6304184A

QR dinamik dengan jumlah:
00020201021226410014A000000615000101065016640209123456789520499995303458540510.005802MY5909QRCSDNBHD6005BANGI6304D3BE

Rentetan semak 123456789 memulangkan 29B1, nilai standard untuk CRC-16/CCITT-FALSE, membuktikan fungsi itu varian yang betul. Muatan contoh rasmi dengan jumlah 10.00 menghasilkan CRC 343F, sama dengan dokumentasi rasmi. QR statik tidak membawa tag 54, manakala QR dinamik memasukkannya antara tag 53 dan tag 58.

Jika anda mahu menyambung gerbang pembayaran lain dari CFML, lihat panduan ToyyibPay, Billplz dan senangPay, yang memakai kunci API dan bukannya muatan QR. Untuk invois elektronik LHDN, rujuk panduan integrasi MyInvois.

Soalan Lazim

Apakah perbezaan antara tag 26 dan tag 00 di dalamnya?

Tag 26 ialah medan akar Merchant Account Information, manakala sub-tag 00 di dalamnya ialah Application Identifier (AID) skema DuitNow, iaitu A0000006150001. Jangan keliru dengan tag 00 di peringkat akar, iaitu Payload Format Indicator.

Kenapa kod DuitNow QR saya ditolak oleh aplikasi bank?

Hampir selalu kerana CRC16-CCITT salah atau susunan medan tidak mengikut tertib. Sahkan fungsi CRC anda memulangkan 29B1 untuk rentetan 123456789, dan pastikan tag disusun 00, 01, 26, 52, 53, 54, 58, 59, 60 sebelum 6304.

Bolehkah saya menerima bayaran dengan hanya menjana kod QR ini?

Tidak. Menerima dana memerlukan onboarding dengan bank atau penyedia pemeroleh berdaftar PayNet, yang memberikan Acquirer ID dan QR ID yang diikat kepada akaun peniaga. Kod yang dijana dengan nilai rekaan sah dari segi struktur tetapi tidak menunjuk kepada akaun yang menerima wang.

Apakah maksud CRC 6304 di hujung muatan?

63 ialah tag CRC, 04 ialah panjang nilainya, dan empat aksara selepasnya ialah nilai CRC. CRC dikira ke atas semua aksara sebelum nilai itu, termasuk 6304 itu sendiri, tetapi tidak termasuk empat aksara nilainya.

Mengapa Payload Format Indicator ialah 02 dan bukan 01?

Dokumen DuitNow QR PayNet menetapkan versi 02 untuk tag 00, walaupun spesifikasi EMVCo generik sering memakai 01. Ikut nilai 02 supaya aplikasi perbankan Malaysia menghuraikan kod anda dengan betul.

Sumber

  • https://docs.developer.paynet.my/docs/duitNow-QR/integration/QR-generation-specification/merchant-presented-mode/qr-data-object
  • https://docs.developer.paynet.my/docs/duitNow-QR/integration/QR-generation-specification/merchant-presented-mode/example
  • https://docs.developer.paynet.my/docs/duitNow-QR/integration/QR-generation-specification/merchant-presented-mode/overview
  • https://www.emvco.com/emv-technologies/qrcodes/
  • https://en.wikipedia.org/wiki/Cyclic_redundancy_check

Log masuk untuk menyimpan kemajuan bacaan anda.

0 komen

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk