Passer au contenu

Présentation

Les webhooks sont des notifications déclenchées par des événements système. Lorsqu'un événement spécifique se produit, Xsolla envoie à votre application une requête HTTP, généralement sous la forme d'une requête POST au format JSON, contenant les données de l'événement.

Exemples d'événement :

  • interaction de l'utilisateur avec le catalogue des objets ;
  • paiement ou annulation d'une commande.

Lorsqu'un événement se produit, Xsolla envoie une notification à votre système via un webhook. Vous pouvez ensuite effectuer des actions telles que :

  • recharger le solde de l'utilisateur ;
  • effectuer un remboursement de paiement ;
  • créditer des objets au compte de l'utilisateur ou en débiter ;
  • commencer à fournir un abonnement ;
  • bloquer un utilisateur en cas de soupçon de fraude.

Exemple de flux de travail d'un webhook de traitement de paiement :

Webhook de traitement de paiement

Note

En fonction de la solution utilisée et du type d'intégration, l'ensemble des webhooks et la séquence des interactions peuvent différer de l'exemple fourni.

Guide vidéo pour l'intégration des webhooks Xsolla :

Paramètres des webhooks lors de l'interaction avec les produits et solutions Xsolla :

Produit/SolutionObligatoire/FacultatifÀ quoi servent les webhooks ?
PaymentsObligatoire
  • Validation utilisateur.
  • Réception d'informations détaillées sur la transaction en cas de paiement réussi ou de remboursement de paiement.
  • Octroi des objets achetés à l'utilisateur et déduction de ceux-ci en cas d'annulation de la commande.
StoreObligatoire
  • Validation utilisateur.
  • Réception d'informations détaillées sur la transaction en cas de paiement réussi ou de remboursement de paiement.
  • Octroi des objets achetés à l'utilisateur et déduction de ceux-ci en cas d'annulation de la commande.
Game SalesFacultatifPour la vente de clés de jeu, la validation utilisateur et le crédit des objets ne sont pas nécessaires. Connectez des webhooks si vous souhaitez recevoir des informations sur des événements tels que le paiement ou l'annulation de commandes.
Assurez-vous de traiter tous les webhooks entrants requis.
SubscriptionsFacultatifRéception d'informations sur la création, la mise à jour ou l'annulation d'abonnements. Vous pouvez également demander des informations via API.
Web ShopObligatoire
  • Validation utilisateur.
  • Réception d'informations détaillées sur la transaction en cas de paiement réussi ou de remboursement de paiement.
  • Octroi des objets achetés à l'utilisateur et déduction de ceux-ci en cas d'annulation de la commande.
  • Authentification utilisateur, si vous utilisez l'authentification par ID utilisateur. Vous pouvez également utiliser l'authentification utilisateur via Xsolla Login.
Digital Distribution HubObligatoire
  • Validation utilisateur.
  • Liaison de l'ID de transaction côté Xsolla à l'ID de transaction de votre système.
  • Transfert de paramètres de transaction supplémentaires dans la commande.
  • Octroi des objets achetés à l'utilisateur et déduction de ceux-ci en cas d'annulation de la commande.

Reportez-vous à la documentation pour obtenir plus d'informations sur la configuration des webhooks pour Digital Distribution Hub.

LoginFacultatif

Réception d'informations sur les événements :

  • enregistrement/autorisation d'utilisateur
  • confirmation d'adresse e-mail d'utilisateur
  • liaison du compte de réseau social de l'utilisateur

Reportez-vous à la documentation Login pour des informations détaillées sur la configuration des webhooks.

Liste des webhooks requis

Si vous utilisez des produits et des solutions nécessitant de travailler avec des webhooks, activez et testez ces webhooks dans votre Compte éditeur, puis configurez leur traitement. Lorsque des événements spécifiques se produisent, les webhooks sont envoyés de manière séquentielle. Assurez-vous de traiter tous les webhooks requis, sinon les suivants ne seront pas envoyés. La liste des webhooks requis est présentée ci-dessous.

Store et Payments

Deux options d'envoi de webhook sont configurées côté Xsolla lors de l'achat et du retour de biens sur le site : les informations sur les données de paiement et de transaction, ainsi que celles sur les biens achetés, peuvent être envoyées séparément ou être combinées dans un seul webhook.

Réception d'informations dans des webhooks combinés :

Si vous avez enregistré un Compte éditeur après le 22 janvier 2025, vous recevez toutes les informations dans les webhooks Paiement de commande réussi (order_paid) et Annulation de commande (order_canceled). Dans ce cas, vous n'avez pas besoin de traiter les webhooks Paiement (payment) et Remboursement (refund).

Réception d'informations dans des webhooks distincts :

Si vous avez enregistré un Compte éditeur au plus tard le 22 janvier 2025, vous recevez les webhooks suivants  :

Vous devez traiter tous les webhooks entrants. Pour passer à la nouvelle option de réception des webhooks combinés, contactez vos responsables de la réussite client ou envoyez un e-mail à csm@xsolla.com.

Pour assurer le fonctionnement complet du magasin en jeu et de la gestion des paiements, il est nécessaire d'implémenter le traitement des principaux webhooks.

Si vous recevez des webhooks combinés :

Nom et type du webhookDescription
Validation utilisateur >Validation utilisateur (user_validation)Est envoyé à différentes étapes du processus de paiement pour s'assurer que l'utilisateur est enregistré dans le jeu.
Services de jeux > Webhooks combinés >Paiement de commande réussi (order_paid)Il contient les données du paiement et de la transaction ainsi que des informations sur les biens achetés. Utilisez les données du webhook pour octroyer les objets à l'utilisateur.
Services de jeux > Webhooks combinés >Annulation de commande (order_canceled)Il contient les données du paiement annulé et de la transaction ainsi que des informations sur les biens achetés. Utilisez les données du webhook pour retirer les objets achetés.

Si vous recevez des webhooks distincts :

Nom et type du webhookDescription
Validation utilisateur >Validation utilisateur (user_validation)Est envoyé à différentes étapes du processus de paiement pour s'assurer que l'utilisateur est enregistré dans le jeu.
Payments >Paiement (payment)Il contient les données du paiement et de la transaction.
Services de jeux > Webhooks distincts >Paiement de commande réussi (order_paid)Il contient des informations sur les biens achetés. Utilisez les données du webhook pour octroyer les objets à l'utilisateur.
Payments >Remboursement (refund )Il contient les données du paiement et de la transaction.
Services de jeux > Webhooks distincts >Annulation de commande (order_canceled)Il contient des informations sur les biens achetés et l'ID de la transaction annulée. Utilisez les données du webhook pour retirer les objets achetés.

Si la personnalisation du catalogue des objets est implémentée du côté de votre application, configurez le traitement du webhook Personnalisation du catalogue côté partenaire.

Note

Pour recevoir des paiements réels, vous devez simplement signer le contrat de licence et implémenter le traitement des webhooks :

Subscriptions

Pour gérer les plans d'abonnement de manière automatique, il est nécessaire d'implémenter le traitement des principaux webhooks :

  • Validation utilisateur (user_validation) — envoyé à différentes étapes du processus de paiement pour s'assurer que l'utilisateur est bel et bien enregistré dans le jeu.
  • Paiement (payment) — envoyé lorsqu'une commande est payée et contient les données de paiement ainsi que les détails de la transaction.
  • Abonnement créé (create_subscription) — envoyé lorsqu'un webhook Paiement est traité avec succès ou lorsque l'utilisateur achète un abonnement avec une période d'essai. Il contient les détails de l'abonnement acheté ainsi que les données de l'utilisateur. Utilisez les données du webhook pour ajouter l'abonnement à l'utilisateur.
  • Abonnement mis à jour (update_subscription) — envoyé lorsqu'un abonnement est renouvelé ou modifié, lorsqu'un webhook Paiement est traité avec succès. Il contient les détails de l'abonnement acheté et les données de l'utilisateur. Utilisez les données du webhook pour prolonger l'abonnement de l'utilisateur ou modifier les paramètres de l'abonnement.
  • Remboursement (refund) — envoyé lorsqu'une commande est annulée et contient les données du paiement annulé ainsi que les détails de la transaction.
  • Abonnement annulé (cancel_subscription) — envoyé lorsqu'un webhook Remboursement est traité avec succès ou lorsque l'abonnement est annulé pour une autre raison. Il contient des informations sur l'abonnement et les données de l'utilisateur. Utilisez les données du webhook pour déduire les abonnements achetés de l'utilisateur.

Configurer les webhooks dans le Compte éditeur

Paramètres généraux

Pour activer la réception des webhooks :

  1. Dans le projet dans le Compte éditeur, accédez à la section Project settings > Webhooks.
  2. Dans le champ Webhook server, spécifiez l'URL du serveur où vous souhaitez recevoir des webhooks au format https://example.com. Vous pouvez également indiquer l'URL que vous trouvez dans un outil de test de webhooks.

Attention

Le protocole HTTPS est utilisé pour transférer les données ; le protocole HTTP n'est pas pris en charge.

  1. Générez une clé secrète :
    1. Dans la section Secret keys, appuyez sur Add key.
    2. Dans la fenêtre modale qui s'ouvre, entrez un nom pour identifier facilement la clé dans la liste générale.
    3. Appuyez sur Create key.
    4. Appuyez sur Copy secret et enregistrez la clé générée de votre côté.
    5. Appuyez sur Done.
    6. Confirmez que vous avez bel et bien enregistré la clé et appuyez sur Ok, close.

Ajoutez une 
clé

Important

Recommandations concernant la clé :

  • Enregistrez la clé secrète générée de votre côté. Elle s'affichera qu'une seule fois dans le Compte éditeur, au moment de sa création.
  • Ne communiquez votre clé secrète à personne.
  • La clé secrète doit être stockée sur votre serveur et jamais dans des binaires ni côté client.

  1. Appuyez sur Enable webhooks.

Note

Pour tester les webhooks, sélectionnez n'importe quel site Web dédié, tel que webhook.site, ou une plateforme, telle que ngrok.

Remarque

Il est impossible d'envoyer simultanément des webhooks à différentes URL. Une approche consiste à spécifier d'abord une URL pour les tests dans le Compte éditeur, puis à la remplacer par l'URL réelle.

Pour désactiver la réception de webhooks :

  1. Dans le projet dans le Compte éditeur, accédez à la section Project settings > Webhooks.
  2. Cliquez sur Disable webhooks.

Rotation des clés secrètes

La rotation régulière des clés secrètes renforce la sécurité de votre intégration. Créez jusqu'à 5 clés secrètes par projet afin de faciliter leur rotation. Pour ce faire, suivez les étapes ci-dessous :

  1. Dans la section Project settings > Webhooks, appuyez sur Add key.

Ajoutez une 
clé

  1. Dans la fenêtre modale qui s'ouvre, entrez un nom pour identifier facilement la clé dans la liste générale.
  2. Appuyez sur Create key.
  3. Appuyez sur Copy secret et enregistrez la clé générée de votre côté.
  4. Appuyez sur Done.
  5. Confirmez que vous avez bel et bien enregistré la clé et appuyez sur Ok, close.

Important

Recommandations concernant la clé :

  • Enregistrez la clé secrète générée de votre côté. Elle s'affichera qu'une seule fois dans le Compte éditeur, au moment de sa création.
  • Ne communiquez votre clé secrète à personne.
  • La clé secrète doit être stockée sur votre serveur et jamais dans des binaires ni côté client.

Il ne peut y avoir qu'une seule clé secrète active par projet. Pour la modifier, appuyez sur Set as active sur la ligne d'une autre clé, puis confirmez l'action. Une fois la migration vers la nouvelle clé effectuée, nous vous recommandons de supprimer les clés désactivées.

Changez une clé 
active

Paramètres avancés

Pour les webhooks de la section Payments and Store, des paramètres avancés sont disponibles. Ils apparaîtront automatiquement sous le bloc General settings après que vous aurez cliqué sur le bouton Get webhooks.

Note

Si les paramètres avancés ne s'affichent pas, assurez-vous que la réception de webhook est connectée dans les paramètres généraux et que vous êtes sur l'onglet Testing > Payments and Store.

Dans cette section, vous pouvez configurer la réception d'informations supplémentaires dans les webhooks. Pour ce faire, réglez les bascules correspondantes en position active. La ligne de chaque autorisation indique les webhooks qui seront affectés par la modification des paramètres.

BasculeDescription
Afficher les informations du compte de paiement enregistré (visible uniquement si votre Compte éditeur a été créé au plus tard le 22 janvier 2025 et si vous recevez des webhooks distincts).Les informations relatives au mode de paiement enregistré sont passées à l'objet personnalisé payment_account.
Afficher les informations relatives aux transactions effectuées via les modes de paiement enregistrés.

Les informations sont passées dans les paramètres personnalisés suivants du webhook :

  • saved_payment_method:
    • 0 — le mode de paiement enregistré n'a pas été utilisé ;
    • 1 — le mode de paiement a été enregistré lors du paiement en cours ;
    • 2 — le mode de paiement précédemment enregistré est utilisé.
  • payment_type:
    • 1 — paiement unique ;
    • 2 — paiement récurrent.
Ajouter l'objet order au webhook (affiché uniquement si votre Compte éditeur a été créé au plus tard le 22 janvier 2025 et que vous recevez des webhooks distincts).Les informations relatives à la commande sont passées dans l'objet order du webhook Paiement.
Envoyer uniquement des paramètres utilisateur nécessaires sans données sensibles.

Seules les informations suivantes sur l'utilisateur sont passées dans le webhook :

  • ID ;
  • pays.
Envoyer des paramètres personnalisésLes informations relatives aux paramètres du jeton personnalisé sont passées dans le webhook.
Afficher le BIN et le suffixe de la carte.

Les informations suivantes sur le numéro de la carte bancaire sont passées dans le webhook :

  • les 6 premiers chiffres du paramètre card_bin ;
  • les 4 derniers chiffres du card_suffix.
Afficher marque de carte.La marque de la carte utilisée pour effectuer le paiement. Par exemple, Mastercard ou Visa.
Afficher des informations sur le motif du remboursement.Informations détaillées sur les motifs de remboursement.
Afficher les frais de retenue à la source par pays et les frais d'acquisition utilisateur.Les objets payment_details.​country_wht et payment_details.​user_acquisition_fee seront passés dans le webhook. Cette option est activée par défaut.
Envoyer les informations 3DS.L'objet cards contenant des données sur la vérification 3-D Secure sera passé dans le webhook.

Paramètres 
avancés

Tester les webhooks dans le Compte éditeur

Tester les webhooks permet de s'assurer de la bonne configuration du projet, tant de votre côté que du côté de Xsolla.

Si les webhooks sont configurés avec succès, une section de test des webhooks s'affiche sous celle de configuration des webhooks.

Section de test des 
webhooks

La section de test dans le Compte éditeur varie en fonction de l'option de réception du webhook.

Si vous avez enregistré votre Compte éditeur après le 22 janvier 2025, vous recevrez des webhooks combinés :

Nom de l'onglet pour le test du webhookNom et type du webhook
Payments and storeValidation utilisateur >Validation utilisateur (user_validation)
Services de jeux > Webhooks combinés >Paiement de commande réussi (order_paid)
Services de jeux > Webhooks combinés >Annulation de commande (order_canceled)
SubscriptionsValidation utilisateur >Validation utilisateur (user_validation)
Payments >Paiement (payment)

Si vous avez enregistré votre Compte éditeur avant ou le 22 janvier 2025, vous recevrez des webhooks distincts :

Nom de l'onglet pour le test du webhookNom et type du webhook
StoreServices de jeux > Webhooks distincts >Paiement de commande réussi (order_paid)
Services de jeux > Webhooks distincts >Annulation de commande (order_canceled)
PaymentsValidation utilisateur >Validation utilisateur (user_validation)
Payments >Paiement (payment)
SubscriptionsValidation utilisateur >Validation utilisateur (user_validation)
Payments >Paiement (payment)

Note

Si un avertissement indiquant que le test a échoué apparaît dans la section de test, vérifiez les paramètres de réponse du webhook dans votre écouteur webhook. Les raisons des erreurs dans les tests sont indiquées dans les résultats.

Exemple :

Vous utilisez le site spécialisé webhook.site pour effectuer des tests.

Une erreur s'affiche dans la section Testing response to invalid signature.

Cela se produit parce que Xsolla envoie un webhook avec une signature incorrecte et s'attend à ce que votre gestionnaire réponde avec un code HTTP 4xx spécifiant le code d'erreur INVALID_SIGNATURE.

webhook.site renvoie un code HTTP 200 en réponse à tous les webhooks, y compris à ceux avec une signature incorrecte. Le code HTTP 4xx attendu ne pouvant pas être obtenu, une erreur apparaît dans le résultat du test.

Le processus de test du scénario avec des webhooks combinés est décrit ci- dessous.

Payments and Store

Dans l'onglet Payments and Store, vous pouvez tester les webhooks suivants :

Pour tester les webhooks :

  1. Dans la section de test des webhooks, accédez à l'onglet Payments and Store.
  2. Dans la liste déroulante, sélectionnez le type d'objet. Si ce type n'est pas encore configuré dans le Compte éditeur, appuyez sur le bouton pour le configurer. Une fois l'objet créé, revenez à la section de test des webhooks et passez à l'étape suivante.
  3. Remplissez les champs nécessaires :
    • User ID — lors des tests, vous pouvez utiliser n'importe quelle combinaison de lettres et de chiffres.
    • Entrez une valeur aléatoire dans le champ Xsolla order ID
    • Xsolla invoice ID — ID de transaction côté Xsolla. Lors des tests, vous pouvez utiliser n'importe quelle valeur numérique.
    • Invoice ID — ID de transaction côté de votre jeu. Lors des tests, vous pouvez utiliser n'importe quelle combinaison de lettres et de chiffres. Ce n'est pas un paramètre requis pour un paiement réussi, mais vous pouvez le transmettre pour lier l'ID de transaction de votre côté à l'ID de transaction côté Xsolla.
    • Amount — montant du paiement. Lors des tests, vous pouvez utiliser n'importe quelle valeur numérique.
    • Currency — sélectionnez une devise dans la liste déroulante.
    • Sélectionnez l'UGS de l'objet dans la liste déroulante et indiquez le montant. Pour choisir plusieurs objets du même type, appuyez sur + et ajoutez-les sur une nouvelle ligne.
  4. Appuyez sur Test webhooks.

Les webhooks Validation urilisateur, Paiement de commande réussi et Annulation de commande avec les données spécifiées sont envoyés à l'URL fournie. Les résultats du test de chaque type de webhook sont affichés sous le bouton Tester les webhooks.

Si la case Use public user ID est cochée dans la section Project settings

Integration settings, le webhook User search sera également envoyé à l'URL de votre serveur de webhooks et le résultat du test s'affichera.

Il est nécessaire de configurer le traitement des deux scénarios pour chaque webhook : un scénario réussi et un scénario avec une erreur.

Section de test des 
paiements

Subscriptions

Remarque

Pour tester les webhooks, vous devez avoir au moins un plan d'abonnement créé dans le Compte éditeur dans la section Items catalog> Subscriptions.

Dans l'onglet Subscriptions, vous pouvez tester les webhooks suivants :

Remarque

Vous trouverez des informations détaillées sur le test d'autres scénarios de gestion des abonnements dans le guide d'intégration.

Pour tester les webhooks :

  1. Dans la section de test, accédez à l'onglet Subscriptions.
  2. Remplissez les champs nécessaires :
    • User ID — lors des tests, vous pouvez utiliser n'importe quelle combinaison de lettres et de chiffres.
    • Xsolla invoice ID — ID de transaction côté Xsolla. Lors des tests, vous pouvez utiliser n'importe quelle valeur numérique.
    • Public user ID — ID connu de l'utilisateur, par exemple, un e-mail ou un pseudo. Ce champ s'affiche si vous avez coché la case Use public user ID dans le projet dans la section Project settings > Integration settings.
    • Amount — montant du paiement. Lors des tests, vous pouvez utiliser n'importe quelle valeur numérique.
    • Currency — sélectionnez une devise dans la liste déroulante.
    • Plan ID — un plan d'abonnement. Choisissez un plan dans la liste déroulante.
    • Subscription product — choisissez un produit dans la liste déroulante (facultatif). La liste s'affiche si des produits sont configurés dans le projet.
    • Invoice ID — ID de transaction côté de votre jeu. Lors des tests, vous pouvez utiliser n'importe quelle combinaison de lettres et de chiffres. Ce n'est pas un paramètre requis pour un paiement réussi, mais vous pouvez le transmettre pour lier l'ID de transaction de votre côté à l'ID de transaction côté Xsolla.
    • Trial period. Pour tester l'achat d'un abonnement sans période d'essai ou pour tester le renouvellement d'un abonnement , spécifiez la valeur 0.
  3. Appuyez sur Test.

À l'URL spécifiée, vous recevrez des webhooks avec les données remplies. Les résultats des tests de chaque webhook, pour un scénario réussi et un scénario avec une erreur, sont affichés sous le bouton Test.

Écouteur webhook

L'écouteur webhook est un code de programme qui permet de recevoir des webhooks entrants à une adresse URL spécifiée, de générer une signature et d'envoyer une réponse au serveur webhook de Xsolla.

Note

Vous pouvez utiliser la bibliothèque Pay Station PHP SDK, qui contient des classes prêtes à l'emploi, pour le traitement des webhooks.

Du côté de votre application, implémentez la réception des webhooks envoyés depuis les adresses IP suivantes :

  • 185.30.20.0/24
  • 185.30.21.0/24
  • 185.30.22.0/24
  • 185.30.23.0/24
  • 34.102.38.178
  • 34.94.43.207
  • 35.236.73.234
  • 34.94.69.44
  • 34.102.22.197

Si vous avez intégré le produit Login, ajoutez également le traitement des webhooks envoyés depuis les adresses IP suivantes :

  • 34.94.0.85
  • 34.94.14.95
  • 34.94.25.33
  • 34.94.115.185
  • 34.94.154.26
  • 34.94.173.132
  • 34.102.48.30
  • 35.235.99.248
  • 35.236.32.131
  • 35.236.35.100
  • 35.236.117.164

Restrictions :

  • La base de données de votre application ne doit pas contenir plusieurs transactions réussies avec le même ID.
  • Si l'écouteur reçoit un webhook avec un ID qui existe déjà dans la base de données, renvoyez le résultat précédent du traitement de cette transaction. Il est déconseillé de créditer l'utilisateur pour un achat déjà effectué et de créer des enregistrements en double dans la base de données.

Génération de la signature

Pour garantir la sécurité de la transmission des données, vérifiez que le webhook provient bien du serveur Xsolla et qu’il n’a pas été altéré pendant le transport. Pour ce faire, générez votre propre signature sur la base de la charge utile du corps de la requête et comparez-la à celle fournie dans l’en- tête authorization de la requête entrante. Si les deux signatures correspondent, le webhook est authentique et peut être traité en toute sécurité.

Étapes de vérification :

  1. Récupérez la signature depuis l’en-tête authorization de la requête webhook entrante. Le format de cet en-tête est : Signature <signature_value>.

  2. Récupérez le corps de la requête webhook au format JSON.

    Remarque

    Utilisez la charge utile JSON exactement telle qu’elle est reçue. Ne la parsez ni ne la réencodez, car cela modifierait son formatage et entraînerait l’échec de la vérification de la signature.

  3. Générez votre propre signature à des fins de comparaison :

    1. Concaténez la charge utile JSON avec la clé secrète de votre projet, en ajoutant cette dernière à la fin de la chaîne.
    2. Appliquez la fonction de hachage cryptographique SHA-1 à la chaîne obtenue. Le résultat sera une chaîne hexadécimale en minuscules.
    3. Comparez la signature que vous avez générée avec celle fournie dans l’en-tête authorization. Si elles correspondent, le webhook est authentique.

    Voici des exemples d’implémentation de la génération de signatures pour les langages suivants : C#, C++, Go, PHP et Node.js.

    Exemple de webhook (HTTP) :

    POST /your_uri HTTP/1.1
    host: your.host
    accept: application/json
    content-type: application/json
    content-length: 165
    authorization: Signature 52eac2713985e212351610d008e7e14fae46f902
    {
      "notification_type":"user_validation",
      "user":{
          "ip":"127.0.0.1",
          "phone":"18777976552",
          "email":"email@example.com",
          "id":1234567,
          "name":"Xsolla User",
          "country":"US"
      }
    }

    Exemple de webhook (curl) :

    curl -v 'https://your.hostname/your/uri' \
    -X POST \
    -H 'authorization: Signature 52eac2713985e212351610d008e7e14fae46f902' \
    -d '{
      "notification_type":
        "user_validation",
        "user":
          {
            "ip": "127.0.0.1",
            "phone": "18777976552",
            "email": "email@example.com",
            "id": 1234567,
            "name": "Xsolla User",
            "country": "US"
          }
        }'

    Exemple d'implémentation de la génération de signatures en C# (exemple général) :

    Note

    Ce code fonctionne avec .NET Framework 4.0 et versions ultérieures, .NET Core et d'autres versions récentes de .NET. La vérification des signatures utilise ConstantTimeEquals pour une comparaison en temps constant, réduisant le risque d'attaques temporelles.

    using System;
    using System.Security.Cryptography;
    using System.Text;
    public static class XsollaWebhookSignature
    {
        public static string ComputeSha1(string jsonBody, string secretKey)
        {
            // Concatenation of the JSON from the request body and the project's secret key
            string dataToSign = jsonBody + secretKey;
            using (SHA1 sha1 = SHA1.Create())
            {
                byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(dataToSign));
                // Convert hash bytes to lowercase hexadecimal string
                var hexString = new StringBuilder(hashBytes.Length * 2);
                foreach (byte b in hashBytes)
                {
                    hexString.Append(b.ToString("x2"));
                }
                return hexString.ToString();
            }
        }
        public static bool VerifySignature(string jsonBody, string secretKey, string receivedSignature)
        {
            string computedSignature = ComputeSha1(jsonBody, secretKey);
            string receivedSignatureLower = receivedSignature.ToLower();
            // Use constant-time comparison to prevent timing attacks
            return ConstantTimeEquals(computedSignature, receivedSignatureLower);
        }
        private static bool ConstantTimeEquals(string a, string b)
        {
            if (a.Length != b.Length)
            {
                return false;
            }
            int result = 0;
            for (int i = 0; i < a.Length; i++)
            {
                result |= a[i] ^ b[i];
            }
            return result == 0;
        }
    }

    Exemple C# d'implémentation de la génération de signatures (.NET 5.0 et versions supérieures) :

    Note

    La méthode Convert.ToHexString nécessite .NET 5.0 ou ultérieure.

    Avec .NET 7.0 ou ultérieure, vous pouvez aussi utiliser la méthode CryptographicOperations.FixedTimeEquals à la place de ConstantTimeEquals.

    // For .NET 5.0 and later, you can use the more concise Convert.ToHexString method:
    using System;
    using System.Security.Cryptography;
    using System.Text;
    public static class XsollaWebhookSignature
    {
        public static string ComputeSha1(string jsonBody, string secretKey)
        {
            string dataToSign = jsonBody + secretKey;
            using var sha1 = SHA1.Create();
            byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(dataToSign));
            return Convert.ToHexString(hashBytes).ToLower();
        }
        public static bool VerifySignature(string jsonBody, string secretKey, string receivedSignature)
        {
            string computedSignature = ComputeSha1(jsonBody, secretKey);
            string receivedSignatureLower = receivedSignature.ToLower();
            // Use constant-time comparison to prevent timing attacks
            return ConstantTimeEquals(computedSignature, receivedSignatureLower);
        }
        private static bool ConstantTimeEquals(string a, string b)
        {
            if (a.Length != b.Length)
            {
                return false;
            }
            int result = 0;
            for (int i = 0; i < a.Length; i++)
            {
                result |= a[i] ^ b[i];
            }
            return result == 0;
        }
    }

    Exemple C# d'implémentation de la génération de signatures (.NET 7.0 et versions supérieures) :

    Note

    Si vous disposez de .NET 7.0 ou ultérieure, vous pouvez utiliser la méthode CryptographicOperations.FixedTimeEquals.

    // For .NET 7.0+, you can use the built-in CryptographicOperations.FixedTimeEquals:
    using System.Security.Cryptography;
    public static bool VerifySignature(string jsonBody, string secretKey, string receivedSignature)
    {
        string computedSignature = ComputeSha1(jsonBody, secretKey);
        byte[] computedBytes = Encoding.UTF8.GetBytes(computedSignature);
        byte[] receivedBytes = Encoding.UTF8.GetBytes(receivedSignature.ToLower());
        return CryptographicOperations.FixedTimeEquals(computedBytes, receivedBytes);
    }

    Exemple d'implémentation de la génération de signatures en C++ :

    #include <string>
    #include <sstream>
    #include <iomanip>
    #include <openssl/sha.h>
    class XsollaWebhookSignature {
    public:
        static std::string computeSha1(const std::string& jsonBody, const std::string& secretKey) {
            // Concatenation of the JSON from the request body and the project's secret key
            std::string dataToSign = jsonBody + secretKey;
            unsigned char digest[SHA_DIGEST_LENGTH];
            // Create SHA1 hash
            SHA1(reinterpret_cast<const unsigned char*>(dataToSign.c_str()),
                 dataToSign.length(), digest);
            // Convert to lowercase hexadecimal string
            std::ostringstream hexStream;
            hexStream << std::hex << std::setfill('0');
            for (int i = 0; i < SHA_DIGEST_LENGTH; ++i) {
                hexStream << std::setw(2) << static_cast<unsigned int>(digest[i]);
            }
            return hexStream.str();
        }
        static bool verifySignature(const std::string& jsonBody, const std::string& secretKey, const std::string& receivedSignature) {
            std::string computedSignature = computeSha1(jsonBody, secretKey);
            // Timing-safe comparison
            if (computedSignature.length() != receivedSignature.length()) {
                return false;
            }
            volatile unsigned char result = 0;
            for (size_t i = 0; i < computedSignature.length(); ++i) {
                result |= (computedSignature[i] ^ receivedSignature[i]);
            }
            return result == 0;
        }
    };

    Exemple d'implémentation de la génération de signatures en Go :

    package main
    import (
    	"crypto/sha1"
        "crypto/subtle"
    	"encoding/hex"
    	"strings"
    )
    type XsollaWebhookSignature struct{}
    func (x *XsollaWebhookSignature) ComputeSha1(jsonBody, secretKey string) string {
    	// Concatenation of the JSON from the request body and the project's secret key
    	dataToSign := jsonBody + secretKey
    	// Create SHA1 hash
    	h := sha1.New()
    	h.Write([]byte(dataToSign))
    	signature := h.Sum(nil)
    	// Convert to lowercase hexadecimal string
    	return strings.ToLower(hex.EncodeToString(signature))
    }
    func (x *XsollaWebhookSignature) VerifySignature(jsonBody, secretKey, receivedSignature string) bool {
    	computedSignature := x.ComputeSha1(jsonBody, secretKey)
    	receivedSignatureLower := strings.ToLower(receivedSignature)
    	// Use constant time comparison to prevent timing attacks
    	return subtle.ConstantTimeCompare([]byte(computedSignature), []byte(receivedSignatureLower)) == 1
    }

    Exemple d'implémentation de la génération de signatures en PHP :

    <?php
    class XsollaWebhookSignature
    {
        /**
         * Compute SHA1 signature from webhook JSON body and secret key
         *
         * @param string $jsonBody The raw JSON body from webhook
         * @param string $secretKey The project's secret key
         * @return string The lowercase SHA1 signature
         */
        public static function computeSha1(string $jsonBody, string $secretKey): string
        {
            // Concatenation of the JSON from the request body and the project's secret key
            $dataToSign = $jsonBody . $secretKey;
            // Generate SHA1 signature
            $signature = sha1($dataToSign);
            return strtolower($signature);
        }
        /**
         * Verify webhook signature using timing-safe comparison
         *
         * @param string $jsonBody The raw JSON body from webhook
         * @param string $secretKey The project's secret key  
         * @param string $receivedSignature The signature from authorization header
         * @return bool True if signature is valid, false otherwise
         */
        public static function verifySignature(string $jsonBody, string $secretKey, string $receivedSignature): bool
        {
            $computedSignature = self::computeSha1($jsonBody, $secretKey);
            // Use hash_equals for timing-safe comparison
            return hash_equals($computedSignature, strtolower($receivedSignature));
        }
    }
    ?>

    Exemple d'implémentation de la génération de signatures en Node.js :

    const crypto = require('crypto');
    class XsollaWebhookSignature {
        // IMPORTANT: jsonBody must be the raw JSON string exactly as received from Xsolla
        static computeSha1(jsonBody, secretKey) {
            // Concatenation of the JSON from the request body and the project's secret key
            const dataToSign = jsonBody + secretKey;
            // Create SHA1 hash
            const hash = crypto.createHash('sha1');
            hash.update(dataToSign, 'utf8');
            // Convert to lowercase hexadecimal string
            return hash.digest('hex').toLowerCase();
        }
        static verifySignature(jsonBody, secretKey, receivedSignature) {
            const computedSignature = this.computeSha1(jsonBody, secretKey);
            const cleanReceivedSignature = receivedSignature.toLowerCase();
            // Check if signatures have the same length before using timingSafeEqual
            if (computedSignature.length !== cleanReceivedSignature.length) {
                return false;
            }
            try {
                return crypto.timingSafeEqual(
                    Buffer.from(computedSignature, 'hex'),
                    Buffer.from(cleanReceivedSignature, 'hex')
                );
            } catch (error) {
                // Return false if there's any error (e.g., invalid hex characters)
                return false;
            }
        }
    }

    Envoi de réponses au webhook

    Pour confirmer la réception du webhook, votre serveur doit renvoyer :

    • Un code HTTP 200, 201 ou 204 en cas de réponse positive ;
    • Un code HTTP 400 avec description du problème au cas où l'utilisateur spécifié n'a pas été trouvé ou une signature non valide a été passée. Le gestionnaire de webhook peut également renvoyer un code HTTP 5xx en cas de problèmes temporaires sur votre serveur.

    Si le serveur Xsolla n'a pas reçu de réponse aux webhooks Paiement de commande réussi et Annulation de commande, ou s'il reçoit une réponse contenant un code 5xx, les webhooks sont renvoyés selon le calendrier suivant :

    • 2 tentatives à intervalles de 5 minutes ;
    • 7 tentatives à intervalles de 15 minutes ;
    • 10 tentatives à intervalles de 60 minutes.

    Un maximum de 20 tentatives d'envoi de webhooks sont effectuées dans les 12  heures suivant la première tentative.

    La logique de réessai pour les webhooks Payment et Refund est décrite sur la page du webhook concerné.

    Remarque

    Le paiement sera quand même remboursé à l'utilisateur si toutes les conditions suivantes sont réunies :

    • Xsolla a initié le remboursement.
    • En réponse au webhook, un code d'état 4xx est renvoyé, ou aucune réponse n'est reçue après toutes les tentatives, ou un code d'état 5xx est renvoyé.

    Si le serveur Xsolla n'a pas reçu de réponse au webhook Validation utilisateur ou s'il a reçu une réponse contenant un code 400 ou 5xx, le webhook Validation utilisateur n'est pas renvoyé. Dans ce cas, l'utilisateur voit une erreur et les webhooks Paiement et Paiement de commande réussi ne sont pas envoyés.

    Erreurs

    Codes d'erreur pour le code HTTP 400 :

    CodeMessage
    INVALID_USERUtilisateur non valide
    INVALID_PARAMETERParamètre non valide
    INVALID_SIGNATURESignature non valide
    INCORRECT_AMOUNTMontant incorrect
    INCORRECT_INVOICEFacture incorrecte
    HTTP/1.1 400 Bad Request
    {
        "error":{
            "code":"INVALID_USER",
            "message":"Invalid user"
        }
    }

    Bonnes pratiques

    Sécurité

    Suivez ces lignes directrices :

    • Utilisez uniquement le protocole HTTPS, avec un certificat valide.
    • Vérifiez toujours la signature à partir du corps brut de la requête ; n'analysez pas et ne réencodez pas les données.
    • Ne passez pas de données sensibles dans les URL et évitez de divulguer des détails techniques dans les messages d'erreur.
    • Exemptez le point de terminaison du webhook du middleware CSRF. Les requêtes entrantes de Xsolla n'incluent pas de jeton CSRF et seront rejetées sans ce paramètre.
    • Liste blanche Adresses IP de Xsolla.

    Architecture du gestionnaire de webhook

    Suivez ces lignes directrices :

    1. Acceptez la requête POST avec son corps et ses en-têtes tels quels, sans modification.
    2. Vérifiez la signature du webhook et renvoyez le code d'état approprié :
      • 4xx : si les signatures ne correspondent pas ;
      • 2xx : en cas de succès. Nous recommandons de renvoyer 204 No Content avant d'exécuter la logique métier principale. 200 OK est également acceptable.
    3. Passez la charge utile à une tâche asynchrone ou à une file d'attente pour un traitement ultérieur.
    4. Implémentez l'idempotence. Vous devez vous assurer que votre système est capable de gérer la réception d'un même webhook plusieurs fois.

    Exemple de flux :

    HTTP POST /webhooks/xsolla
      read raw_body, headers
      if !verify_signature(raw_body, headers['authorization']):
         return 400 {"error":{"code":"INVALID_SIGNATURE","message":"Invalid signature"}}
      enqueue(raw_body)
      return 204  # or 200

    Idempotence et doublons

    Suivez ces lignes directrices :

    • Utilisez l'ID de transaction et/ou l'ID externe, ainsi que l'ID de commande comme clés d'idempotence.
    • Enregistrez les identifiants traités et renvoyez le résultat précédent en cas de doublon.
    • Évitez les réattributions d'objets, les doublons en base de données et les doubles facturations.
    • Gardez à l'esprit qu'avec une livraison séquentielle, un échec sur un événement antérieur bloque le traitement de tous les suivants.

    Résilience du système

    Suivez ces lignes directrices :

    • Utilisez des files d'attente et un traitement asynchrone pour les opérations gourmandes en ressources, comme les appels à des API tierces, la facturation et l'attribution d'objets.
    • Définissez des délais d'expiration pour le gestionnaire de webhook (1 à 3 s). En cas d'échecs temporaires, appuyez-vous sur le mécanisme de réessai de Xsolla.
    • N'implémentez pas de tentatives de réessai dans le gestionnaire de webhook : cela est pris en charge par Xsolla.
    • Enregistrez les horodatages de livraison des webhooks et les statuts de traitement ; configurez des alertes en cas de pics d'erreurs 5xx et de nouvelles tentatives de passage.
    • Transférez les ID de corrélation du webhook vers vos journaux et votre système de surveillance (APM).
    • Configurez la journalisation et le suivi des erreurs. En cas d'échec non récupérable, transférez les tâches vers une file de messages morts (DLQ). Développez un outil sécurisé de relecture des événements, protégé par un mécanisme d'idempotence.

    Exemples d'implémentation

    Achat réussi — objet obtenu dès la première tentative :

    Achat

    Livraison en double (timeout du partenaire lors de la première tentative) :

    Timeout

    Remboursement :

    Remboursement

    Interruption de service chez un partenaire :

    Interruption de service chez un 
partenaire

    FAQ

    Ai-je besoin d'utiliser HTTPS pour un protocole de webhook ?

    Oui.

    Puis-je recevoir des webhooks de paiement sur plusieurs URL ?

    Non. Les webhooks de paiement utilisent un protocole serveur à serveur et sont envoyés à une URL unique définie dans les paramètres du projet. Si vous souhaitez recevoir des notifications dans votre jeu, site web ou application mobile, configurez les webhooks sur votre serveur pour assurer l'échange de données entre Xsolla et votre application. Vous pouvez également les tester depuis la console développeur.

    Note

    Si vous testez l'intégration localement, les requêtes `POST` de Xsolla n'atteignent pas des URLs comme http://localhost:3000/my-webhook-endpoint. Utilisez des services tels que Ngrok pour créer un tunnel d'accès externe et recevoir les requêtes Xsolla localement. Vous pouvez en savoir plus dans la documentation Ngrok.

    Pourquoi la notification Xsolla n'a-t-elle pas été envoyée à l'URL du webhook ?

    Assurez-vous que votre serveur de webhooks prend en charge les types de requêtes HTTP POST et GET.

    Comment éviter les doublons d'identifiants de transaction lors du traitement ?

    Utilisez l'ID externe : il s'agit de l'identifiant de transaction dans votre jeu, attribué à la commande dans votre système. Côté Xsolla, l'ID externe est associé à l'ID de transaction, ce qui permet d'éviter les paiements en double pour une même transaction. Pour en savoir plus sur la configuration, consultez notre documentation.

    Existe-t-il de bonnes pratiques pour l'utilisation des webhooks ?

    Nous vous recommandons :

    • Retourner le code 204 ou 200 immédiatement après la vérification de la signature.
    • Vérifier la signature du webhook par rapport au corps brut de la requête, sans modification.
    • Implémenter l'idempotence pour toutes les opérations.
    • Enregistrer tous les événements et configurer un système de surveillance des erreurs.
    • Éviter d'inclure des données sensibles dans les URL et de divulguer des détails techniques dans les messages d'erreur.

    Consultez la section Meilleures pratiques pour plus d'informations.

    Liste de contrôle pour l'intégration des webhooks

    Pour que le bon fonctionnement des webhooks, assurez-vous que les éléments suivants sont bien en place avant de passer en production :

    • Le protocole HTTPS est utilisé.
    • La vérification de la signature du webhook s'effectue à partir du corps brut de la requête, sans aucune modification.
    • Une réponse 204/200 est renvoyée dès que la signature est confirmée.
    • L'idempotence est assurée pour toutes les opérations.
    • La journalisation et la surveillance des erreurs sont configurées.
    • Les données sensibles ne sont pas transmises dans les URL, et les messages d'erreur ne divulguent aucun détail technique.
    • Les tentatives de réenvoi des webhooks sont prises en charge conformément à la logique de réessai de Xsolla.
    • L'ensemble du processus d'intégration est documenté.

    Liste des webhooks

    Note

    Le type de notification est passé dans le paramètre notification_type.

    WebhookType de notificationDescription
    Validation utilisateuruser_validationEnvoyé pour vérifier si l'utilisateur existe dans le jeu.
    Recherche utilisateuruser_searchEnvoyé pour récupérer les informations sur l'utilisateur à partir de son ID utilisateur public.
    PaiementpaymentEnvoyé lorsque l'utilisateur effectue un paiement.
    RemboursementrefundEnvoyé lorsqu'un paiement doit être annulé pour une raison quelconque.
    Remboursement partielpartial_refundEnvoyé lorsqu'un paiement doit être partiellement annulé pour une raison quelconque.
    Paiement refuséps_declinedEnvoyé lorsqu'un paiement est refusé par le système de paiement.
    Transaction rejetée par AFSafs_rejectEnvoyé lorsqu'une transaction est refusée lors d'un contrôle AFS.
    Mise à jour de la liste noire AFSafs_black_listEnvoyé lorsque la liste noire AFS est mise à jour.
    Abonnement créécreate_subscriptionEnvoyé lorsque l'utilisateur crée un abonnement.
    Abonnement mis à jourupdate_subscriptionEnvoyé lors du renouvellement ou de la modification d'un abonnement.
    Abonnement annulécancel_subscriptionEnvoyé lorsqu'un abonnement est annulé.
    Abonnement non renouvelablenon_renewal_subscriptionEnvoyé lorsque le statut est défini sur non renouvelable.
    Ajout de compte de paiementpayment_account_addEnvoyé lorsque l'utilisateur ajoute ou enregistre un compte de paiement.
    Suppression de compte de paiementpayment_account_removeEnvoyé lorsque l'utilisateur supprime un compte de paiement des comptes enregistrés.
    Validation utilisateur dans Web Shop-Envoyé depuis le site d'un Web Shop pour vérifier si l'utilisateur existe dans le jeu.
    Personnalisation du catalogue côté partenairepartner_side_catalogEnvoyé lorsque l'utilisateur interagit avec le magasin.
    Paiement de commande réussiorder_paidEnvoyé lorsqu'une commande est payée.
    Annulation de commandeorder_canceledEnvoyé lorsqu'une commande est annulée.
    ContestationdisputeEnvoyé lorsqu'une nouvelle contestation est ouverte.
    Télécharger la description d'OpenAPI
    Langues
    Serveurs
    https://api.xsolla.com/merchant/v2/
    Mock server
    https://xsolla.redocly.app/_mock/fr/webhooks/
    Webhooks
    Webhooks
    Webhooks
    Webhooks
    Webhooks

    Personnalisation du catalogue côté partenaireWebhook

    Requête

    Xsolla enverra à l'URL du webhook un webhook partner_side_catalog contenant les paramètres de l'utilisateur et du projet chaque fois que l'utilisateur interagit avec le magasin.

    En réponse, renvoyez la liste des item_id ou des UGS des biens disponibles pour l'utilisateur. Vous pouvez également inclure des informations sur la possibilité pour un utilisateur spécifique d'acheter certains biens un certain nombre de fois. Cette fonctionnalité vous permet de contrôler le nombre et le type de biens que l'utilisateur peut ajouter au panier et acheter.

    Avis

    Lors du traitement du webhook, tenez compte des limitations suivantes :

    • Le webhook doit être traité en moins de 3 secondes. Si le traitement prend plus de temps, les appels API récupérer la liste des objets virtuels, créer un jeton de paiement, et créer une commande renvoient une erreur.
    • La taille de la réponse au webhook ne doit pas dépasser 64 Ko. Les réponses dépassant cette limite ne sont pas traitées : l'utilisateur voit un catalogue vide et ne peut pas acheter d'objets. Pour modifier la taille maximale de la réponse, contactez votre responsable de la réussite client ou envoyez un e-mail à csm@xsolla.com.

    Corpsapplication/json
    userobjectobligatoire

    Informations sur l'utilisateur (objet).

    user.​countrystring(user.country)

    Pays de l'utilisateur. Code pays à deux lettres majuscules selon la norme ISO 3166-1 alpha-2.

    user.​currencystring(currency)

    Devise. Code de devise à trois lettres selon la norme ISO 4217.

    user.​localestring(locale)

    Langue de l'utilisateur. Code de langue à deux lettres minuscules.

    user.​user_idstringobligatoire

    ID utilisateur. Si l'utilisateur n'est pas authentifié, la valeur null est envoyée.

    curl -v 'https://your.hostname/your/uri' \
    -X POST \
    -H 'accept: application/json' \
    -H 'content-type: application/json' \
    -H 'authorization: Signature d90d319f05df7b0f86d2485f48e7079f0f752523' \
    -d '{
            "notification_type": "partner_side_catalog",
            "user": {
                "user_id": "12345",
                "country": "US"
            }
        }'

    Réponses

    Renvoyez une liste de biens disponibles pour l'utilisateur et le nombre de fois qu'un utilisateur spécifique peut acheter un certain bien.

    Corpsapplication/jsonArray [
    Any of:
    One of:
    contentArray of objects(bundle_content)

    Tableau d’objets avec le contenu du lot à afficher dans le catalogue. Ne peut être utilisé que pour le type de lot partner_side_content.

    content[].​descriptionstring<= 255 characters

    Description de l’objet à afficher dans le catalogue comme composant du lot. Si elle n’est pas fournie, la valeur null est passée.

    content[].​image_urlstring(uri)<= 255 characters

    URL de l’image de l’objet à afficher dans le catalogue comme composant du lot (seul le protocole HTTPS est pris en charge). Si elle n’est pas fournie, la valeur null est passée.

    content[].​namestring<= 255 characters

    Nom de l’objet à afficher dans le catalogue comme composant du lot. S’il n’est pas fourni, une chaîne vide est passée.

    content[].​quantityinteger>= 1

    Quantité de l’objet dans le lot.

    Par défaut 1
    date_fromstring(date_from)

    Date de début de disponibilité de l'objet à la vente. Formatée selon la norme RFC 3339.

    date_untilstring(date_until)

    Date de début d'indisponibilité de l'objet à la vente. Formatée selon la norme RFC 3339.

    descriptionstring(description)<= 255 characters

    Description de l’objet à afficher dans le catalogue. Elle remplace la description stockée dans un objet.

    image_urlstring(uri)(image_url)<= 255 characters

    URL de l’image à afficher dans le catalogue. Elle remplace l’URL de l’image stockée dans un objet (seul le protocole HTTPS est pris en charge). Si l’URL n’est pas conforme aux exigences, elle sera ignorée.

    json_attributesobject(json)(json_attributes)<= 500 characters

    Un objet JSON contenant les attributs d’objet et leurs valeurs. Il remplace custom_attributes stocké dans un objet. Si le JSON n’est pas conforme aux exigences ou s’il est plus long que la longueur maximale, il sera ignoré.

    namestring(name)<= 255 characters

    Nom de l’objet à afficher dans le catalogue. Il remplace le nom stocké dans un objet.

    skustring(sku)obligatoire

    ID unique de l'objet que vous avez indiqué dans le Compte éditeur. Passez soit le skuou le item_id.

    quantityinteger(quantity)Obsolète

    Nombre d'objets qu'un utilisateur unique peut acheter. Pour définir une quantité illimitée, passez null. Pour rendre l'objet visible dans le catalogue sans permettre l'achat, passez 0.

    Si vous utilisez ce paramètre, les informations de limite d'achat ne sont pas affichées dans le catalogue. Pour afficher la limite d'achat dans le catalogue (par exemple, 7/10), passez la paire availableet totalau lieu de quantity.

    ]
    Réponse
    application/json
    [ { "date_from": "2024-08-11T23:59:59+08:00", "date_until": "2024-08-12T23:59:59+08:00", "quantity": 0, "sku": "com.xsolla.boots_1" }, { "date_from": "2024-08-11T23:59:59+08:00", "date_until": "2024-08-12T23:59:59+08:00", "quantity": null, "sku": "com.xsolla.sword_1" }, { "quantity": 1, "sku": "com.xsolla.helmet_1" }, { "content": [], "description": "Custom description", "image_url": "https://example.com/image.png", "json_attributes": {}, "name": "Custom name", "quantity": null, "sku": "com.xsolla.custom_item_1" }, { "available": 7, "sku": "com.xsolla.limited_item_1", "total": 10 } ]
    Webhooks
    Webhooks