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

Category: Laravel
Updated on: 20 Nov, 2024
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.

Download Source Code

Please give your email address. We will send you the source code on your email.