Un JSON contenant les attributs des objets et leurs valeurs.
- Annulation de commande (sans données de paiement et de transaction)
Webhooks (1.0)
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 :
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/Solution | Obligatoire/Facultatif | À quoi servent les webhooks ? |
|---|---|---|
| Payments | Obligatoire |
|
| In-Game Store | Obligatoire |
|
| Game Sales | Facultatif | Pour 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. |
| Subscriptions | Facultatif | Réception d'informations sur la création, la mise à jour ou l'annulation d'abonnements. Vous pouvez également demander des informations via API. |
| Web Shop | Obligatoire |
|
| Digital Distribution Hub | Obligatoire |
Reportez-vous à la documentation pour obtenir plus d'informations sur la configuration des webhooks pour Digital Distribution Hub. |
| Login | Facultatif | Réception d'informations sur les événements :
Reportez-vous à la documentation Login pour des informations détaillées sur la configuration des webhooks. |
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.
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 :
- Paiement (
payment) et Remboursement (refund) avec des informations sur les données de paiement et de transaction. - Paiement de commande réussi (
order_paid) et Annulation de commande (order_canceled) avec des informations sur les objets achetés.
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 webhook | Description |
|---|---|
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 webhook | Description |
|---|---|
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 :
- Paiement, Paiement de commande réussi et Validation utilisateur si vous recevez des webhooks distincts ;
- Paiement de commande réussi et Validation utilisateur si vous recevez des webhooks combinés.
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.
Pour activer la réception des webhooks :
- Dans le projet dans le Compte éditeur, accédez à la section Paramètres du projet > Webhooks.
- 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.
- Une clé secrète pour signer les webhooks du projet est générée par défaut. Si vous souhaitez générer une nouvelle clé secrète, cliquez sur l'icône d'actualisation.
- Cliquez 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 :
- Dans le projet dans le Compte éditeur, accédez à la section Paramètres du projet > Webhooks.
- Cliquez sur Disable webhooks.
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.
| Bascule | Description |
|---|---|
| Afficher infos sur le compte de paiement enregistré | Les informations relatives au mode de paiement enregistré sont passées à l'objet personnalisé payment_account. |
| Afficher infos sur transactions effectuées via modes de paiement enregistrés | Les informations sont passées dans les paramètres personnalisés suivants du webhook :
|
| Ajouter l'objet de la commande au webhook | Les informations relatives à la commande sont passées dans l'objet order du webhook Paiement. |
| Envoyer paramètres utilisateur nécessaires seulement sans données sensibles | Seules les informations suivantes sur l'utilisateur sont passées dans le webhook :
|
| Envoyer paramètres personnalisés | Les informations relatives aux paramètres du jeton personnalisé sont passées dans le webhook. |
| Afficher BIN et suffixe de carte | Les informations suivantes sur le numéro de la carte bancaire sont passées dans le webhook :
|
| Afficher marque de carte | La marque de la carte utilisée pour effectuer le paiement. Par exemple, Mastercard ou Visa. |

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.

La section de test dans le Compte éditeur varie en fonction de l'option de réception du webhook.
Si vous recevez des webhooks combinés :
| Nom de l'onglet pour le test du webhook | Nom et type du webhook |
|---|---|
| Payments and store | Validation 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) | |
| Subscriptions | Validation utilisateur >Validation utilisateur (user_validation) |
Payments >Paiement (payment) |
Si vous recevez des webhooks distincts :
| Nom de l'onglet pour le test du webhook | Nom et type du webhook |
|---|---|
| Store | Services de jeux > Webhooks distincts >Paiement de commande réussi (order_paid) |
Services de jeux > Webhooks distincts >Annulation de commande (order_canceled) | |
| Payments | Validation utilisateur >Validation utilisateur (user_validation) |
Payments >Paiement (payment) | |
| Subscriptions | Validation 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.
Dans l'onglet Payments and Store, vous pouvez tester les webhooks suivants :
- Validation utilisateur (
user_validation) ; - Paiement de commande réussi (
order_paid) ; - Annulation de commande (
order_canceled).
Pour tester :
Dans la section de test des webhooks, accédez à l'onglet Payments and Store.
Dans le menu déroulant, sélectionnez le type d'objet. Si l'objet du type sélectionné n'est pas configuré dans le Compte éditeur, cliquez sur :
- Connect — si le module contenant des objets de ce type n'est pas connecté ;
- Configure — si vous avez connecté le module précédemment, mais n'avez pas encore terminé la configuration.
En cliquant sur le bouton, vous serez redirigé vers la section correspondante du Compte éditeur selon le type d'objet sélectionné. Après avoir créé l'objet, revenez à la section de test des webhooks et passez à l'étape suivante.
Remplissez les champs nécessaires :
- Sélectionnez l'UGS du bien dans la liste déroulante et indiquez le montant. Pour choisir plusieurs biens du même type, cliquez sur + et ajoutez-les sur une nouvelle ligne ;
- ID utilisateur — lors des tests, utilisez n'importe quelle combinaison de lettres et de chiffres.
- ID utilisateur public — ID connu de l'utilisateur, par exemple, une adresse e-mail ou un pseudo. Ce champ s'affiche si l'ID utilisateur public est activé dans votre projet dans Pay Station > Paramètres ;
- Entrez n'importe quelle valeur dans le champ ID de commande Xsolla ;
- ID de facture Xsolla — ID de la transaction côté Xsolla. Lors des tests, utilisez n'importe quelle valeur numérique ;
- ID de facture — ID de la transaction du côté de votre jeu. Lors des tests, utilisez n'importe quelle combinaison de lettres et de chiffres. Ce n'est pas un paramètre obligatoire pour un paiement réussi, mais vous pouvez le passer pour lier l'ID de la transaction de votre côté à l'ID de la transaction côté Xsolla ;
- Montant — montant du paiement. Lors des tests, utilisez n'importe quelle valeur numérique ;
- Devise — sélectionnez une devise dans la liste déroulante.
Cliquez sur Tester les 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 l'ID utilisateur public est activé dans votre projet, les résultats de la vérification de la recherche utilisateur seront également visibles.
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.

Dans l'onglet Subscriptions, vous pouvez tester les webhooks suivants :
- Validation utilisateur (
user_validation) ; - Paiement (
payment).
Note
Dans le Compte éditeur, vous ne pouvez tester que les webhooks basiques : Validation utilisateur et Paiement. Pour tester d'autres types de webhooks, accédez à :
Note
Pour tester les webhooks, vous devez avoir créé au moins un plan d'abonnement dans la section Compte éditeur> Subscriptions > Subscription Plans.
Pour tester :
- Dans la section de test, accédez à l'onglet Subscriptions.
- Remplissez les champs nécessaires :
- ID utilisateur — lors des tests, utilisez n'importe quelle combinaison de lettres et de chiffres ;
- ID de facture Xsolla — ID de transaction côté Xsolla. Lors des tests, utilisez n'importe quelle valeur numérique ;
- ID utilisateur public — ID connu de l'utilisateur, par exemple, une adresse e-mail ou un pseudo. Ce champ s'affiche si l'ID utilisateur public est activé dans votre projet dans la section Pay Station > Paramètres > Paramètres supplémentaires ;
- Devise — sélectionnez une devise dans la liste déroulante ;
- ID de plan — un plan d'abonnement. Choisissez un plan dans la liste déroulante ;
0.Vous recevrez des webhooks avec des données remplies à l'URL spécifiée. 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 webhooks.
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/24185.30.21.0/24185.30.22.0/24185.30.23.0/2434.102.38.17834.94.43.20735.236.73.23434.94.69.4434.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.8534.94.14.9534.94.25.3334.94.115.18534.94.154.2634.94.173.13234.102.48.3035.235.99.24835.236.32.13135.236.35.10035.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.
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 :
Récupérez la signature depuis l’en-tête
authorizationde la requête webhook entrante. Le format de cet en-tête est :Signature <signature_value>.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.
Générez votre propre signature à des fins de comparaison :
- 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.
- Appliquez la fonction de hachage cryptographique SHA-1 à la chaîne obtenue. Le résultat sera une chaîne hexadécimale en minuscules.
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.
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"
}
}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"
}
}'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;
}
}Note
La méthode Convert.ToHexString nécessite .NET 5.0 ou ultérieure.
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;
}
}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);
}#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;
}
};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
}<?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));
}
}
?>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;
}
}
}Pour confirmer la réception du webhook, votre serveur doit renvoyer :
- Un code HTTP
200,201ou204en cas de réponse positive ; - Un code HTTP
400avec 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 HTTP5xxen 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.
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
4xxest renvoyé, ou aucune réponse n'est reçue après toutes les tentatives, ou un code d'état5xxest 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.
Codes d'erreur pour le code HTTP 400 :
| Code | Message |
|---|---|
| INVALID_USER | Utilisateur non valide |
| INVALID_PARAMETER | Paramètre non valide |
| INVALID_SIGNATURE | Signature non valide |
| INCORRECT_AMOUNT | Montant incorrect |
| INCORRECT_INVOICE | Facture incorrecte |
HTTP/1.1 400 Bad Request
{
"error":{
"code":"INVALID_USER",
"message":"Invalid user"
}
}Note
Le type de notification est passé dans le paramètre notification_type.
| Webhook | Type de notification | Description |
|---|---|---|
| Validation utilisateur | user_validation | Envoyé pour vérifier si l'utilisateur existe dans le jeu. |
| Recherche utilisateur | user_search | Envoyé pour récupérer les informations sur l'utilisateur à partir de son ID utilisateur public. |
| Paiement | payment | Envoyé lorsque l'utilisateur effectue un paiement. |
| Remboursement | refund | Envoyé lorsqu'un paiement doit être annulé pour une raison quelconque. |
| Remboursement partiel | partial_refund | Envoyé lorsqu'un paiement doit être partiellement annulé pour une raison quelconque. |
| Paiement refusé | ps_declined | Envoyé lorsqu'un paiement est refusé par le système de paiement. |
| Transaction rejetée par AFS | afs_reject | Envoyé lorsqu'une transaction est refusée lors d'un contrôle AFS. |
| Mise à jour de la liste noire AFS | afs_black_list | Envoyé lorsque la liste noire AFS est mise à jour. |
| Abonnement créé | create_subscription | Envoyé lorsque l'utilisateur crée un abonnement. |
| Abonnement mis à jour | update_subscription | Envoyé lors du renouvellement ou de la modification d'un abonnement. |
| Abonnement annulé | cancel_subscription | Envoyé lorsqu'un abonnement est annulé. |
| Abonnement non renouvelable | non_renewal_subscription | Envoyé lorsque le statut est défini sur non renouvelable. |
| Ajout de compte de paiement | payment_account_add | Envoyé lorsque l'utilisateur ajoute ou enregistre un compte de paiement. |
| Suppression de compte de paiement | payment_account_remove | Envoyé 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é partenaire | partner_side_catalog | Envoyé lorsque l'utilisateur interagit avec le magasin. |
| Paiement de commande réussi | order_paid | Envoyé lorsqu'une commande est payée. |
| Annulation de commande | order_canceled | Envoyé lorsqu'une commande est annulée. |
| Contestation | dispute | Envoyé lorsqu'une nouvelle contestation est ouverte. |
Requête
Xsolla envoie le webhook order_canceled à l'URL spécifiée lorsque le paiement est annulé par l'utilisateur, le partenaire ou automatiquement. Le webhook inclut des informations sur les objets retournés et la commande annulée.
Le webhook n'est pas envoyé si le paiement n'a pas abouti, par exemple :
- l'interface de paiement a été ouverte, mais l'utilisateur n'a pas procédé au paiement de la commande ;
- l'interface de paiement a été ouverte, mais des erreurs se sont produites lors du paiement.
Le temps de traitement recommandé pour le webhook est de 3 secondes.
Liste des objets achetés par l'utilisateur.
L'ensemble des paramètres inclus dans le tableau dépend de la version du webhook. La version 2 comprend des paramètres supplémentaires : is_free, is_bonus et is_bundle_content. Pour changer de version, passez son numéro dans le paramètre version de l'appel API Update information about webhook settings.
Promotions s'appliquant à des objets spécifiques de la commande. Le tableau est renvoyé dans les cas suivants :
- Une promotion par réduction est configurée pour un objet spécifique ;
- Un code promo avec le paramètre Discount on selected items est appliqué.
Si aucune promotion n'est appliquée à un objet spécifique, un tableau vide est renvoyé.
ID unique de l'objet. Pour les objets de type game_key, une valeur au format sku_drm est utilisée.
Type d'objet. Pour les objets de type bundle, y compris les packages de monnaie virtuelle, le tableau items affichera : - paramètres du lot ou du package de monnaie virtuelle les objets inclus dans le lot ou la monnaie incluse dans le package de monnaie virtuelle
Le type value_point est utilisé dans les opérations liées aux [points de fidélité(/solutions/loyalty-as-service/) lorsqu'ils sont dépensés ou attribués.
Informations sur commande.
Coupons appliqués. Si aucun coupon n'a été appliqué, le tableau n'est pas renvoyé.
Devise de commande. L'UGS est utilisée pour la monnaie virtuelle et un code à trois lettres selon la norme ISO 4217 pour les devises réelles.
Type de devise de paiement. Pour une commande gratuite, la valeur unknown est spécifiée.
| Enum Valeur | Description |
|---|---|
| loyalty_point | points de fidélité |
| real | devise réelle |
| unknown | commande gratuite |
| virtual | monnaie virtuelle |
ID de facture pour les paiements en devises réelles. Les paiements en monnaie virtuelle ou les biens gratuits ont une valeur null.
Mode de paiement. La valeur default est utilisée pour les paiements réels et sandbox pour les paiements test.
Plateforme de paiement. La valeur xsolla est utilisée pour les paiements via Xsolla. Pour les autres paiements, la valeur correspondant au nom de la plateforme de publication de jeux est utilisée : playstation_network, xbox_live, pc_standalone, nintendo_shop, google_play, app_store_ios, android_standalone, ios_standalone, android_other, ios_other, pc_other.
Codes promo appliqués. Si aucun code promo n'a été appliqué, le tableau n'est pas renvoyé.
Promotions s'appliquant à l'ensemble de la commande. Le tableau est renvoyé dans les cas suivants :
- Une promotion affecte le montant total de l'achat, par exemple un code promo avec le paramètre Discount on purchase ;
- Aucune remise n'est appliquée à l'achat, mais des objets bonus sont ajoutés à la commande. Dans ce cas, les valeurs du coût avec remise (amount_with_discount) et sans remise (amount_without_discount) sont renvoyées et sont identiques, puisqu'aucune remise n'est appliquée.
Si aucune promotion n'est appliquée à l'ensemble de la commande, un tableau vide est renvoyé.
Informations sur l'utilisateur.
Pays de l'utilisateur. Code pays à deux lettres majuscules selon la norme ISO 3166-1 alpha-2.
- Mock serverhttps://xsolla.redocly.app/_mock/fr/webhooks/order-cancellation-separate
- https://api.xsolla.com/merchant/v2/order-cancellation-separate
- CURL
- Payload
curl -v 'https://your.hostname/your/uri' \
-X POST \
-H 'accept: application/json' \
-H 'content-type: application/json' \
-H 'authorization: Signature d09695066c52c1b8bdae92f2d6eb59f5b5f89843' \
-d '{
"notification_type": "order_canceled",
"items": [
{
"sku": "com.xsolla.v.item_1",
"type": "virtual_good",
"is_pre_order": false,
"quantity": 3,
"amount": "1000",
"promotions": [
{
"amount_without_discount": "6000",
"amount_with_discount": "5000",
"sequence": 1
},
{
"amount_without_discount": "5000",
"amount_with_discount": "4000",
"sequence": 2
}
],
"custom_attributes": {
"purchased": 0,
"attr": "value"
}
},
{
"sku": "com.xsolla.v.item_new_1",
"type": "bundle",
"is_pre_order": false,
"quantity": 1,
"amount": "1000",
"promotions": []
},
{
"sku": "com.xsolla.gold_1",
"type": "virtual_currency",
"is_pre_order": false,
"quantity": 1500,
"amount": "[null]",
"promotions": []
}
],
"order": {
"id": 1,
"mode": "default",
"currency_type": "virtual",
"currency": "sku_currency",
"amount": "2000",
"status": "paid",
"platform": "xsolla",
"comment": null,
"invoice_id": "1",
"promotions": [
{
"amount_without_discount": "4000",
"amount_with_discount": "2000",
"sequence": 1
}
],
"promocodes": [
{
"code": "promocode_some_code",
"external_id": "promocode_sku"
}
],
"coupons": [
{
"code": "WINTER2021",
"external_id": "coupon_sku"
}
]
},
"user": {
"external_id": "id_xsolla_login_1",
"email": "email@example.com",
"country": "US"
}
}'Requête
Xsolla envoie le webhook order_paid à l'URL spécifiée lorsque les conditions suivantes sont remplies :
- L'utilisateur a procédé au paiement de la commande avec succès.
- Xsolla a reçu une réponse de traitement réussi du webhook Paiement.
Le webhook order_paid contient des informations sur les objets achetés et les détails de la transaction.
Le webhook order_paid n'est pas envoyé si :
- Le paiement n'a pas été effectué, par exemple :
- le formulaire de paiement a été ouvert, mais l'utilisateur n'a pas procédé au paiement de la commande ;
- le formulaire de paiement a été ouvert, mais des erreurs se sont produites lors du paiement.
- Aucune réponse de traitement réussi du webhook Paiement n'a été reçue.
Il est recommandé de veiller à ce que la temps de traitement du webhook order_paid soit inférieur à 3 secondes.
Les réponses attendues sont décrites dans la section Réponses. Vous pouvez utiliser d'autres codes de réponse. En fonction du code de réponse et de la connexion à la fonctionnalité de remboursement automatique de paiement, la logique de traitement du webhook côté Xsolla est la suivante :
| Code de réponse | Remboursement automatique de paiement désactivé (par défaut) | Remboursement automatique de paiement activé |
|---|---|---|
400, 401, 402, 403, 404, 409, 422, 415 | Aucune action | Remboursement automatique à l'utilisateur |
200, 201, 204 | Aucune action | Aucune action |
| Code différent ou absence de réponse au webhook | Plusieurs webhooks sont envoyés à des intervalles de temps spécifiques : 2 tentatives à intervalles de 5 minutes, 7 tentatives à intervalles de 15 minutes, 10 tentatives à intervalles de 60 minutes. | Plusieurs webhooks sont envoyés à des intervalles de temps spécifiques : 2 tentatives à intervalles de 5 minutes, 7 tentatives à intervalles de 15 minutes, 10 tentatives à intervalle de 60 minutes. Si tous les webhooks sont envoyés mais qu'aucune réponse n'est reçue, l'utilisateur est automatiquement remboursé. |
Pour connecter la fonctionnalité de remboursement automatique, contactez vos responsables de réussite client ou envoyez un e-mail à csm@xsolla.com.
Liste des objets achetés par l'utilisateur.
L'ensemble des paramètres inclus dans le tableau dépend de la version du webhook. La version 2 comprend des paramètres supplémentaires : is_free, is_bonus et is_bundle_content. Pour changer de version, passez son numéro dans le paramètre version de l'appel API Update information about webhook settings.
Promotions s'appliquant à des objets spécifiques de la commande. Le tableau est renvoyé dans les cas suivants :
- Une promotion par réduction est configurée pour un objet spécifique ;
- Un code promo avec le paramètre Discount on selected items est appliqué.
Si aucune promotion n'est appliquée à un objet spécifique, un tableau vide est renvoyé.
ID unique de l'objet. Pour les objets de type game_key, une valeur au format sku_drm est utilisée.
Type d'objet. Pour les objets de type bundle, y compris les packages de monnaie virtuelle, le tableau items affichera : - paramètres du lot ou du package de monnaie virtuelle les objets inclus dans le lot ou la monnaie incluse dans le package de monnaie virtuelle
Le type value_point est utilisé dans les opérations liées aux [points de fidélité(/solutions/loyalty-as-service/) lorsqu'ils sont dépensés ou attribués.
Informations sur commande.
Coupons appliqués. Si aucun coupon n'a été appliqué, le tableau n'est pas renvoyé.
Devise de commande. L'UGS est utilisée pour la monnaie virtuelle et un code à trois lettres selon la norme ISO 4217 pour les devises réelles.
Type de devise de paiement. Pour une commande gratuite, la valeur unknown est spécifiée.
| Enum Valeur | Description |
|---|---|
| loyalty_point | points de fidélité |
| real | devise réelle |
| unknown | commande gratuite |
| virtual | monnaie virtuelle |
ID de facture pour les paiements en devises réelles. Les paiements en monnaie virtuelle ou les biens gratuits ont une valeur null.
Mode de paiement. La valeur default est utilisée pour les paiements réels et sandbox pour les paiements test.
Plateforme de paiement. La valeur xsolla est utilisée pour les paiements via Xsolla. Pour les autres paiements, la valeur correspondant au nom de la plateforme de publication de jeux est utilisée.
Codes promo appliqués. Si aucun code promo n'a été appliqué, le tableau n'est pas renvoyé.
Promotions s'appliquant à l'ensemble de la commande. Le tableau est renvoyé dans les cas suivants :
- Une promotion affecte le montant total de l'achat, par exemple un code promo avec le paramètre Discount on purchase ;
- Aucune remise n'est appliquée à l'achat, mais des objets bonus sont ajoutés à la commande. Dans ce cas, les valeurs du coût avec remise (amount_with_discount) et sans remise (amount_without_discount) sont renvoyées et sont identiques, puisqu'aucune remise n'est appliquée.
Si aucune promotion n'est appliquée à l'ensemble de la commande, un tableau vide est renvoyé.
Informations sur l'utilisateur.
Pays de l'utilisateur. Code pays à deux lettres majuscules selon la norme ISO 3166-1 alpha-2.
- Mock serverhttps://xsolla.redocly.app/_mock/fr/webhooks/successful-order-payment-separate
- https://api.xsolla.com/merchant/v2/successful-order-payment-separate
- CURL
- Payload
curl -v 'https://your.hostname/your/uri' \
-X POST \
-H 'accept: application/json' \
-H 'content-type: application/json' \
-H 'authorization: Signature d09695066c52c1b8bdae92f2d6eb59f5b5f89843' \
-d '{
"notification_type": "order_paid",
"items": [
{
"sku": "com.xsolla.v.item_1",
"type": "virtual_good",
"is_pre_order": false,
"quantity": 3,
"amount": "1000",
"promotions": [
{
"amount_without_discount": "6000",
"amount_with_discount": "5000",
"sequence": 1
},
{
"amount_without_discount": "5000",
"amount_with_discount": "4000",
"sequence": 2
}
],
"custom_attributes":
{
"purchased": 0,
"attr": "value"
}
},
{
"sku": "com.xsolla.v.item_new_1",
"type": "bundle",
"is_pre_order": false,
"quantity": 1,
"amount": "1000",
"promotions": []
},
{
"sku": "com.xsolla.gold_1",
"type": "virtual_currency",
"is_pre_order": false,
"quantity": 1500,
"amount": "[null]",
"promotions": []
}
],
"order": {
"id": 1,
"mode": "default",
"currency_type": "virtual",
"currency": "sku_currency",
"amount": "2000",
"status": "paid",
"platform": "xsolla",
"comment": null,
"invoice_id": "1",
"promotions": [
{
"amount_without_discount": "4000",
"amount_with_discount": "2000",
"sequence": 1
}
],
"promocodes": [
{
"code": "promocode_some_code",
"external_id": "promocode_sku"
}
],
"coupons": [
{
"code": "WINTER2021",
"external_id": "coupon_sku"
}
]
},
"user": {
"external_id": "id_xsolla_login_1",
"email": "gc_user@xsolla.com",
"country": "US"
}
}'