Enqre

Pubblicato il 16/08/2026

QR code dinamici in PHP: quando serve un'API e quando no

"Come genero un QR code in PHP" ha due risposte molto diverse, e sbagliare costa denaro o una ristampa.

Se il codice è statico, fatelo in locale

Se vi serve solo l'immagine di un URL — biglietto, fattura, scontrino —, installate una libreria e avete finito. endroid/qr-code disegna PNG e SVG offline: nessuna chiave, nessuna quota, nessuna dipendenza dalla disponibilità altrui, nessun costo.

Questo copre la maggior parte di queste domande, e ogni articolo che salta il punto per vendervi qualcosa vi sta sprecando il pomeriggio.

Cosa cambia con un codice stampato

Un codice statico è la sua destinazione: l'URL sta nel disegno. Se cambia, tutto lo stampato è sbagliato per sempre.

La domanda non è "PHP o servizio", ma: dopo la stampa, la destinazione dovrà spostarsi? Se sì — e su confezioni, targhette o volantini è la regola —, il codice deve portare un indirizzo breve che controllate voi. È l'unica cosa che una libreria non può darvi, perché richiede che qualcuno risponda a quell'indirizzo per anni.

Crearne uno

<?php
$ch = curl_init("https://enqre.com/api/v1/qrcodes");
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("ENQRE_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "name" => "Order 10432 – delivery note",
        "url"  => "https://shop.example/orders/10432",
    ]),
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

if ($status !== 201) {
    throw new RuntimeException("enqre: HTTP $status — $body");
}

$code = json_decode($body, true)["data"];
// $code["id"]       — store this against your record
// $code["shortUrl"] — the address the QR image should encode
  • Salvate l'id restituito accanto al vostro record.
  • Mettete il vostro identificativo nel nome.

Disegnate shortUrl con la libreria locale che preferite: sono due compiti distinti.

Spostare la destinazione

<?php
$id = $code["id"];
$ch = curl_init("https://enqre.com/api/v1/qrcodes/$id");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "PATCH",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("ENQRE_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "url" => "https://shop.example/orders/10432/tracking",
    ]),
]);
curl_exec($ch);
curl_close($ch);
// The printed code is untouched. It now opens the tracking page.

Leggere le scansioni

<?php
$ch = curl_init("https://enqre.com/api/v1/qrcodes/$id/scans");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("ENQRE_API_KEY")],
]);
$res = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $res["total"];             // every scan ever counted
foreach ($res["data"] as $scan) {
    // createdAt, device, os, browser — and nothing else
}

Da sapere prima di progettare un report: una scansione contiene ora, tipo di dispositivo, sistema e browser. Nessuna identità e nessuna posizione.

Gli errori veri

  • 401 invalid_api_key
  • 400 invalid_body — quasi sempre un URL che non lo è.
  • 402 plan_limit_reached
  • 429 rate_limited — oltre 60 richieste al minuto.

Controllate CURLINFO_RESPONSE_CODE invece di fidarvi del corpo.

Due cose dal primo giorno

Rendete idempotente la creazione. Due chiamate creano due codici.

Non stampate ciò che non avete riletto.

Quando non scrivere l'integrazione

Per qualche centinaio di codici una tantum, il caricamento CSV è più veloce di qualsiasi codice scriviate. Integrate quando i codici nascono di continuo.

Risposte rapide

  • Migliore libreria PHP? endroid/qr-code per disegnare.
  • Dinamico in PHP puro? Sì, se ospitate voi il reindirizzamento.
  • Autenticazione? Authorization: Bearer enq_….
  • Limite? 60 richieste al minuto.
  • L'API restituisce l'immagine? No, restituisce shortUrl.
  • Posizione nelle scansioni? No.

Continua a leggere