How to Integrate Paystack Payment Gateway in Laravel 10 - Part 2

Category: Laravel
Updated on: 22 Jan, 2025
First, you have to install a fresh version of Laravel 10. You can go to the official documentation of Laravel:
You will see a section there: "Creating A Laravel Project". Here you will get your codes to install Laravel 10. I am going to write the commands you will need to install laravel. First, open your terminal where you want to install laravel on your computer. Then use these commands:
composer create-project laravel/laravel paystack
cd paystack
php artisan serve
You can run your application now using this url into your browser: http://127.0.0.1:8000
Now go to this location: resources > views > welcome.blade.php.

Change the codes of this page like this:
welcome.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Laravel - Paystack Integration</title>
</head>
<body>
    <h2>Product: Laptop</h2>
    <h3>Price: 15 NGN</h3>
    <form id="paymentForm">
        <div class="form-submit">
            <button type="submit" onclick="payWithPaystack()">Pay with Paystack</button>
        </div>
    </form>
    <script src="https://js.paystack.co/v1/inline.js"></script>
    <script>
        const paymentForm = document.getElementById('paymentForm');
        paymentForm.addEventListener("submit", payWithPaystack, false);
        function payWithPaystack(e) {
            e.preventDefault();
            let handler = PaystackPop.setup({
                key: "{{ env('PAYSTACK_PUBLIC_KEY') }}",
                email: "codewitharefin@gmail.com",
                amount: 1500,
                metadata: {
                    custom_fields: [
                        {
                            display_name: "Laptop",
                            variable_name: "laptop",
                            value: "Laptop"
                        },
                        {
                            display_name: "Quantity",
                            variable_name: "quantity",
                            value: "1"
                        }
                    ]
                },
                onClose: function(){
                    alert('Window closed.');
                },
                callback: function(response){
                    // let message = 'Payment complete! Reference: ' + response.reference;
                    // alert(message);
                    //alert(JSON.stringify(response));
                    window.location.href = "{{ route('callback') }}" + response.redirecturl;
                }
            });
            handler.openIframe();
        }
    </script>
</body>
</html>
Create a migration file using this command:
php artisan make:migration create_payments_table
A migration file will be created in this location: "database > migrations > 2023_11_30_031735_create_payments_table.php"

Now write the following code here:
2023_11_30_031735_create_payments_table.php
<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('payments', function (Blueprint $table) {
            $table->id();
            $table->string('payment_id');
            $table->string('product_name');
            $table->string('quantity');
            $table->string('amount');
            $table->string('currency');
            $table->string('payment_status');
            $table->string('payment_method');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('payments');
    }
};
Write this command to create the "payments" table.
php artisan migrate
You have to create a model now. The model name will be the singular form of the table name. So it will be "Payment". Run this command in the terminal to create this model:
php artisan make:model Payment
I am going to create a controller now. So run this command in terminal:
php artisan make:controller PaystackController
Modify the "route > web.php" file as this:
web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PaystackController;

Route::get('/', function () {
    return view('welcome');
});

Route::get('callback', [PaystackController::class, 'callback'])->name('callback');
Route::get('success', [PaystackController::class, 'success'])->name('success');
Route::get('cancel', [PaystackController::class, 'cancel'])->name('cancel');
Now add this line in the .env file:
PAYSTACK_PUBLIC_KEY=pk_test_e8d220b7463d64569f0053e78534f38e6b10cf4a
PAYSTACK_SECRET_KEY=sk_test_6d62cb976e1e0ab43f1e48b2934b0dfc7f32a1fe
PaystackController.php
<?php

namespace App\Http\Controllers;

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

class PaystackController extends Controller
{
    public function callback(Request $request)
    {
        //dd($request->all());
        $reference = $request->reference;
        $secret_key = env('PAYSTACK_SECRET_KEY');
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => "https://api.paystack.co/transaction/verify/".$reference,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_HTTPHEADER => array(
                "Authorization: Bearer $secret_key",
                "Cache-Control: no-cache",
            ),
        ));
        $response = curl_exec($curl);
        curl_close($curl);
        $response = json_decode($response);
        //dd($response);
        $meta_data = $response->data->metadata->custom_fields;
        if($response->data->status == 'success')
        {
            $obj = new Payment;
            $obj->payment_id = $reference;
            $obj->product_name = $meta_data[0]->value;
            $obj->quantity = $meta_data[1]->value;
            $obj->amount = $response->data->amount / 100;
            $obj->currency = $response->data->currency;
            $obj->payment_status = "Completed";
            $obj->payment_method = "Paystack";
            $obj->save();
            return redirect()->route('success');
        } else {
            return redirect()->route('cancel');
        }
    }

    public function success()
    {
        return "Payment is successful";
    }
    public function cancel()
    {
        return "Payment is cancelled";
    }
}

See Full Tutorial on YouTube

If you want to see the full functionality in live, you can see my video on youtube.