qrCodes() ->where('type', QrCode::TYPE_PAYMENT) ->latest() ->get(); $previewDataUris = $qrCodes->mapWithKeys(function (QrCode $qr) { return [$qr->id => $this->imageGenerator->previewDataUri($qr)]; }); $wallet = $this->manager->walletFor($account); return view('mini.payment-qrs.index', [ 'qrCodes' => $qrCodes, 'previewDataUris' => $previewDataUris, 'wallet' => $wallet, 'activeCount' => $qrCodes->where('is_active', true)->count(), 'pricePerQr' => QrWallet::pricePerQr(), 'topupUrl' => 'https://'.config('app.account_domain').'/wallet', ]); } public function create(): View { return view('mini.payment-qrs.create'); } public function store(Request $request): RedirectResponse { $account = ladill_account(); $data = $request->validate([ 'label' => 'required|string|max:120', 'business_name' => 'required|string|max:120', 'branch_label' => 'nullable|string|max:80', ]); $data['type'] = QrCode::TYPE_PAYMENT; $data['currency'] = 'GHS'; try { $qrCode = $this->manager->create($account, $data); } catch (RuntimeException $e) { return back()->withInput()->with('error', $e->getMessage()); } return redirect()->route('mini.payment-qrs.show', $qrCode)->with('success', 'Payment QR created.'); } public function show(QrCode $paymentQr): View { $this->authorizePaymentQr($paymentQr); $previewDataUri = $this->imageGenerator->previewDataUri($paymentQr); return view('mini.payment-qrs.show', [ 'qrCode' => $paymentQr->fresh(), 'previewDataUri' => $previewDataUri, ]); } public function update(Request $request, QrCode $paymentQr): RedirectResponse { $this->authorizePaymentQr($paymentQr); $data = $request->validate([ 'label' => 'sometimes|string|max:120', 'business_name' => 'sometimes|string|max:120', 'branch_label' => 'nullable|string|max:80', 'is_active' => 'sometimes|boolean', ]); $data['is_active'] = $request->boolean('is_active', $paymentQr->is_active); try { $this->manager->update($paymentQr, $data); } catch (RuntimeException $e) { return back()->withInput()->with('error', $e->getMessage()); } return back()->with('success', 'Payment QR updated.'); } public function destroy(QrCode $paymentQr): RedirectResponse { $this->authorizePaymentQr($paymentQr); $this->manager->delete($paymentQr); return redirect() ->route('mini.payment-qrs.index') ->with('success', 'Payment QR deleted.'); } public function preview(QrCode $paymentQr): Response { $this->authorizePaymentQr($paymentQr); $qrCode = $this->imageGenerator->ensureValidImages($paymentQr); $bytes = $this->imageGenerator->normalizeStoredPng($qrCode->png_path); if ($bytes === null) { $bytes = $this->imageGenerator->renderPng($qrCode->encodedPayload(), $qrCode->style()); $this->imageGenerator->generateAndStore($qrCode); } return response($bytes, 200, [ 'Content-Type' => 'image/png', 'Cache-Control' => 'private, max-age=3600', ]); } public function download(QrCode $paymentQr, string $format): StreamedResponse { $this->authorizePaymentQr($paymentQr); $qrCode = $this->imageGenerator->ensureValidImages($paymentQr); $path = $format === 'svg' ? $qrCode->svg_path : $qrCode->png_path; $filename = Str::slug($qrCode->label).'-qr.'.($format === 'svg' ? 'svg' : 'png'); if ($format === 'png') { $bytes = $this->imageGenerator->normalizeStoredPng($path); if ($bytes === null) { $bytes = $this->imageGenerator->renderPng($qrCode->encodedPayload(), $qrCode->style()); $this->imageGenerator->generateAndStore($qrCode); } return response()->streamDownload(fn () => print($bytes), $filename, [ 'Content-Type' => 'image/png', ]); } if ($format === 'pdf') { $bytes = $this->imageGenerator->normalizeStoredPng($qrCode->png_path); if ($bytes === null) { $bytes = $this->imageGenerator->renderPng($qrCode->encodedPayload(), $qrCode->style()); $this->imageGenerator->generateAndStore($qrCode); } $pdf = $this->pdfExporter->fromPng($bytes, $qrCode->label); $filename = Str::slug($qrCode->label).'-qr.pdf'; return response()->streamDownload(fn () => print($pdf), $filename, [ 'Content-Type' => 'application/pdf', ]); } abort_unless($path && Storage::disk('qr')->exists($path), 404); return Storage::disk('qr')->download($path, $filename); } private function authorizePaymentQr(QrCode $paymentQr): void { abort_unless($paymentQr->type === QrCode::TYPE_PAYMENT, 404); abort_unless($paymentQr->user_id === ladill_account()->id, 403); } }