Files
ladill-merchant/app/Http/Controllers/Public/BookingController.php
T
isaacclad b737725be4
Deploy Ladill Merchant / deploy (push) Successful in 1m46s
Restore Paystack Inline in-page sheet/modal; stop separate-browser checkout.
Pass access_code through pay responses and launch PaystackPop from the shared sheet instead of window.open.
2026-07-21 19:12:24 +00:00

119 lines
3.7 KiB
PHP

<?php
namespace App\Http\Controllers\Public;
use App\Http\Controllers\Controller;
use App\Models\QrCode;
use App\Services\Merchant\BookingSlotService;
use App\Services\Merchant\MerchantSaleService;
use App\Support\LadillLink;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use RuntimeException;
class BookingController extends Controller
{
public function __construct(
private BookingSlotService $slots,
private MerchantSaleService $sales,
) {}
public function slots(Request $request, string $shortCode): JsonResponse
{
$qrCode = $this->resolveBookingQr($shortCode);
$validated = $request->validate([
'date' => ['required', 'date', 'after_or_equal:today'],
'service_index' => ['required', 'integer', 'min:0'],
]);
return response()->json([
'slots' => $this->slots->availableSlots(
$qrCode,
$validated['date'],
(int) $validated['service_index'],
),
]);
}
public function store(Request $request, string $shortCode): JsonResponse
{
$qrCode = $this->resolveBookingQr($shortCode);
$validated = $request->validate([
'customer_name' => ['required', 'string', 'max:120'],
'customer_email' => ['nullable', 'email', 'max:200'],
'customer_phone' => ['required', 'string', 'max:30'],
'service_index' => ['required', 'integer', 'min:0'],
'starts_at' => ['required', 'date'],
]);
try {
$result = $this->sales->initiateBooking($qrCode, $validated);
} catch (RuntimeException $e) {
return response()->json(['error' => $e->getMessage()], 422);
}
if ($result['checkout_url']) {
return response()->json([
'checkout_url' => $result['checkout_url'],
'access_code' => $result['access_code'] ?? null,
'public_key' => $result['public_key'] ?? null,
'callback_url' => $result['callback_url'] ?? null,
'callback_url' => $result['callback_url'],
]);
}
return response()->json([
'confirmed' => true,
'redirect_url' => LadillLink::path($shortCode, 'booking/confirmed/'.$result['booking']->id),
]);
}
public function callback(Request $request, string $shortCode): View
{
$reference = trim((string) $request->query('reference', ''));
if ($reference === '') {
return view('public.payment-return', [
'redirect' => LadillLink::url($shortCode),
]);
}
try {
$booking = $this->sales->completeBooking($reference);
} catch (\Throwable) {
return view('public.payment-return', [
'redirect' => LadillLink::url($shortCode),
]);
}
return view('public.payment-return', [
'redirect' => LadillLink::path($shortCode, 'booking/confirmed/'.$booking->id),
]);
}
public function confirmed(string $shortCode, int $booking): View
{
$qrCode = $this->resolveBookingQr($shortCode);
$record = $qrCode->bookings()->whereKey($booking)->firstOrFail();
return view('public.qr.booking-confirmed', [
'qrCode' => $qrCode,
'booking' => $record,
]);
}
private function resolveBookingQr(string $shortCode): QrCode
{
$qrCode = QrCode::query()
->where('short_code', $shortCode)
->where('is_active', true)
->firstOrFail();
abort_unless($qrCode->isBookingType(), 404);
return $qrCode;
}
}