Menu

Le flux Connect

Les connecteurs obtiennent une clé sans que le propriétaire de la boutique n’en copie jamais une. Deux chemins mènent au même résultat : un aller-retour navigateur avec PKCE, ou un code d’appairage saisi dans le plugin. Les deux lient la clé à l’URL de la boutique et à l’application, et apparaissent sous Intégrations › Connexions dans Wamia Shop.

Point d’accès

HTTPURL
GEThttps://api.wamia.tn/connect/authorize
POSThttps://api.wamia.tn/connect/token
POSThttps://api.wamia.tn/connect/pair
POSThttps://api.wamia.tn/connect/revoke

Autorisation avec PKCE

Envoyez le navigateur du propriétaire de la boutique vers GET /connect/authorize avec client_id (le code de votre application), une redirect_uri en https correspondant aux motifs enregistrés, la liste scope, un state d’au moins 8 caractères, un code_challenge (S256) et l’URL shop. Le propriétaire de la boutique se connecte, relit les portées sur la page de consentement et revient avec code et state.

Échangez le code sur POST /connect/token avec grant_type: authorization_code, le code_verifier, client_id, redirect_uri, votre plugin_version et shop_url. La réponse contient la clé et son budget ; le code est à usage unique et expire après 60 secondes : échangez-le dès le retour du navigateur.

Code d’appairage

Quand le plugin ne peut pas ouvrir d’aller-retour navigateur (installations en ligne de commande, back-offices sans navigateur), le propriétaire de la boutique génère un code dans le tableau de bord — Intégrations › Connexions › Appairer un plugin — et le saisit dans le plugin. Celui-ci l’envoie à POST /connect/pair avec client_id, shop_url et plugin_version et reçoit la même réponse que le point d’accès token. Les codes vivent 10 minutes et sont consommés au premier usage.

PKCE en TypeScript

connect.ts
import { createHash, randomBytes } from 'node:crypto';

const verifier = randomBytes(48).toString('base64url');            // 43–128 chars, [A-Za-z0-9-._~]
const challenge = createHash('sha256').update(verifier).digest('base64url');
const state = randomBytes(16).toString('hex');

const authorize = new URL('https://api.wamia.tn/connect/authorize');
authorize.searchParams.set('client_id', 'woocommerce');
authorize.searchParams.set('redirect_uri', 'https://shop.example.tn/wp-admin/admin.php?page=wamia');
authorize.searchParams.set('response_type', 'code');
authorize.searchParams.set('code_challenge', challenge);
authorize.searchParams.set('code_challenge_method', 'S256');
authorize.searchParams.set('scope', 'offers.manage catalog.media inventory.adjust orders.read orders.fulfil webhooks.manage');
authorize.searchParams.set('state', state);
authorize.searchParams.set('shop', 'https://shop.example.tn');
// Send the shop owner's browser to authorize.toString(); on return, verify state and exchange:

const token = await fetch('https://api.wamia.tn/connect/token', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code', code, code_verifier: verifier, client_id: 'woocommerce',
    redirect_uri, plugin_version: '1.2.0', shop_url: 'https://shop.example.tn',
  }),
}).then((r) => r.json());
// → { api_key: 'wamia_…', key_prefix, key_id, connection_id, organization_id, scopes[], expires_at,
//     rate_limit: { reads_per_minute, writes_per_minute, bulk_per_minute } }
// Store api_key encrypted at rest: it is shown once. Rotate before expires_at (365 days).

Appairage avec curl

curl
curl -sS https://api.wamia.tn/connect/pair \
  -H 'content-type: application/json' \
  --data '{ "code": "K7P2M9QX", "client_id": "prestashop", "shop_url": "https://shop.example.tn", "plugin_version": "1.0.0" }'
# → { "api_key": "wamia_…", "key_prefix": "…", "connection_id": "…", "organization_id": "…", "scopes": [ … ], "expires_at": "…", "rate_limit": { … } }

POST /connect/token

NomSignification
api_keyLe secret, affiché une fois. Préfixe wamia_ ; stockez-le chiffré.
key_prefix / key_idIdentifiants sans risque à journaliser et afficher dans vos réglages.
connection_idLa connexion que la boutique voit dans le tableau de bord.
organization_idLa boutique ; chaque ressource que vous touchez lui appartient.
scopesCe qui a été accordé — parfois moins que demandé.
expires_at365 jours après l’émission ; faites tourner avant.
rate_limitreads_per_minute, writes_per_minute, bulk_per_minute pour ce type de clé.

Cycle de vie de la clé

Liaison

Les clés connecteur sont liées à shop_url et à l’application. Un appel depuis un autre hôte est refusé avec UNAUTHENTICATED ; une copie de préproduction de la boutique a besoin de sa propre connexion.

Rotation

Appelez apiRotateKey 30 jours avant expires_at (le tableau de bord le rappelle aussi à la boutique). La réponse porte la nouvelle clé ; l’ancienne fonctionne encore 24 heures pour qu’un déploiement à moitié fini ne perde pas de commandes.

Version minimale

L’équipe Wamia peut relever la version minimale d’un connecteur. Les plugins plus anciens reçoivent CONNECTOR_UPGRADE_REQUIRED (HTTP 426) avec extensions.minSupportedVersion à chaque appel jusqu’à leur mise à jour ; affichez la bannière et arrêtez les planificateurs plutôt que de réessayer.

Révocation et déconnexion

La boutique peut révoquer une connexion depuis le tableau de bord ; le plugin peut appeler POST /connect/revoke avec la clé. Ensuite chaque appel répond CONNECTION_REVOKED. Le plugin doit alors effacer la clé, arrêter ses planificateurs et garder les données locales — Wamia ne supprime jamais les annonces d’une boutique à la déconnexion.