SIKEU Payment Gateway integration package for Laravel - supporting multiple payment with Virtual Account and QRIS
sikeu/laravel-payment is a Laravel package for sikeu payment gateway integration package for laravel - supporting multiple payment with virtual account and qris.
It currently has 0 GitHub stars and 13 downloads on Packagist (latest version v1.2.2).
Install it with composer require sikeu/laravel-payment.
Discover more Laravel packages by sikeu
or browse all Laravel packages to compare alternatives.
Last updated
Laravel package untuk integrasi SIKEU Payment Gateway. Package ini hanya menyediakan service layer; controller, route, dan callback handler dibuat di aplikasi Laravel Anda.
composer require sikeu/laravel-payment
php artisan vendor:publish --tag=sikeu-config
Tambahkan ke .env:
SIKEU_API_BASE_URL=https://api.sikeu.id
SIKEU_API_KEY=your-api-key
SIKEU_SHARED_SECRET=your-shared-secret
SIKEU_SOURCE_APP=YOUR_APP_NAME
SIKEU_DEFAULT_PROVIDER=BRI
SIKEU_DEFAULT_QRIS_PROVIDER=BRI_QRIS
Lalu refresh config:
php artisan config:clear
service_category lewat getAvailableServices().revenue_account_code lewat getRevenueAccountCodes().checkPaymentRequest() atau proses notifikasi callback dari SIKEU.
service_categorydanrevenue_account_codetidak boleh di-hardcode berdasarkan asumsi. Dua field ini harus mengikuti master data dari SIKEU.
Controller paling sederhana yang siap dipakai:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Sikeu\LaravelPayment\Exceptions\SikeuPaymentException;
use Sikeu\LaravelPayment\Services\SikeuPaymentService;
class PaymentController extends Controller
{
public function __construct(
private SikeuPaymentService $payment
) {}
public function serviceCategories()
{
return response()->json($this->payment->getAvailableServices());
}
public function revenueAccountCodes()
{
return response()->json($this->payment->getRevenueAccountCodes());
}
public function create(Request $request)
{
$validated = $request->validate([
'service_category' => 'required|string',
'customer_no' => 'required|string',
'customer_name' => 'required|string',
'amount' => 'required|numeric|min:1',
'description' => 'required|string',
'revenue_account_code' => 'required|string',
'provider' => 'nullable|string',
'attributes' => 'nullable|array',
]);
try {
return response()->json($this->payment->createPaymentRequest($validated));
} catch (SikeuPaymentException $e) {
return response()->json([
'message' => $e->getMessage(),
'errors' => $e->getResponseData(),
], 400);
}
}
public function show(string $paymentRequestId)
{
try {
return response()->json($this->payment->checkPaymentRequest($paymentRequestId));
} catch (SikeuPaymentException $e) {
return response()->json([
'message' => $e->getMessage(),
'errors' => $e->getResponseData(),
], 400);
}
}
}
Route yang direkomendasikan:
use App\Http\Controllers\PaymentController;
use Illuminate\Support\Facades\Route;
Route::prefix('payments')->group(function () {
Route::get('/service-categories', [PaymentController::class, 'serviceCategories']);
Route::get('/revenue-account-codes', [PaymentController::class, 'revenueAccountCodes']);
Route::post('/', [PaymentController::class, 'create']);
Route::get('/{paymentRequestId}', [PaymentController::class, 'show']);
});
Contoh request:
{
"service_category": "UKT",
"customer_no": "2024000001",
"customer_name": "John Doe",
"amount": 5000000,
"description": "Pembayaran UKT",
"revenue_account_code": "411100",
"attributes": {
"nim": "2024000001",
"faculty": "Teknik",
"study_program": "Informatika",
"semester": "2"
}
}
Nilai UKT dan 411100 di atas hanya contoh. Ambil nilai validnya dari SIKEU melalui getAvailableServices() dan getRevenueAccountCodes().
Jika ingin membuat payment QRIS, gunakan method khusus berikut:
$result = $payment->createQrisPaymentRequest([
'service_category' => 'UKT',
'customer_no' => '2024000001',
'customer_name' => 'John Doe',
'amount' => 5000000,
'description' => 'Pembayaran UKT',
'revenue_account_code' => '411100',
'provider' => 'BRI_QRIS', // opsional, default dari config
]);
Response QRIS akan mengandung data seperti paymentRequestId, qrId, qrContent, dan expiryDate/qrExpiryDate.
Setelah pembayaran diproses, SIKEU dapat mengirim HTTP POST ke endpoint callback aplikasi Anda. Callback ini dipakai untuk sinkronisasi status pembayaran tanpa harus terus melakukan polling.
Alur yang direkomendasikan:
paymentRequestId di database lokal.paymentRequestId, lalu mengubah status pembayaran.Tambahkan callback URL yang bisa diakses publik:
SIKEU_CALLBACK_URL=https://your-domain.tld/api/sikeu/callback
Sampaikan ke admin SIKEU bahwa URL callback ini harus didaftarkan di sisi SIKEU agar notifikasi pembayaran dapat dikirim ke aplikasi Anda.
Route yang direkomendasikan:
use App\Http\Controllers\SikeuCallbackController;
use Illuminate\Support\Facades\Route;
Route::post('/sikeu/callback', [SikeuCallbackController::class, 'handle'])
->middleware('sikeu.signature');
Header penting yang perlu divalidasi:
X-TimestampX-SignatureContoh middleware validasi signature:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ValidateSikeuSignature
{
public function handle(Request $request, Closure $next)
{
$timestamp = $request->header('X-Timestamp');
$signature = $request->header('X-Signature');
$secret = config('sikeu.auth.shared_secret');
if (!$timestamp || !$signature) {
return response()->json(['message' => 'Missing signature headers'], 401);
}
$body = $request->getContent();
$expected = hash_hmac('sha256', $timestamp . ':' . $body, $secret);
if (!hash_equals($expected, $signature)) {
return response()->json(['message' => 'Invalid signature'], 401);
}
return $next($request);
}
}
Daftarkan middleware tersebut dengan alias sikeu.signature sesuai versi Laravel yang Anda gunakan.
Contoh payload callback:
{
"paymentRequestId": "PAY-123456",
"virtualAccountNo": "88881234567890001",
"customerNo": "2024000001",
"amount": 5000000,
"paidAmount": 5000000,
"status": "PAID",
"paidAt": "2026-04-02T14:30:00+07:00",
"transactionId": "TXN-BRI-20260402-001",
"sourceApp": "YOUR_APP_NAME"
}
Contoh handler callback:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class SikeuCallbackController extends Controller
{
public function handle(Request $request)
{
$data = $request->json()->all();
$paymentRequestId = $data['paymentRequestId'] ?? null;
if (!$paymentRequestId) {
return response()->json(['status' => 'ignored'], 200);
}
$payment = DB::table('payments')
->where('payment_request_id', $paymentRequestId)
->first();
if (!$payment) {
return response()->json(['status' => 'ignored'], 200);
}
if ($payment->status === 'PAID') {
return response()->json(['status' => 'already_processed'], 200);
}
DB::table('payments')
->where('payment_request_id', $paymentRequestId)
->update([
'status' => $data['status'] ?? $payment->status,
'paid_amount' => $data['paidAmount'] ?? null,
'transaction_id' => $data['transactionId'] ?? null,
'paid_at' => $data['paidAt'] ?? null,
'updated_at' => now(),
]);
return response()->json(['status' => 'ok'], 200);
}
}
Hal penting saat implementasi callback:
paymentRequestId tidak ditemukan, tetap balas 200 OK agar SIKEU tidak terus retry.200 OK.getAvailableServices(): array
Ambil daftar service_category yang valid dari SIKEU. Gunakan nilai code dari response.getRevenueAccountCodes(): array
Ambil daftar revenue_account_code yang valid dari SIKEU. Gunakan nilai code dari response.createPaymentRequest(array $data): array
Membuat payment request. Field utama: service_category, customer_no, customer_name, amount, description, revenue_account_code. Field opsional: provider, attributes.getPaymentRequest(string $paymentRequestId): array
Ambil detail payment request.checkPaymentRequest(string $paymentRequestId): array
Cek status payment request.cancelPaymentRequest(string $paymentRequestId): array
Batalkan payment request.createQrisPaymentRequest(array $data): array
Membuat payment request QRIS. Jika provider tidak dikirim, package memakai SIKEU_DEFAULT_QRIS_PROVIDER.checkQrisPaymentStatus(string $paymentRequestId): array
Cek status pembayaran QRIS.service_category wajib berasal dari getAvailableServices().revenue_account_code wajib berasal dari getRevenueAccountCodes().amount akan dikirim sebagai integer.config/sikeu.php.MIT