Integrasi Xendit ke Laravel: Panduan Lengkap untuk Pembayaran Modern

Mengelola pembayaran dalam aplikasi web adalah inti dari banyak bisnis digital. Bagi developer Laravel di Indonesia, integrasi payment gateway yang andal, lokal, dan mudah digunakan seringkali menjadi prioritas utama. Xendit hadir sebagai salah satu solusi terdepan yang menawarkan berbagai metode pembayaran dan API yang cukup fleksibel. Jika Anda sedang membangun aplikasi Laravel dan ingin mengimplementasikan sistem pembayaran yang kuat, artikel ini akan memandu Anda langkah demi langkah untuk melakukan integrasi Xendit.

Integrasi payment gateway bukan hanya sekadar menambahkan fitur “bayar sekarang”. Ini melibatkan alur yang kompleks mulai dari pembuatan invoice, penanganan notifikasi pembayaran (webhook), hingga pembaruan status order. Dengan Xendit, proses ini bisa lebih efisien, terutama dengan dukungan library PHP resminya.

Dalam panduan ini, kita akan fokus pada integrasi dasar menggunakan Xendit API untuk membuat invoice atau payment link, menangani callback, dan memastikan sistem pembayaran Anda berjalan lancar di lingkungan Laravel.

Prasyarat

Sebelum kita mulai, pastikan Anda memiliki hal-hal berikut:

  • Proyek Laravel yang sudah berjalan.
  • Composer terinstal di mesin Anda.
  • Akun Xendit (Anda bisa mendaftar gratis untuk menggunakan mode Sandbox).
  • API Keys Xendit (Public Key dan Secret Key), tersedia di dashboard Xendit Anda.

Langkah 1: Setup Proyek Laravel

Jika Anda belum memiliki proyek Laravel, Anda bisa membuatnya dengan perintah berikut:

composer create-project laravel/laravel nama-proyek-anda

Pastikan juga koneksi database Anda sudah diatur dengan benar di file .env.

Langkah 2: Instalasi Xendit PHP Library

Xendit menyediakan library PHP resmi yang sangat memudahkan interaksi dengan API mereka. Instal library ini melalui Composer di proyek Laravel Anda:

composer require xendit/xendit-php

Library ini akan mengelola otentikasi, struktur request, dan respons dari Xendit API, sehingga Anda tidak perlu lagi berinteraksi langsung dengan HTTP request yang mentah.

Langkah 3: Konfigurasi Xendit API Keys

Keamanan API key adalah hal yang sangat penting. Jangan pernah menyimpan API key langsung di kode Anda. Gunakan file .env untuk menyimpan key Xendit Anda, lalu akses dari konfigurasi Laravel.

Tambahkan API Keys ke .env

Buka file .env di root proyek Laravel Anda dan tambahkan baris berikut:

XENDIT_PUBLIC_KEY=xnd_public_your_public_key

XENDIT_SECRET_KEY=xnd_secret_your_secret_key

Ganti xnd_public_your_public_key dan xnd_secret_your_secret_key dengan API key yang Anda dapatkan dari dashboard Xendit (pastikan ini adalah Sandbox Keys saat pengujian).

Konfigurasi di config/services.php

Selanjutnya, buka file config/services.php dan tambahkan konfigurasi Xendit agar lebih mudah diakses di seluruh aplikasi:

‘xendit’ => [

‘public_key’ => env(‘XENDIT_PUBLIC_KEY’),

‘secret_key’ => env(‘XENDIT_SECRET_KEY’),

],

Dengan begini, Anda bisa mengakses key ini di mana saja menggunakan config(‘services.xendit.secret_key’).

Langkah 4: Membuat Service atau Repository untuk Xendit

Untuk menjaga kode tetap bersih dan modular, sangat disarankan untuk membuat sebuah Service atau Repository khusus yang menangani semua interaksi dengan Xendit API. Ini akan memisahkan logika bisnis dari integrasi pihak ketiga.

Buat folder app/Services jika belum ada, lalu buat file XenditService.php di dalamnya:

php artisan make:service XenditService (Anda mungkin perlu menginstal package generator jika command ini tidak ada)

Atau buat file secara manual di app/Services/XenditService.php:

<?php

namespace App\Services;

use Xendit\Xendit;

class XenditService

{

public function __construct()

{

Xendit::setApiKey(config(‘services.xendit.secret_key’));

}

public function createInvoice(array $params)

{

try {

$createInvoice = \Xendit\Invoice::create($params);

return $createInvoice;

} catch (\Xendit\Exceptions\ApiException $e) {

// Handle API exceptions here

// Log the error for debugging

\Log::error(‘Xendit Invoice Creation Error: ‘ . $e->getMessage(), [‘params’ => $params]);

throw new \Exception(‘Failed to create Xendit invoice: ‘ . $e->getMessage());

}

}

public function retrieveInvoice($invoiceId)

{

try {

$invoice = \Xendit\Invoice::retrieve($invoiceId);

return $invoice;

} catch (\Xendit\Exceptions\ApiException $e) {

\Log::error(‘Xendit Invoice Retrieval Error: ‘ . $e->getMessage(), [‘invoiceId’ => $invoiceId]);

throw new \Exception(‘Failed to retrieve Xendit invoice: ‘ . $e->getMessage());

}

}

}

Di konstruktor, kita menginisialisasi API key Xendit. Kemudian, kita memiliki metode createInvoice untuk membuat invoice baru dan retrieveInvoice untuk mendapatkan status invoice.

Langkah 5: Implementasi Pembayaran (Invoice/Payment Link)

Sekarang saatnya menggunakan XenditService untuk membuat invoice dan mengarahkan pengguna ke halaman pembayaran Xendit.

Buat Controller Pembayaran

Buat controller baru, misalnya PaymentController:

php artisan make:controller PaymentController

Kemudian, tambahkan metode create di app/Http/Controllers/PaymentController.php:

<?php

namespace App\Http\Controllers;

use App\Services\XenditService;

use Illuminate\Http\Request;

use Illuminate\Support\Str;

class PaymentController extends Controller

{

protected $xenditService;

public function __construct(XenditService $xenditService)

{

$this->xenditService = $xenditService;

}

public function createPayment(Request $request)

{

// Anda bisa mengambil data produk dari database

$orderId = (string) Str::uuid(); // Contoh order ID

$amount = 50000; // Contoh jumlah pembayaran

$description = ‘Pembelian Produk ABC’;

$customerEmail = ‘customer@example.com’; // Ambil dari user yang login

$customerName = ‘Nama Pelanggan’;

$returnUrl = route(‘payment.success’); // Route untuk halaman sukses

$callbackUrl = route(‘xendit.webhook’); // Route untuk webhook Xendit

$invoiceDuration = 172800; // 2 hari dalam detik

$items = [

[‘name’ => ‘Produk ABC’, ‘quantity’ => 1, ‘price’ => $amount],

];

try {

$params = [

‘external_id’ => $orderId,

‘amount’ => $amount,

‘payer_email’ => $customerEmail,

‘description’ => $description,

‘invoice_duration’ => $invoiceDuration,

‘customer’ => [

‘given_names’ => $customerName,

‘email’ => $customerEmail,

],

‘items’ => $items,

‘success_redirect_url’ => $returnUrl,

‘failure_redirect_url’ => route(‘payment.failure’),

‘callback_url’ => $callbackUrl,

];

$invoice = $this->xenditService->createInvoice($params);

// Redirect user ke halaman pembayaran Xendit

return redirect($invoice[‘invoice_url’]);

} catch (\Exception $e) {

return back()->with(‘error’, ‘Gagal membuat pembayaran: ‘ . $e->getMessage());

}

}

public function paymentSuccess()

{

return view(‘payment.success’);

}

public function paymentFailure()

{

return view(‘payment.failure’);

}

}

Definisikan Route

Tambahkan route di file routes/web.php:

use App\Http\Controllers\PaymentController;

Route::post(‘/payment/create’, [PaymentController::class, ‘createPayment’])->name(‘payment.create’);

Route::get(‘/payment/success’, [PaymentController::class, ‘paymentSuccess’])->name(‘payment.success’);

Route::get(‘/payment/failure’, [PaymentController::class, ‘paymentFailure’])->name(‘payment.failure’);

Anda bisa membuat form sederhana di view untuk memicu route /payment/create ini.

Langkah 6: Menangani Callback/Webhook

Webhook adalah fitur krusial agar aplikasi Anda tahu kapan pembayaran telah berhasil atau gagal. Xendit akan mengirim notifikasi ke URL yang Anda tentukan ketika status invoice berubah.

Definisikan Route Webhook

Tambahkan route untuk webhook di routes/api.php (webhook biasanya diakses tanpa session atau CSRF token):

use App\Http\Controllers\PaymentController;

Route::post(‘/xendit/webhook’, [PaymentController::class, ‘handleWebhook’])->name(‘xendit.webhook’);

Pastikan URL ini dapat diakses dari internet. Jika Anda mengembangkan secara lokal, gunakan layanan tunneling seperti Ngrok.

Tambahkan Metode handleWebhook ke PaymentController

Tambahkan metode berikut di app/Http/Controllers/PaymentController.php:

public function handleWebhook(Request $request)

{

// Penting: Verifikasi X-Callback-Token untuk keamanan

$xCallbackToken = $request->header(‘X-Callback-Token’);

if (!$xCallbackToken || $xCallbackToken !== config(‘services.xendit.secret_key’)) { // Sesuaikan jika Anda menggunakan Callback Token terpisah

// Untuk invoice, Xendit menggunakan Secret Key sebagai X-Callback-Token

// Untuk event lain, bisa jadi token yang berbeda, cek dokumentasi Xendit

\Log::warning(‘Invalid X-Callback-Token received from Xendit.’, [‘token’ => $xCallbackToken]);

return response()->json([‘message’ => ‘Unauthorized’], 401);

}

$payload = $request->all();

\Log::info(‘Xendit Webhook Received’, $payload);

// Contoh penanganan invoice callback

if (isset($payload[‘status’]) && isset($payload[‘external_id’])) {

$orderId = $payload[‘external_id’];

$invoiceId = $payload[‘id’]; // Xendit Invoice ID

$status = $payload[‘status’];

// Di sini Anda akan memperbarui status order di database Anda

// Contoh: Ambil order dari database berdasarkan $orderId

// $order = Order::where(‘id’, $orderId)->first();

// if ($order) {

// if ($status === ‘PAID’) {

// $order->status = ‘paid’;

// // Lakukan proses lain seperti mengirim email konfirmasi

// } elseif ($status === ‘EXPIRED’) {

// $order->status = ‘expired’;

// }

// $order->xendit_invoice_id = $invoiceId;

// $order->save();

// }

\Log::info(“Order {$orderId} status updated to {$status}”);

}

return response()->json([‘message’ => ‘Webhook received successfully’], 200);

}

Pastikan Anda menambahkan middleware \App\Http\Middleware\VerifyCsrfToken::class ke exception di app/Http/Middleware/VerifyCsrfToken.php untuk route webhook Anda agar tidak terkena validasi CSRF.

protected $except = [

‘xendit/webhook’, // Tambahkan route webhook Anda di sini

];

Atau, karena webhook biasanya diletakkan di routes/api.php, maka secara default tidak ada middleware CSRF.

Langkah 7: Uji Coba (Sandbox Environment)

Selalu uji integrasi Anda di lingkungan Sandbox Xendit terlebih dahulu. Gunakan Sandbox API keys yang Anda dapatkan dari dashboard Xendit. Setelah semuanya berfungsi dengan baik, barulah beralih ke Production API keys.

Xendit menyediakan simulasi pembayaran di lingkungan Sandbox mereka, sehingga Anda bisa menguji alur pembayaran dan penerimaan webhook tanpa transaksi nyata.

Masalah yang Sering Terjadi

Dalam proses integrasi payment gateway, beberapa masalah umum sering muncul. Berikut adalah beberapa di antaranya dan cara mengatasinya:

1. Invalid API Key atau Authentication Failed

  • Gejala: Pesan error seperti “Authentication failed” atau “Invalid API Key” dari Xendit API.
  • Penyebab: API key yang digunakan salah, tidak lengkap, atau merupakan Production key saat mencoba di Sandbox (atau sebaliknya). Bisa juga ada spasi ekstra di file .env.
  • Solusi:
    • Periksa kembali API Public Key dan Secret Key Anda di dashboard Xendit.
    • Pastikan Anda menggunakan Sandbox keys untuk testing dan Production keys untuk live.
    • Bersihkan cache konfigurasi Laravel dengan php artisan config:clear.
    • Pastikan tidak ada spasi ekstra di sekitar nilai key di file .env.

2. Webhook Tidak Diterima oleh Aplikasi

  • Gejala: Status order di aplikasi tidak berubah meskipun pembayaran di Xendit sudah sukses.
  • Penyebab: URL webhook salah, aplikasi lokal tidak bisa diakses dari internet, atau ada masalah di konfigurasi server/firewall.
  • Solusi:
    • Pastikan URL webhook yang Anda daftarkan di Xendit sudah benar dan mengarah ke route webhook Anda.
    • Jika di localhost, gunakan Ngrok atau sejenisnya untuk membuat URL publik.
    • Periksa log server atau aplikasi Anda untuk melihat apakah ada request masuk ke route webhook.
    • Pastikan tidak ada masalah firewall yang memblokir request dari Xendit.

3. X-Callback-Token Tidak Valid

  • Gejala: Aplikasi merespons 401 Unauthorized saat menerima webhook.
  • Penyebab: Token verifikasi callback (X-Callback-Token) dari header request tidak cocok dengan Secret Key Xendit Anda (atau token yang dikonfigurasi).
  • Solusi:
    • Pastikan logika verifikasi X-Callback-Token di metode handleWebhook Anda sudah benar.
    • Untuk invoice callback, Xendit biasanya mengirim Secret Key Anda sebagai X-Callback-Token. Pastikan nilai di config(‘services.xendit.secret_key’) sama persis dengan yang ada di dashboard Xendit.
    • Cek dokumentasi Xendit untuk jenis event webhook yang berbeda, mungkin ada perbedaan token.

4. Missing dependency xendit/xendit-php

  • Gejala: Error “Class ‘Xendit\Xendit’ not found” atau “Undefined class ‘Xendit\Invoice'”.
  • Penyebab: Library Xendit PHP belum terinstal dengan benar atau autoload Composer belum diperbarui.
  • Solusi:
    • Jalankan ulang composer require xendit/xendit-php.
    • Setelah instalasi, jalankan composer dump-autoload untuk memperbarui file autoload.
    • Pastikan namespace use Xendit\Xendit; sudah ditambahkan di file service atau controller Anda.

Pengalaman dan Pertimbangan Praktis

Mengintegrasikan payment gateway seperti Xendit tidak hanya tentang membuat kode, tetapi juga tentang memahami alur bisnis dan pengalaman pengguna. Berikut beberapa pertimbangan praktis berdasarkan pengalaman pengembangan:

1. Keamanan API Key dan Webhook

Selalu simpan API key Anda di variabel lingkungan (.env) dan akses melalui konfigurasi Laravel. Untuk webhook, verifikasi X-Callback-Token adalah lapisan keamanan penting untuk memastikan bahwa notifikasi benar-benar datang dari Xendit dan bukan dari sumber jahat. Dalam praktiknya, seringkali developer lupa menambahkan validasi ini, yang bisa menjadi celah keamanan besar.

2. Penanganan Error yang Robust

Pembayaran adalah bagian kritis. Pastikan Anda memiliki penanganan error yang baik di setiap interaksi dengan Xendit API. Tangkap exception (seperti \Xendit\Exceptions\ApiException), log pesan error, dan berikan feedback yang jelas kepada pengguna. Jangan biarkan aplikasi crash atau gagal tanpa alasan yang jelas bagi pengguna. Di project skala kecil hal ini mungkin tidak terasa, tetapi di aplikasi produksi, logging yang baik sangat membantu debugging.

3. Pengalaman Pengguna (UX)

Setelah membuat invoice Xendit, pengguna akan diarahkan ke halaman pembayaran Xendit. Pastikan Anda juga mendefinisikan success_redirect_url dan failure_redirect_url dengan benar. Ini akan membawa pengguna kembali ke aplikasi Anda setelah pembayaran selesai atau gagal, memberikan pengalaman yang seamless. Tampilan loading saat menunggu respons dari Xendit juga bisa meningkatkan UX.

4. Skema Database untuk Transaksi

Anda perlu menyimpan informasi terkait transaksi di database Anda. Minimal, Anda akan menyimpan external_id (yang Anda kirimkan ke Xendit, biasanya ID order Anda), xendit_invoice_id (ID invoice yang dikembalikan Xendit), dan status pembayaran. Ini memungkinkan Anda melacak setiap transaksi dan melakukan rekonsiliasi jika diperlukan.

5. Pengujian Menyeluruh (Sandbox)

Xendit menyediakan lingkungan Sandbox untuk pengujian. Manfaatkan ini semaksimal mungkin. Uji berbagai skenario: pembayaran sukses, gagal, kadaluarsa, pembatalan, dan lainnya. Hal yang sering terlewat adalah menguji edge cases, misalnya ketika pengguna menutup browser sebelum redirect kembali atau ketika webhook terlambat diterima. Pastikan juga API key Sandbox Anda benar-benar berbeda dengan Production key.

6. Beyond Invoices: Virtual Accounts, QRIS, dll.

Xendit tidak hanya tentang invoice. Mereka menawarkan Virtual Accounts, Pembayaran Ritel (Indomaret/Alfamart), QRIS, dan banyak lagi. Setelah Anda menguasai integrasi invoice, eksplorasi fitur-fitur lain yang mungkin relevan dengan kebutuhan bisnis Anda. Setiap fitur mungkin memiliki struktur request dan payload webhook yang sedikit berbeda, jadi selalu rujuk ke dokumentasi resmi Xendit.

7. Idempotency

Saat membuat invoice atau melakukan operasi kritis lainnya, pertimbangkan Idempotency. Ini memastikan bahwa operasi yang sama yang diulang berkali-kali (misalnya karena masalah koneksi) hanya akan dieksekusi sekali. Xendit mendukung header X-Idempotency-Key untuk beberapa API mereka. Ini sangat penting untuk mencegah duplikasi order atau pembayaran.

FAQ

Apa itu Xendit?

Xendit adalah platform pembayaran terkemuka di Asia Tenggara yang menyediakan berbagai solusi pembayaran untuk bisnis, mulai dari invoice, virtual account, kartu kredit, e-wallet, hingga pembayaran ritel. Mereka memudahkan bisnis untuk menerima dan mengirim pembayaran.

Mengapa menggunakan Xendit di Laravel?

Xendit menawarkan integrasi yang relatif mudah dengan API yang didokumentasikan dengan baik dan library PHP resmi, menjadikannya pilihan yang kuat untuk aplikasi Laravel. Keunggulan lainnya adalah dukungan metode pembayaran lokal yang lengkap, cocok untuk pasar Indonesia.

Apakah Xendit aman?

Ya, Xendit adalah platform pembayaran yang aman dan tersertifikasi. Mereka mematuhi standar keamanan global seperti PCI DSS. Namun, keamanan juga sangat bergantung pada implementasi Anda, terutama dalam penanganan API key dan verifikasi webhook.

Bagaimana cara menguji integrasi Xendit?

Xendit menyediakan lingkungan Sandbox yang terpisah dari produksi. Anda bisa mendapatkan API key Sandbox dari dashboard Xendit dan menggunakannya untuk semua pengujian. Mereka juga menyediakan simulasi pembayaran untuk menguji alur secara end-to-end.

Apa itu webhook dalam konteks Xendit?

Webhook adalah mekanisme di mana Xendit akan mengirimkan notifikasi otomatis ke URL yang Anda tentukan di aplikasi Anda ketika terjadi perubahan status pada transaksi (misalnya, pembayaran berhasil, invoice kadaluarsa). Ini adalah cara utama bagi aplikasi Anda untuk mengetahui status pembayaran secara real-time.

Kesimpulan

Mengintegrasikan Xendit ke dalam aplikasi Laravel Anda memang memerlukan beberapa langkah, mulai dari instalasi library, konfigurasi key, hingga penanganan webhook. Namun, dengan mengikuti panduan ini dan menerapkan praktik terbaik, Anda dapat membangun sistem pembayaran yang modern, andal, dan aman. Xendit, dengan ekosistem pembayarannya yang luas, akan membantu aplikasi Anda menerima pembayaran dari berbagai metode, memperluas jangkauan bisnis Anda di pasar digital.

Ingatlah untuk selalu memprioritaskan keamanan, pengujian, dan pengalaman pengguna. Integrasi yang baik tidak hanya berfungsi, tetapi juga memberikan ketenangan pikiran bagi developer dan kemudahan bagi pengguna. Terus eksplorasi fitur-fitur Xendit lainnya untuk memaksimalkan potensi aplikasi Anda!

TAGS: Xendit, Laravel, Payment Gateway, Integrasi Pembayaran, PHP, Webhook, API, Developer Tools, Coding, Software Engineering


Baca Juga

You May Also Like

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *