abdasis / laravel-duitku
Laravel payment gateway integration for Duitku with polymorphic payable support.
Requires
- php: ^8.2
- illuminate/contracts: ^11.0|^12.0
- illuminate/database: ^11.0|^12.0
- illuminate/http: ^11.0|^12.0
- illuminate/routing: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
This package is auto-updated.
Last update: 2026-03-04 09:49:19 UTC
README
Package Laravel untuk integrasi payment gateway Duitku dengan dukungan polymorphic payable — model apapun (User, Team, Order) bisa punya pembayaran.
Fitur
- Polymorphic Payable — Tidak hardcode ke User/Order, model apapun bisa bayar
- POP (Popup) & Direct API — Support VA, QRIS, retail outlet, dan popup payment
- Event-Driven —
PaymentSuccess,PaymentFailed,PaymentExpiredotomatis dispatch saat callback - Auto-Registered Webhook — Route
POST /duitku/callbacklangsung aktif - Facade Support —
Duitku::createPayment(),Duitku::checkStatus() - Signature Verification Middleware — Validasi otomatis callback dari Duitku
- Configurable — Table name, route prefix, expiry period bisa disesuaikan
Persyaratan
- PHP 8.2+
- Laravel 11 atau 12
Instalasi
Via GitHub (Private/Local)
Tambahkan repository di composer.json project kamu:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/abdasis/laravel-duitku"
}
]
}
Lalu install:
composer require abdasis/laravel-duitku:dev-main
Via Path (Development Lokal)
{
"repositories": [
{
"type": "path",
"url": "packages/abdasis/laravel-duitku"
}
]
}
composer require abdasis/laravel-duitku:@dev
Konfigurasi
1. Publish Config
php artisan vendor:publish --tag=duitku-config
File config/duitku.php akan muncul:
return [ 'merchant_code' => env('DUITKU_MERCHANT_CODE'), 'api_key' => env('DUITKU_API_KEY'), 'sandbox' => env('DUITKU_SANDBOX', true), 'expiry_period' => env('DUITKU_EXPIRY_PERIOD', 60), 'base_url' => env('DUITKU_SANDBOX', true) ? 'https://api-sandbox.duitku.com' : 'https://api-prod.duitku.com', 'route_prefix' => 'duitku', 'table_name' => 'payments', ];
2. Environment Variables
Tambahkan ke file .env:
DUITKU_MERCHANT_CODE=your_merchant_code DUITKU_API_KEY=your_api_key DUITKU_SANDBOX=true DUITKU_EXPIRY_PERIOD=60
3. Jalankan Migrasi
Migrasi otomatis di-load dari package. Cukup jalankan:
php artisan migrate
Jika ingin kustomisasi migration:
php artisan vendor:publish --tag=duitku-migrations
Penggunaan
Membuat Pembayaran (POP/Popup)
use Abdasis\Duitku\Facades\Duitku; $payment = Duitku::createPayment($user, [ 'amount' => 150000, 'product_details' => 'Langganan Premium', 'customer_name' => $user->name, 'customer_email' => $user->email, 'customer_phone' => '081234567890', 'callback_url' => route('duitku.callback'), 'return_url' => route('payment.success'), 'metadata' => ['plan_id' => 3], ]); // Redirect user ke halaman pembayaran Duitku return redirect($payment->payment_url);
Membuat Pembayaran Direct (VA/QRIS/Retail)
$payment = Duitku::createDirectPayment($user, [ 'amount' => 200000, 'payment_method' => 'VA', // kode metode pembayaran Duitku 'product_details' => 'Langganan Gold', 'customer_name' => $user->name, 'customer_email' => $user->email, 'callback_url' => route('duitku.callback'), 'return_url' => route('payment.success'), ]);
Mendapatkan Daftar Metode Pembayaran
$methods = Duitku::getPaymentMethods(100000); // Contoh response: // [ // ['paymentMethod' => 'VA', 'paymentName' => 'Virtual Account', 'totalFee' => 4000], // ['paymentMethod' => 'QR', 'paymentName' => 'QRIS', 'totalFee' => 1500], // ]
Cek Status Pembayaran
use Abdasis\Duitku\Models\Payment; $payment = Payment::find(1); $payment = Duitku::checkStatus($payment); echo $payment->status->label(); // "Berhasil", "Menunggu Pembayaran", dll.
Polymorphic Payable
Model apapun bisa jadi "pemilik" pembayaran:
// User bayar Duitku::createPayment($user, [...]); // Team bayar Duitku::createPayment($team, [...]); // Order bayar Duitku::createPayment($order, [...]); // Akses relasi $payment->payable; // returns User, Team, atau Order
Event Handling
Package ini dispatch event otomatis saat menerima callback dari Duitku. Kamu tinggal listen di aplikasi host.
Event yang Tersedia
| Event | Kapan Dispatch |
|---|---|
Abdasis\Duitku\Events\PaymentSuccess |
resultCode = 00 |
Abdasis\Duitku\Events\PaymentFailed |
resultCode selain 00, 01, 02 |
Abdasis\Duitku\Events\PaymentExpired |
resultCode = 02 |
Contoh Listener
Buat listener:
// app/Listeners/HandlePaymentSuccess.php namespace App\Listeners; use Abdasis\Duitku\Events\PaymentSuccess; class HandlePaymentSuccess { public function handle(PaymentSuccess $event): void { $payment = $event->payment; $payable = $payment->payable; // Aktivasi langganan, kirim email, update status order, dll. } }
Register di AppServiceProvider:
use Abdasis\Duitku\Events\PaymentSuccess; use Abdasis\Duitku\Events\PaymentFailed; use App\Listeners\HandlePaymentSuccess; use App\Listeners\HandlePaymentFailed; use Illuminate\Support\Facades\Event; public function boot(): void { Event::listen(PaymentSuccess::class, HandlePaymentSuccess::class); Event::listen(PaymentFailed::class, HandlePaymentFailed::class); }
Callback Route
Package otomatis mendaftarkan route:
POST /duitku/callback → duitku.callback
Route ini tidak pakai CSRF karena dipanggil server-to-server oleh Duitku. Prefix bisa diubah via config duitku.route_prefix.
Verifikasi route sudah terdaftar:
php artisan route:list --path=duitku
Payment Model
Status Enum
use Abdasis\Duitku\Enums\PaymentStatus; PaymentStatus::Pending; // 'pending' - Menunggu Pembayaran (yellow) PaymentStatus::Success; // 'success' - Berhasil (green) PaymentStatus::Failed; // 'failed' - Gagal (red) PaymentStatus::Expired; // 'expired' - Kedaluarsa (gray) $status->label(); // "Menunggu Pembayaran" $status->color(); // "yellow"
Helper Methods
$payment->isPending(); // bool $payment->isSuccess(); // bool $payment->isFailed(); // bool $payment->isExpired(); // bool
Query Scopes
use Abdasis\Duitku\Models\Payment; Payment::query()->pending()->get(); Payment::query()->success()->count(); Payment::query()->failed()->where('payable_type', User::class)->get();
Metadata
Kolom metadata (JSON) bisa dipakai untuk menyimpan data tambahan:
$payment = Duitku::createPayment($user, [ 'amount' => 100000, 'metadata' => [ 'subscription_plan_id' => 5, 'coupon_code' => 'DISC10', ], // ... ]); $payment->metadata['subscription_plan_id']; // 5
Skema Database
Tabel payments (nama bisa dikonfigurasi):
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
bigint | Primary key |
payable_type |
string | Morph class (e.g. App\Models\User) |
payable_id |
bigint | Morph ID |
merchant_order_id |
string | Unique, generated otomatis |
duitku_order_id |
string (nullable) | ID dari Duitku |
payment_url |
string (nullable) | URL redirect pembayaran |
amount |
integer | Jumlah pembayaran |
product_details |
string (nullable) | Deskripsi produk |
payment_method |
string (nullable) | Kode metode bayar |
status |
string | pending/success/failed/expired |
result_code |
string (nullable) | Response code dari Duitku |
reference |
string (nullable) | Reference number |
metadata |
json (nullable) | Data tambahan |
created_at |
timestamp | |
updated_at |
timestamp |
Middleware (Opsional)
Jika ingin verifikasi signature di route custom:
use Abdasis\Duitku\Http\Middleware\VerifyDuitkuSignature; Route::post('/custom-webhook', CustomController::class) ->middleware(VerifyDuitkuSignature::class);
Arsitektur Package
src/
├── Client/DuitkuClient.php # Low-level HTTP calls + signature
├── DuitkuService.php # High-level API (Facade target)
├── DuitkuServiceProvider.php # Register bindings, config, routes
├── Facades/Duitku.php # Facade
├── Enums/PaymentStatus.php # Status enum dengan label & color
├── Models/Payment.php # Eloquent model (polymorphic)
├── Events/
│ ├── PaymentSuccess.php
│ ├── PaymentFailed.php
│ └── PaymentExpired.php
├── Exceptions/
│ ├── DuitkuApiException.php
│ └── InvalidSignatureException.php
└── Http/
├── Controllers/DuitkuCallbackController.php
└── Middleware/VerifyDuitkuSignature.php
Testing
Package dilengkapi 66 test (141 assertions) menggunakan Pest:
php artisan test packages/abdasis/laravel-duitku/tests
Lisensi
MIT License.