Laravel SDK
Official Laravel integration package for Royat Pay
Overview
The Royat Pay Laravel SDK lets Laravel stores connect to Royat Pay using a simple PHP interface. The store only needs its Royat Pay client token from the dashboard.
Do not use the central payment provider token inside customer stores.
Keep the central integration token inside Royat Pay only. The Laravel store should use its Royat Pay client token. Royat Pay will apply the settlement account configured for that client.
Installation
The package source is available in the Royat Pay repository under:
packages/royat-pay-laravel
For a Laravel store, add the package repository to composer.json:
{
"repositories": [
{
"type": "path",
"url": "packages/royat-pay-laravel"
}
]
}
Then install the package:
composer require royatsa/royat-pay-laravel
For external customer stores, publish this SDK as its own private Composer repository first.
After that, the same composer require command can install it directly.
Configuration
Publish the configuration file:
php artisan vendor:publish --tag=royat-pay-config
Add the Royat Pay client token to the store .env file:
ROYAT_PAY_BASE_URL=https://panel.royat.sa
ROYAT_PAY_TOKEN=your_client_token
ROYAT_PAY_TIMEOUT=30
Embedded Checkout
Use Embedded Checkout when you want the customer to pay inside your Laravel store page without being redirected to an external hosted checkout page.
Recommended for Laravel stores: Create a session, render the Royat Pay embedded widget, then verify the session server-side once the widget calls back.
1. Create the checkout page
use Royat\Pay\Facades\RoyatPay;
public function checkout(Order $order)
{
$session = RoyatPay::createSession([
'InvoiceValue' => $order->total,
'CurrencyIso' => 'SAR',
'CustomerName' => $order->customer_name,
'CustomerMobile' => $order->customer_mobile,
'CustomerReference' => (string) $order->id,
'CallbackUrl' => route('payments.callback', $order),
'ErrorUrl' => route('payments.failed', $order),
]);
return view('checkout.payment', [
'order' => $order,
'sessionId' => $session['Data']['SessionId'],
]);
}
2. Render Royat Pay on the same page
Load MyFatoorah's session widget directly — not royatpay.js, which loads the
older, deprecated widget and is incompatible with a v3 SessionId.
<div id="royat-pay-embedded"></div>
<script src="https://sa.myfatoorah.com/sessions/v1/session.js"></script>
<script>
const sessionId = "{{ $sessionId }}";
function completePayment(response) {
if (response && response.isSuccess === false) {
alert('Payment was not completed. Please try again.');
return;
}
fetch("{{ route('payments.verify', $order) }}", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": "{{ csrf_token() }}"
},
body: JSON.stringify({ session_id: sessionId })
})
.then((res) => res.json())
.then((result) => {
if (result.redirect) window.location.href = result.redirect;
});
}
const mf = window.myfatoorah || window.myFatoorah || window.MyFatoorah;
mf.init({
sessionId: sessionId,
containerId: "royat-pay-embedded",
shouldHandlePaymentUrl: true,
callback: completePayment,
});
</script>
Do not add countryCode, currencyCode, amount,
paymentOptions, or supportedNetworks to mf.init() — this widget
doesn't recognize them and can reject the session outright. It reads the amount/currency from the
session and shows every payment method enabled on your account (including Apple Pay and mada)
automatically.
3. Verify and complete the order from the backend
use Illuminate\Http\Request;
use Royat\Pay\Facades\RoyatPay;
public function verify(Request $request, Order $order)
{
$request->validate([
'session_id' => ['required', 'string'],
]);
$details = RoyatPay::sessionDetails($request->string('session_id')->toString());
$invoice = $details['Data']['TransactionResult']['Invoice'] ?? [];
$reference = (string) ($details['Data']['Customer']['Reference'] ?? '');
$paid = ($invoice['Status'] ?? null) === 'Paid'
&& ($reference === '' || $reference === (string) $order->id)
&& (float) ($invoice['Value'] ?? 0) >= (float) $order->total - 0.01;
if (! $paid) {
return response()->json(['success' => false], 422);
}
$order->markPaid((string) $invoice['Id']); // your own order-completion logic
return response()->json(['success' => true, 'redirect' => route('orders.show', $order)]);
}
Always verify with sessionDetails() before marking an order paid — the widget's
callback runs in the customer's browser and must never be trusted on its own.
Hosted Checkout
Use Hosted Checkout only if you want to redirect the customer to a hosted payment page. This is the flow that opens an external checkout page before returning to your store.
use Royat\Pay\Facades\RoyatPay;
$payment = RoyatPay::executePayment([
'InvoiceValue' => 100,
'CurrencyIso' => 'SAR',
'PaymentMethodId' => 2,
'CustomerName' => 'Customer Name',
'CustomerEmail' => '[email protected]',
'CustomerMobile' => '500000000',
'CustomerReference' => 'ORDER-1001',
'CallBackUrl' => route('payments.callback'),
'ErrorUrl' => route('payments.failed'),
]);
return redirect($payment['Data']['PaymentURL']);
Check Payment Status
Use this in your callback route to verify the payment result:
use Royat\Pay\Facades\RoyatPay;
$status = RoyatPay::paymentStatus(request('PaymentId'));
if (($status['Data']['InvoiceStatus'] ?? null) === 'Paid') {
// Mark the order as paid.
}
Available Payment Methods
use Royat\Pay\Facades\RoyatPay;
$methods = RoyatPay::initiatePayment(100, 'SAR');
Refund
use Royat\Pay\Facades\RoyatPay;
$refund = RoyatPay::refund([
'Key' => '123456789',
'KeyType' => 'PaymentId',
'ServiceChargeOnCustomer' => false,
'Amount' => 25,
'Comment' => 'Customer refund',
]);
Supplier Invoices
The SDK can also read the authenticated client's invoice list:
use Royat\Pay\Facades\RoyatPay;
$invoices = RoyatPay::supplierInvoices([
'from' => '2026-06-01',
'to' => '2026-06-30',
]);
Main Account Settlement
If your own Laravel store should settle to the main Royat account, keep the settlement code configured as 0
on that client inside the Royat Pay admin panel. The store still uses the Royat Pay client token only.