Allow Paystack fullscreen on Mini payment pages.
Deploy Ladill Mini / deploy (push) Successful in 47s

Patch Inline iframes for fullscreen/payment permissions and advertise a
Permissions-Policy on the public payment landing.
This commit is contained in:
isaacclad
2026-07-21 22:09:51 +00:00
parent 75d201bcae
commit 4291d95518
2 changed files with 48 additions and 1 deletions
@@ -147,6 +147,48 @@
activePopup = null; activePopup = null;
} }
function ensurePaystackIframePermissions(root) {
try {
var nodes = (root || document).querySelectorAll(
'iframe[src*="checkout.paystack.com"], iframe[id^="inline-checkout"], iframe[id^="inline-background"], iframe[src*="paystack"]'
);
nodes.forEach(function (iframe) {
var allow = (iframe.getAttribute('allow') || '').trim();
var needed = ['payment', 'fullscreen', 'clipboard-read', 'clipboard-write'];
var parts = allow ? allow.split(';').map(function (p) { return p.trim(); }).filter(Boolean) : [];
var lower = parts.map(function (p) { return p.toLowerCase(); });
needed.forEach(function (perm) {
if (!lower.some(function (p) { return p === perm || p.indexOf(perm + ' ') === 0; })) {
parts.push(perm);
}
});
iframe.setAttribute('allow', parts.join('; '));
if (!iframe.hasAttribute('allowfullscreen')) {
iframe.setAttribute('allowfullscreen', '');
}
});
} catch (e) {}
}
function watchPaystackIframes() {
if (window.__ladillPaystackIframeWatch) return;
window.__ladillPaystackIframeWatch = true;
ensurePaystackIframePermissions(document);
try {
var obs = new MutationObserver(function (mutations) {
for (var i = 0; i < mutations.length; i++) {
var m = mutations[i];
if (m.addedNodes && m.addedNodes.length) {
ensurePaystackIframePermissions(document);
break;
}
}
});
obs.observe(document.documentElement || document.body, { childList: true, subtree: true });
} catch (e) {}
}
function createStoreDefinition() { function createStoreDefinition() {
return { return {
frameable: false, frameable: false,
@@ -224,10 +266,12 @@
cancelInline(); cancelInline();
var popup = new PaystackPop(); var popup = new PaystackPop();
activePopup = popup; activePopup = popup;
watchPaystackIframes();
popup.resumeTransaction(accessCode, { popup.resumeTransaction(accessCode, {
onLoad: function () { onLoad: function () {
if (token !== store._launchToken) return; if (token !== store._launchToken) return;
store.launching = false; store.launching = false;
ensurePaystackIframePermissions(document);
}, },
onSuccess: function (transaction) { onSuccess: function (transaction) {
if (token !== store._launchToken) return; if (token !== store._launchToken) return;
@@ -283,6 +327,8 @@
ensureStore(); ensureStore();
} }
watchPaystackIframes();
window.LadillPayCheckout = { window.LadillPayCheckout = {
isFrameable: isFrameable, isFrameable: isFrameable,
isPaystackCheckoutUrl: isPaystackCheckoutUrl, isPaystackCheckoutUrl: isPaystackCheckoutUrl,
@@ -384,7 +430,7 @@
:src="showSheet && $store.ladillPayCheckout && $store.ladillPayCheckout.frameable ? checkoutUrl : ''" :src="showSheet && $store.ladillPayCheckout && $store.ladillPayCheckout.frameable ? checkoutUrl : ''"
class="h-full min-h-[60dvh] w-full border-0 md:min-h-0" class="h-full min-h-[60dvh] w-full border-0 md:min-h-0"
style="min-height: 28rem" style="min-height: 28rem"
allow="payment *" allow="payment *; fullscreen *; clipboard-read *; clipboard-write *"
title="{{ $iframeTitle }}"></iframe> title="{{ $iframeTitle }}"></iframe>
<div x-show="!$store.ladillPayCheckout || !$store.ladillPayCheckout.frameable" <div x-show="!$store.ladillPayCheckout || !$store.ladillPayCheckout.frameable"
@@ -17,6 +17,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="csrf-token" content="{{ $csrf }}"> <meta name="csrf-token" content="{{ $csrf }}">
<meta http-equiv="Permissions-Policy" content="payment=(self &quot;https://checkout.paystack.com&quot;), fullscreen=(self &quot;https://checkout.paystack.com&quot;), clipboard-read=(self &quot;https://checkout.paystack.com&quot;), clipboard-write=(self &quot;https://checkout.paystack.com&quot;)">
<title>Pay {{ $businessName }}</title> <title>Pay {{ $businessName }}</title>
<link rel="preconnect" href="https://fonts.bunny.net"> <link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600,700&display=swap" rel="stylesheet" /> <link href="https://fonts.bunny.net/css?family=figtree:400,500,600,700&display=swap" rel="stylesheet" />