fix: Use base64-encoded PNG for QR code in PDF stickers

DomPDF renders embedded PNG images more reliably than inline SVG.
Changed QR code generation to OUTPUT_IMAGE_PNG with base64 encoding,
then embed as img tag in the PDF HTML.
This commit is contained in:
twotalesanimation
2026-01-02 20:42:19 +02:00
parent 09198a9f7d
commit 5dfb63dacb
2 changed files with 108 additions and 31 deletions
+25 -31
View File
@@ -85,16 +85,16 @@ class QrStickerService
*/
private function generatePdf(Order $order, string $qrUrl): string
{
// Generate inline QR code as SVG
// Generate QR code as base64-encoded PNG (DomPDF handles this better than SVG)
$options = new QROptions([
'outputType' => QRCode::OUTPUT_MARKUP_SVG,
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
'eccLevel' => QRCode::ECC_H,
'scale' => 4,
'imageBase64' => false,
'scale' => 8,
'imageBase64' => true,
]);
$qrCode = new QRCode($options);
$qrSvg = $qrCode->render($qrUrl);
$qrBase64 = $qrCode->render($qrUrl);
// Determine order type
$orderType = $order->type === 'standard' ? 'STOCK ORDER' : 'CUSTOM ORDER';
@@ -111,15 +111,14 @@ class QrStickerService
$nameParts = explode(' ', trim($customerName));
$customerSurname = end($nameParts);
// Build HTML directly (no view file dependency)
$html = <<<HTML
<!DOCTYPE html>
// Build HTML with proper SVG embedding (avoid heredoc issues)
$html = '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: Arial, sans-serif; }
body { font-family: Arial, sans-serif; margin: 0; padding: 0; }
.sticker {
width: 148mm;
height: 105mm;
@@ -127,6 +126,7 @@ class QrStickerService
flex-direction: column;
padding: 5mm;
background: white;
page-break-after: avoid;
}
.container {
display: flex;
@@ -141,10 +141,11 @@ class QrStickerService
overflow: hidden;
}
.qr-section {
width: 55mm;
width: 50mm;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.header {
border-bottom: 1pt solid #ddd;
@@ -207,12 +208,8 @@ class QrStickerService
.qr-code {
width: 50mm;
height: 50mm;
display: flex;
align-items: center;
justify-content: center;
background: white;
}
.qr-code svg {
.qr-code img {
width: 100%;
height: 100%;
}
@@ -222,7 +219,6 @@ class QrStickerService
text-align: center;
border-top: 0.5pt solid #eee;
padding-top: 1mm;
margin-top: auto;
}
</style>
</head>
@@ -231,49 +227,47 @@ class QrStickerService
<div class="container">
<div class="info-section">
<div class="header">
<span class="order-type">{$orderType}</span>
<div class="order-number">{$order->order_number}</div>
<span class="order-type">' . htmlspecialchars($orderType) . '</span>
<div class="order-number">' . htmlspecialchars($order->order_number) . '</div>
</div>
<div class="customer-info">
<div class="label">Customer</div>
<div class="name">{$customerSurname}</div>
<div class="name">' . htmlspecialchars($customerSurname) . '</div>
</div>
<div class="details">
<div class="detail-row">
<span class="detail-label">Design:</span>
<span class="detail-value" style="font-size: 6.5pt;">
{$this->truncate($designName, 12)}
</span>
<span class="detail-value" style="font-size: 6.5pt;">' . htmlspecialchars($this->truncate($designName, 12)) . '</span>
</div>
<div class="detail-row">
<span class="detail-label">Date:</span>
<span class="detail-value">{$order->created_at->format('M d')}</span>
<span class="detail-value">' . htmlspecialchars($order->created_at->format('M d')) . '</span>
</div>
<div class="detail-row">
<span class="detail-label">Status:</span>
<span class="detail-value" style="text-transform: capitalize;">
{$this->formatStatus($order->status)}
</span>
<span class="detail-value">' . htmlspecialchars($this->formatStatus($order->status)) . '</span>
</div>
</div>
<div class="footer">
Gen: {$order->created_at->format('Y-m-d H:i')}
Gen: ' . htmlspecialchars($order->created_at->format('Y-m-d H:i')) . '
</div>
</div>
<div class="qr-section">
<div class="qr-code">
{$qrSvg}
<img src="' . $qrBase64 . '" alt="QR Code" />
</div>
</div>
</div>
</div>
</body>
</html>
HTML;
</html>';
try {
$pdf = Pdf::loadHTML($html);
$pdf->setPaper([0, 0, 420.94, 297.64], 'portrait');
// Set to A6 size (105mm × 148mm) in portrait orientation
// 105mm = 297.64 points, 148mm = 420.94 points
$pdf->setPaper([0, 0, 297.64, 420.94], 'portrait');
$pdf->setOption('isRemoteEnabled', true);
$filename = "{$order->uuid}.pdf";
$path = "qr-stickers/{$filename}";