Intégrer le SDK mobile
Ce que le SDK iOS et Android sait faire, ce que votre application garde à sa charge, comment l'installer aujourd'hui, et pourquoi il n'est pas encore distribuable à une équipe extérieure.
Sur cette page
- Où en est ce SDK aujourd'hui
- Le partage du travail
- Un produit peut porter deux codes, et ils ne prouvent pas la même chose
- Plateformes et versions minimales
- Installer
- Créer le client
- Vérifier un scan
- Le scellé électronique et la déclaration de vol
- Lire un passeport, ses preuves et son certificat
- Revendiquer la propriété d'un produit
- Les trois écrans prêts à poser
- Les erreurs
- Plafonds d'appels
- Coordonnées et vie privée
- Ce qui n'est pas dans le SDK
Le SDK mobile est un client typé de l'API publique SealTrust, plus trois écrans prêts à poser, pour iOS et pour Android. En quittant cette page, vous saurez ce qu'il sait faire, ce qu'il ne fera jamais, ce que votre application doit garder à sa charge, comment le brancher, et dans quel état de distribution il se trouve aujourd'hui.
Commençons par cet état, parce qu'il change la réponse à la question « puis-je m'en servir cette semaine ».
#Où en est ce SDK aujourd'hui
Les deux plateformes sont en version 0.1.0 et ne sont publiées sur aucun
dépôt de paquets.
Côté iOS, le manifeste du paquet Swift ne se trouve pas à la racine d'un dépôt
git. Le gestionnaire de paquets Swift ne résout un paquet depuis une adresse
git que dans ce cas. La déclaration .package(url:) ne fonctionne donc pas, et
seule la déclaration par chemin local fonctionne.
Côté Android, les deux modules déclarent bien des coordonnées Maven,
io.sealtrust:sealtrust-core et io.sealtrust:sealtrust-ui, en version
0.1.0. La configuration de publication ne déclare aucun dépôt distant. La
seule publication possible est donc locale, sur votre propre machine.
#Le partage du travail
Le SDK ne lit pas la puce. C'est la première chose à comprendre, parce qu'elle détermine tout le reste.
Une puce NFC SealTrust prouve son authenticité en calculant une signature neuve à chaque lecture, avec une clef propre à la puce. Vérifier cette signature exige les clefs de puce de la marque, et ces clefs ne quittent pas nos serveurs.
| Qui | Fait quoi |
|---|---|
| Le système du téléphone | Lit l'adresse que la puce émet, ou le QR imprimé. |
| Votre application | Possède la session NFC, l'appareil photo, la connexion de l'utilisateur. |
| Le SDK | Lit cette adresse, appelle l'API, transforme la réponse en verdict affichable. |
| L'API SealTrust | Vérifie la cryptographie de la puce et répond. |
Trois conséquences concrètes.
Le SDK ne demande aucune autorisation NFC et aucune autorisation de localisation. C'est le module Android des écrans qui déclare l'autorisation d'accès à internet, et c'est la seule qu'il déclare. Le module client seul ne déclare aucune autorisation.
La vérification hors ligne n'existe pas. Chaque contrôle est un appel réseau.
Le SDK ne contient aucun secret. Il n'y a pas de clef d'API mobile, pas de clef de signature, pas d'identifiant embarqué. La seule chose qu'il peut porter est le jeton de session d'un utilisateur déjà connecté par vos soins. Il l'envoie sur les appels de revendication de propriété, et sur la lecture de passeport quand ce jeton est disponible.
#Un produit peut porter deux codes, et ils ne prouvent pas la même chose
Le SDK nomme lequel des deux a été lu. Le traitement diffère ensuite pour chacun.
| Ce qui a été scanné | Ce que cela prouve | Ce que vous appelez |
|---|---|---|
| La puce NFC | L'objet physique était là. La puce recalcule une signature neuve à chaque lecture. | verifyScan |
| Le QR imprimé | Quel article c'est. Une photographie de l'étiquette redonne la même chaîne. | passport, certificate, history, et requestClaimTicket à partir du numéro de série |
Beaucoup de produits ne portent qu'un QR. La plateforme sert ce mode à part entière. Le passeport, le certificat et l'historique se lisent alors normalement, à partir du seul numéro imprimé. C'est la preuve de présence physique qui n'est pas fournie.
La fonction de lecture d'adresse vous dit laquelle des deux vous avez entre les mains, et rend une valeur vide quand l'adresse n'est ni l'une ni l'autre. Ce dernier cas arrive souvent en production : un client qui pointe votre scanner sur le lien GS1 d'une autre marque mérite une réponse propre.
import SealTrustKit
func traiter(_ chaineScannee: String, avec client: SealTrustClient) async throws {
switch ScanURL.read(chaineScannee) {
case .chip(let preuve):
let verification = try await client.verifyScan(preuve)
print(verification.productName ?? "")
case .printedSerial(let numeroDeSerie):
let passeport = try await client.passport(identifier: numeroDeSerie)
print(passeport.productName ?? "")
case nil:
print("Ce code n'est pas un code SealTrust.")
}
}import io.sealtrust.sdk.core.ScanUrl
import io.sealtrust.sdk.core.ScannedCode
import io.sealtrust.sdk.core.SealTrustClient
// Le client bloque : appelez-le hors du fil principal.
fun traiter(chaineScannee: String, client: SealTrustClient) {
when (val code = ScanUrl.read(chaineScannee)) {
is ScannedCode.Chip -> println(client.verifyScan(code.proof).productName)
is ScannedCode.PrintedSerial -> println(client.passport(code.serial).productName)
null -> println("Ce code n'est pas un code SealTrust.")
}
}Le QR imprimé porte deux formes : /p/{serial} et la forme GS1
/01/{gtin}/21/{serial}. Un lien /01/{gtin} sans numéro de série nomme une
référence produit, donc la lecture ne rend aucun numéro de série. Ce n'est pas
une impasse : une référence a son propre passeport, celui du modèle, et le
client le lit avec referencePassport. Gardez la distinction en tête, un
passeport de référence décrit un modèle et ne prouve rien sur l'objet que vous
tenez.
Le passeport se sert à deux niveaux seulement : le modèle, par son code produit GTIN, et l'article, par son identifiant. Un passeport de modèle couvre tous les exemplaires qui partagent le même code produit. Le règlement ESPR autorise aussi un passeport de lot, que la plateforme ne sert pas aujourd'hui.
Le numéro de série est rendu exactement tel qu'il est imprimé, jamais réécrit. C'est le serveur qui applique les règles de normalisation. Une application publiée ne se met pas à jour au même rythme que le serveur, et un client qui appliquerait ses propres règles répondrait « produit introuvable » sur une étiquette valable le jour où les deux jeux de règles divergeraient.
#Plateformes et versions minimales
| Caractéristique | iOS | Android |
|---|---|---|
| Version minimale | iOS 16 | niveau d'API 26 |
| Distribution | Paquet Swift SealTrustSDK | Projet Gradle, deux modules |
| Client | Bibliothèque SealTrustKit | Module sealtrust-core |
| Écrans | Bibliothèque SealTrustUI | Module sealtrust-ui |
| Dépendances du client | Aucune, Foundation seul | Aucune |
| Dépendances des écrans | SwiftUI seul | Jetpack Compose et androidx.lifecycle:lifecycle-viewmodel-compose |
Le module Android du client est un module Kotlin ordinaire, sans rien d'Android dedans. Il compile en Java 17. Le module des écrans vise le niveau de compilation 35 et le niveau minimal 26, ce dernier étant imposé par la lecture des dates. Descendez plus bas uniquement avec le sucre syntaxique de la bibliothèque de base active dans votre application.
#Installer
// Package.swift de votre application.
// Remplacez le chemin par celui de votre copie locale des sources.
dependencies: [
.package(name: "SealTrustSDK", path: "<chemin-vers-les-sources>/ios"),
],
targets: [
.target(
name: "VotreApplication",
dependencies: [
.product(name: "SealTrustKit", package: "SealTrustSDK"),
.product(name: "SealTrustUI", package: "SealTrustSDK"),
]
),
]// settings.gradle.kts de votre application.
// Remplacez le chemin par celui de votre copie locale des sources.
includeBuild("<chemin-vers-les-sources>/android")
// build.gradle.kts de votre module.
dependencies {
implementation("io.sealtrust:sealtrust-core")
implementation("io.sealtrust:sealtrust-ui")
}Le paramètre name: est obligatoire sur iOS. Un paquet déclaré par chemin
prend pour identité le nom de son répertoire. Sans ce paramètre, le
gestionnaire de paquets Swift ne trouve pas SealTrustSDK et la compilation
échoue.
Sur Android, une seconde voie existe si le build composite ne vous convient
pas. Depuis le répertoire du projet Gradle du SDK, ./gradlew publishToMavenLocal installe les deux modules dans votre dépôt Maven local.
Vous les consommez ensuite comme des dépendances versionnées.
repositories {
mavenLocal()
}
dependencies {
implementation("io.sealtrust:sealtrust-core:0.1.0")
implementation("io.sealtrust:sealtrust-ui:0.1.0")
}Si vous ne voulez que le client, prenez SealTrustKit seul, ou
sealtrust-core seul. Vous ne payez alors rien pour les écrans.
Une conséquence sur Android : c'est le module des écrans qui déclare
l'autorisation d'accès à internet. Si vous prenez sealtrust-core seul,
déclarez android.permission.INTERNET dans votre propre manifeste.
#Créer le client
Le client se construit avec une configuration. Ses quatre valeurs :
| Valeur | Défaut | Rôle |
|---|---|---|
| Adresse de base | https://api.sealtrust.io | À remplacer pour viser un autre environnement ou votre propre relais. |
| Délai d'attente | 15 secondes | Délai de connexion et de lecture. |
| Identifiant du client | sealtrust-sdk-ios/0.1.0 ou sealtrust-sdk-android/0.1.0 | Envoyé en en-tête X-SealTrust-Client. |
| Fournisseur de jeton | absent | Rend le jeton de session de l'utilisateur connecté, ou rien. |
Le SDK ne connecte personne. Les appels de revendication de propriété exigent un utilisateur authentifié, donc votre application fournit le jeton. Rendez une valeur vide quand personne n'est connecté : le SDK échoue alors avec une erreur d'authentification au lieu d'envoyer une requête qui ne peut revenir qu'en 401.
import Foundation
import SealTrustKit
enum SessionApplication {
/// Jeton de l'utilisateur connecté, alimenté par votre propre connexion.
static var jeton: String?
}
let client = SealTrustClient(
configuration: SealTrustConfiguration(
accessTokenProvider: { SessionApplication.jeton }
)
)import io.sealtrust.sdk.core.SealTrustClient
import io.sealtrust.sdk.core.SealTrustConfiguration
object SessionApplication {
/** Jeton de l'utilisateur connecté, alimenté par votre propre connexion. */
@Volatile
var jeton: String? = null
}
val client = SealTrustClient(
SealTrustConfiguration(accessTokenProvider = { SessionApplication.jeton }),
)Deux en-têtes accompagnent chaque appel : Accept: application/json et
X-SealTrust-Client. Les appels qui portent un corps ajoutent
Content-Type: application/json.
L'en-tête Authorization est ajouté sur les appels de revendication, et sur la
lecture de passeport quand votre application a fourni un jeton. Un propriétaire
connecté voit alors sa lecture élargie.
Une différence de style entre les deux plateformes, à ne pas rater. Sur iOS, toutes les méthodes qui appellent le réseau sont asynchrones. La construction de l'adresse du certificat en PDF est synchrone, parce qu'elle n'appelle rien. Sur Android, les méthodes sont bloquantes : appelez-les hors du fil principal. Les trois écrans Android le font déjà pour vous.
#Vérifier un scan
C'est l'appel central. Vous lui donnez l'adresse lue sur la puce, il rend un verdict.
import SealTrustKit
func verifier(_ adresse: URL, avec client: SealTrustClient) async -> ScanOutcome {
do {
return ScanOutcome.from(try await client.verifyScan(url: adresse))
} catch {
return ScanOutcome.from(error)
}
}import io.sealtrust.sdk.core.ScanOutcome
import io.sealtrust.sdk.core.SealTrustClient
fun verifier(adresse: String, client: SealTrustClient): ScanOutcome = try {
ScanOutcome.of(client.verifyScan(adresse))
} catch (erreur: Throwable) {
ScanOutcome.of(erreur)
}Le verdict prend huit formes, et les distinguer compte pour l'utilisateur.
| Verdict | Ce qui s'est passé | Ce que l'écran doit dire |
|---|---|---|
| Authentique | La puce a répondu une signature que le serveur a validée. | Produit authentique. |
| Rejeu | Cette adresse exacte a déjà été présentée. | Alerte. C'est le signal qu'une étiquette a pu être copiée. |
| Signature invalide | La signature ne correspond pas à cette puce. | Ce n'est pas une puce SealTrust, ou c'est une copie. |
| Frappe en cours | Puce authentique, son certificat est en cours d'écriture. | Demandez à l'utilisateur de réessayer dans un moment. |
| Jamais enregistré | Puce authentique, rien n'a jamais été enregistré pour elle. | L'anomalie est du côté de la marque. L'acheteur n'a rien à corriger. |
| Lien illisible | L'adresse ne portait pas de preuve exploitable, ou l'API a refusé les paramètres. | Invitez à rescanner. |
| Trop d'appels | Le plafond par adresse IP est atteint. | Invitez à réessayer dans une minute. |
| Échec | Tout le reste, y compris le réseau injoignable. | Erreur technique, sans verdict d'authenticité. |
Un conflit non reconnu est lu comme un rejeu. Le SDK remonte donc l'anomalie au lecteur.
#Le scellé électronique et la déclaration de vol
Deux informations voyagent avec la vérification et méritent un traitement particulier.
Le scellé Tag Tamper est un état à trois valeurs : jamais ouvert, ouvert, ou rien à dire. Une puce standard et une puce dont le scellé n'a jamais été activé rendent toutes deux la troisième valeur, sur des produits authentiques. N'affichez jamais l'absence d'information comme un scellé rompu. Le SDK expose une propriété qui combine cet état avec la politique choisie par la marque, et qui rend une valeur vide dès qu'il n'y a rien à montrer. Trois politiques existent : silence, information, et confiance affichée dégradée. La valeur par défaut est l'information.
Une déclaration de vol ouverte sur une unité ne fait pas échouer la vérification. Le scan répond normalement, et un booléen porte l'avertissement. Affichez-le, sinon il n'est dit nulle part.
#Lire un passeport, ses preuves et son certificat
Le client expose sept lectures, toutes publiques.
| Appel | Ce qu'il rend |
|---|---|
passport | Le passeport numérique publié d'une unité. |
passportProof | Le faisceau de preuves de ce passeport. |
referencePassport | Le passeport du modèle, à partir d'un GTIN. |
referencePassportProof | Le faisceau de preuves du modèle. |
certificate | Le certificat d'authenticité public. |
certificatePDFURL sur iOS, certificatePdfUrl sur Android | L'adresse du même certificat en PDF. Rien n'est appelé, l'adresse est construite. |
history | Les mouvements de propriété et les scans d'authentification, du plus récent au plus ancien. |
Le passeport se lit à un niveau d'accès. Le SDK expose les six valeurs que
l'API accepte : public, end_user, repairer, recycler, upstream et
authority. Les trois niveaux de métier sont des publics distincts. Aucun ne contient
les autres : détenir l'accréditation de réparateur n'ouvre pas celle du
recycleur. Le défaut est public. Les niveaux supérieurs sont contrôlés par
le serveur, qui répond 401 ou 403 à un appelant qui n'y a pas droit. Le niveau
réellement servi figure dans la réponse, et il n'est pas toujours celui
demandé : un propriétaire connecté voit sa lecture publique élargie
automatiquement.
let passeport = try await client.passport(
identifier: "0x0000000000000000000000000000000000000000000000000000000000000000"
)
print(passeport.accessTier, passeport.productName ?? "")
let preuves = try await client.passportProof(
identifier: "0x0000000000000000000000000000000000000000000000000000000000000000"
)
print(preuves.dataHash ?? "", preuves.ipfsURI ?? "")
let modele = try await client.referencePassport(gtin: "03701234567890")
print(modele.productName ?? "")val passeport = client.passport(
"0x0000000000000000000000000000000000000000000000000000000000000000",
)
println("${passeport.accessTier} ${passeport.productName}")
val preuves = client.passportProof(
"0x0000000000000000000000000000000000000000000000000000000000000000",
)
println("${preuves.dataHash} ${preuves.ipfsUri}")
val modele = client.referencePassport("03701234567890")
println(modele.productName)Le faisceau de preuves porte l'empreinte du contenu, la copie sur IPFS, l'état d'ancrage sur Base et l'état du certificat vérifiable. L'état d'ancrage prend trois valeurs distinctes : ancré, jamais ancré, et ancré puis modifié. La troisième est la seule que ce mécanisme existe pour lever. Ne l'affichez jamais comme un « non ancré ».
Il prend une quatrième forme, une valeur vide, quand le serveur n'a servi aucun bloc d'ancrage. Traitez ce cas à part et n'affichez jamais cette valeur vide comme un « non ancré ». Elle signifie que vous n'avez aucune information sur l'ancrage de ce produit. L'ancrage sur Base est une opération que SealTrust déclenche à la main, et la plupart des produits ne sont jamais ancrés. Une marque ne peut pas le déclencher elle-même.
#Revendiquer la propriété d'un produit
Le parcours enregistre un produit scanné au nom de l'utilisateur connecté. Il tient en deux appels, plus une lecture d'état.
Le premier appel demande un ticket à partir de la lecture de la puce. Un ticket n'est délivré que tant que le produit n'appartient à personne.
Une réponse en succès sans ticket est normale. Le champ de détail dit alors pourquoi : déjà revendiqué, déjà transféré, identifiant inconnu, revendication concurrente en cours, ou code d'achat exigé.
import SealTrustKit
func revendiquer(_ chaineScannee: String, avec client: SealTrustClient) async throws {
guard case .chip(let preuve) = ScanURL.read(chaineScannee) else {
print("Ce code n'est pas une lecture de puce.")
return
}
let demande = try await client.requestClaimTicket(for: preuve)
guard let ticket = demande.ticket else {
print(demande.detail ?? "Aucun ticket délivré.")
return
}
let resultat = try await client.completeClaim(ticket)
print(resultat.txHash ?? "")
}import io.sealtrust.sdk.core.ScanUrl
import io.sealtrust.sdk.core.ScannedCode
import io.sealtrust.sdk.core.SealTrustClient
// Le client bloque : appelez-le hors du fil principal.
fun revendiquer(chaineScannee: String, client: SealTrustClient) {
val code = ScanUrl.read(chaineScannee)
if (code !is ScannedCode.Chip) {
println("Ce code n'est pas une lecture de puce.")
return
}
val demande = client.requestClaimTicket(code.proof)
val ticket = demande.ticket
if (ticket == null) {
println(demande.detail ?: "Aucun ticket délivré.")
} else {
val resultat = client.completeClaim(ticket)
println(resultat.txHash)
}
}Le second appel transforme le ticket en propriété inscrite sur la chaîne. Il exige le jeton de l'utilisateur connecté. La réponse est écrite dès que le transfert est diffusé, avant qu'il soit gravé, donc l'empreinte de transaction qu'elle porte désigne une opération en attente.
Certaines marques remettent un code d'achat avec le produit. N'en demandez un à l'utilisateur qu'après que l'API a répondu une première fois qu'il est exigé. Les clients des marques qui n'en émettent aucun ne verront alors jamais ce champ.
Le ticket porte un nonce. C'est la preuve que quelqu'un a physiquement lu l'étiquette. Gardez-le en mémoire, ne le journalisez pas, ne le stockez pas.
Un troisième appel lit l'état d'un ticket : délivré, consommé, expiré ou annulé. Il exige aussi le jeton de l'utilisateur. Le serveur renvoie cet état tel quel, sans filtrage. Traitez-le comme une chaîne ouverte et prévoyez un affichage par défaut pour une valeur que vous ne connaissez pas.
Il existe une variante qui demande un ticket à partir du numéro de série imprimé, sans puce. Elle est authentifiée, et elle ne fonctionne que sur la toute première revendication d'un produit : un produit déjà possédé ou déjà revendiqué est refusé en 409. Un numéro imprimé prouve beaucoup moins qu'une lecture de puce, et ce verrouillage en est la conséquence. Elle n'est pas ouverte sur tous les comptes : si elle ne l'est pas sur le vôtre, elle répond 404, et c'est la seule lecture à faire de ce code sur cet appel. Vérifiez avec nous qu'elle est ouverte pour votre application avant de l'intégrer.
#Les trois écrans prêts à poser
Le module d'interface fournit trois écrans construits sur le client. Ils existent en SwiftUI et en Compose, avec les mêmes paramètres.
| Écran | Ce qu'il prend | Ce qu'il rend à votre application |
|---|---|---|
| Vérification | Le client, l'adresse scannée ou la preuve, des coordonnées facultatives, les textes. | Deux rappels : ouvrir le passeport, ou lancer la revendication. |
| Revendication | Le client, la preuve, un booléen disant si un utilisateur est connecté, le nom du produit, les textes. | Deux rappels : demander la connexion, ou annoncer la revendication faite. |
| Passeport | Le client, l'identifiant, le niveau d'accès, les textes. | Rien, c'est un écran de lecture. |
L'écran de revendication ne lance pas votre connexion. Vous lui dites si un utilisateur est connecté, il demande la connexion au lieu de déclencher un appel qui ne peut revenir qu'en 401.
Tous les textes visibles sont surchargeables champ par champ. Un jeu anglais complet et un jeu français complet sont fournis, et aucune phrase visible n'est figée à l'intérieur d'un écran.
Les couleurs sont des champs d'un thème et se remplacent une par une. Les trois écrans n'ont qu'une seule apparence : le thème porte des couleurs fixes et ne réagit pas au mode sombre du système.
#Les erreurs
Le SDK ramène tout à cinq cas.
| Cas | Quand |
|---|---|
| Adresse de scan invalide | Le lien ne portait pas de preuve exploitable. |
| Non authentifié | Un appel authentifié a été tenté sans jeton de session. |
| Erreur d'API | L'API a répondu en 4xx ou 5xx. Le cas porte le code HTTP, le détail, et le code machine quand l'API en préfixe un. |
| Décodage | Le corps de la réponse n'a pas la forme attendue. |
| Transport | La requête n'a jamais abouti : DNS, TLS, délai dépassé, pas de réseau. |
Le code machine est extrait du détail quand celui-ci commence par un mot en
majuscules contenant au moins un tiret bas, par exemple MINT_PENDING ou
CLAIM_EXPIRED. Un mot en majuscules sans tiret bas n'est jamais extrait. Le
code machine vaut une valeur vide quand l'API répond une phrase libre.
#Plafonds d'appels
Les appels du SDK visent des points d'entrée publics, dont les plafonds se comptent par adresse IP, sur une fenêtre de 60 secondes.
| Point d'entrée | Plafond |
|---|---|
| Vérification de scan | 30 par minute |
| Demande de ticket depuis un scan | 30 par minute |
| Passeport et preuves | 60 par minute |
| Certificat | 60 par minute |
| Historique du produit | 30 par minute |
| Revendication | 20 par minute |
Un dépassement revient en 429, et le SDK le traduit par le verdict « trop d'appels » sur le chemin de vérification.
#Coordonnées et vie privée
Les coordonnées sont facultatives sur la vérification de scan. Les deux paramètres valent une valeur vide par défaut, sur les deux plateformes : un intégrateur qui ne les passe jamais ne transmet rien.
Elles servent aux contrôles anti-fraude côté serveur. Ne les passez qu'avec le consentement de l'utilisateur.
Le SDK ne lit aucune position, ne demande aucune autorisation de localisation et ne vérifie pas que vous avez obtenu quoi que ce soit. Le consentement, sa trace et sa mention dans votre politique de confidentialité sont votre obligation d'éditeur de l'application.
Ce que la réponse rend en retour est une zone de scan au niveau de la ville, sous la forme d'un nom de ville et d'un code pays, et uniquement quand vous avez fourni des coordonnées. La réponse ne contient aucune coordonnée.
Sur iOS, le paquet embarque un manifeste de confidentialité Apple. Il déclare l'absence de suivi et deux types de données collectées.
La position précise, uniquement quand votre application passe des coordonnées.
L'identifiant utilisateur, c'est-à-dire le jeton de session. Le manifeste dit
qu'il est envoyé uniquement sur POST /claims/from-serial, sur
POST /claims/complete, sur GET /claims/{id}, et sur GET /passport/{id}
quand un jeton est disponible. Reprenez cette liste telle quelle si vous
remplissez la déclaration de confidentialité de l'App Store.
Sur Android, rien d'équivalent ne se déclare à l'intérieur du module. C'est l'éditeur de l'application qui remplit le formulaire de sécurité des données de la boutique, et il doit y couvrir les données collectées par chaque bibliothèque embarquée, celle-ci comprise.
#Ce qui n'est pas dans le SDK
- Le transfert de propriété entre deux personnes. Il demande un code à usage unique et un scan concordant des deux côtés. C'est un autre parcours.
- La frappe de produits et la destruction. Ce sont des opérations authentifiées, elles se conduisent depuis la console.
- La lecture des puces, le scan des QR, le chargement des images, la connexion des utilisateurs. Votre application possède déjà tout cela, et le SDK n'embarque volontairement aucune dépendance pour les faire.
Cette page vous a-t-elle été utile ?
Votre réponse ouvre un courriel pré-rempli dans votre messagerie, à destination de contact@sealtrust.io. Vous le relisez avant de l'envoyer.