- QrCodeService: generate unique 48-char token, create QR PNG (400x400, error-correction H) - QrCodeController: show, generate, download PNG, deactivate - Admin QR page: preview, copy URL, download, regenerate, deactivate - Existing active QR deactivated on regenerate - Token-based URL (not program ID) for PDPA compliance Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
52 lines
1.4 KiB
PHP
52 lines
1.4 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\Program;
|
||
use App\Models\ProgramQrCode;
|
||
use Illuminate\Support\Facades\Storage;
|
||
use Illuminate\Support\Str;
|
||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||
|
||
class QrCodeService
|
||
{
|
||
public function generateForProgram(Program $program): ProgramQrCode
|
||
{
|
||
// Deactivate existing active QR codes
|
||
$program->qrCodes()->where('is_active', true)->update(['is_active' => false]);
|
||
|
||
$token = Str::random(48);
|
||
$url = route('public.checkin.show', $token);
|
||
$path = 'public/qrcodes/' . $token . '.png';
|
||
$absPath = Storage::path($path);
|
||
|
||
// Ensure directory exists
|
||
Storage::makeDirectory('public/qrcodes');
|
||
|
||
// Generate QR code PNG (400×400, with quiet zone)
|
||
$png = QrCode::format('png')
|
||
->size(400)
|
||
->margin(2)
|
||
->errorCorrection('H')
|
||
->generate($url);
|
||
|
||
Storage::put($path, $png);
|
||
|
||
return $program->qrCodes()->create([
|
||
'token' => $token,
|
||
'qr_image_path' => $path,
|
||
'is_active' => true,
|
||
]);
|
||
}
|
||
|
||
public function getPublicUrl(ProgramQrCode $qrCode): string
|
||
{
|
||
return Storage::url($qrCode->qr_image_path);
|
||
}
|
||
|
||
public function getRawPng(ProgramQrCode $qrCode): string
|
||
{
|
||
return Storage::get($qrCode->qr_image_path);
|
||
}
|
||
}
|