Los webhooks son notificaciones sobre eventos que se producen en el sistema. Cuando ocurre un evento específico, Xsolla envía una solicitud HTTP, en la cual se transmiten los datos del evento, a su aplicación. Generalmente, se trata de una solicitud POST en formato JSON.
Ejemplos de eventos:
Cuando se produce un evento definido, Xsolla lo notifica a su sistema mediante un webhook. En consecuencia, puede realizar acciones como:
Ejemplo de un flujo de trabajo de webhook de procesamiento de pagos:
Nota
Dependiendo de la solución utilizada y del tipo de integración, el conjunto de webhooks y la secuencia de interacciones pueden ser distintos a los del ejemplo proporcionado.
Videoguía para la integración de webhooks con Xsolla:
Configuración de Webhooks para trabajar con productos y soluciones de Xsolla:
Producto/Solución | Obligatorio/Opcional | ¿Para qué se utilizan los webhooks? |
---|---|---|
Payments | Obligatorio |
|
In-Game Store | Obligatorio |
|
Game Sales | Opcional | Para vender claves del juego, la validación del usuario y el abono de los artículos no son necesarios. Puede conectar los webhooks si desea recibir información sobre eventos, como el pago o la cancelación de pedidos. Si conecta webhooks, es esencial procesar todos los webhooks requeridos entrantes. |
Suscripciones | Opcional | Recibir información sobre la creación, actualización o cancelación de una suscripción. También puede solicitar información mediante la API. |
Web Shop | Obligatorio |
|
Digital Distribution Hub | Obligatorio |
Consulte la documentación para obtener información detallada sobre cómo establecer webhooks para el Digital Distribution Hub. |
Login | Opcional |
Recibir información sobre un evento:
Consulte la documentación de Login para obtener información detallada sobre cómo establecer webhooks. |
Si utiliza productos y soluciones que requieren trabajar con webhooks, active y pruebe los webhooks en su Cuenta del editor y establezca su procesamiento. Cuando se producen eventos específicos, los webhooks se envían secuencialmente. Por lo tanto, si no procesa uno de los webhooks, no se enviarán los posteriores. La lista de webhooks requeridos se muestra a continuación.
Se han configurado 2 opciones de envío de webhook por parte de Xsolla al comprar y devolver artículos en el sitio: la información con los datos de pago y transacción, y la información sobre los artículos comprados pueden enviarse por separado o pueden combinarse en un solo webhook.
Recibir información en webhooks combinados:
Si se registró en Cuenta del editor
después del 22 de enero de 2025, recibirá toda la información en los webhooks
Successful payment for
order (order_paid
) y Order cancellation (order_canceled
). En este caso, no es
necesario procesar los webhooks Payment (payment
) y Refund (refund
).
Recibir información en webhooks separados:
Si se registró en Cuenta del editor el 22 de enero de 2025 o antes, recibirá los siguientes webhooks:
payment
) y Reembolso (refund
) con información
sobre los datos de pago y los detalles de la transacción.order_paid
) y Order cancellation (order_canceled
) con
información sobre los artículos comprados.Debe procesar todos los webhooks entrantes. Para cambiar a la nueva opción con la recepción de webhooks combinados, contacte con sus gestores de éxito del cliente o escriba a csm@xsolla.com.
Para el funcionamiento completo de la tienda del juego y la gestión de pagos, es necesario implementar el procesamiento de los principales webhooks.
Si recibe webhooks combinados:
Nombre y tipo de webhook | Descripción |
---|---|
Validación del usuario > Validación del usuario (user_validation ) |
Se envía en diferentes etapas del proceso de pago para garantizar que el usuario está registrado en el juego. |
> Webhooks combinados > de Game services Successful payment for order (order_paid ) |
Contiene datos de pago, detalles de la transacción e información sobre los artículos comprados. Utilice los datos del webhook para añadir artículos al usuario. |
Servicios de juego > Webhooks combinados > Cancelación del pedido (order_canceled ) |
Contiene datos del pago cancelado, detalles de la transacción e información sobre los artículos comprados. Utilice los datos del webhook para eliminar los artículos comprados. |
Si recibe webhooks por separado:
Nombre y tipo de webhook | Descripción |
---|---|
Validación del usuario > Validación del usuario (user_validation ) |
Se envía en diferentes etapas del proceso de pago para garantizar que el usuario está registrado en el juego. |
Pagos > Pago (payment ) |
Contiene los datos del pago y los detalles de la transacción. |
> Webhooks separados >de Game services Successful payment for order (order_paid ) |
Contiene información sobre los artículos comprados. Utilice los datos del webhook para añadir artículos al usuario. |
Pagos > Reembolso (refund ) |
Contiene los datos del pago y los detalles de la transacción. |
Servicios de juego > Webhooks separados > Cancelación del pedido (order_canceled ) |
Contiene información sobre los artículos comprados y el ID de la transacción cancelada. Utilice los datos del webhook para eliminar los artículos comprados. |
Si la personalización del catálogo de artículos se implementa en el lado de su aplicación, establezca el procesamiento del webhook Personalización del catálogo en el lado del socio.
Nota
Para recibir pagos reales, solo es necesario firmar el acuerdo de licencia e implementar el procesamiento de los webhooks:
Para gestionar automáticamente los planes de suscripción, es necesario implementar el procesamiento de los principales webhooks:
user_validation
): se envía en diferentes etapas del proceso de pago para
garantizar que el usuario esté registrado en el juego.payment
): se envía cuando se
paga un pedido y contiene los datos del pago y los detalles de la transacción.create_subscription
): se envía cuando se ha procesado correctamente un
webhook de Pago o el usuario ha
adquirido una suscripción con un periodo de prueba. Contiene los detalles de la
suscripción adquirida y los datos del usuario. Use los datos del webhook para
agregar una suscripción al usuario.update_subscription
): se envía cuando se renueva o modifica una suscripción,
cuando se ha procesado correctamente un webhook de Pago.
Contiene los detalles de la suscripción adquirida y los datos del usuario. Use
los datos del webhook para ampliar la suscripción del usuario o cambiar los
parámetros de la suscripción.refund
): se envía cuando
se cancela un pedido y contiene los datos del pago cancelado y los detalles de
la transacción.cancel_subscription
): se envía cuando se ha procesado correctamente un
webhook de Reembolso o se ha cancelado
la suscripción por otro motivo. Contiene información sobre la suscripción y los
datos del usuario. Use los datos del webhook para sustraer al usuario las
suscripciones adquiridas.Para habilitar la recepción de webhooks:
https://example.com
. También puede
especificar la URL que encuentre en una herramienta para probar webhooks.Atención
El protocolo HTTPS se utiliza para transferir datos; el protocolo HTTP no es compatible.
Tenga en cuenta
Para probar los webhooks, puede seleccionar cualquier sitio web específico, como webhook.site, o una plataforma, como ngrok.
Atención
No puede enviar simultáneamente webhooks a diferentes URL. Lo que sí puede hacer en la Cuenta del editor es especificar primero una URL de prueba y luego sustituirla por la real.
Para deshabilitar la recepción de webhooks:
Para los webhooks de la sección Payments and Store, hay opciones de configuración avanzada disponibles. Aparecerán automáticamente en el bloque General settings después de hacer clic en el botón Get webhooks.
Nota
Si no se muestra la configuración avanzada, asegúrese de que la recepción de webhooks está conectada en la configuración general y de que se encuentra en la pestaña Testing > Payments and Store.
En esta sección puede configurar la recepción de información adicional en webhooks. Para ello, active la opción. La línea de cada permiso indica los webhooks que se verán afectados al cambiar la configuración.
Conmutador | Descripción |
---|---|
Mostrar información sobre la cuenta de pago guardada | La información sobre el método de pago guardado se transmite en el objeto personalizado payment_account . |
Mostrar información sobre las transacciones mediante los métodos de pago guardados | La información se transmite en los siguientes parámetros personalizados del webhook:
|
Añadir objeto del pedido al webhook | La información sobre el pedido se transmite en el objeto order del webhook Pago. |
Enviar solamente los parámetros de usuario necesarios sin datos confidenciales | Solamente la siguiente información sobre el usuario se transmite en el webhook:
|
Enviar parámetros personalizados | La información sobre los parámetros de token personalizados se transmite en el webhook. |
Mostrar número de BIC y sufijo de la tarjeta | La siguiente información sobre el número de tarjeta bancaria se transmite en el webhook:
|
Mostrar marca de tarjeta | La marca de la tarjeta empleada para realizar el pago. Por ejemplo, Mastercard o Visa. |
Probar los webhooks ayuda a asegurar la correcta configuración del proyecto tanto en su lado como en el lado de Xsolla.
Si los webhooks están establecidos correctamente, aparecerá una sección de prueba de webhooks bajo la sección de configuración de webhooks.
La sección de pruebas de la Cuenta del editor varía en función de la opción de recepción del webhook.
Si recibe webhooks combinados:
Nombre de la pestaña para pruebas de webhook | Nombre y tipo de webhook |
---|---|
Payments and store | Validación del usuario > Validación del usuario (user_validation ) |
> Webhooks combinados > de Game services Successful payment for order (order_paid ) |
|
Servicios de juego > Webhooks combinados > Cancelación del pedido (order_canceled ) |
|
Subscriptions | Validación del usuario > Validación del usuario (user_validation ) |
Pagos > Pago (payment ) |
Si recibe webhooks por separado:
Nombre de la pestaña para pruebas de webhook | Nombre y tipo de webhook |
---|---|
Store | > Webhooks separados >de Game services Successful payment for order (order_paid ) |
Servicios de juego > Webhooks separados > Cancelación del pedido (order_canceled ) |
|
Payments | Validación del usuario > Validación del usuario (user_validation ) |
Pagos > Pago (payment ) |
|
Subscriptions | Validación del usuario > Validación del usuario (user_validation ) |
Pagos > Pago (payment ) |
Tenga en cuenta
Si aparece un aviso de que la prueba no se ha superado en la sección de pruebas, verifique la configuración de la respuesta del webhook en su agente de escucha del webhook. Los motivos de los errores en la prueba se indican en los resultados de la prueba.
Ejemplo:
Cuando utiliza el sitio especializado webhook.site para la prueba.
Aparece un error en la sección Testing response to invalid signature.
Esto ocurre porque Xsolla envía un webhook con una firma incorrecta y espera que su controlador responda con un código HTTP 4xx
que especifique el código de error INVALID_SIGNATURE
.
webhook.site envía un código HTTP 200
en respuesta a todos los webhooks, incluyendo un webhook con una firma incorrecta. No se puede obtener el código HTTP 4xx
esperado, por lo que aparece un error en el resultado de la prueba.
A continuación se describe el proceso de pruebas para el escenario con webhooks combinados.
En la pestaña Payments and Store, puede probar los siguientes webhooks:
user_validation
)order_paid
)order_canceled
)Para realizar la prueba:
En la sección de pruebas de webhooks, vaya a la pestaña Payments and Store.
En el menú desplegable, seleccione el tipo de artículo. Si el artículo del tipo seleccionado no está establecido en Cuenta del editor, haga clic en:
Rellene los campos necesarios:
Haga clic en Test webhooks.
Los webhooks User validation, Successful payment for order y Order cancellation con los datos especificados se envían a la URL facilitada. Los resultados de la prueba de cada tipo de webhook se muestran debajo del botón Test webhooks.
Si el ID de usuario público está activado en su proyecto, también verá los resultados de una comprobación de búsqueda de usuarios.
Para cada webhook, tiene que establecer el procesamiento de ambos escenarios: uno, satisfactorio, y el otro, fallido.
En la pestaña Subscriptions puede probar los siguientes webhooks:
user_validation
)payment
)Nota
En la Cuenta del editor, solo es posible probar los webhooks básicos de Validación del usuario y Pago. Para probar otros tipos de webhooks, vaya a:
Nota
Para probar los webhooks, debe tener al menos un plan de suscripción creado en la sección Cuenta del editor > Subscriptions > Subscription Plans.
Para realizar pruebas:
0
.En la URL especificada, recibirá webhooks con datos rellenados. Los resultados de las pruebas de cada webhook, tanto para un escenario con satisfactorio como para un escenario fallido, se muestran bajo el botón Test webhooks.
El agente de escucha es un código de programa que permite recibir webhooks entrantes en una dirección URL especificada, generar una firma y enviar una respuesta al servidor de webhooks de Xsolla.
Nota
Puede utilizar la biblioteca de SDK para PHP de Pay Station, que contiene clases predefinidas para procesar webhooks.
En el lado de su aplicación, implemente la recepción de webhooks desde las siguientes direcciones IP:
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 ha integrado el producto Login, añada webhooks de procesamiento desde las siguientes direcciones IP:
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
Limitaciones:
Para garantizar una transmisión de datos segura, debe comprobar que el webhook
se ha enviado desde el servidor de Xsolla y que no ha sido manipulado durante
el tránsito. Para ello, genere su propia firma basada en la carga útil del
cuerpo de la solicitud y compárela con la firma proporcionada en el encabezado
authorization
de la solicitud entrante. Si las firmas coinciden, significa
que el webhook es auténtico y seguro de procesar.
Pasos de verificación:
Obtenga la firma del encabezado authorization
de la solicitud de webhook
entrante. El formato del encabezado es Signature <signature_value>
.
Obtenga el cuerpo de la solicitud del webhook en formato JSON.
Atención
Utilice la carga JSON tal y como la recibió. No analice ni recodifique la carga útil, ya que modificaría el formato y provocaría un error en la verificación de la firma.
Genere su propia firma para comparar:
Compare su firma generada con la del encabezado authorization
. Si coinciden,
significa que el webhook es auténtico.
A continuación encontrará ejemplos de implementación de generación de firmas para los siguientes lenguajes: C#, C++, Go, PHP y 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"
}
}'
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 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);
return string.Equals(computedSignature, receivedSignature, StringComparison.OrdinalIgnoreCase);
}
}
#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;
}
}
}
Para confirmar la recepción del webhook, su servidor debe devolver:
Si el servidor de Xsolla no ha recibido respuesta a los webhooks Successful payment for
order y Order
cancellation o ha recibido una respuesta con un código 5xx
, los webhooks
se reenvían de la siguiente manera:
Se realiza un máximo de 20 intentos de envío de webhooks en un plazo de 12 horas desde el primer intento.
Si el servidor de Xsolla no ha recibido una respuesta al webhook Pago o al webhook Reembolso, ni ha recibido una respuesta
con un código 5xx
, los webhooks también se reenviarán con un intervalo de
tiempo mayor. Se realiza un máximo de 12 intentos en 12 horas.
Atención
Si la devolución del pago fue iniciado por Xsolla y llegó una respuesta con un código HTTP `5xx` como respuesta al webhook Reembolso, el pago seguirá siendo reembolsado.
Si el servidor de Xsolla no ha recibido respuesta al webhook User validation o ha recibido
una respuesta con un código 400
o 5xx
, el webhook User validation no se reenvía.
En este caso, el usuario ve un error y los webhooks Payment y Successful payment for order no se envían.
Códigos de error para el código HTTP 400:
Código | Mensaje |
---|---|
INVALID_USER | Usuario no válido |
INVALID_PARAMETER | Parámetro no válido |
INVALID_SIGNATURE | Firma no válida |
INCORRECT_AMOUNT | Importe incorrecto |
INCORRECT_INVOICE | Factura incorrecta |
HTTP/1.1 400 Bad Request
{
"error":{
"code":"INVALID_USER",
"message":"Invalid user"
}
}
Observación
El tipo de notificación se envía en el parámetro notification_type
.
Webhook | Tipo de notificación | Descripción |
---|---|---|
Validación del usuario | user_validation |
Se envía para comprobar si un usuario existe en el juego. |
Búsqueda de usuario | user_search |
Se envía para obtener información de usuario basada en el ID público del usuario. |
Pago | payment |
Se envía cuando un usuario realiza un pago. |
Reembolso | refund |
Se envía cuando un pago debe cancelarse por cualquier motivo. |
Reembolso parcial | partial_refund |
Se envía cuando un pago debe cancelarse parcialmente por cualquier motivo. |
Transacción de AFS rechazada | afs_reject |
Se envía cuando se rechaza una transacción durante una comprobación de AFS. |
Lista de bloqueo de AFS rechazada | afs_black_list |
Se envía cuando se actualiza la lista de bloqueo de AFS. |
Suscripción creada | create_subscription |
Se envía cuando un usuario crea una suscripción. |
Suscripción actualizada | update_subscription |
Se envía cuando se renueva o modifica una suscripción. |
Suscripción cancelada | cancel_subscription |
Se envía cuando se cancela una suscripción. |
Suscripción con renovación suspendida | non_renewal_subscription |
Se envía cuando el estado es de renovación suspendida. |
Añadir cuenta de pago | payment_account_add |
Se envía cuando un usuario añade o guarda una cuenta de pago. |
Eliminar cuenta de pago | payment_account_remove |
Se envía cuando un usuario elimina la cuenta de pago de las cuentas guardadas. |
Validación del usuario en Web Shop | - |
Se envía desde un sitio de Web Shop para comprobar si un usuario existe en el juego. |
Personalización del catálogo en el lado del socio | partner_side_catalog |
Se envía cuando un usuario interactúa con la tienda. |
Successful payment for order | order_paid |
Se envía cuando se paga un pedido. |
Order cancellation | order_canceled |
Se envía cuando se cancela un pedido. |
Dispute | dispute |
Se envía cuando se abre una nueva disputa. |