Ketika melakukan pembayaran di dalam Midtrans, maka Midtrans akan mengirim sebuah webhook yang berisi informasi pembayaran ke dalam website kita. Disini kita perlu membuat sebuah callback yang berfungsi untuk menerima sebuah reqesut webhook yang kirim oleh Midtrans tersebut.
Di dalam callback kita bisa melakukan beberapa kondisi yang bisa disesuaikan dengan keinginan, misalnya saja jika pembayaran sukses, makan akan melakukan update stock, update status pembayaran dan lain sebagainya.
Langkah 1 - Membuat Controller Notification Handler
Silahkan jalankan perintah berikut ini di dalam terminal/CMD untuk membuat controller baru.
go
php artisan make:controller Api/CallbackController -i
Jika perintah di atas berhasil dijalankan, maka kita akan mendapatkan 1 file controller baru dengan nama CallbackController.php yang berada di dalam folder app/Http/Controllers/Api.
Silahkan buka file tersebut dan ubah semua kode-nya menjadi seperti berikut ini :
php
<?php
namespace App\Http\Controllers\Api;
use App\Models\Transaction;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class CallbackController extends Controller
{
/**
* Handle the incoming request.
*/
public function __invoke(Request $request)
{
$payload = $request->getContent();
$notification = json_decode($payload);
$validSignatureKey = hash("sha512", $notification->order_id . $notification->status_code . $notification->gross_amount . config('midtrans.server_key'));
if ($notification->signature_key != $validSignatureKey) {
return response(['message' => 'Invalid signature'], 403);
}
$transaction = $notification->transaction_status;
$type = $notification->payment_type;
$orderId = $notification->order_id;
//data tranaction
$data_transaction = Transaction::where('invoice', $orderId)->first();
if ($transaction == 'capture') {
// For credit card transaction, we need to check whether transaction is challenge by FDS or not
if ($type == 'credit_card') {
//nothing
}
} elseif ($transaction == 'settlement') {
/**
* update invoice to success
*/
$data_transaction->update([
'status' => 'success'
]);
} elseif($transaction == 'pending'){
/**
* update invoice to pending
*/
$data_transaction->update([
'status' => 'pending'
]);
} elseif ($transaction == 'deny') {
/**
* update invoice to failed
*/
$data_transaction->update([
'status' => 'failed'
]);
} elseif ($transaction == 'expire') {
/**
* update invoice to expired
*/
$data_transaction->update([
'status' => 'expired'
]);
} elseif ($transaction == 'cancel') {
/**
* update invoice to failed
*/
$data_transaction->update([
'status' => 'failed'
]);
}
}
}
Dari perubahan kode di atas, pertama kita import Model Transaction.
perl
use App\Models\Transaction;
Di dalam method __invoke, kita akan melakukan beberapa kondisi, pertama kita akan mendapatkan content JSON yang dikirim melalui Midtrans dengan kode seperti berikut ini :
php
$payload = $request->getContent();
$notification = json_decode($payload);
Kemudian kita membuat variable yang isinya adalah data signatur yang akan kita cocokan dengan variable $notification di atas.
php
$validSignatureKey = hash("sha512", $notification->order_id . $notification->status_code . $notification->gross_amount . config('midtrans.server_key'));
Jika nilai dari $notification dan $validSignaturKey tidak sama, maka akan melakukan return dengan status code 403.
php
if ($notification->signature_key != $validSignatureKey) {
return response(['message' => 'Invalid signature'], 403);
}
Jika data signatur ditemukan, maka kita akan melakukan query ke dalam table Transaction berdasarkan data order ID/invoice yang dikirim dari Midtrans.
php
$transaction = $notification->transaction_status;
$type = $notification->payment_type;
$orderId = $notification->order_id;
//data tranaction
$data_transaction = Transaction::where('invoice', $orderId)->first();
Setelah itu, kita akan melakukan pengecekan kondisi pembayaran, kurang lebih kode-nya seperti berikut ini :
php
if ($transaction == 'capture') {
// For credit card transaction, we need to check whether transaction is challenge by FDS or not
if ($type == 'credit_card') {
//nothing
}
} elseif ($transaction == 'settlement') {
/**
* update invoice to success
*/
$data_transaction->update([
'status' => 'success'
]);
} elseif($transaction == 'pending'){
/**
* update invoice to pending
*/
$data_transaction->update([
'status' => 'pending'
]);
} elseif ($transaction == 'deny') {
/**
* update invoice to failed
*/
$data_transaction->update([
'status' => 'failed'
]);
} elseif ($transaction == 'expire') {
/**
* update invoice to expired
*/
$data_transaction->update([
'status' => 'expired'
]);
} elseif ($transaction == 'cancel') {
/**
* update invoice to failed
*/
$data_transaction->update([
'status' => 'failed'
]);
}
Di atas jika nilai $transaction bernilai settlement, maka pembayaran berhasil dilakukan dan di dalamnya kita melakukan proses update status menjadi success.
Langkah 2 - Membuat Route API Callback
Sekarang kita akan membuat route API untuk callback payment gateway. Pertama tentu kita akan publish dulu konfigurasi file route untuk API di Laravel.
Silahkan jalankan perintah berikut ini di dalam terminal/CMD dan pastikan berada di dalam project Laravel-nya.
undefinedphp artisan install:api
Setelah proses installasi selesai, sekarang silahkan buka file routes/api.php, kemudian ubah semua kode-nya menjadi seperti berikut ini.
php
<?php
use Illuminate\Support\Facades\Route;
// route callback
Route::post('callback', App\Http\Controllers\Api\CallbackController::class);
Di atas, kita menambahkan route baru dengan method POST dan untuk URL-nya adalah callback dan kita arahkan ke dalam CallbackController.