where('short_code', $shortCode) ->whereIn('type', QrTypeCatalog::storefrontTypes()) ->where('is_active', true) ->firstOrFail(); if (! $qrCode->acceptsOrders()) { return response()->json(['error' => 'This QR code does not accept orders.'], 422); } if (empty($qrCode->content()['accepts_payment'])) { return response()->json(['error' => 'Online payments are not enabled for this storefront.'], 422); } $validated = $request->validate([ 'customer_name' => ['required', 'string', 'max:120'], 'customer_email' => ['nullable', 'email', 'max:200'], 'customer_phone' => ['required', 'string', 'max:30'], 'shipping_fee' => ['nullable', 'numeric', 'min:0', 'max:10000'], 'items' => ['required', 'array', 'min:1'], 'items.*.name' => ['required', 'string', 'max:200'], 'items.*.price' => ['required', 'numeric', 'min:0'], 'items.*.qty' => ['required', 'integer', 'min:1', 'max:100'], ]); try { $result = $this->sales->initiateOrder($qrCode, $validated); } catch (RuntimeException $e) { return response()->json(['error' => $e->getMessage()], 422); } return response()->json([ 'checkout_url' => $result['checkout_url'], 'callback_url' => $result['callback_url'], ]); } public function callback(Request $request, string $shortCode): RedirectResponse|View { $reference = trim((string) $request->query('reference', '')); if ($reference === '') { return redirect('/q/'.$shortCode)->with('error', 'Missing payment reference.'); } try { $order = $this->sales->completeOrder($reference); } catch (\Throwable) { return redirect('/q/'.$shortCode)->with('order_error', 'Payment could not be verified. Contact the merchant with reference: '.$reference); } return view('public.qr.order-success', [ 'order' => $order, 'qrCode' => $order->qrCode, ]); } }