Tutorial Pasukan Lucee MY

Sambung senangPay ke Lucee (REST API senangPay)

Sambung senangPay ke Lucee dengan cfhttp: bina hash MD5 dan HMAC-SHA256, hantar borang pembayaran, sahkan Return URL dan Callback URL, dan semak status order.

Sambung senangPay ke Lucee (REST API senangPay)
0
Kandungan

Sambung senangPay ke Lucee (REST API senangPay)

senangPay ialah gerbang pembayaran Malaysia yang menerima FPX, kad kredit dan e-dompet. Untuk integrasi manual, ia bukan API JSON tulen: anda menghantar medan borang ke https://app.senangpay.my/payment/{merchantID}, pelanggan di-redirect ke halaman pembayaran senangPay, dan selepas selesai senangPay menghantar status kembali melalui Return URL (GET) dan Callback URL (POST). Artikel ini menunjukkan cara menyambung semuanya daripada Lucee menggunakan cfhttp, termasuk membina hash selamat dan mengesahkan respons yang diterima.

Apa itu senangPay dan model pembayarannya

senangPay menyediakan dua laluan integrasi. Laluan pertama ialah Integrasi Manual (Open API) yang berasaskan borang web: anda menghantar parameter sebagai application/x-www-form-urlencoded dan senangPay membalas 302 yang membawa pelanggan ke halaman pembayarannya. Laluan kedua ialah API MOTO (pay_cc) untuk kad sahaja, yang menggunakan HTTP Basic Auth. Artikel ini tertumpu pada laluan borang, iaitu laluan yang paling sesuai untuk kebanyakan laman e-dagang.

URL production ialah https://app.senangpay.my, dan endpoint pembayaran ialah https://app.senangpay.my/payment/{merchantID}. Untuk ujian, sandbox tersedia di https://sandbox.senangpay.my dan https://api.sandbox.senangpay.my. Perhatikan bahawa endpoint pembayaran biasa ialah borang web, bukan titik akhir REST JSON, jadi anda tidak boleh menghantar JSON mentah kepadanya.

Dapatkan Merchant ID dan Secret Key

Untuk mula, log masuk ke dashboard senangPay dan pergi ke Menu > Settings > Profile. Dalam bahagian Shopping Cart Integration Link anda akan temui dua nilai penting: Merchant ID dan Secret Key. Di halaman yang sama, anda mesti mengisi Return URL (wajib) tempat senangPay mengarahkan pembeli selepas pembayaran, dan Callback URL sebagai saluran pemberitahuan alternatif.

Secret Key ialah rahsia aplikasi yang mesti dijaga seperti kata laluan pangkalan data. Jangan masukkan ia terus dalam kod yang dikongsi; simpan dalam fail .env atau pemboleh ubah persekitaran seperti yang diterangkan dalam panduan rahsia dan pemboleh ubah persekitaran.

Bina hash selamat

Setiap permintaan pembayaran mesti disertakan medan hash untuk melindungi integriti data antara keranjang anda dan senangPay. Hash keluar dibina daripada rentetan yang menggabungkan, mengikut urutan, Secret Key, detail, amount dan order_id. Dokumen menyenaraikan dua algoritma: MD5 atau HMAC-SHA256 dengan Secret Key sebagai kunci.

secretKey = "53-784";
detail = "Shopping_cart_id_30";
amount = "24.50";
order_id = "56";

str = secretKey & detail & amount & order_id;
hashMd5 = lcase(hash(str, "md5"));
hashHmac = hmac(str, secretKey, "HmacSHA256");

Nilai amount mesti diformat kepada dua tempat perpuluhan sebagai rentetan, contohnya 24.50 dan bukan 24.5. Untuk contoh di atas, MD5 menghasilkan 0bde51ff340f110ab7331a902aa969e7 dan HMAC-SHA256 menghasilkan 74422328b44d30bf150fffbae89bbb42b885f9ac0960e2a3ddccc0cf9aa48e39. Anda boleh guna nilai ini untuk mengesahkan pelaksanaan anda sendiri.

Had medan yang perlu dipatuhi: detail maksimum 500 aksara dan tanda garis bawah bertukar menjadi ruang; order_id maksimum 100 aksara dengan aksara dibenarkan A-Z, a-z, 0-9 dan sengkang; amount sentiasa dua tempat perpuluhan.

Hantar borang pembayaran dengan cfhttp

Permintaan dihantar sebagai POST dengan Content-Type: application/x-www-form-urlencoded. Medan teras ialah detail, amount, order_id dan hash, manakala name, email dan phone mengisi maklumat pelanggan. Swagger menanda name, email, phone, return_url dan callback_url sebagai wajib, tetapi panduan teks menyifatkan name, email dan phone sebagai pilihan yang boleh diubah; rujuk kedua-dua sumber dan hantar kesemua medan untuk selamat. Medan timeout ialah pilihan, dalam saat, dengan minimum 60 saat; jika pembayaran tidak selesai dalam tempoh itu ia tamat dan mengarah ke Return URL.

cfhttp(
    method = "POST",
    url = "https://app.senangpay.my/payment/" & merchantID,
    result = "resp",
    redirect = "false"
) {
    cfhttpparam(type = "formfield", name = "detail", value = detail);
    cfhttpparam(type = "formfield", name = "amount", value = amount);
    cfhttpparam(type = "formfield", name = "order_id", value = order_id);
    cfhttpparam(type = "formfield", name = "hash", value = hashMd5);
    cfhttpparam(type = "formfield", name = "name", value = "Ali Bin Abu");
    cfhttpparam(type = "formfield", name = "email", value = "ali@example.com");
    cfhttpparam(type = "formfield", name = "phone", value = "0123456789");
    cfhttpparam(type = "formfield", name = "return_url", value = returnUrl);
    cfhttpparam(type = "formfield", name = "callback_url", value = callbackUrl);
}

if (resp.statuscode == 302 && structKeyExists(resp.responseHeader, "location")) {
    location(resp.responseHeader.location, false);
}

Dengan redirect = "false", cfhttp tidak mengikut pengalihan sendiri, jadi anda dapat membaca pengepala Location dan menghantar pelayar pelanggan ke halaman pembayaran. Jika anda biarkan cfhttp mengikut pengalihan, pelayan akan memuatkan halaman pembayaran dan pelanggan tidak akan sampai ke sana. Pendekatan setara di sisi pelayar ialah melukis borang HTML dengan medan yang sama dan menyerahkannya secara automatik; kedua-duanya menghantar data yang sama ke endpoint yang sama. Untuk butiran lanjut tentang menghantar permintaan luar, rujuk panduan cfhttp dan panggilan API luar.

Terima Return URL dan sahkan hash

Selepas pembayaran, senangPay mengarahkan pelanggan ke Return URL melalui GET dengan parameter status_id, order_id, msg, transaction_id dan hash. Nilai status_id hanya ada tiga: 2 untuk pending authorisation, 1 untuk berjaya dan 0 untuk gagal. Medan msg menerangkan status (maksimum 100 aksara, garis bawah bermaksud ruang) dan transaction_id ialah ID transaksi senangPay.

Hash balasan dibina daripada md5(secretKey + status_id + order_id + transaction_id + msg), atau HMAC-SHA256 dengan Secret Key sebagai kunci. Gunakan nilai mentah yang diterima, jangan ganti garis bawah dalam msg sebelum mengira hash.

dikira = lcase(hash(
    secretKey & url.status_id & url.order_id & url.transaction_id & url.msg,
    "md5"
));

if (lcase(dikira) != lcase(url.hash)) {
    writeLog(text = "Hash senangPay tidak sepadan untuk order " & url.order_id, type = "warning");
} else if (url.status_id == 1) {
    // pembayaran berjaya
} else if (url.status_id == 2) {
    // pending authorisation
} else {
    // pembayaran gagal
}

Jangan percaya nilai status_id semata-mata. Hash yang tidak sepadan bermaksud data mungkin diusik, dan anda patut semak semula status di sisi senangPay sebelum menutup pesanan.

Callback POST dan pengesahan

Callback ialah saluran pemberitahuan alternatif yang dihantar melalui POST dengan parameter yang sama seperti Return URL. Baca ia daripada skop form dan ulangi pengesahan hash yang sama. Pola ini sama untuk kedua-dua Return URL dan Callback, hanya skopnya berbeza: url untuk GET dan form untuk POST.

dikira = lcase(hash(
    secretKey & form.status_id & form.order_id & form.transaction_id & form.msg,
    "md5"
));

if (lcase(dikira) != lcase(form.hash)) {
    cfheader(statuscode = 400);
    cfcontent(reset = true);
    abort;
}

Untuk aliran tokenization (3D Get Token), senangPay menembak callback kira-kira satu minit selepas pengesahan kad, dan endpoint callback mesti mencetak OK tanpa sebarang tag HTML. Keperluan itu khusus untuk tokenization; untuk borang pembayaran biasa, anda membalas seperti biasa. Pengendalian callback yang lebih mendalam, termasuk idempotensi dan pengesahan tandatangan, dibincangkan dalam panduan webhook tempatan dalam CFML.

Semak status dengan query_order_status

Selain Return URL dan Callback, anda boleh menyemak status pesanan secara aktif melalui GET https://app.senangpay.my/apiv1/query_order_status. Parameter yang diperlukan ialah merchant_id, order_id dan hash. Perhatikan bahawa formula hash di sini berbeza daripada hash pembayaran: md5(merchant_id + secret_key + order_id).

statusHash = lcase(hash(merchant_id & secretKey & order_id, "md5"));

cfhttp(method = "GET", url = "https://app.senangpay.my/apiv1/query_order_status", result = "resp") {
    cfhttpparam(type = "url", name = "merchant_id", value = merchant_id);
    cfhttpparam(type = "url", name = "order_id", value = order_id);
    cfhttpparam(type = "url", name = "hash", value = statusHash);
}

if (resp.statuscode == 200 && isJSON(resp.fileContent)) {
    status = deserializeJSON(resp.fileContent);
}

Untuk penyelarasan akaun, senangPay juga menyediakan GET https://app.senangpay.my/apiv1/get_transaction_list dengan parameter merchant_id, timestamp_start, timestamp_end (UNIX timestamp, akhir mesti lebih besar daripada mula) dan hash md5(merchant_id + secret_key + timestamp_start + timestamp_end). Gunakan semakan status ini sebelum menandakan pesanan selesai, dan bukannya bergantung sepenuhnya pada callback.

Ujian sandbox

Sandbox senangPay boleh didaftar sendiri di https://register-sandbox.senangpay.my/. Proses pendaftaran melibatkan pembayaran simulasi, jadi pilih FPX dan Maybank apabila diminta. Selepas mendaftar, log masuk di https://sandbox.senangpay.my/. Anda tidak memerlukan akaun perniagaan sebenar untuk menguji integrasi, dan anda boleh menggunakan domain sandbox untuk mencuba aliran pembayaran penuh sebelum ke production.

Migrasi DOKU dan perkara yang perlu disemak

Dokumen sokongan senangPay menyebut migrasi platform senangPay ke DOKU. Kesan migrasi ini terhadap API lama belum disahkan, jadi sebelum bergantung kepada integrasi pengeluaran, semak portal rasmi untuk status terkini. Begitu juga, dokumen API yang dibuka tidak menyenaraikan endpoint pembatalan atau bayaran balik programatik; bayaran balik diuruskan melalui dashboard senangPay. Jika anda memerlukan pembatalan programatik, sahkan ketersediaannya di portal rasmi dan bukannya menganggap ia wujud atau tidak wujud. Had jumlah minimum atau maksimum dan kadar fi juga tidak dinyatakan dalam dokumen API, jadi semak maklumat itu di portal rasmi atau terus dengan senangPay.

Soalan Lazim (FAQ)

Bolehkah saya terus menghantar JSON ke senangPay?

Tidak untuk pembayaran biasa. Endpoint pembayaran ialah borang web application/x-www-form-urlencoded yang membalas 302; JSON hanya untuk API tertentu seperti MOTO dan query. Hantar medan borang melalui cfhttpparam type="formfield".

Bagaimana saya tahu pembayaran berjaya?

Semak status_id: 1 bermaksud berjaya, 2 pending authorisation, dan 0 gagal. Jangan bergantung pada Return URL sahaja; sahkan hash dan silang-semak dengan query_order_status.

Apa itu timeout dan berapa nilai minimumnya?

timeout ialah masa dalam saat pelanggan dibenarkan menyiapkan pembayaran. Minimum ialah 60 saat; sebarang nilai di bawahnya menjadi 60 saat. Jika tamat, pembayaran tamat dan pelanggan diarah ke Return URL.

Perlukah saya sahkan hash pada setiap respons?

Ya. Bandingkan md5(secretKey + status_id + order_id + transaction_id + msg) dengan hash yang diterima. Jika tidak sepadan, data mungkin diusik dan anda tidak patut mempercayai status itu.

Bagaimana menguji tanpa akaun perniagaan sebenar?

Daftar sandbox di https://register-sandbox.senangpay.my/ dan log masuk di https://sandbox.senangpay.my/. Guna domain sandbox untuk menguji aliran penuh sebelum beralih ke production.

Sumber

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk