Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

CookieMonster's avatar

Signed URL for QR code

So I have been grasping the concept on how to implement of signed URL in my QR code and I was hoping if someone is kind enough to have a look through my code. How it works if a customers buys something, they received an email with a PDF invoice attached. Inside the PDF, it contains the QR code, when scanned, shall bring to a page that shows your purchase information,etc and he/she can confirm the order and done. Customer does not need to login for verify this QR code. The purchase number is unique in the purchase table every purchases made by a customer will be tied to a purchase number (or you can refer to it as invoice number).

So my route in web.php:

//Show order confirmation when customer scan QR (invoice)
Route::get('/orders/confirm/{purchase_num}', 'OrderController@show')->name('confirm-order')->middleware('signed');

I implemented the signedURL for data integrity so you cannot change the URL however you liked. Next after I made a purchase and checkout and finalize everything:

Purchase Controller:

  $pdf = PDF::loadView('documents.invoice',compact('purchase'))->setPaper('a4'); 
            
            // Make a copy of the PDF invoice and store in public/storage/....
            $content = $pdf->download()->getOriginalContent();
             Storage::put('public/storage/documents/invoice/invoice_'.$purchase->purchase_number. '.pdf',$content) ;

            //Send email to customer after placing order( attach with invoice)
            $message = new InvoiceEmailCustomer($purchase);
            $message->attachData($pdf->output(), "invoice.pdf");     
            Mail::to($purchase->user->email)->send($message);

It will email the invoice pdf to the customer email (tested and worked) and pass in data to the invoice pdf via compact as well as making a copy of the pdf file in storage (both tested and worked). So in my invoice blade, it has the QR code that requires the signedURL and purchase number which looks like below:

<body>

    @php
      $url = URL::signedRoute 
    ('confirm-order', [ 
        'purchase_num' => $purchase->purchase_number,
        
    ]);   
    @endphp
    <div class="container"> 
        <img style="float:right; margin-bottom:10px;"
            src="data:images/png;base64, {{ base64_encode(QrCode::format('png')->size(100)->generate('www.demo3.bujishu.com/orders/confirm/{$url}')) }} ">
    </div>

This is the part where I am unsure if my method was correct. Once it scans the QR, it will call this controller:

Order controller:

public function show(Request $request)
    {
        if (! $request->hasValidSignature()) {
            abort(401);
        }
       
        return view('qr.confirm-order')->
        with(['purchase'=>Purchase::where('purchase_num', $request->purchase_num)->get()]);
     
    }

where it brings the customer to the confirm order page along with all the order details,etc. (this blade is still WIP).

I hope this is not confusing, I know it's pretty complicated. Can anyone confirm my logic is correct?

0 likes
2 replies
bobbybouwmann's avatar

There is only a problem in here

{{ base64_encode(QrCode::format('png')->size(100)->generate('www.demo3.bujishu.com/orders/confirm/{$url}')) }} ">

$url returns a full URL already. Right now you prefix the URL with another URL which results in a double URL. Try this instead

{{ base64_encode(QrCode::format('png')->size(100)->generate('{$url}')) }}
1 like
CookieMonster's avatar

I overlooked it sorry.

But in my route, I did not defined the domain, so shouldn't it be like this?:

{{ base64_encode(QrCode::format('png')->size(100)->generate('www.demo3.bujishu.com/{$url}')) }}

Please or to participate in this conversation.