How to implement square payment gateway in laravel?

This guide provides a step-by-step process on how to integrate the Square payment gateway into a PHP or a Laravel application without using a package, I prefer to use laravel but this process will work in PHP aswell.

Note : We will be using Checkout API

Step 1 : Create a controller.

To create a controller use the command below.

php artisan make:controller SquareController
Step 2 : Create a function for idempotency key.

In the Square payment gateway, an idempotency key is a unique string that is provided by API operations to protect against accidental duplicate calls. This key ensures that only one operation will be processed, regardless of how many times the same request is sent.


So we will create a function in SquareController.php

//SquareController.php
public function generateIdempotencyKey()
{
    $idempotency_key = str_random(8) . '-' . str_random(4) . '-' . str_random(4) . '-' . str_random(4) . '-' . time().str_random(2);
    return $idempotency_key;
}
Step 3 : Create a payment form.

Now we will create a payment form so you can ask user for the detials and conformation you need, So first lets create a route in web.php

Route::get('square-payment-form', [\App\Http\Controllers\SquareController::class, 'index'])->name('square.index');

Now create a function named index in SquareController.php

public function index()
{
    return view('square.payment-form');
}

Now create a payment form so you can get the required fields you need from users, 


resources/views/square/payment-form.blade.php 


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Square Payment Gateway</title>

    <!-- BOOTSTRAP -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />

    <!-- Styles -->
    <style>
        body {
            background: #f7f7f7;
        }

        .form-box {
            max-width: 500px;
            margin: auto;
            padding: 50px;
            background: #ffffff;
            border: 10px solid #f2f2f2;
            margin-top: 100px;
        }

        h1, p {
            text-align: center;
        }

        input, textarea {
            width: 100%;
        }
    </style>
</head>
<body>
<div class="form-box">
    <h1>Pay with Square</h1>
    <form action="{{ route('pay-with-square') }}" method="post">
        @csrf
        <div class="form-group">
            <label for="product_name">Product Name</label>
            <input class="form-control" id="product_name" type="text" name="product_name">
        </div>
        <div class="form-group">
            <label for="quantity">Quantity</label>
            <input class="form-control" id="quantity" type="number" name="quantity">
        </div>
        <div class="form-group">
            <label for="amount">Amount</label>
            <input class="form-control" id="amount" type="number" name="amount">
        </div>
        <input class="btn btn-primary" type="submit" value="Submit" />
    </form>
</div>
</body>
</html>
Step 4 : Create payment function.

Now we will create a checkout payment function and callback function, So first lets create callback and payment processing route in web.php

//PAYMENT ROUTE
Route::post('pay-with-square', [\App\Http\Controllers\SquareController::class, 'payWithSquare'])->name('pay-with-square');
//CALLBACK ROUTE
Route::get('square-callback', [\App\Http\Controllers\SquareController::class, 'callback'])->name('square-callback');

Now create a function named payWithSquare in SquareController.php

public function checkoutCo(Request $request)
{
    $sandbox = true;
    $apiVersion = '2023-09-25';
    $locationID = 'L8XDMNB******';
    $currency = 'USD';

    $afterpay_clearpay = false;
    $apple_pay = false;
    $cash_app_pay = false;
    $google_pay = true;

    $callback_url = route('square-callback');

    $accessToken = 'EAAAELDmSbCSKJ1lNUF2wYgSaGZSFRwj***************************';
    if($sandbox)
    {
        //SANDBOX API ENDPOINT
        $chUrl = 'https://connect.squareupsandbox.com/v2/locations/'.$locationID.'/checkouts';
    }
    else
    {
        //PRODUCTION API ENDPOINT
        $chUrl = 'https://connect.squareup.com/v2/locations/'.$locationID.'/checkouts';
    }

    $postValues = [];
    $postValues['idempotency_key'] = $this->generateIdempotencyKey();
    $postValues['checkout_page_url'] = $callback_url;
    $postValues['redirect_url'] = $callback_url;

    $postValues['order'] = [
        'idempotency_key' => $this->generateIdempotencyKey(),
        'order' => [
            'location_id' => $locationID,
            'line_items' => [
                [
                    'name' => $request->product_name,
                    'quantity' => $request->quantity,
                    'base_price_money' => [
                        'amount' => $request->amount * 100,
                        'currency' => $currency
                    ],
                ]
            ],
        ],
    ];

    $postValues['checkout_options'] = [
        'accepted_payment_methods' =>
            [
                'afterpay_clearpay' => $afterpay_clearpay,
                'apple_pay' => $apple_pay,
                'cash_app_pay' => $cash_app_pay,
                'google_pay' => $google_pay,
            ],
        'redirect_url' => $callback_url
    ];

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $chUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postValues));

    $headers = [];
    $headers[] = 'Square-Version: '.$apiVersion;
    $headers[] = 'Authorization: Bearer '.$accessToken;
    $headers[] = 'Content-Type: application/json';

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $result = curl_exec($ch);
    $err = curl_errno($ch);

    if ($err)
    {
        //HANDLE YOUR ERROR MESSAGE HERE
        $errorMessage = curl_error($ch);
        dd('ERROR : ' . $errorMessage);
    }

    curl_close($ch);

    $response = json_decode($result,true);

    if(isset($response['checkout']['checkout_page_url']))
    {
        //REDIRECT TO SQUARE HOSTED CHECKOUT PAGE
        return redirect($response['checkout']['checkout_page_url']);
    }
    else
    {
        //HANDLE YOUR ERROR MESSAGE HERE
        dd('ERROR : ' . $response);
    }
}

Square Checkout Page


Step 5 : Callback Function.

Now create a function named callback in SquareController.php, In this function you will receive checkoutId and transactionId

Note : You will receive data in GET Method

public function callback(Request $request)
{
     //$request['checkoutId'] , $request['transactionId']
    dd($request->all());
    //Transaction completed, You can add transaction details into database
}