Cara Handle Notifikasi Midtrans pada API — CoreAPI #ep3
By: Azhar Ogi
Tags: Lumen, Payment Gateway, Rest Api, Laravel, Backend

Jika brosis lebih tertarik dengan metode video, brosis bisa langsung akses video dibawah ini yah.

Btw karna disini kita masih menggunakan localhost, maka kita menggunakan simulasi menggunakan webhook.

—

Tahap 1 : Request Checkout

Untuk brosis yang belum paham Checkout menggunakan Core API Midtrans brosis bisa baca dulu di Ep1 & Ep2

Tahap 2 : Handle Notification

Kali ini kita menyiapkan table terlebih dahulu yah guys. Siapkan dulu saja schemanya sesuai dengan database yang kalian gunakan, disini kita menggunakan MySQL. Buat 1 migration pada lumen kalian.

php artisan make:migration orders --create=orders

Masukan syntax ini ke dalam file migration kalian pada function up()

Schema::create('orders', function (Blueprint $table) {

$table->bigIncrements('id');

$table->string('invoice','30')->nullable();

$table->bigInteger('product_reference')->nullable();

$table->string('transaction_id','255')->nullable();

$table->enum('status', ['WAITING', 'PENDING', 'CANCEL', 'SUCCESS'])->nullable();

$table->softDeletes('deleted_at',0);

$table->timestamps();

});

Sehingga menghasilkan struktur table seperti dibawah ini

Jika sudah jangan lupa buat 1 class model untuk table orders ya

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model; class Order extends Model{

protected $table = "orders";

}

Kita buat 1 class controller baru dengan nama NotificationController dan buat 1 function di dalamnya yaitu post() , brosis bisa lihat syntaxnya dibawah ini :

public function post(Request $req)

{

try {

$notification_body = json_decode($req->getContent(), true);

$invoice = $notification_body['order_id'];

$transaction_id = $notification_body['transaction_id'];

$status_code = $notification_body['status_code']; $order = Order::where('invoice', $invoice)->where('transaction_id', $transaction_id)->first();

if (!$order)

return ['code' => 0, 'messgae' => 'Terjadi kesalahan | Pembayaran tidak valid']; switch ($status_code) {

case '200':

$order->status = "SUCCESS";

break;

case '201':

$order->status = "PENDING";

break;

case '202':

$order->status = "CANCEL";

break;

} $order->save();

return response('Ok', 200)->header('Content-Type', 'text/plain');

} catch (\Exception $e) {

return response('Error', 404)->header('Content-Type', 'text/plain');

}

}

Penting : Notifikasi yang dikirim oleh midtrans memiliki format JSON, sehingga brosis harus melakukan decode pada json yang diterima oleh API ini.

Jangan lupa untuk routingnya

$router->post('/payment/notification/post','NotificationController@post');

Lanjut, brosis modifikasi class PaymentController agar menyimpan data checkoutnya ke dalam sebuah table orders

(tambah) function buyProduct



{

try {

$result = null;

$payment_method = $req->payment_method;

$order_id = "CXS" . date('YmdHis');

$total_amount = 10000;

$transaction = array(

"transaction_details" => [

"gross_amount" => $total_amount,

"order_id" => $order_id

],

"customer_details" => [

"email" => "

"first_name" => "Azhar",

"last_name" => "Ogi",

"phone" => "+628948484848"

],

"item_details" => array([

"id" => "1388998298204",

"price" => 5000,

"quantity" => 1,

"name" => "Ayam Zozozo"

], [

"id" => "1388998298202",

"price" => 5000,

"quantity" => 1,

"name" => "Ayam Xoxoxo"

]),

); public function buyProduct(Request $req)try {$result = null;$payment_method = $req->payment_method;$order_id = "CXS" . date('YmdHis');$total_amount = 10000;$transaction = array("transaction_details" => ["gross_amount" => $total_amount,"order_id" => $order_id],"customer_details" => ["email" => " budi.utomo@Midtrans.com ","first_name" => "Azhar","last_name" => "Ogi","phone" => "+628948484848"],"item_details" => array(["id" => "1388998298204","price" => 5000,"quantity" => 1,"name" => "Ayam Zozozo"], ["id" => "1388998298202","price" => 5000,"quantity" => 1,"name" => "Ayam Xoxoxo"]),); switch ($payment_method) {

case 'bank_transfer':

$result = self::bankTransfer($order_id, $total_amount, $transaction);

break;

case 'credit_card':

$token_id = $req->token_id;

$result = self::chargeCreditCard($order_id, $total_amount, $token_id, $transaction);

break;

} return $result;

} catch (\Exception $th) {

dd($th);

return ['code' => 0, 'messgae' => 'Terjadi kesalahan'];

}

}

(modifikasi) function bankTransfer

static function bankTransfer($order_id, $total_amount, $transaction_object)

{

try {

$transaction = $transaction_object;

$transaction['payment_type'] = "bank_transfer";

$transaction['bank_transfer'] = array(

"bank" => "bca",

"va_number" => "111111",

); $charge = CoreApi::charge($transaction);

if (!$charge) {

return ['code' => 0, 'messgae' => 'Terjadi kesalahan'];

} $order = new Order();

$order->invoice = $order_id;

$order->transaction_id = $charge->transaction_id;

$order->status = "PENDING"; if (!$order->save())

return false; return ['code' => 1, 'messgae' => 'Success', 'result' => $charge];

} catch (\Exception $e) {

return ['code' => 0, 'messgae' => 'Terjadi kesalahan'];

}

}

(modifikasi) function chargeCreditCard

static function chargeCreditCard($order_id, $total_amount, $token_id, $transaction_object)

{

try {

$credit_card = array(

'token_id' => $token_id,

'authentication' => true,

'bank' => "bni"

); $transaction = $transaction_object; $transaction['payment_type'] = "credit_card";

$transaction['credit_card'] = $credit_card; $charge = CoreApi::charge($transaction);

if (!$charge) {

return ['code' => 0, 'messgae' => 'Terjadi kesalahan'];

} $order = new Order();

$order->invoice = $order_id;

$order->transaction_id = $charge->transaction_id;

$order->status = "PENDING"; if (!$order->save())

return false; return ['code' => 1, 'message' => 'Success', 'result' => $charge];

} catch (\Exception $e) {

return ['code' => 0, 'message' => 'Something wrong | Internal Charge Credit Card'];

}

}

Jika sudah maka jangan lupa di serve dulu

php -S localhost:8001 -t public

Kita buka webhook : https://webhook.site/

Kita copy unique url

Oke sekarang kita buka akun midtrans > settings > configuration, dan paste unique url ke kolom Payment Notification URL.

Kita uji coba, lakukan checkout terlebih dahulu menggunakan bank transfer

Brosis bisa cek data pada table orders

Brosis bisa cek notification history / log ke : https://dashboard.sandbox.midtrans.com/settings/vtweb_configuration/history

Jika statusnya complete, kalian bisa cek di webhook kalian

Brosis bisa copy va_number pada json di column raw content

Untuk simulasi pembayarannya kalian bisa buka : https://simulator.sandbox.midtrans.com/bca/va/index

Jika berhasil maka brosis akan mendapatkan payment confirmation seperti dibawah ini.

Dan jangan lupa klik pay.

Brosis buka kembali webhook kalian dan wala… ada notifikasi success

Sekarang, brosis copy json pada raw content.

Kita sekarang test json request menggunakan Postman,

Jangan lupa send, jika status 200 OK maka kalian bisa cek data kalia pada table orders. Jika status berubah sukses maka kalian sudah berhasil sampai sini

—

Oke, sekian dulu dan semoga bermanfaat. Jika brosis merasa bingung atau mengalami error, bisa chat aja langsung ke socmed ya.

Jika kalian suka silahkan di clap ya :D