Exigences de sécurité
Chaque application installée sur une boutique DZBuild détient un jeton vers les commandes, les clients ou le catalogue d'un marchand. Ces règles s'appliquent à toutes les applications, en mode test comme après approbation. DZBuild peut suspendre une application qui les enfreint, et une application suspendue reçoit 403 app_suspended à chaque appel.
Adresses de redirection
Enregistrez 1 à 5 adresses de redirection dans la console développeur. Chacune doit :
- utiliser
https, - faire 512 caractères au plus,
- ne contenir ni nom d'utilisateur, ni mot de passe, ni
#fragment, - ne contenir aucun joker
*.
DZBuild compare le redirect_uri de chaque requête à la liste enregistrée, caractère pour caractère. https://app.example.com/callback et https://app.example.com/callback/ sont deux adresses différentes. La console n'accepte que https : pour tester le flux d'installation, passez par une adresse workers.dev ou un tunnel https et enregistrez cette adresse.
Générez un state aléatoire nouveau pour chaque demande d'autorisation, liez-le à la session du marchand, et refusez un retour dont le state ne correspond pas.
Client secret et jetons d'accès
Le client secret (dzas_ suivi de 48 caractères hexadécimaux) s'affiche une seule fois, à la création de l'application ou au renouvellement du secret. DZBuild n'en garde qu'une empreinte. Utilisez-le uniquement sur votre serveur : jamais dans un navigateur, une application mobile, un dépôt public ou une ligne de journal.
En cas de fuite du secret, renouvelez-le dans la console développeur. L'ancien secret cesse de fonctionner immédiatement, et les jetons d'accès déjà émis continuent de fonctionner.
Les jetons d'accès (dzpk_live_...) donnent l'accès à l'API que le marchand a approuvé, sans expiration. Gardez-les côté serveur, chiffrés au repos, un par boutique. Les applications n'ont aucun endpoint pour révoquer un jeton. En cas de fuite d'un jeton, demandez au marchand d'installer de nouveau votre application sur cette boutique : le nouveau jeton remplace l'ancien immédiatement. Le marchand peut aussi désinstaller l'application, ce qui le révoque.
Vérifier les signatures des webhooks
Chaque webhook que DZBuild envoie à votre application est signé avec le secret de signature de l'application, une chaîne hexadécimale de 64 caractères que vous pouvez afficher et renouveler dans la console. La requête porte X-DZ-Timestamp, X-DZ-Event, X-DZ-Delivery et :
X-DZ-Signature: t=1758880000,v1=5d41402abc4b2a76b9719d911017c592...
Calculez un HMAC-SHA256 avec le secret de signature sur l'horodatage, un point et le corps brut de la requête, comparez-le à v1 en temps constant, et rejetez une requête dont l'horodatage a plus de 5 minutes. Les endpoints webhook des applications ne reçoivent jamais l'en-tête X-DZ-Token : la signature est la seule preuve qu'une requête vient de DZBuild. La page webhooks donne le schéma complet et du code dans plusieurs langages.
Un seul secret de signature couvre toutes les boutiques qui ont installé votre application. Le renouveler change la clé de toutes en une seule opération.
Vérifier les jetons d'ouverture
Quand le marchand ouvre votre application depuis le tableau de bord DZBuild, DZBuild redirige le navigateur vers votre lien d'ouverture avec un paramètre de requête dz_launch. Le lien d'ouverture doit utiliser https. Le paramètre est un JWT signé en HS256 avec le secret de signature de l'application : la chaîne de 64 caractères exactement comme la console l'affiche.
| Claim | Valeur |
|---|---|
iss | dzbuild |
aud | Votre client_id. |
sub | L'identifiant de l'utilisateur DZBuild qui a ouvert l'application, en chaîne. |
store_id | La boutique depuis laquelle l'application a été ouverte. |
install_id | Votre installation sur cette boutique. |
is_owner | true pour le propriétaire de la boutique, false pour un membre d'équipe. |
iat | Heure d'émission, en secondes Unix. |
exp | iat plus 300 secondes. |
jti | 16 caractères hexadécimaux aléatoires. |
N'acceptez le jeton que si la signature correspond, que l'en-tête indique HS256, que iss vaut dzbuild, que aud est votre identifiant client et que exp n'est pas dépassé. Refusez ensuite tout jti déjà accepté dans les 5 dernières minutes. Après avoir lu le jeton, redirigez vers une URL qui ne le contient plus, pour qu'il reste hors de l'historique du navigateur et des journaux.
Un jeton d'ouverture prouve qui a ouvert l'application et depuis quelle boutique. Il n'appelle pas l'API : utilisez le jeton d'accès enregistré pour ce store_id et cet install_id.
En PHP :
<?php
/** Claims of a valid dz_launch token, or null. $clientId is your app's client_id. */
function verifyLaunchToken(string $jwt, string $signingSecret, string $clientId): ?array
{
$parts = explode('.', $jwt);
if (count($parts) !== 3) {
return null;
}
[$head, $body, $sig] = $parts;
$b64 = static fn(string $s): string|false => base64_decode(strtr($s, '-_', '+/'), true);
$expected = rtrim(strtr(base64_encode(hash_hmac('sha256', "$head.$body", $signingSecret, true)), '+/', '-_'), '=');
if (!hash_equals($expected, $sig)) {
return null;
}
$header = json_decode((string) $b64($head), true);
$claims = json_decode((string) $b64($body), true);
if (($header['alg'] ?? '') !== 'HS256' || !is_array($claims)) {
return null;
}
$now = time();
if (($claims['iss'] ?? '') !== 'dzbuild' || ($claims['aud'] ?? '') !== $clientId
|| !is_int($claims['exp'] ?? null) || $claims['exp'] < $now || ($claims['iat'] ?? 0) > $now + 60) {
return null;
}
return $claims; // Then refuse a jti you have already seen in the last 5 minutes.
}
En Node.js :
const crypto = require('node:crypto');
// Claims of a valid dz_launch token, or null. clientId is your app's client_id.
function verifyLaunchToken(jwt, signingSecret, clientId) {
const parts = String(jwt).split('.');
if (parts.length !== 3) return null;
const [head, body, sig] = parts;
const expected = crypto.createHmac('sha256', signingSecret).update(`${head}.${body}`).digest();
const given = Buffer.from(sig, 'base64url');
if (given.length !== expected.length || !crypto.timingSafeEqual(given, expected)) return null;
const header = JSON.parse(Buffer.from(head, 'base64url').toString('utf8'));
const claims = JSON.parse(Buffer.from(body, 'base64url').toString('utf8'));
const now = Math.floor(Date.now() / 1000);
if (header.alg !== 'HS256' || claims.iss !== 'dzbuild' || claims.aud !== clientId) return null;
if (!Number.isInteger(claims.exp) || claims.exp < now || claims.iat > now + 60) return null;
return claims; // Then refuse a jti you have already seen in the last 5 minutes.
}
Supprimer les données après la désinstallation
Quand un marchand désinstalle votre application, DZBuild révoque le jeton de la boutique, abandonne les livraisons webhook encore en attente pour cette installation, et envoie un seul événement app.uninstalled à votre URL de webhook si elle est vérifiée et active :
{
"id": "evt_...",
"event": "app.uninstalled",
"created_at": "2026-09-26T10:15:00+01:00",
"store_id": 141,
"data": {
"install_id": 57,
"client_id": "dzapp_0123456789abcdef0123",
"store_id": 141,
"uninstalled_at": "2026-09-26T09:15:00+00:00"
}
}
Supprimez les données que vous détenez pour cette boutique dans les 30 jours qui suivent l'événement : commandes, clients, produits et toute copie du jeton d'accès. Si votre application n'a pas d'URL de webhook vérifiée, un 401 sur le jeton de la boutique est votre signal.
Demander le moins de scopes possible
Demandez uniquement les scopes que vos fonctionnalités utilisent : pas de scope d'écriture sur des données que vous ne faites que lire, pas de customers:read pour une application qui n'affiche jamais de client. DZBuild compare les scopes demandés à ce que votre fiche dit de l'application, et le marchand voit une ligne par ressource sur l'écran de consentement avant d'approuver.
Pas d'extraction automatisée
N'accédez aux données de la boutique que par l'API REST et les webhooks. N'automatisez pas le tableau de bord DZBuild, ne vous connectez pas à la place du marchand, et n'extrayez pas les pages du tableau de bord ou de la boutique en ligne. Ne demandez jamais à un marchand son mot de passe DZBuild ni une clé API marchand.
Répondre à l'e-mail de support
Enregistrez une adresse e-mail de support que vous lisez, et répondez aux marchands qui y écrivent. L'écran de consentement et la page de l'application dans le tableau de bord du marchand l'affichent. DZBuild envoie les décisions de vérification à l'e-mail de votre compte, pas à cette adresse.