Validation des commandes
La création de produits Snipcart se résume à ajouter un bouton à votre site et à le définir avec des attributs data.
Vous vous demandez peut-être :
"Que se passe-t-il si je modifie les informations sur les produits avec les outils de développement de mon navigateur? Je pourrai trafiquer le prix et passer des commandes frauduleuses."
Notre processus de validation des commandes est la façon dont nous garantissons l'intégrité de la commande tout au long du processus de paiement. Avant qu'une commande soit créée, nos serveurs récupèrent chaque article du panier depuis votre propre site web et comparent ce que le client s'apprête à payer avec ce que votre site annonce réellement.
- Le fonctionnement
- Ce que nous comparons
- Attribut data-item-url
- Domaines et sous-domaines
- Nos appels vers votre site
- Indexeur JSON
- Importer des produits depuis un document JSON
- Diagnostic
Le fonctionnement
La validation s'exécute lorsque le client confirme le paiement, une fois pour chaque article du panier :
- Nous transformons l'attribut
data-item-urlde l'article en URL absolue. - Nous vérifions que cette URL se trouve sur l'un de vos domaines autorisés.
- Nous y envoyons une requête
GET. - Si l'en-tête
Content-Typede la réponse estapplication/json, notre indexeur JSON la lit. Sinon, nous analysons le HTML et cherchons le bouton d'achat portant l'identifiant de l'article. - Nous comparons la définition récupérée avec l'article présent dans le panier.
Chaque article doit passer. Si un seul échoue, le paiement est refusé et aucune commande n'est créée.
Ce que nous comparons
| Élément | Indexeur HTML | Indexeur JSON |
|---|---|---|
| Identifiant de l'article | data-item-id |
id |
| Prix | data-item-price |
price |
| Prix alternatifs | data-{attribut du rabais} |
otherPossiblePrices |
| Champs personnalisés, et les modificateurs de prix de leurs options | data-item-custom{n}-* |
customFields |
| Dimensions | data-item-weight, data-item-width, data-item-height, data-item-length |
dimensions |
| Fichier d'un bien numérique | data-item-file-guid |
fileGuid |
| Plans d'abonnement | data-plan{n}-* |
availablePlans |
| Quantité maximale | data-item-max-quantity |
— |
| Stock | — | stock, allowOutOfStockPurchases |
Le nom, la description et l'image de l'article ne sont pas comparés : ils ne peuvent pas changer ce que le client paie.
Attribut data-item-url
Lors de la configuration d'un produit, il y a un attribut obligatoire appelé data-item-url. C'est là que nous allons chercher la définition de l'article, elle doit donc être une URL où le bouton d'achat Snipcart pour ce produit est disponible.
Quatre formes sont acceptées :
| Forme | Exemple | Ce que nous appelons |
|---|---|---|
| Absolue | https://exemple.com/produits/1 |
l'URL telle quelle |
| Relative à la racine | /produits/1 |
votre domaine par défaut, plus le chemin |
| Relative au protocole | //boutique.exemple.com/produits/1 |
l'hôte fourni, avec votre protocole configuré |
| Chaîne de requête seulement | ?produit=1 |
votre domaine par défaut, plus la chaîne de requête |
Les trois formes relatives sont résolues à partir du domaine web par défaut défini dans votre tableau de bord, avec le protocole configuré à côté. Elles ne peuvent pas être utilisées tant que ce champ est vide : la commande échoue avec un message vous demandant de le remplir.
Avis important : pour les utilisateurs ayant un site web monopage, le champ data-item-url doit uniquement être rempli avec votre nom de domaine racine, tel que www.exemple.com, ou avec une simple barre oblique /.
Un fragment (#details) est retiré de l'URL avant l'envoi de la requête.
Vous pouvez en savoir plus à ce sujet dans l'entrée sur la sécurité.
Domaines et sous-domaines
Avant de commencer à vendre, vous devez autoriser les domaines et sous-domaines où Snipcart peut explorer vos produits. Dans votre tableau de bord, sous Store configurations → Domains & URLs, vous pouvez définir votre nom de domaine par défaut ainsi que les domaines et sous-domaines supplémentaires autorisés.
Nous acceptons une URL lorsque son hôte correspond à votre domaine par défaut ou à l'un de vos domaines autorisés. La comparaison porte sur le nom d'hôte, et un préfixe www. est ignoré des deux côtés : exemple.com et www.exemple.com sont interchangeables.
Tout le reste doit être inscrit explicitement. Par exemple, si la valeur de data-item-url est https://test.exemple.com/produits/1 et que votre domaine par défaut est exemple.com, notre validation échouera. Vous devez ajouter test.exemple.com dans les sous-domaines autorisés pour que cela fonctionne.
Nos appels vers votre site
Chaque validation est une simple requête GET provenant de nos serveurs, sans témoins et sans authentification. L'URL doit donc être accessible publiquement. Si vous développez localement, cet article montre comment travailler avec Snipcart derrière ngrok.
Trois en-têtes permettent d'identifier une requête comme étant la nôtre :
User-Agent: Snipcart/1.0
X-Snipcart-Purpose: Crawling
X-Snipcart-RequestToken: {token}Nous envoyons également Cache-Control: no-store, max-age=0, et nous suivons une seule redirection : 301, 302, 307 et 308.
Valider le jeton de requête
X-Snipcart-RequestToken est un jeton aléatoire généré par nos serveurs. Pour confirmer qu'une requête provient bien de Snipcart, appelez notre API avec ce jeton, en vous authentifiant avec votre clé API secrète :
GET https://app.snipcart.com/api/requestvalidation/{token}Un 200 signifie que le jeton est authentique. Le corps de la réponse contient aussi la ressource (resource) que nous avons demandée, ce qui vous permet de la comparer à l'URL appelée. Un 404 signifie que le jeton est inconnu, déjà validé ou expiré.
Deux contraintes sont propres aux requêtes de validation :
- Le jeton est valide une minute. Validez-le pendant que vous traitez la requête, pas depuis une file d'attente ou une tâche en arrière-plan.
- Le jeton ne peut être validé qu'une seule fois. Un deuxième appel retourne
404.
Le même en-tête est envoyé avec les requêtes de webhooks.
Indexeur JSON
Lorsque Snipcart valide l'intégrité d'une commande, il utilise la valeur spécifiée dans l'attribut data-item-url de chaque produit.
La plupart du temps, cette valeur sera l'URL unique où vous vendez l'article, et notre indexeur HTML trouve le bouton d'achat sur cette page. Cependant, les sites des commerçants peuvent parfois exiger des scénarios de validation plus complexes.
Si c'est votre cas, il existe une alternative à notre indexeur HTML par défaut : notre indexeur JSON. Il n'y a rien à activer : lorsque Snipcart fait la requête à l'URL, si l'en-tête Content-Type de votre réponse est application/json, nous utiliserons notre validateur JSON au lieu du validateur HTML.
Vous devez nous retourner un objet JSON ayant les propriétés suivantes.
| Propriété | Obligatoire? | Description |
|---|---|---|
id |
Oui | Le même identifiant que celui spécifié dans la définition du produit dans votre HTML. |
price |
Oui | Un nombre, ou un objet dont les clés sont des devises pour les boutiques multidevises. |
customFields |
Si l'article a des champs personnalisés | N'a besoin de contenir que les champs obligatoires ou qui modifient le prix. Retournez [] si aucun ne le fait. |
url |
Recommandé | N'est pas comparé lors de la validation, mais utilisé pour importer des produits dans votre tableau de bord. |
dimensions |
Si l'article a des mesures | weight, width, height et length. |
fileGuid |
Pour les biens numériques | Doit correspondre au GUID de fichier de l'article. |
otherPossiblePrices |
Pour les rabais à prix alternatif | Un tableau d'objets code / price. |
availablePlans |
Pour les abonnements | Les plans avec lesquels l'article peut être acheté. |
stock, allowOutOfStockPurchases |
Facultatif | Vérifiés au paiement, et pas seulement lors de l'importation des produits. |
valid |
Facultatif | Accepte l'article sans aucune autre vérification. |
{
"id": "20",
"price": 50.00,
"customFields": [],
"url": "https://exemple.com/produits/1.json"
}Champs personnalisés
Seuls les champs personnalisés obligatoires ou qui modifient le prix doivent être listés. Si l'article a des champs personnalisés mais qu'aucun ne correspond à ces cas, retournez un tableau vide.
{
"id": "20",
"price": 50.00,
"customFields": [
{
"name": "Frame color",
"options": "Black|Brown[+100.00]|Gold[+300.00]"
},
{
"name": "Note",
"required": true
}
],
"url": "/"
}Les options et leurs modificateurs de prix doivent être les mêmes que dans la définition de votre produit. Un champ portant un modificateur de prix absent de votre réponse échoue à la validation comme une différence de prix.
Devises multiples
Si vous utilisez notre fonctionnalité multidevise, la propriété price peut être un objet avec plusieurs devises.
{
"id": "20",
"price": {
"usd": 30.00,
"cad": 35.00
},
"url": "/"
}Chaque devise dans laquelle vous vendez doit s'y trouver. Si la devise du panier est absente de l'objet, nous ne pouvons lire aucun prix et l'article est signalé comme inaccessible plutôt que comme une différence de prix.
Dimensions
Si vous fournissez des mesures précises pour votre produit, incluez la propriété dimensions. Elle est comparée dans son ensemble : envoyer des dimensions pour un article qui n'en déclare aucune échoue de la même manière qu'en envoyer de mauvaises.
{
"id": "20",
"price": 50.00,
"dimensions": {
"weight": 300,
"width": 20,
"height": 10,
"length": 30
},
"url": "/"
}Prix alternatifs
Si un rabais du panier définit un prix alternatif, indiquez-le sous otherPossiblePrices. Le code est le nom du prix alternatif configuré sur le rabais, le même nom que vous mettriez dans l'attribut data- avec l'indexeur HTML.
{
"id": "20",
"price": 50.00,
"otherPossiblePrices": [
{
"code": "vip",
"price": 35.00
}
],
"url": "/"
}Sans cela, un panier contenant ce rabais échoue avec une différence de prix.
Retourner plusieurs produits à la fois
Vous pouvez également retourner un tableau contenant plusieurs objets comme définis ci-dessus. Nous cherchons l'entrée dont le id correspond à l'article en cours de validation.
[
{
"id": "20",
"price": 50.00,
"url": "https://exemple.com/produits.json"
},
{
"id": "21",
"price": 100.00,
"url": "https://exemple.com/produits.json"
}
]Cela peut être utile lorsque votre site web est piloté par un API et utilise un framework monopage tel que React ou Vue.
Passer outre les vérifications pour un article
Retourner "valid": true nous indique que votre propre point de terminaison a déjà vérifié la ligne. Nous acceptons l'article tel quel et sautons toutes les autres vérifications : prix, champs personnalisés, dimensions, GUID de fichier, plans et stock inclus.
{
"valid": true
}Utilisez cette propriété avec parcimonie. Comme elle court-circuite tout, un point de terminaison qui répond valid: true à chaque requête — une route attrape-tout, par exemple — désactive la validation des prix pour toute votre boutique, et rien dans votre tableau de bord ne vous l'indiquera.
Dans un tableau, l'entrée est tout de même repérée par son id d'abord.
Importer des produits depuis un document JSON
À partir de notre tableau de bord, vous pouvez récupérer des produits si vous avez besoin de définir un stock d'inventaire, par exemple. Si vous utilisez notre validateur JSON, vous pouvez également utiliser vos documents JSON pour récupérer les produits.
Le document peut être un fichier JSON contenant tous vos produits dans un tableau ou un produit individuellement.
Une importation lit plus de propriétés que la validation : name, image, description, categories, metadata, inventoryManagementMethod et variants.
L'exemple suivant représente un seul produit qui peut être récupéré. Veuillez noter que cet exemple définit également des niveaux de stock par défaut.
{
"id": "JSON_PRODUCT",
"name": "JSON Product",
"url": "/products.json",
"price": 20.00,
"image": "http://placehold.it/300x300",
"inventoryManagementMethod": "Variant",
"dimensions": {
"weight": 300,
"width": 20,
"height": 10,
"length": 30
},
"variants": [
{
"variation": [
{
"name": "Color",
"option": "Red"
},
{
"name": "Size",
"option": "Small"
}
],
"stock": 10,
"allowOutOfStockPurchases": true
}
],
"categories": ["category1", "category2"],
"customFields": [
{
"name": "Size",
"options": "Small|Medium|Large",
"type": "dropdown"
},
{
"name": "Color",
"options": "Red|Blue|Green",
"type": "dropdown"
}
]
}Diagnostic
| Ce que vous voyez | Où regarder en premier |
|---|---|
| Nous n'avons pas pu joindre l'article | L'URL n'est pas accessible publiquement, son domaine ne fait pas partie de vos domaines autorisés, ou data-item-url est relative alors que votre domaine par défaut est vide. |
| L'article est introuvable | L'identifiant sur la page explorée, ou dans le document JSON, ne correspond pas au data-item-id de l'article. |
| Le prix ne correspond pas | Le prix a changé après l'ajout de l'article au panier, un rabais à prix alternatif est absent de otherPossiblePrices, ou le modificateur de prix d'un champ personnalisé est absent de la définition récupérée. |
| Un champ personnalisé obligatoire est manquant | La définition récupérée marque un champ comme obligatoire et le panier le contient vide. |
Les articles sont validés avec le prix, les champs personnalisés et les options qu'ils avaient au moment de leur ajout au panier. Modifier les attributs d'un article en JavaScript une fois qu'il est dans le panier cause une différence.