Saltar al contenido

Descripción general

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:

  • interacción del usuario con un catálogo de artículos
  • pago o cancelación de un pedido

Cuando se produce un evento definido, Xsolla lo notifica a su sistema mediante un webhook. En consecuencia, puede realizar acciones como:

  • reponer el saldo del usuario
  • efectuar una devolución de pago
  • abonar o cargar nuevos artículos en la cuenta de usuario
  • empezar a proveer una suscripción
  • bloquear a un usuario si hay una sospecha de fraude

Ejemplo de un flujo de trabajo de webhook de procesamiento de pagos:

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ónObligatorio/Opcional¿Para qué se utilizan los webhooks?
PaymentsObligatorio
  • Validación del usuario.
  • Recibir información sobre los datos de la transacción en caso de pago aceptado o devolución del pago.
  • Abonar a un usuario los artículos comprados y cargar en su cuenta los artículos si se cancela el pedido.
In-Game StoreObligatorio
  • Validación del usuario.
  • Recibir información sobre los datos de la transacción en caso de pago aceptado o devolución del pago.
  • Abonar a un usuario los artículos comprados y cargar en su cuenta los artículos si se cancela el pedido.
Game SalesOpcionalPara 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.
SuscripcionesOpcionalRecibir 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 ShopObligatorio
  • Validación del usuario.
  • Recibir información sobre los datos de la transacción en caso de pago aceptado o devolución del pago.
  • Abonar a un usuario los artículos comprados y cargar en su cuenta los artículos si se cancela el pedido.
  • Autenticación de usuario, si usa la autenticación mediante ID de usuario. Como alternativa, puede utilizar autenticación de usuario mediante Xsolla Login.
Digital Distribution HubObligatorio
  • Validación del usuario.
  • Vincular el ID de transacción en el lado de Xsolla con el ID de transacción en su sistema.
  • Transferir parámetros de transacción adicionales en el pedido.
  • Abonar al usuario los artículos comprados y cargar en su cuenta los artículos si se cancela el pedido.

Consulte la documentación para obtener información detallada sobre cómo establecer webhooks para el Digital Distribution Hub.

LoginOpcional

Recibir información sobre un evento:

  • registro/autorización del usuario
  • Confirmación de la dirección de correo electrónico del usuario
  • vincular la cuenta de redes sociales de un usuario

Consulte la documentación de Login para obtener información detallada sobre cómo establecer webhooks.

Lista de webhooks requeridos

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.

In-Game Store y Payments

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:

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 webhookDescripció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 webhookDescripció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:

Suscripciones

Para gestionar automáticamente los planes de suscripción, es necesario implementar el procesamiento de los principales webhooks:

  • 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.
  • Pago (payment): se envía cuando se paga un pedido y contiene los datos del pago y los detalles de la transacción.
  • Suscripción creada (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.
  • Suscripción actualizada (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.
  • Reembolso (refund): se envía cuando se cancela un pedido y contiene los datos del pago cancelado y los detalles de la transacción.
  • Suscripción cancelada (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.

Establecer webhooks en Cuenta del editor

Configuración general

Para habilitar la recepción de webhooks:

  1. En el proyecto en la Cuenta del editor vaya a Project Settings > Webhooks.
  2. En el campo Webhook server, especifique la URL de su servidor en el que desea recibir webhooks en el formato 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.

  1. Por defecto, se genera una clave secreta para firmar los webhooks del proyecto. Si desea generar una nueva clave secreta, haga clic en el icono de actualización.
  2. Haga clic en Enable webhooks.

Enable 
webhooks

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:

  1. En el proyecto en la Cuenta del editor vaya a Project Settings > Webhooks.
  2. Haga clic en Disable webhooks.

Configuración avanzada

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.

ConmutadorDescripción
Mostrar información sobre la cuenta de pago guardadaLa 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:

  • saved_payment_method:
    • 0: no se utilizó el método de pago guardado
    • 1: el método de pago se guardó al realizar el pago actual
    • 2: se utiliza el método de pago guardado previamente
  • payment_type:
    • 1: pago único
    • 2: pago periódico
Añadir objeto del pedido al webhookLa 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:

  • ID
  • país
Enviar parámetros personalizadosLa 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:

  • los 6 primeros dígitos del parámetro card_bin
  • los 4 últimos dígitos del card_suffix
Mostrar marca de tarjetaLa marca de la tarjeta empleada para realizar el pago. Por ejemplo, Mastercard o Visa.

Configuración 
avanzada

Probar webhooks en Cuenta del editor

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.

Sección de pruebas 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 webhookNombre y tipo de webhook
Payments and storeValidació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)
SubscriptionsValidació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 webhookNombre 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)
PaymentsValidación del usuario >Validación del usuario (user_validation)
Pagos >Pago (payment)
SubscriptionsValidació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.

Error en la prueba

A continuación se describe el proceso de pruebas para el escenario con webhooks combinados.

Payments and Store

En la pestaña Payments and Store, puede probar los siguientes webhooks:

Para realizar la prueba:

  1. En la sección de pruebas de webhooks, vaya a la pestaña Payments and Store.

  2. 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:

    • Connect: si el módulo con artículos de este tipo no está conectado.
    • Configure: si conectó el módulo anteriormente, pero no ha finalizado la configuración
      Cuando haga clic en el botón, se le redirigirá a la sección de Cuenta del editor correspondiente al tipo de artículo seleccionado. Cuando haya creado el artículo, vuelva a la sección de pruebas de webhooks y proceda al siguiente paso.
  3. Rellene los campos necesarios:

    1. Seleccione el SKU de los artículos en la lista desplegable e indique la cantidad. Puede elegir varios artículos del mismo tipo haciendo clic en + y añadiéndolos en una nueva línea.
    2. User ID: al realizar la prueba, puede utilizar cualquier combinación de letras y dígitos.
    3. Public user ID: ID conocido por un usuario, por ejemplo, un correo electrónico o un apodo. Este campo se muestra si el ID de usuario público está habilitado en su proyecto en Pay Station > Settings.
    4. Introduzca cualquier valor en el campo Xsolla Order ID.
    5. Xsolla Invoice ID: ID de transacción en el lado de Xsolla. Al realizar la prueba, puede usar cualquier valor numérico.
    6. Invoice ID: ID de transacción del lado de su juego. Al realizar la prueba, puede utilizar cualquier combinación de letras y dígitos. No es un parámetro requerido para pagar correctamente, pero puede transmitirlo para enlazar el ID de transacción de su lado con el ID de transacción del lado de Xsolla.
    7. Amount: cantidad del pago. Al realizar la prueba, puede utilizar cualquier valor numérico.

  4. Currency: seleccione una moneda de la lista desplegable.
  5. 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.

Sección de pruebas de 
pagos

Suscripciones

En la pestaña Subscriptions puede probar los siguientes webhooks:

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:

  1. En la sección de pruebas, vaya a la pestaña Subscriptions.
  2. Rellene los campos necesarios:
    1. User ID: al realizar la prueba, puede usar cualquier combinación de letras y dígitos.
    2. Xsolla Invoice ID: ID de transacción en el lado de Xsolla. Cuando realice pruebas, puede usar cualquier valor numérico.
    3. Public user ID: ID conocido por un usuario, p. ej., un correo electrónico o un alias. Este campo se muestra si el ID público de usuario está habilitado en su proyecto en la sección Pay Station > Settings > Additional settings.
    4. Currency: seleccione una moneda de la lista desplegable.
    5. Plan ID: un plan de suscripción. Elija un plan de la lista desplegable.
    6. Subscription product: elija un producto de la lista desplegable (opcional).
    7. Amount: importe del pago. Al realizar pruebas, puede usar cualquier valor numérico.
    8. Invoice ID: ID de transacción en el lado del juego. Cuando realice pruebas, puede usar cualquier combinación de letras y dígitos. No es un parámetro obligatorio para que el pago sea aceptado, pero puede transmitirlo para vincular el ID de transacción de su lado con el ID de transacción del lado de Xsolla.
    9. Periodo de prueba. Para probar la comp ra de una suscripción sin periodo de prueba o para probar la renovación de una suscripción, especifique el valor 0.
  3. Haga clic en Test webhooks.

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.

Agente de escucha de 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:

  • En la base de datos de su aplicación no debería haber varias transacciones aceptadas con el mismo ID.
  • Si el agente de escucha de webhooks recibió un webhook con un ID que ya existe en la base de datos, deberá devolver el resultado del procesamiento anterior de esta transacción. No se recomienda acreditar al usuario una compra duplicada ni crear registros duplicados en la base de datos.

Generación de firma

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:

  1. Obtenga la firma del encabezado authorization de la solicitud de webhook entrante. El formato del encabezado es Signature <signature_value>.

  2. 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.

  3. Genere su propia firma para comparar:

    1. Concatene la carga JSON con la clave secreta de su proyecto al añadir la clave al final de la cadena.
    2. Aplique la función hash criptográfica SHA-1 a la cadena obtenida. El resultado será una cadena hexadecimal en minúsculas.

  4. 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.

Ejemplo 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"
  }
}

Ejemplo 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"
      }
    }'

Ejemplo C# de implementación de generación de firmas (muestra general):

Nota

Este ejemplo de código es compatible con .NET Framework 4.0 y versiones posteriores, así como con .NET Core y otras versiones modernas de .NET. La verificación de firmas utiliza la comparación en tiempo constante a través del método ConstantTimeEquals para ayudar a prevenir ataques de temporización.

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;
    }
}

Ejemplo C# de implementación de generación de firmas (.NET 5.0 y posteriores):

Nota

Para utilizar el método Convert.ToHexString, necesita .NET 5.0 y posterior.

Si tiene .NET 7.0 y posterior, también puede utilizar el método CryptographicOperations.FixedTimeEquals en lugar 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;
    }
}

Ejemplo C# de implementación de generación de firmas (.NET 7.0 y posteriores):

Nota

Si dispone de .NET 7.0 y versiones posteriores, puede utilizar el método 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);
}

Ejemplo C++ de implementación de generación de firmas:

#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;
    }
};

Ejemplo Go de implementación de generación de firmas:

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
}

Ejemplo PHP de implementación de generación de firmas:

<?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));
    }
}
?>

Ejemplo Node.js de implementación de generación de firmas:

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;
        }
    }
}

Enviar respuestas al webhook

Para confirmar la recepción del webhook, su servidor debe devolver:

  • Código HTTP "200", "201" o "204" en el caso de una respuesta satisfactoria.
  • Código HTTP "400" con la descripción del problema si no se encontró el usuario especificado o se transmitió una firma no válida. Su gestor de webhooks también puede devolver un código HTTP "5xx" si hay problemas temporales en su servidor.

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:

  • 2 intentos con un intervalo de 5 minutos
  • 7 intentos con un intervalo de 15 minutos
  • 10 intentos con un intervalo de 60 minutos

Se realiza un máximo de 20 intentos de envío de webhooks en un plazo de 12 horas desde el primer intento.

La lógica de reintento para los webhooks de pago y reembolso se describe en la página del webhook correspondiente.

Aviso

El pago se reembolsará al usuario si se cumplen las siguientes condiciones:

  • El reembolso lo inició Xsolla.
  • En respuesta a un webhook, se devolvió un código de estado 4xx, o no se recibió ninguna respuesta tras todos los intentos, o se devolvió un código de estado 5xx.

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.

Errores

Códigos de error para el código HTTP 400:

CódigoMensaje
INVALID_USERUsuario no válido
INVALID_PARAMETERParámetro no válido
INVALID_SIGNATUREFirma no válida
INCORRECT_AMOUNTImporte incorrecto
INCORRECT_INVOICEFactura incorrecta
HTTP/1.1 400 Bad Request
{
    "error":{
        "code":"INVALID_USER",
        "message":"Invalid user"
    }
}

Lista de webhooks

Observación

El tipo de notificación se envía en el parámetro notification_type.

WebhookTipo de notificaciónDescripción
Validación del usuariouser_validationSe envía para comprobar si un usuario existe en el juego.
Búsqueda de usuariouser_searchSe envía para obtener información de usuario basada en el ID público del usuario.
PagopaymentSe envía cuando un usuario realiza un pago.
ReembolsorefundSe envía cuando un pago debe cancelarse por cualquier motivo.
Reembolso parcialpartial_refundSe envía cuando un pago debe cancelarse parcialmente por cualquier motivo.
Pago rechazadops_declinedSe envía cuando un pago es rechazado por el sistema de pago.
Transacción de AFS rechazadaafs_rejectSe envía cuando se rechaza una transacción durante una comprobación de AFS.
Lista de bloqueo de AFS rechazadaafs_black_listSe envía cuando se actualiza la lista de bloqueo de AFS.
Suscripción creadacreate_subscriptionSe envía cuando un usuario crea una suscripción.
Suscripción actualizadaupdate_subscriptionSe envía cuando se renueva o modifica una suscripción.
Suscripción canceladacancel_subscriptionSe envía cuando se cancela una suscripción.
Suscripción con renovación suspendidanon_renewal_subscriptionSe envía cuando el estado es de renovación suspendida.
Añadir cuenta de pagopayment_account_addSe envía cuando un usuario añade o guarda una cuenta de pago.
Eliminar cuenta de pagopayment_account_removeSe 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 sociopartner_side_catalogSe envía cuando un usuario interactúa con la tienda.
Successful payment for orderorder_paidSe envía cuando se paga un pedido.
Order cancellationorder_canceledSe envía cuando se cancela un pedido.
DisputedisputeSe envía cuando se abre una nueva disputa.
Descargar descripción de OpenAPI
Idiomas
Servidores
Mock server
https://xsolla.redocly.app/_mock/es/webhooks/
https://api.xsolla.com/merchant/v2/
Webhooks
Webhooks
Webhooks
Webhooks
Webhooks
Webhooks

Transacción rechazada por el sistema Anti-fraudWebhook

Solicitud

Cuando se rechaza una transacción durante una comprobación del sistema Antifraude, Xsolla envía los detalles de la transacción en el webhook con el tipo de afs_reject a la URL del webhook. Para recibir este webhook, contacte con su gestor del éxito del cliente o envíe un correo electrónico a csm@xsolla.com.

Al guardar la URL del webhook en Cuenta del editor, puede dar permisos para recibir información detallada en los webhooks. Para ello, active la siguiente opción en Cuenta del editor en Project settings > Webhooks > Advanced settings.

Nota

Si se registró en Cuenta del editor el 22 de enero de 2025 o antes, encontrará las opciones en Project settings > Webhooks > Testing > Payments > Advanced settings.

ConmutadorDescripción
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:

  • saved_payment_method:
    • 0: no se utilizó el método de pago guardado
    • 1: el método de pago se guardó al realizar el pago actual
    • 2: se utiliza el método de pago guardado previamente
  • payment_type:
    • 1: pago único
    • 2: pago periódico
Cuerpoapplication/json
notification_typestring(notification_type)requerido

Tipo de notificación.

refund_detailsobject

Detalles del reembolso (objeto).

settingsobject

Configuración del proyecto personalizada (objeto).

transactionobjectrequerido

Datos de la transacción (objeto).

transaction.​agreementinteger

ID del acuerdo.

transaction.​dry_runinteger

Transacción de prueba. El parámetro tiene el valor 1 si es una transacción de prueba, o no se envía si la transacción es real.

transaction.​external_idstring

ID externo de la transacción.

transaction.​idinteger

ID de la transacción.

userobject

Datos del usuario (objeto).

curl -v 'https://your.hostname/your/uri' \
-X POST \
-d '{
  "notification_type": "afs_reject",
  "settings": {
    "project_id": 18404,
    "merchant_id": 2340
  },
  "user": {
    "ip": "127.0.0.1",
    "phone": "18777976552",
    "email": "email@example.com",
    "id": "1234567",
    "name": "John Smith",
    "country": "US"
  },
  "transaction": {
    "id": 1,
    "external_id": 1,
    "dry_run": 1,
    "agreement": 1
  },
  "refund_details": {
    "code": 4,
    "reason": "Potential fraud"
  }
}'

Respuestas

Devuelve para indicar un procesamiento realizado correctamente.

Respuesta
Sin contenido

Solicitud

Cuando se abre una nueva disputa o una disputa cambia de estado, Xsolla envía un webhook con el tipo dispute a la URL del webhook. Para recibir este webhook, contacte con su gestor de éxito del cliente o envíe un correo electrónico a csm@xsolla.com.

Cuerpoapplication/json
actionstringrequerido

Tipo de acción.

Enumeración ValorDescripción
adding

Se ha abierto una nueva disputa.

updating

El estado de una disputa ha cambiado.

disputeobjectrequerido

Objeto con información sobre la disputa.

dispute.​incoming_datestring(dispute-date)requerido

Fecha de apertura de la disputa según la norma RFC 3339.

dispute.​reasonstring(dispute-reason)requerido

Motivo de la apertura de la disputa. Consulte la documentación para obtener una descripción de los grupos de motivos.

Enumeración"non_receipt""not_as_described""duplicate_processing""paid_by_other_means""incorrect_amount""credit_not_processed""general""fraud""cancelled_recurring""cancelled_merchandise"
dispute.​statusstring(dispute-status)requerido

Estado de la disputa.

Enumeración ValorDescripción
accepted

Aceptada

lost

Perdida

new

Nueva

no_actions_required

En curso

won

Ganada

dispute.​typestring(dispute-type)requerido

Tipo de disputa.

Enumeración ValorDescripción
1st_time_chargeback

Primer contracargo.

2nd_time_chargeback

Segundo contracargo (previo al arbitraje).

arbitration

Resolver una disputa entre el banco emisor y el comerciante cuando se rechazaron el 1.er contracargo y el 2.º contracargo.

chargeback

Primer contracargo.

chargeback_reversal

El contracargo ha sido revocado.

claim

Una disputa en PayPal entre un cliente y un comerciante.

dispute

Un titular de tarjeta ha solicitado los detalles del pago al banco.

inquiry

Un titular de tarjeta ha solicitado los detalles del pago al banco.

other

Se utiliza para los tipos de contracargos no cubiertos por ningún otro tipo.

reimbursement

Se ha realizado el reembolso.

notification_typestring(notification_type)requerido

Tipo de notificación.

settingsobjectrequerido

Objeto con información sobre la configuración del proyecto personalizada.

settings.​merchant_idinteger(settings.merchant_id)requerido

ID de vendedor.

settings.​project_idinteger(settings.project_id)requerido

ID del proyecto. Encontrará este parámetro en su cuenta Publisher junto al nombre del proyecto.

transactionobjectrequerido

Objeto con información sobre la transacción.

transaction.​country_codestring(user.country)requerido

Código de país. Dos letras mayúsculas de conformidad con la norma ISO 3166-1 alpha-2.

transaction.​date_createstring(date-create)requerido

Fecha de pago.

transaction.​external_idstring(external-id)

ID externo de la transacción. Consulte FAQs para obtener información detallada.

transaction.​idinteger(transaction-id)requerido

ID de la transacción.

transaction.​payment_methodstring(dispute-payment-method)requerido

Método de pago.

Enumeración ValorDescripción
credit_debit_card

Tarjeta de crédito o débito

paypal

PayPal

transaction.​totalobjectrequerido

Objeto con información sobre el importe de la transacción.

transaction.​total.​amountnumber(float)(transaction-total-amount)requerido

Importe del pago.

transaction.​total.​currencystring(currency)requerido

Moneda. Código de moneda de tres letras de conformidad con la norma ISO 4217.

userobjectrequerido

Objeto con información sobre un usuario.

user.​emailstring(user.email)

Correo electrónico del usuario.

user.​idstring(user.id)requerido

ID de usuario.

curl -v 'https://your.hostname/your/uri' \
-X POST \
-H 'authorization: Signature 32c64a80d2527dc08906ae1891bac4489509b9f6' \
-d '{
  "notification_type": "dispute",
  "action": "adding",
  "transaction": {
    "id": 123456789,
    "date_create": "2023-08-24T10:21:00+04:00",
    "total": {
      "amount": 1,
      "currency": "EUR"
    },
    "payment_method": "credit_debit_card"
  },
  "settings": {
    "project_id": 18404,
    "merchant_id": 2340
  },
  "user": {
    "id": "1234567",
    "email": "email@example.com",
    "country_code": "US"
  },
  "dispute": {
    "incoming_date": "2024-01-25T01:02:03+04:00",
    "reason": "not_as_described",
    "type": "retrieval",
    "status": "new"
  }
}'

Respuestas

Devuelve para indicar un procesamiento realizado correctamente.

Respuesta
Sin contenido
Webhooks