Tutorial Integrasi Payment Midtrans Pada Projek Laravel 11 Website Beli Laptop Online

Di era digital saat ini, website modern tidak hanya berfokus pada desain yang menarik, tetapi juga harus memberikan pengalaman terbaik bagi penggunanya. Salah satu fitur yang penting adalah payment gateway. Fitur ini memudahkan pengguna dalam memilih metode pembayaran yang sesuai, mulai dari transfer bank, e-wallet, hingga kartu kredit.

Dengan adanya payment gateway seperti Midtrans, proses pembayaran bisa berjalan lebih cepat, aman, dan efisien. Ini sangat penting untuk meningkatkan kepuasan pengguna dan mendukung keberhasilan bisnis online. Ketika pengguna merasa dimudahkan, peluang mereka untuk menyelesaikan transaksi akan semakin besar.

Menerapkan Payment Gateway Midtrans pada Website Laravel 11

Pada artikel ini, kita akan membahas bagaimana cara menerapkan payment gateway Midtrans ke dalam proyek Laravel 11. Untuk studi kasus, kita akan menggunakan website e-commerce sederhana yang berfokus pada jual beli laptop online.

Midtrans dipilih karena platform ini sudah mendukung berbagai metode pembayaran yang sering digunakan di Indonesia, seperti transfer bank, kartu kredit, e-wallet, dan lain sebagainya. Dengan mengintegrasikan Midtrans, pengguna website dapat memilih metode pembayaran yang paling mereka sukai dengan mudah.

Laravel 11 sebagai framework PHP terbaru menawarkan fitur yang lebih modern dan efisien. Hal ini membuat proses integrasi payment gateway menjadi lebih lancar dan terstruktur.

Langkah Selanjutnya

Di artikel ini, kita tidak akan langsung masuk ke dalam contoh coding. Namun, pemahaman dasar tentang payment gateway Midtrans di Laravel 11 sangat penting sebelum melangkah ke implementasi teknis. Beberapa poin yang perlu dipersiapkan antara lain:

  1. Memiliki akun Midtrans untuk mendapatkan Server Key dan Client Key.
  2. Menyiapkan proyek Laravel 11 dengan struktur e-commerce sederhana.
  3. Memahami alur kerja integrasi Midtrans, seperti pembuatan transaksi, validasi pembayaran, dan penerimaan notifikasi.

Dengan mempersiapkan hal-hal tersebut, kita bisa memulai proses integrasi secara bertahap. Payment gateway Midtrans akan membantu meningkatkan profesionalisme website e-commerce dan memberikan kenyamanan ekstra bagi pengguna dalam bertransaksi.

Fitur payment gateway seperti Midtrans sangat penting untuk meningkatkan pengalaman pengguna di website modern, khususnya dalam proyek e-commerce. Dengan penerapan yang tepat di Laravel 11, Anda bisa menciptakan website yang lebih profesional dan ramah pengguna.

Di artikel selanjutnya, kita akan masuk lebih dalam ke langkah-langkah teknis untuk mengintegrasikan Midtrans di proyek Laravel 11 Anda. Tetap semangat belajar dan terus kembangkan skill web development Anda!

Cara Membuat File Migration dan Model untuk Table Product, Customer, dan Transaction di Laravel 11

Untuk membuat file migration dan model dalam proyek Laravel 11, kita bisa memanfaatkan perintah Artisan yang tersedia. Berikut adalah langkah-langkah lengkap beserta contoh kode untuk tabel product, customer, dan transaction.

Membuat File Migration dan Model untuk Tabel Product

Pertama, buat model dan file migration dengan perintah Artisan:

php artisan make:model Product -m

Perintah ini akan membuat file model Product di folder app/Models dan file migration di folder database/migrations.

Buka file migration yang telah dibuat (misalnya xxxx_xx_xx_create_products_table.php), lalu tambahkan struktur tabel seperti berikut:

<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('description')->nullable();
            $table->decimal('price', 10, 2);
            $table->integer('stock')->default(0);
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

Lalu, buka file model Product dan tambahkan properti $fillable agar dapat diisi melalui query:

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;

class Product extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'description', 'price', 'stock'];
}

Membuat File Migration dan Model untuk Tabel Customer

Jalankan perintah berikut di terminal:

php artisan make:model Customer -m

Kemudian buka file migration yang dibuat (misalnya xxxx_xx_xx_create_customers_table.php) dan tambahkan struktur tabel:

<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('customers', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('phone_number');
            $table->text('address')->nullable();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('customers');
    }
};

Buka file model Customer di app/Models dan tambahkan properti $fillable:

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;

class Customer extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'email', 'phone_number', 'address'];
}

Membuat File Migration dan Model untuk Tabel Transaction

Buat file migration dan model untuk transaksi dengan perintah:

php artisan make:model Transaction -m

Buka file migration (misalnya xxxx_xx_xx_create_transactions_table.php) dan tambahkan struktur tabel berikut:

<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('product_id')->constrained()->onDelete('cascade');
            $table->foreignId('customer_id')->constrained()->onDelete('cascade');
            $table->integer('quantity');
            $table->decimal('total_price', 10, 2);
            $table->string('status')->default('pending');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('transactions');
    }
};

Selanjutnya, tambahkan properti $fillable di file model Transaction:

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;

class Transaction extends Model
{
    use HasFactory;

    protected $fillable = ['product_id', 'customer_id', 'quantity', 'total_price', 'status'];

    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    public function customer()
    {
        return $this->belongsTo(Customer::class);
    }
}

Menjalankan File Migration

Setelah semua file migration selesai dibuat, jalankan perintah berikut untuk membuat tabel di database:

php artisan migrate

Perintah ini akan membaca semua file migration di folder database/migrations dan membuat tabel sesuai struktur yang telah didefinisikan.

Penjelasan Relasi Antar Tabel

  • Tabel transactions memiliki foreign key product_id dan customer_id yang berelasi dengan tabel products dan customers.
  • Relasi diatur di model Transaction menggunakan metode belongsTo, sedangkan di model Product dan Customer relasi dapat ditambahkan jika diperlukan.

Dengan langkah-langkah di atas, Anda telah berhasil membuat file migration dan model untuk tabel product, customer, dan transaction, serta mengatur relasi antar tabel tersebut dalam proyek Laravel 11.

Alur Bekerja Fitur Checkout pada Website Beli Laptop Online dengan Payment Midtrans dan Penerapan Service Repository Pattern, Blade, dan Controller (Analogi Restoran)

Untuk memahami cara kerja fitur checkout pada website beli laptop online menggunakan Midtrans, dengan penerapan Service Repository Pattern, Blade, dan Controller, mari kita gunakan analogi sederhana seperti proses di sebuah restoran modern.

1. Pelanggan Memilih Menu (Laptop) – Blade sebagai Tampilan di Website

Ketika pelanggan datang ke restoran, mereka melihat menu makanan yang disediakan oleh restoran. Menu ini ditampilkan dengan rapi dan menarik sehingga memudahkan pelanggan dalam memilih.

Dalam website, Blade bertindak sebagai tampilan atau "menu" yang disajikan ke pelanggan. Blade menampilkan daftar laptop, informasi harga, dan detail lain seperti stok.

  • Pelanggan memilih laptop yang diinginkan, memasukkan jumlah barang, dan melanjutkan ke proses checkout.

2. Pelanggan Menginformasikan Pesanan ke Kasir – Controller sebagai Pengatur Alur

Setelah memilih menu, pelanggan mendatangi kasir dan memberitahu makanan yang ingin dipesan. Kasir bertindak sebagai penghubung antara pelanggan dan dapur.

Di website, Controller adalah "kasir" yang menerima data pesanan dari pelanggan.

  • Controller menerima data seperti ID laptop, jumlah barang, total harga, dan informasi pelanggan.
  • Controller kemudian memerintahkan bagian lain untuk memproses pesanan.

3. Kasir Mengatur Pesanan ke Dapur – Service sebagai Logika Bisnis

Setelah menerima pesanan dari pelanggan, kasir meneruskan informasi tersebut ke dapur yang memiliki sistem untuk mempersiapkan makanan. Di sini, dapur bertanggung jawab menjalankan logika utama, seperti memasak makanan.

Dalam website, Service Layer bertindak sebagai dapur yang memproses logika bisnis.

  • Service layer menghitung detail transaksi, seperti total harga.
  • Service juga berkomunikasi dengan Midtrans untuk membuat "token pembayaran" yang akan digunakan pelanggan di halaman pembayaran.
  • Service layer memastikan semua langkah logis berjalan dengan benar.

4. Kasir Menghubungi Sistem Keuangan – Midtrans Sebagai Sistem Pembayaran

Di restoran modern, kasir menggunakan mesin pembayaran (seperti EDC atau QR Code) untuk meminta pelanggan menyelesaikan pembayaran. Mesin pembayaran ini menghubungkan sistem restoran dengan bank atau penyedia pembayaran.

Di website, Midtrans adalah "mesin pembayaran" yang menangani pembayaran digital.

  • Service layer akan mengirim data transaksi (seperti total harga dan detail pelanggan) ke Midtrans.
  • Midtrans akan mengembalikan Snap Token sebagai akses ke halaman pembayaran.

Controller menerima token ini dari Service dan mengembalikan ke tampilan Blade agar pelanggan bisa diarahkan ke halaman pembayaran Midtrans.

5. Pelanggan Melakukan Pembayaran – Midtrans Halaman Pembayaran

Di restoran, pelanggan membayar melalui mesin pembayaran menggunakan kartu debit, e-wallet, atau metode lainnya. Setelah pembayaran selesai, mesin akan memberikan notifikasi bahwa pembayaran berhasil.

Pada website, pelanggan menggunakan halaman pembayaran Midtrans untuk menyelesaikan transaksi. Mereka memilih metode pembayaran seperti e-wallet, transfer bank, atau kartu kredit.

6. Kasir Menerima Konfirmasi Pembayaran – Webhook Midtrans dan Repository

Setelah pembayaran berhasil, mesin pembayaran akan mengirimkan konfirmasi ke kasir. Kasir mencatat bahwa pembayaran telah diterima dan memberi tahu dapur bahwa makanan siap disiapkan.

Di website:

  • Midtrans mengirim notifikasi webhook ke server Laravel.
  • Controller menerima notifikasi ini dan meneruskan data ke Repository.
  • Repository bertugas memperbarui status transaksi di database menjadi paid.

Repository berfungsi seperti buku catatan yang dikelola oleh kasir untuk mencatat pembayaran.

7. Pelanggan Menerima Konfirmasi dan Pesanan Diproses

Setelah pembayaran berhasil, kasir memberitahu pelanggan bahwa pesanannya sudah diterima dan dalam proses. Pelanggan juga menerima bukti pembayaran (struk).

Di website:

  • Blade menampilkan halaman konfirmasi pembayaran yang sukses.
  • Pelanggan mendapatkan notifikasi melalui email atau tampilan website bahwa transaksi berhasil.
  • Status transaksi di database diperbarui menjadi paid.

Kesimpulan

  1. Blade bertindak sebagai "menu restoran" yang ditampilkan ke pelanggan untuk memilih laptop dan melakukan checkout.
  2. Controller bertindak sebagai "kasir" yang mengatur alur proses antara pelanggan, sistem, dan Midtrans.
  3. Service bertindak sebagai "dapur" yang menangani logika bisnis utama, seperti berkomunikasi dengan Midtrans.
  4. Repository adalah "buku catatan kasir" yang menyimpan data transaksi dan memperbarui status pembayaran di database.
  5. Midtrans bertindak sebagai "mesin pembayaran" yang memproses transaksi digital dari pelanggan.

Dengan alur ini, proses checkout di website beli laptop online menjadi terstruktur, mudah dipahami, dan efisien, sama seperti pengalaman pelanggan yang memesan makanan di restoran modern.

Cara Menambahkan Midtrans ke Proyek Laravel 11

Untuk mengintegrasikan Midtrans sebagai payment gateway ke proyek Laravel, berikut adalah langkah-langkah lengkapnya beserta kode yang diperlukan.

Menginstal Midtrans SDK

Tambahkan Midtrans SDK ke dalam proyek Laravel menggunakan Composer. Buka terminal dan jalankan perintah berikut:

composer require midtrans/midtrans-php

Konfigurasi Midtrans

Setelah instalasi selesai, tambahkan konfigurasi Server Key dan Client Key di file .env:

MIDTRANS_SERVER_KEY=your-server-key
MIDTRANS_CLIENT_KEY=your-client-key
MIDTRANS_IS_PRODUCTION=false

Kemudian, buat file konfigurasi Midtrans di dalam proyek Laravel. Jalankan perintah berikut untuk membuat file konfigurasi:

php artisan make:config midtrans

Tambahkan konfigurasi berikut di file config/midtrans.php:

<?php

return [
    'server_key' => env('MIDTRANS_SERVER_KEY'),
    'client_key' => env('MIDTRANS_CLIENT_KEY'),
    'is_production' => env('MIDTRANS_IS_PRODUCTION', false),
    'is_sanitized' => true,
    'is_3ds' => true,
];

Cara Membuat File Service Repository Pattern untuk Fitur Checkout Product Menggunakan Midtrans

Repository pattern digunakan untuk memisahkan logika bisnis dari logika database agar kode lebih terstruktur dan mudah dipelihara. Untuk fitur checkout product menggunakan Midtrans, kita akan menerapkan repository pattern dengan langkah-langkah berikut.

Membuat Struktur Folder Repository dan Service

Buat dua folder baru di dalam direktori app untuk menyimpan repository dan service:

mkdir app/Repositories app/Services

Membuat Interface dan Repository untuk Transaksi

Buat file interface TransactionRepositoryInterface.php di app/Repositories:

<?php

namespace App\\Repositories;

interface TransactionRepositoryInterface
{
    public function createTransaction(array $data);
}

Selanjutnya, buat file implementasi TransactionRepository.php di app/Repositories:

<?php

namespace App\\Repositories;

use App\\Models\\Transaction;

class TransactionRepository implements TransactionRepositoryInterface
{
    public function createTransaction(array $data)
    {
        return Transaction::create($data);
    }
}

Membuat Midtrans Service

Buat file service CheckoutService.php di app/Services untuk menangani logika checkout dan Midtrans:

<?php

namespace App\\Services;

use App\\Repositories\\TransactionRepositoryInterface;
use Midtrans\\Config;
use Midtrans\\Snap;

class CheckoutService
{
    protected $transactionRepository;

    public function __construct(TransactionRepositoryInterface $transactionRepository)
    {
        $this->transactionRepository = $transactionRepository;

        // Konfigurasi Midtrans
        Config::$serverKey = config('midtrans.server_key');
        Config::$isProduction = config('midtrans.is_production');
        Config::$isSanitized = true;
        Config::$is3ds = true;
    }

    public function processCheckout($data)
    {
        // Simpan transaksi ke database menggunakan repository
        $transaction = $this->transactionRepository->createTransaction([
            'product_id' => $data['product_id'],
            'customer_id' => $data['customer_id'],
            'quantity' => $data['quantity'],
            'total_price' => $data['total_price'],
            'status' => 'pending'
        ]);

        // Membuat Snap Token Midtrans
        $params = [
            'transaction_details' => [
                'order_id' => $transaction->id,
                'gross_amount' => $transaction->total_price
            ],
            'customer_details' => [
                'first_name' => $data['customer_name'],
                'email' => $data['customer_email'],
                'phone' => $data['customer_phone']
            ]
        ];

        $snapToken = Snap::getSnapToken($params);

        return [
            'transaction' => $transaction,
            'snap_token' => $snapToken
        ];
    }
}

Membuat Binding Repository di Service Container

Agar repository dapat di-inject ke dalam service, daftarkan binding di AppServiceProvider:

Buka file app/Providers/AppServiceProvider.php dan tambahkan baris berikut di metode register:

use App\\Repositories\\TransactionRepositoryInterface;
use App\\Repositories\\TransactionRepository;

public function register()
{
    $this->app->bind(TransactionRepositoryInterface::class, TransactionRepository::class);
}

Menggunakan Service di Controller

Buat atau update PaymentController untuk memanggil CheckoutService:

<?php

namespace App\\Http\\Controllers;

use App\\Services\\CheckoutService;
use Illuminate\\Http\\Request;

class PaymentController extends Controller
{
    protected $checkoutService;

    public function __construct(CheckoutService $checkoutService)
    {
        $this->checkoutService = $checkoutService;
    }

    public function checkout(Request $request)
    {
        $data = [
            'product_id' => $request->input('product_id'),
            'customer_id' => $request->input('customer_id'),
            'quantity' => $request->input('quantity'),
            'total_price' => $request->input('total_price'),
            'customer_name' => $request->input('name'),
            'customer_email' => $request->input('email'),
            'customer_phone' => $request->input('phone_number'),
        ];

        $result = $this->checkoutService->processCheckout($data);

        return response()->json([
            'snap_token' => $result['snap_token'],
            'transaction' => $result['transaction']
        ]);
    }
}

Menambahkan Route Checkout

Tambahkan route di routes/web.php untuk fitur checkout:

use App\\Http\\Controllers\\PaymentController;

Route::post('/checkout', [PaymentController::class, 'checkout']);

Contoh Payload Permintaan Checkout

Kirimkan data JSON berikut menggunakan Postman atau frontend Anda:

{
    "product_id": 1,
    "customer_id": 1,
    "quantity": 2,
    "total_price": 200000,
    "name": "John Doe",
    "email": "[email protected]",
    "phone_number": "08123456789"
}

Output Snap Token

Jika berhasil, Midtrans akan mengembalikan Snap Token. Respons JSON dari API akan terlihat seperti ini:

{
    "snap_token": "abc123snap-token",
    "transaction": {
        "id": 1,
        "product_id": 1,
        "customer_id": 1,
        "quantity": 2,
        "total_price": 200000,
        "status": "pending",
        "created_at": "2024-06-18T12:00:00",
        "updated_at": "2024-06-18T12:00:00"
    }
}

Penjelasan Akhir

  • Repository Pattern digunakan untuk mengelola query database dengan lebih terstruktur.
  • Service Layer memproses logika bisnis, seperti komunikasi dengan Midtrans dan pembuatan transaksi.
  • Controller hanya bertindak sebagai pemanggil service untuk menjaga kode tetap bersih.

Dengan langkah ini, Anda telah berhasil membuat service repository pattern untuk fitur checkout menggunakan Midtrans dalam proyek Laravel 11.

Mengatur Webhook untuk Memeriksa Status Transaksi di Laravel dan Mengubah Status Transaksi

Webhook digunakan untuk menerima notifikasi dari Midtrans mengenai status transaksi, seperti berhasil (settlement), gagal, atau dibatalkan. Notifikasi ini dikirim oleh Midtrans ke endpoint yang kita tentukan.

Menambahkan Endpoint Webhook di Controller

Buka file PaymentController dan tambahkan metode baru handleWebhook untuk menangani notifikasi dari Midtrans:

<?php

namespace App\\Http\\Controllers;

use Illuminate\\Http\\Request;
use App\\Models\\Transaction;

class PaymentController extends Controller
{
    public function handleWebhook(Request $request)
    {
        // Mengambil konfigurasi Server Key
        $serverKey = config('midtrans.server_key');

        // Validasi signature key dari Midtrans
        $signatureKey = hash("sha512",
            $request->order_id .
            $request->status_code .
            $request->gross_amount .
            $serverKey
        );

        if ($signatureKey !== $request->signature_key) {
            return response()->json(['message' => 'Invalid signature key'], 403);
        }

        // Cek status transaksi
        $transaction = Transaction::find($request->order_id);

        if (!$transaction) {
            return response()->json(['message' => 'Transaction not found'], 404);
        }

        if ($request->transaction_status == 'settlement' || $request->transaction_status == 'capture') {
            $transaction->status = 'paid'; // Status pembayaran berhasil
        } elseif ($request->transaction_status == 'cancel' || $request->transaction_status == 'expire') {
            $transaction->status = 'failed'; // Status pembayaran gagal atau kadaluarsa
        } elseif ($request->transaction_status == 'pending') {
            $transaction->status = 'pending'; // Status menunggu pembayaran
        }

        $transaction->save();

        return response()->json(['message' => 'Webhook processed successfully']);
    }
}

Menambahkan Route untuk Webhook

Tambahkan route baru di routes/web.php untuk menangkap notifikasi webhook dari Midtrans:

use App\\Http\\Controllers\\PaymentController;

Route::post('/midtrans/webhook', [PaymentController::class, 'handleWebhook']);

Mengatur Endpoint Webhook di Dashboard Midtrans

Buka Dashboard Midtrans dan login ke akun Anda.

Masuk ke menu Settings > Configuration.

Di bagian Payment Notification URL, masukkan endpoint yang sudah Anda buat:

<https://your-domain.com/midtrans/webhook>

Simpan konfigurasi tersebut.

Contoh Payload Notifikasi dari Midtrans

Saat Midtrans mengirim notifikasi webhook, payload JSON yang dikirim akan memiliki struktur seperti berikut:

{
    "transaction_status": "settlement",
    "order_id": "1",
    "gross_amount": "200000",
    "signature_key": "valid-signature-key",
    "status_code": "200"
}

Validasi Signature Key

  • Signature key digunakan untuk memverifikasi bahwa notifikasi berasal dari Midtrans.
  • Laravel memvalidasi order_id, status_code, dan gross_amount menggunakan hash sha512 dan mencocokkannya dengan signature key yang dikirimkan.

Status Transaksi yang Dapat Diterima

Midtrans akan mengirim status berikut:

  • pending: Pembayaran menunggu konfirmasi.
  • settlement atau capture: Pembayaran berhasil.
  • cancel atau expire: Pembayaran gagal atau kadaluarsa.

Menguji Webhook Secara Lokal

Jika Anda ingin menguji webhook di server lokal, gunakan ngrok untuk membuat tunnel ke server Anda:

ngrok http 8000

Kemudian gunakan URL ngrok sebagai endpoint webhook di dashboard Midtrans.

Penjelasan Akhir

  1. Midtrans mengirim notifikasi webhook ke endpoint /midtrans/webhook.
  2. Laravel memvalidasi signature key untuk memastikan keaslian notifikasi.
  3. Status transaksi diperiksa dan disimpan ke dalam tabel transactions berdasarkan notifikasi Midtrans.
  4. Jika status transaksi adalah settlement atau capture, maka status di database diubah menjadi paid.

Dengan implementasi ini, status transaksi pada tabel transactions akan selalu diperbarui berdasarkan notifikasi dari Midtrans.

5 Contoh Kesalahan Web Developer Pemula Ketika Mengatur Midtrans yang Dapat Merugikan Perusahaan

Integrasi Midtrans sebagai payment gateway sangat penting untuk memastikan transaksi berjalan lancar dan aman. Namun, web developer pemula sering kali melakukan kesalahan konfigurasi atau implementasi yang berpotensi merugikan perusahaan. Berikut adalah contoh kesalahan umum beserta penjelasan dan kode untuk memperbaikinya:

1. Tidak Memvalidasi Signature Key Midtrans

Kesalahan pertama adalah mengabaikan validasi signature key. Signature key digunakan untuk memastikan bahwa notifikasi webhook berasal dari Midtrans, bukan pihak luar yang mencoba melakukan manipulasi.

Kesalahan Kode:

public function handleWebhook(Request $request)
{
    // Tidak ada validasi signature key
    $transaction = Transaction::find($request->order_id);
    $transaction->status = 'paid';
    $transaction->save();
}

Perbaikan Kode: Pastikan signature key divalidasi sebelum memproses notifikasi webhook.

public function handleWebhook(Request $request)
{
    $serverKey = config('midtrans.server_key');
    $signatureKey = hash("sha512", $request->order_id . $request->status_code . $request->gross_amount . $serverKey);

    if ($signatureKey !== $request->signature_key) {
        return response()->json(['message' => 'Invalid signature key'], 403);
    }

    $transaction = Transaction::find($request->order_id);
    if ($transaction) {
        $transaction->status = 'paid';
        $transaction->save();
    }

    return response()->json(['message' => 'Webhook processed successfully']);
}

2. Tidak Mengatur Status Transaksi untuk Berbagai Kondisi

Web developer pemula sering kali hanya menangani satu kondisi transaksi, seperti success, tetapi mengabaikan kondisi lain seperti pending, expire, atau cancel.

Kesalahan Kode:

$transaction->status = 'paid';
$transaction->save();

Perbaikan Kode: Tangani semua status transaksi yang dikirimkan oleh Midtrans.

if ($request->transaction_status == 'settlement' || $request->transaction_status == 'capture') {
    $transaction->status = 'paid';
} elseif ($request->transaction_status == 'cancel' || $request->transaction_status == 'expire') {
    $transaction->status = 'failed';
} elseif ($request->transaction_status == 'pending') {
    $transaction->status = 'pending';
}
$transaction->save();

3. Tidak Menangani Callback Webhook Secara Aman

Web developer pemula sering kali langsung memproses data webhook tanpa memeriksa keberadaan transaksi di database. Ini berisiko jika order ID yang dikirim Midtrans tidak valid.

Kesalahan Kode:

$transaction = Transaction::find($request->order_id);
$transaction->status = 'paid';
$transaction->save();

Perbaikan Kode: Periksa keberadaan transaksi sebelum memprosesnya.

$transaction = Transaction::find($request->order_id);

if (!$transaction) {
    return response()->json(['message' => 'Transaction not found'], 404);
}

if ($request->transaction_status == 'settlement') {
    $transaction->status = 'paid';
    $transaction->save();
}

4. Tidak Menggunakan HTTPS untuk Webhook Endpoint

Webhook dari Midtrans seharusnya hanya dikirim ke endpoint yang aman menggunakan HTTPS. Developer pemula kadang masih menggunakan HTTP selama deployment ke production.

Kesalahan Kode: Webhook endpoint terdaftar di Midtrans:

<http://yourdomain.com/midtrans/webhook>

Perbaikan Kode: Pastikan endpoint menggunakan HTTPS di Midtrans Dashboard:

<https://yourdomain.com/midtrans/webhook>

5. Menyimpan Data Sensitif di Hardcode atau File Publik

Developer pemula sering kali menyimpan Server Key dan Client Key Midtrans langsung di file kode atau hardcode, sehingga rawan dicuri jika file bocor.

Kesalahan Kode:

Config::$serverKey = 'your-hardcoded-server-key';

Perbaikan Kode: Simpan data sensitif di file .env dan panggil menggunakan konfigurasi Laravel.

File .env:

MIDTRANS_SERVER_KEY=your-server-key
MIDTRANS_CLIENT_KEY=your-client-key

Kode di Service:

Config::$serverKey = config('midtrans.server_key');
Config::$isProduction = config('midtrans.is_production');

Kelima kesalahan ini sering diabaikan oleh web developer pemula, tetapi dapat berdampak serius seperti manipulasi transaksi, kebocoran data, atau kesalahan pembaruan status pembayaran.

Dengan menerapkan validasi yang aman, menangani semua kondisi transaksi, menggunakan HTTPS, dan menyimpan kunci dengan benar, integrasi Midtrans menjadi lebih aman dan andal untuk bisnis online.

Saran untuk Web Developer Pemula: Belajar Laravel Lebih Dalam Bersama Mentor Expert di BuildWithAngga

Bagi web developer pemula yang ingin menguasai framework Laravel secara lebih mendalam, belajar dengan bimbingan mentor expert adalah langkah yang tepat. Salah satu platform yang direkomendasikan adalah BuildWithAngga, di mana Anda bisa mendapatkan pembelajaran yang terstruktur dan berkualitas.

Keuntungan Belajar di BuildWithAngga

  • Akses Materi Seumur Hidup Semua materi belajar yang Anda dapatkan bisa diakses selamanya. Anda tidak perlu khawatir ketinggalan materi karena bisa belajar kapan saja sesuai dengan kecepatan Anda.
  • Bimbingan Langsung dan Konsultasi Karir Bersama mentor berpengalaman, Anda bisa berkonsultasi tentang tantangan yang dihadapi saat belajar Laravel. Selain itu, mentor akan membantu Anda merencanakan karir di industri teknologi agar lebih terarah dan berhasil.
  • Membangun Portfolio Berkualitas Dalam proses pembelajaran, Anda akan dibimbing untuk membangun portfolio proyek nyata yang bisa digunakan untuk melamar pekerjaan. Portfolio ini akan menjadi bukti kemampuan Anda dalam menggunakan Laravel dan dapat meningkatkan peluang bekerja di perusahaan impian.

Dengan belajar Laravel di BuildWithAngga, Anda tidak hanya mendapatkan pemahaman teknis yang mendalam, tetapi juga bekal yang kuat untuk memulai karir sebagai web developer profesional. Jadi, mulailah belajar sekarang dan jadilah developer yang siap bersaing di industri teknologi! 🚀