# Identification physique, QR et NFC

Choisir le porteur physique de vos produits, connaître la forme exacte du lien GS1 Digital Link, et savoir ce que chaque porteur demande avant la mise en production.

Source : https://docs.sealtrust.io/identification-physique/

---

Un produit physique doit porter quelque chose qu'un téléphone peut lire. Cette
page vous donne les deux porteurs disponibles, le QR imprimé et le sceau NFC. En
la quittant, vous saurez quelle adresse exacte est imprimée ou écrite dans la
puce, ce que le serveur répond quand vous la lisez, ce que chaque porteur apporte au
moment du scan, et le travail que chacun demande avant de lancer une production.

Le règlement ESPR autorise le passeport à trois niveaux : le modèle, le lot et
l'exemplaire. L'acte délégué de votre groupe de produits décide lequel
s'applique. Les deux formes d'adresse décrites ci-dessous couvrent le modèle et
l'exemplaire. Un passeport de modèle couvre tous les exemplaires qui partagent
le même code produit.

> [!INFO] Le QR seul est un mode de plein droit
> Le QR imprimé porte l'identifiant unique du produit, celui que le registre
> européen des passeports numériques attend. C'est le porteur de données prévu
> par la norme. Le sceau NFC ajoute une couche par dessus, pour les marques qui
> en ont besoin.

Voici le trajet complet, du porteur physique jusqu'à la page que voit la
personne qui scanne. Le reste de la page reprend chaque étape en détail.

:::schema chemin-du-scan
Deux colonnes séparées, une par porteur, qui se rejoignent en bas. À gauche, le
QR imprimé sur l'étiquette porte une adresse fixe, toujours la même,
`sealtrust.io/p/0ABCDEFGHJKM`, ou sa forme GS1
`sealtrust.io/01/{gtin}/21/{serial}`. Le résolveur remet le numéro en forme,
retrouve l'unité, puis répond une seule redirection 302 : vers la page produit
par défaut, vers la page passeport avec le paramètre `linkType=dpp`. À droite,
le sceau NFC, une puce NTAG 424 DNA, complète lui-même l'adresse
`sealtrust.io/verify` avec les paramètres `e` et `c`, et cette adresse change à
chaque lecture. La page `/verify` appelle ensuite `GET /sdm/verify-url`, la
signature de la puce et son compteur sont vérifiés, puis la page affiche un
verdict suivi de la fiche : produit, marque, historique, compteur de lectures.
Les deux colonnes aboutissent à une page web publique du site, sans application
à installer, qui répond aux questions du scan et renvoie vers le passeport. Le
QR identifie l'objet, le sceau NFC y ajoute une signature calculée par la puce,
différente à chaque lecture.
:::

## Les trois combinaisons possibles

Chaque produit porte une valeur de méthode d'authentification. Le produit en
stocke une parmi trois.

| Valeur | Ce que porte le produit |
| --- | --- |
| `qr` | Un code imprimé seul. |
| `nfc` | Un sceau NFC seul. |
| `nfc+qr` | Les deux sur le même produit. |

Vous choisissez cette valeur à la création du produit, dans le formulaire de la
console ou dans son import CSV. Renseignez-la toujours. Une valeur absente vaut
`nfc`. Le serveur refuse alors la création en `403` si votre offre n'autorise
que le QR. Pour un produit QR seul, écrivez explicitement `qr`.

Le serveur accepte aussi l'écriture `nfc,qr` et la casse haute. Écrivez
exactement l'une des trois valeurs du tableau, dans l'une de ces écritures. Une
autre valeur ne vous donne pas le porteur que vous demandez.

Demander une valeur qui contient `nfc` exige que votre offre autorise
l'authentification NFC. Sinon le serveur répond un `403` portant le code
`AUTH_METHOD_NOT_ALLOWED`, avec la méthode demandée et la liste de celles que
votre offre autorise. Une demande `qr` seule n'exige pas cette autorisation.

## Le QR imprimé

### Ce qu'il encode

Le QR imprimé sur une unité encode une seule adresse, de cette forme :

```text
https://sealtrust.io/p/0ABCDEFGHJKM
```

Le dernier segment est le numéro de série public de l'unité. Cette forme
[`/p/{serial}`](/reference/get-p-serial/) est l'identifiant unique de produit
destiné au registre européen, et c'est elle que porte l'étiquette. La
génération du code refuse de produire une image pour une unité qui n'a pas de
numéro de série.

### Le numéro de série

Le numéro fait douze caractères. Son alphabet compte trente-deux caractères :
les chiffres de 0 à 9 et les lettres de A à Z privées de I, L, O et U.
Nous retirons ces quatre lettres parce qu'elles se confondent avec des chiffres
sur une étiquette.

Trois conséquences pratiques :

- Le serveur corrige un numéro recopié à la main. Il lit un `I` et un `L` comme
  un `1`, et un `O` comme un `0`.
- La casse n'a aucune importance. Le serveur remet le numéro en majuscules avant
  toute recherche.
- Un numéro qui n'a pas la bonne longueur ou qui contient un caractère hors de
  cet alphabet reçoit un `404` immédiat.

Nous tirons le numéro au hasard. Il ne suit pas l'ordre de production et ne
révèle donc ni vos volumes ni votre ancienneté.

### Ce qui se passe au scan

L'appareil photo d'un téléphone ouvre l'adresse. Le serveur répond une seule
redirection `302` vers la page produit, sur le site public.

```bash
curl -sS -i "https://sealtrust.io/p/0ABCDEFGHJKM"
```

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/product/0ABCDEFGHJKM
```

Le serveur choisit la langue de la page à partir de l'en-tête `Accept-Language`
du lecteur, parmi le français et l'anglais, le français par défaut. Il n'y a
jamais qu'un seul saut de redirection.

La page produit répond aux questions qu'une personne se pose en scannant : ce
qu'est l'objet, s'il est authentique, qui le détient, où se trouve la preuve.
Elle renvoie vers le passeport numérique.

### Demander le passeport avec le paramètre `linkType`

Un lecteur machine qui veut le document lui-même ajoute un paramètre `linkType`.

```bash
curl -sS -i "https://sealtrust.io/p/0ABCDEFGHJKM?linkType=dpp"
```

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/<identifiant de l'unité>
```

Le dernier segment est l'empreinte de l'unité, ou à défaut son identifiant de
jeton, ou à défaut son numéro de série.

Cinq valeurs sont reconnues : `dpp`, `passport`, `gs1:dpp`,
`gs1:digitalproductpassport` et `digitalproductpassport`. Toute autre valeur est
traitée comme si le paramètre était absent, et le lecteur arrive sur la page
produit.

Une unité retirée de la circulation part toujours vers son passeport, même sans
ce paramètre. Son identifiant continue de répondre, ce que la norme exige.

## Le lien GS1 Digital Link

### La forme exacte

Le même produit est adressable par un lien GS1 Digital Link. Sa forme est fixée
par la structure du chemin.

```text
https://sealtrust.io/01/03701234567890/21/0ABCDEFGHJKM
```

- `01` est l'identifiant d'application du GTIN, le code article international.
- `03701234567890` est le GTIN ramené à quatorze chiffres.
- `21` est l'identifiant d'application du numéro de série.
- `0ABCDEFGHJKM` est le même numéro de série public que dans la forme courte.

Les deux formes désignent la même unité et mènent à la même page. Le domaine ne
fait pas le lien GS1 Digital Link, c'est la structure du chemin qui le fait. Un
résolveur hébergé sur votre propre domaine reste conforme.

Servir ces résolveurs sur votre propre nom de domaine fait partie de l'offre
SealTrust Inside. Sans elle, vos liens restent sur `sealtrust.io`.

> [!ATTENTION] Le numéro de série du lien n'est pas l'identifiant de jeton
> L'identifiant de jeton sur la chaîne est un nombre de soixante-dix-sept à
> soixante-dix-huit chiffres. Il ne tient pas dans une adresse et n'est pas ce
> que le résolveur attend. Le segment `21` porte le numéro de série public à
> douze caractères.

### Ce que le serveur vérifie

```bash
curl -sS -i "https://sealtrust.io/01/03701234567890/21/0ABCDEFGHJKM"
```

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/product/0ABCDEFGHJKM
```

Le GTIN du chemin doit correspondre au GTIN du modèle auquel l'unité appartient.
Sinon le serveur répond un `404`. Une unité dont le modèle ne porte aucun GTIN
n'est donc pas adressable par cette forme, et reste adressable par la forme
courte `/p/{serial}`.

Un GTIN qui ne peut pas être normalisé reçoit un `400` avec le message
`Invalid GTIN`. Le serveur retient les chiffres du segment, refuse au delà de
quatorze, et complète à gauche par des zéros jusqu'à quatorze. Les formes
GTIN-8, GTIN-12, GTIN-13 et GTIN-14 passent donc, avec ou sans séparateurs.

Il vérifie ensuite la clé de contrôle GS1, et répond `400` avec le message
`Invalid GTIN: the check digit does not match.` quand le dernier chiffre ne
correspond pas aux précédents. Cette vérification a lieu à la résolution, et
plus seulement à l'enregistrement du modèle : un code mal recopié est donc
nommé comme tel, au lieu de répondre « produit inconnu » et d'envoyer le
lecteur chercher au mauvais endroit.

Toutes les autres impasses reçoivent le même `404` avec le même message. Un numéro
inconnu et un numéro connu sous un autre GTIN sont indiscernables de l'extérieur.

### La forme sans numéro de série

Un lien sans le segment `21` désigne un modèle commercial. Il ne désigne aucune
unité en particulier.

```bash
curl -sS -i "https://sealtrust.io/01/03701234567890"
```

```http
HTTP/1.1 302 Found
Location: https://sealtrust.io/fr/passport/01/03701234567890
```

Il résout vers le passeport de niveau modèle, celui qui est rattaché à un modèle
et à aucune unité. Le serveur ne sert jamais ici un passeport rattaché à une
unité : les données d'un exemplaire ne doivent pas être montrées pour un autre
exemplaire du même modèle.

Le serveur répond un `404` dans quatre cas, sans les distinguer : le GTIN est
inconnu, aucun passeport de modèle public n'est publié pour ce GTIN, plusieurs
marques publient un passeport de modèle sous le même GTIN, ou le GTIN appartient
à une autre marque que celle du domaine sur lequel le scan arrive.

C'est la forme qui convient à tout ce qui se vend au mètre, à la boîte ou à la
palette. Un seul code, imprimé sur chaque unité du modèle, et rien de créé par
exemplaire.

Le niveau lot n'a pas de forme d'adresse à lui. Un passeport se rattache soit à
un modèle, soit à un exemplaire. Le code imprimé est donc celui du modèle ou
celui de l'exemplaire.

### La limite de cinquante caractères

Le registre européen plafonne l'identifiant unique de produit à cinquante
caractères. La structure GS1 en consomme vingt-deux à elle seule, en plus du
domaine : `/01/`, quatorze chiffres de GTIN, `/21/`. Le domaine que vous choisissez
décide donc du nombre de caractères qu'il reste pour le numéro de série.

| Domaine du résolveur | Caractères restants pour le numéro |
| --- | --- |
| `https://id.gs1.org` | 10 |
| `https://sealtrust.io` | 8 |
| `https://api.sealtrust.io` | 4 |

Prenez le domaine le plus court dont vous disposez. Un sous-domaine `api.` est un
piège. L'identifiant destiné au registre est la forme courte `/p/{serial}`, qui
ne dépense pas ces vingt-deux caractères.

Le passeport publié porte les deux valeurs : le GTIN normalisé dans le champ
`gtin`, et le lien complet dans le champ `gs1_digital_link`.

## Ce que le QR seul apporte

- **Il porte l'identifiant destiné au registre.** La forme `/p/{serial}` est
  l'identifiant unique de produit qu'attend le registre européen. Le champ qui
  doit servir le document porte la même adresse suivie de `?linkType=dpp`.
- **Il fonctionne au niveau modèle.** Un seul code pour tout un modèle, sans
  rien créer par exemplaire, avec la forme
  [`/01/{gtin}`](/reference/get-gs1-gtin/). Ce niveau sert le passeport et se
  scanne.
- **Il ne demande aucun matériel.** Le code est une image que vous téléchargez et
  envoyez à l'impression.
- **Il mène à une page web ordinaire.** Aucune application n'est nécessaire pour
  la lire.

> [!ATTENTION] Nous ne déclarons pas à votre place
> Nous produisons le fichier de déclaration au format officiel de la Commission.
> C'est vous, opérateur économique, qui l'enrôlez avec votre sceau qualifié. Le
> registre européen n'accepte aujourd'hui que le groupe batteries, et le fichier
> ne couvre que l'exemplaire sérialisé `/p/{serial}`. Le niveau modèle
> `/01/{gtin}` sert le passeport et se scanne, sans chemin vers le registre à ce
> jour.

Ce qu'il ne fait pas : un QR imprimé encode une adresse fixe. Une photographie
de l'étiquette encode la même adresse. Le résolveur cherche le numéro de série et
redirige ; il n'a rien d'autre à examiner. Le QR identifie donc un objet, et ne
prouve pas à lui seul que l'étiquette n'a pas été recopiée.

## Ce que le sceau NFC ajoute

Le sceau NFC est une puce NTAG 424 DNA. À chaque lecture, elle écrit elle-même
deux paramètres dans l'adresse : une donnée chiffrée et un sceau de
vérification. L'adresse change donc à chaque lecture.

```text
https://sealtrust.io/verify?e=<donnée chiffrée>&c=<sceau>
```

Le paramètre `e` fait trente-deux caractères hexadécimaux. Le paramètre `c` en
fait seize. Un téléphone qui approche la puce ouvre cette adresse déjà
complétée. La page `/verify` interroge ensuite le point d'entrée de vérification
de l'API, sur `api.sealtrust.io`.

Sur l'offre SealTrust Inside, nous gravons votre propre nom de domaine dans la
puce, à la place de `sealtrust.io`. Ce choix se fige au premier encodage : une
fois une puce gravée, le serveur refuse en `409` tout changement de domaine,
parce que les puces déjà posées pointeraient dans le vide.

Trois choses en découlent.

**Une adresse déjà utilisée est refusée.** La puce incrémente un compteur à
chaque lecture. Le serveur exige que ce compteur avance strictement. Une adresse
capturée puis rejouée reçoit un `409`. Une signature qui ne correspond pas reçoit
un `403` avec le code `SDM_MAC_MISMATCH`. Des paramètres mal formés reçoivent un
`422`.

**Le sceau d'ouverture, sur les puces qui en portent un.** Certaines puces
embarquent un fil qui se rompt à l'ouverture. Elles ajoutent alors un paramètre
`t` de deux caractères, placé entre `e` et `c`. La réponse expose trois champs :

| Champ | Contenu |
| --- | --- |
| `tamper_status` | Les deux caractères bruts : `CC` jamais ouvert, `OO` ouvert, `OC` ouvert puis refixé, `II` fonction jamais activée. |
| `seal_intact` | `true` jamais ouvert, `false` ouvert, `null` rien à dire. |
| `tamper_policy` | Ce que votre marque veut qu'on en fasse. |

Le champ `seal_intact` a trois états. La valeur `null` ne veut pas dire rompu :
une puce ordinaire et une puce dont la fonction n'a jamais été activée donnent
toutes deux `null`. L'afficher en alerte poserait un avertissement de
contrefaçon sur des produits authentiques.

> [!ATTENTION] Un sceau rompu n'est pas une contrefaçon
> Le client qui ouvre sa boîte rompt le sceau légitimement, et tout produit
> d'occasion l'a rompu. C'est pourquoi la politique par défaut de la marque est
> `info`, qui affiche l'état sans jugement. Les deux autres valeurs sont `off`,
> qui n'affiche rien, et `gate`, qui présente un sceau rompu comme un
> avertissement. Le verdict d'authenticité ne change dans aucun des trois cas.

**Une réponse plus riche que la redirection du QR.** La lecture d'une puce
renvoie directement un document, avec le nom du produit, la marque, l'identifiant
de jeton, l'adresse du contrat, l'historique, la valeur du compteur, un indicateur
`declared_stolen` si une déclaration de vol est ouverte sur l'unité, et une zone de
scan au grain de la ville quand la position est fournie.

## Ce que chacun coûte en préparation

### Le QR

Vous demandez l'image au moment où vous en avez besoin, et le serveur la renvoie
en PNG. Vous choisissez une taille entre 100 et 1000 pixels. La correction
d'erreur est de niveau M et la marge blanche fait deux modules. Gardez cette
marge à l'impression, sinon la lecture devient incertaine.

Vous pouvez télécharger le code d'un produit, celui d'un certificat, ou l'archive
ZIP de tous les codes d'un lot en une fois.

Pour un QR de niveau modèle, la console refuse de générer l'image tant qu'aucun
passeport de modèle public n'est publié pour ce GTIN. Le message est
explicite. Imprimer un code qui ne mène nulle part coûte plus cher que d'attendre.

En résumé : aucun matériel, aucune manipulation par exemplaire, aucun délai
d'approvisionnement.

### Le sceau NFC

La préparation est d'une autre nature.

1. **Votre offre doit comprendre l'authentification NFC.** Sinon le serveur
   refuse la création des produits en `403`.
2. **Vous approvisionnez les puces.** Ce sont des composants physiques, avec un
   délai et un coût par exemplaire.
3. **Chaque puce passe devant un lecteur avant la création du produit.** Nous
   lisons son identifiant matériel, vous l'associez à une ligne de votre lot,
   vous créez les produits, nous encodons les puces. C'est un parcours en quatre
   étapes, et il se fait puce par puce.
4. **Nous écrivons l'adresse dans la puce au moment de l'encodage.** Vous ne
   pouvez pas la modifier à distance ensuite. Une puce mal encodée est une puce
   à remplacer physiquement.

> [!ATTENTION] L'encodage dépend de votre offre
> La frappe physique et l'encodage des puces se conduisent depuis la console, sur
> un poste équipé d'un lecteur sans contact. Si votre offre ne comprend pas
> l'encodage NFC, la console vous répond que l'encodage physique des tags est
> géré par SealTrust, et vous suivez l'avancement de la frappe et de l'encodage
> depuis la page du lot.

Sur un lot NFC, vous pouvez produire en parallèle un QR imprimé pour les mêmes
unités. L'inverse ne marche pas : une adresse de puce imprimée dans un QR ne
fonctionne pas, parce que c'est la puce qui remplit les paramètres `e` et `c`, et
qu'une image imprimée ne remplit rien.

## Choisir

| Question | QR seul | Sceau NFC |
| --- | --- | --- |
| Identifiant `/p/{serial}` destiné au registre européen | Oui | Oui |
| Niveau modèle, un code pour tout un modèle | Oui | Sans objet |
| Matériel à approvisionner | Non | Oui |
| Manipulation par exemplaire | Non | Oui |
| Lecture sans application | Oui | Oui |
| Adresse différente à chaque lecture | Non | Oui |
| Rejeu d'une adresse capturée refusé | Non | Oui |
| Détection d'ouverture de l'emballage | Non | Sur les puces qui en portent un |
| Correction possible après fabrication | Réimprimer l'étiquette | Remplacer la puce |

Un dernier point sur les domaines. Si vous servez ces résolveurs sur votre propre
nom de domaine, un lien reste sur ce domaine du début à la fin, et vos clients ne
voient jamais le nôtre. Un domaine de marque ne résout que les produits de cette
marque : le code d'une autre marque scanné sur votre domaine reçoit un `404`.
