Keep Mini QR Paystack checkout fully in-app.
Stop form POSTs from 307ing to ladl.link or redirecting away to checkout.paystack.com, open Paystack Inline with access_code, and use the single-chrome sheet so payment stays on the Mini page.
This commit is contained in:
+38
-13
@@ -201,6 +201,17 @@ Alpine.data('miniPaymentLanding', (config = {}) => ({
|
||||
}
|
||||
|
||||
this._syncSheet();
|
||||
|
||||
// Non-JS form POST fallback flashes checkout payload — open Inline in-page.
|
||||
if (config.bootstrapCheckoutUrl || config.bootstrapAccessCode) {
|
||||
this.openInlineCheckout({
|
||||
checkout_url: config.bootstrapCheckoutUrl || '',
|
||||
access_code: config.bootstrapAccessCode || '',
|
||||
public_key: config.bootstrapPublicKey || '',
|
||||
callback_url: config.bootstrapCallbackUrl || '',
|
||||
provider: config.bootstrapProvider || 'paystack',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
destroy() {
|
||||
@@ -211,6 +222,30 @@ Alpine.data('miniPaymentLanding', (config = {}) => ({
|
||||
document.documentElement.classList.remove('mini-payment-page');
|
||||
},
|
||||
|
||||
isSameOrigin(url) {
|
||||
if (!url) return false;
|
||||
try {
|
||||
return new URL(url, window.location.href).origin === window.location.origin;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
openInlineCheckout(data = {}) {
|
||||
// Never navigate to checkout.paystack.com. Same-origin MoMo waiting can navigate.
|
||||
if (data.provider === 'mtn_momo' && this.isSameOrigin(data.checkout_url)) {
|
||||
window.location.assign(data.checkout_url);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.checkoutUrl = data.checkout_url || '';
|
||||
this.accessCode = data.access_code || '';
|
||||
this.publicKey = data.public_key || '';
|
||||
this.returnUrl = data.callback_url || '';
|
||||
this.showSheet = true;
|
||||
return true;
|
||||
},
|
||||
|
||||
async submitPay() {
|
||||
const value = parseFloat(this.amount);
|
||||
if (!value || value <= 0) {
|
||||
@@ -224,8 +259,8 @@ Alpine.data('miniPaymentLanding', (config = {}) => ({
|
||||
this.accessCode = '';
|
||||
this.publicKey = '';
|
||||
this.returnUrl = '';
|
||||
// Show sheet/modal immediately; Paystack Inline opens in-page from the sheet.
|
||||
this.showSheet = true;
|
||||
// Keep sheet closed until we have a checkout payload so Inline syncs once with access_code.
|
||||
this.showSheet = false;
|
||||
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), 45000);
|
||||
@@ -257,17 +292,7 @@ Alpine.data('miniPaymentLanding', (config = {}) => ({
|
||||
return;
|
||||
}
|
||||
|
||||
// Legacy MoMo waiting page must be full-page — never trap it in the Paystack iframe
|
||||
// (cross-origin iframe is blank / looks like "Pay did nothing").
|
||||
const useSheet = data.provider !== 'mtn_momo';
|
||||
if (useSheet) {
|
||||
this.checkoutUrl = data.checkout_url || '';
|
||||
this.accessCode = data.access_code || '';
|
||||
this.publicKey = data.public_key || '';
|
||||
this.returnUrl = data.callback_url || '';
|
||||
} else {
|
||||
this.showSheet = false;
|
||||
window.location.assign(data.checkout_url);
|
||||
if (!this.openInlineCheckout(data)) {
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user