Embed POS checkouts in a modal/sheet using the seller email.
Deploy Ladill POS / deploy (push) Successful in 40s

Card/MoMo always initializes with the merchant email, and Paystack/Flutterwave/Hubtel open in-page (desktop modal, mobile bottomsheet) instead of a full redirect.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-15 08:29:07 +00:00
co-authored by Cursor
parent 3ea9fdfe33
commit 3c0172f098
10 changed files with 230 additions and 35 deletions
+30 -7
View File
@@ -227,30 +227,53 @@ class TicketController extends Controller
$result = $this->sales->startPayPayment($sale, $merchant, $amountMinor);
return redirect()->away($result['checkout_url']);
if ($request->expectsJson() || $request->ajax()) {
return response()->json([
'checkout_url' => $result['checkout_url'],
'sale_id' => $sale->id,
]);
}
return redirect()
->route('pos.tickets.show', $sale)
->with('checkout_url', $result['checkout_url'])
->with('success', 'Complete the payment to settle this ticket.');
} catch (RuntimeException $e) {
return back()->with('error', $e->getMessage());
}
}
public function paymentCallback(Request $request): RedirectResponse
public function paymentCallback(Request $request): RedirectResponse|View
{
$reference = trim((string) $request->query('reference', ''));
if ($reference === '') {
return redirect()->route('pos.floor')->with('error', 'Missing payment reference.');
return view('pos.payment-return', [
'redirect' => route('pos.floor'),
]);
}
try {
$payment = $this->sales->completePayPayment($reference);
} catch (\Throwable) {
return redirect()->route('pos.floor')->with('error', 'Payment could not be verified.');
session()->flash('error', 'Payment could not be verified.');
return view('pos.payment-return', [
'redirect' => route('pos.floor'),
]);
}
$sale = $payment->sale->fresh();
if ($sale->isOpen()) {
session()->flash('success', 'Payment recorded — balance '.$sale->currency.' '.number_format($sale->balanceMinor() / 100, 2));
$url = route('pos.tickets.show', $sale);
} else {
session()->flash('success', 'Ticket settled.');
$url = route('pos.sales.show', $sale);
}
return $sale->isOpen()
? redirect()->route('pos.tickets.show', $sale)->with('success', 'Payment received — balance remaining.')
: redirect()->route('pos.sales.show', $sale)->with('success', 'Payment received.');
return view('pos.payment-return', [
'redirect' => $url,
]);
}
private function authorizeOpen(Request $request, PosSale $sale): void