Fix POS payment sheet host and harden Inline launch.
Deploy Ladill POS / deploy (push) Successful in 42s
Deploy Ladill POS / deploy (push) Successful in 42s
Use this.\$store in the host component so the bottomsheet opens, and share the hardened Paystack sheet sync path used across apps.
This commit is contained in:
@@ -5,26 +5,27 @@
|
||||
accessCode: '',
|
||||
returnUrl: '',
|
||||
syncFromStore() {
|
||||
const store = $store.paymentCheckout;
|
||||
const store = this.$store.paymentCheckout;
|
||||
if (!store) return;
|
||||
this.showSheet = !!store.isOpen;
|
||||
this.checkoutUrl = store.url || '';
|
||||
this.accessCode = store.accessCode || '';
|
||||
},
|
||||
init() {
|
||||
// Keep local reactive mirrors so the teleported sheet always re-renders.
|
||||
this.$watch(() => $store.paymentCheckout.isOpen, () => this.syncFromStore());
|
||||
this.$watch(() => $store.paymentCheckout.url, () => this.syncFromStore());
|
||||
this.$watch(() => $store.paymentCheckout.accessCode, () => this.syncFromStore());
|
||||
this.$watch(() => this.$store.paymentCheckout.isOpen, () => this.syncFromStore());
|
||||
this.$watch(() => this.$store.paymentCheckout.url, () => this.syncFromStore());
|
||||
this.$watch(() => this.$store.paymentCheckout.accessCode, () => this.syncFromStore());
|
||||
this.$watch('showSheet', (open) => {
|
||||
if (!open && $store.paymentCheckout.isOpen) {
|
||||
$store.paymentCheckout.close();
|
||||
if (!open && this.$store.paymentCheckout?.isOpen) {
|
||||
this.$store.paymentCheckout.close();
|
||||
}
|
||||
});
|
||||
|
||||
const url = @js(session('checkout_url'));
|
||||
const code = @js(session('access_code'));
|
||||
if (url || code) {
|
||||
$store.paymentCheckout.open(url || '', code || '');
|
||||
this.$store.paymentCheckout.open(url || '', code || '');
|
||||
this.syncFromStore();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
@once
|
||||
<script>
|
||||
(function () {
|
||||
if (window.LadillPayCheckout) return;
|
||||
if (window.__ladillPayCheckoutBootstrapped) return;
|
||||
window.__ladillPayCheckoutBootstrapped = true;
|
||||
|
||||
var INLINE_SRC = 'https://js.paystack.co/v2/inline.js';
|
||||
var inlineLoading = null;
|
||||
@@ -94,6 +95,10 @@
|
||||
inlineLoading = new Promise(function (resolve, reject) {
|
||||
var existing = document.querySelector('script[data-ladill-paystack-inline]');
|
||||
if (existing) {
|
||||
if (window.PaystackPop) {
|
||||
resolve(window.PaystackPop);
|
||||
return;
|
||||
}
|
||||
existing.addEventListener('load', function () { resolve(window.PaystackPop); });
|
||||
existing.addEventListener('error', function () { reject(new Error('Paystack script failed')); });
|
||||
return;
|
||||
@@ -112,6 +117,15 @@
|
||||
return inlineLoading;
|
||||
}
|
||||
|
||||
// Warm the Paystack script early so resumeTransaction is ready on Pay click.
|
||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||
loadInlineJs().catch(function () {});
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
loadInlineJs().catch(function () {});
|
||||
});
|
||||
}
|
||||
|
||||
function buildReturnUrl(returnUrl, reference) {
|
||||
if (!returnUrl || !reference) return '';
|
||||
try {
|
||||
@@ -133,12 +147,8 @@
|
||||
activePopup = null;
|
||||
}
|
||||
|
||||
function ensureStore() {
|
||||
if (!window.Alpine || typeof window.Alpine.store !== 'function') return null;
|
||||
if (window.Alpine.store('ladillPayCheckout')) {
|
||||
return window.Alpine.store('ladillPayCheckout');
|
||||
}
|
||||
window.Alpine.store('ladillPayCheckout', {
|
||||
function createStoreDefinition() {
|
||||
return {
|
||||
frameable: false,
|
||||
inline: false,
|
||||
ready: false,
|
||||
@@ -156,6 +166,10 @@
|
||||
cancelInline();
|
||||
},
|
||||
sync(show, url, accessCode, returnUrl) {
|
||||
url = (url || '').toString();
|
||||
accessCode = (accessCode || '').toString();
|
||||
returnUrl = (returnUrl || '').toString();
|
||||
|
||||
if (!show) {
|
||||
this._launchToken += 1;
|
||||
this.reset();
|
||||
@@ -165,7 +179,8 @@
|
||||
if (!url && !accessCode) {
|
||||
this.frameable = false;
|
||||
this.inline = false;
|
||||
this.launching = false;
|
||||
this.launching = true; // waiting for checkout payload
|
||||
this.error = '';
|
||||
this._activeCode = '';
|
||||
return;
|
||||
}
|
||||
@@ -173,6 +188,7 @@
|
||||
this.frameable = true;
|
||||
this.inline = false;
|
||||
this.launching = false;
|
||||
this.error = '';
|
||||
this._activeCode = '';
|
||||
cancelInline();
|
||||
return;
|
||||
@@ -187,7 +203,7 @@
|
||||
this.launchInline(code, returnUrl);
|
||||
return;
|
||||
}
|
||||
// Never open checkout.paystack.com in an external tab.
|
||||
// Never navigate to checkout.paystack.com (external tab/window).
|
||||
this.frameable = false;
|
||||
this.inline = false;
|
||||
this.launching = false;
|
||||
@@ -222,7 +238,6 @@
|
||||
window.location.assign(dest);
|
||||
return;
|
||||
}
|
||||
// Fallback: reload so server can reconcile via webhook.
|
||||
window.location.reload();
|
||||
},
|
||||
onCancel: function () {
|
||||
@@ -246,25 +261,34 @@
|
||||
store.error = (err && err.message) ? String(err.message) : 'Could not load payment script.';
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function ensureStore() {
|
||||
if (!window.Alpine || typeof window.Alpine.store !== 'function') return null;
|
||||
try {
|
||||
var existing = window.Alpine.store('ladillPayCheckout');
|
||||
if (existing) return existing;
|
||||
} catch (e) {}
|
||||
window.Alpine.store('ladillPayCheckout', createStoreDefinition());
|
||||
return window.Alpine.store('ladillPayCheckout');
|
||||
}
|
||||
|
||||
function onAlpineReady() {
|
||||
document.addEventListener('alpine:init', function () {
|
||||
ensureStore();
|
||||
});
|
||||
|
||||
// If Alpine already started (late include), register immediately.
|
||||
if (window.Alpine && window.Alpine.version) {
|
||||
ensureStore();
|
||||
}
|
||||
|
||||
if (window.Alpine) {
|
||||
onAlpineReady();
|
||||
}
|
||||
document.addEventListener('alpine:init', onAlpineReady);
|
||||
|
||||
window.LadillPayCheckout = {
|
||||
isFrameable: isFrameable,
|
||||
isPaystackCheckoutUrl: isPaystackCheckoutUrl,
|
||||
accessCodeFromUrl: accessCodeFromUrl,
|
||||
resolveAccessCode: resolveAccessCode,
|
||||
prepare: function () { return null; },
|
||||
prepare: function () { loadInlineJs().catch(function () {}); return null; },
|
||||
cancel: function () {
|
||||
cancelInline();
|
||||
var store = ensureStore();
|
||||
@@ -277,31 +301,37 @@
|
||||
</script>
|
||||
@endonce
|
||||
<template x-teleport="body">
|
||||
<div x-show="showSheet"
|
||||
x-cloak
|
||||
data-ladill-pay-sheet
|
||||
x-effect="
|
||||
document.documentElement.style.overflow = showSheet ? 'hidden' : '';
|
||||
if (typeof window.LadillPayCheckout !== 'undefined') {
|
||||
window.LadillPayCheckout.ensureStore();
|
||||
}
|
||||
const store = $store.ladillPayCheckout;
|
||||
if (store) {
|
||||
{{-- No local x-data: inherit showSheet/checkoutUrl/accessCode from the including scope. --}}
|
||||
<div
|
||||
x-init="
|
||||
window.LadillPayCheckout && window.LadillPayCheckout.ensureStore();
|
||||
const runSync = () => {
|
||||
const store = $store.ladillPayCheckout;
|
||||
if (!store) return;
|
||||
store.sync(
|
||||
showSheet,
|
||||
typeof checkoutUrl !== 'undefined' ? checkoutUrl : '',
|
||||
typeof accessCode !== 'undefined' ? accessCode : '',
|
||||
typeof returnUrl !== 'undefined' ? returnUrl : ''
|
||||
!!showSheet,
|
||||
(typeof checkoutUrl === 'undefined' || checkoutUrl === null) ? '' : String(checkoutUrl),
|
||||
(typeof accessCode === 'undefined' || accessCode === null) ? '' : String(accessCode),
|
||||
(typeof returnUrl === 'undefined' || returnUrl === null) ? '' : String(returnUrl)
|
||||
);
|
||||
}
|
||||
"
|
||||
@keydown.escape.window="if (showSheet) showSheet = false"
|
||||
@ladill-pay-cancelled.window="showSheet = false"
|
||||
class="fixed inset-0 z-[9999] flex items-end justify-center md:items-center md:p-6"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
:aria-hidden="(!showSheet).toString()"
|
||||
aria-label="{{ $sheetAria }}">
|
||||
};
|
||||
$watch('showSheet', () => runSync());
|
||||
$watch('checkoutUrl', () => runSync());
|
||||
$watch('accessCode', () => runSync());
|
||||
$watch('returnUrl', () => runSync());
|
||||
$nextTick(() => runSync());
|
||||
"
|
||||
x-show="showSheet"
|
||||
x-cloak
|
||||
data-ladill-pay-sheet
|
||||
x-effect="document.documentElement.style.overflow = showSheet ? 'hidden' : ''"
|
||||
@keydown.escape.window="if (showSheet) showSheet = false"
|
||||
@ladill-pay-cancelled.window="showSheet = false"
|
||||
class="fixed inset-0 z-[9999] flex items-end justify-center md:items-center md:p-6"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
:aria-hidden="(!showSheet).toString()"
|
||||
aria-label="{{ $sheetAria }}">
|
||||
|
||||
<div class="absolute inset-0 bg-black/60"
|
||||
data-ladill-pay-backdrop
|
||||
@@ -361,7 +391,7 @@
|
||||
class="flex min-h-[60dvh] flex-col items-center justify-center gap-4 px-6 py-10 text-center md:min-h-[28rem] md:px-8 md:py-12"
|
||||
data-ladill-pay-inline-status>
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-indigo-50 text-indigo-600" aria-hidden="true">
|
||||
<svg x-show="!$store.ladillPayCheckout || $store.ladillPayCheckout.launching || $store.ladillPayCheckout && !$store.ladillPayCheckout.error && !$store.ladillPayCheckout.inline"
|
||||
<svg x-show="!$store.ladillPayCheckout || $store.ladillPayCheckout.launching || ($store.ladillPayCheckout && !$store.ladillPayCheckout.error && !$store.ladillPayCheckout.inline)"
|
||||
class="h-6 w-6 animate-spin" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
|
||||
@@ -391,7 +421,7 @@
|
||||
<button type="button"
|
||||
data-ladill-pay-retry
|
||||
x-show="$store.ladillPayCheckout && $store.ladillPayCheckout.error"
|
||||
@click="$store.ladillPayCheckout.sync(true, typeof checkoutUrl !== 'undefined' ? checkoutUrl : '', typeof accessCode !== 'undefined' ? accessCode : '', typeof returnUrl !== 'undefined' ? returnUrl : '')"
|
||||
@click="window.LadillPayCheckout?.ensureStore()?.sync(true, (typeof checkoutUrl==='undefined'||checkoutUrl===null)?'':String(checkoutUrl), (typeof accessCode==='undefined'||accessCode===null)?'':String(accessCode), (typeof returnUrl==='undefined'||returnUrl===null)?'':String(returnUrl))"
|
||||
class="inline-flex w-full max-w-xs items-center justify-center rounded-xl bg-indigo-600 px-4 py-3 text-sm font-semibold text-white hover:bg-indigo-700">
|
||||
Try again
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user