Cómo usar Pay Station en combinación con la autenticación de Firebase
Si ya ha implementado la autenticación de usuario en su aplicación usando Firebase, puede generar un token de pago en el lado de Firebase y, luego, transmitirlo al lado del cliente de la aplicación para abrir la interfaz de pago.
Al usar esta opción de integración, debe implementar de forma independiente la lógica para determinar el país y la moneda del usuario para abonar la compra.
Flujo de integración:
- Regístrese en Cuenta del editor y cree un nuevo proyecto. Necesitará el ID del proyecto creado para los pasos posteriores.
- Establecer un catálogo:
- Cree un catálogo de artículos en el lado de Xsolla. Puede agregar artículos manualmente o importarlos desde Google Play o PlayFab.
- Implemente la obtención y visualización del catálogo en el lado del cliente de la aplicación usando el kit SDK.
- Establecer la compra de un artículo:
- Cree un pedido con los datos del usuario y del artículo en el lado del cliente de la aplicación usando la función de nube de Firebase.
- Implemente la apertura de la interfaz de pago en el lado del cliente de su aplicación usando el kit SDK.
Para ejecutar la integración y empezar a aceptar pagos reales, deberá firmar un acuerdo de concesión de licencia con Xsolla.
Puede firmar el acuerdo de licencia en cualquier paso de la integración, pero tenga en cuenta que el proceso de revisión puede tardar hasta 3 días laborables.
Utilice la aplicación web de muestra como ejemplo para implementar el uso combinado de la autenticación de Firebase y Pay Station. El código fuente de la aplicación de muestra está disponible en GitHub.
Crear proyecto
Registrarse en Cuenta del editor
Cuenta del editor es la herramienta fundamental para configurar las funciones de Xsolla, así como para operar con los análisis y las transacciones.
Los datos sobre la empresa y su aplicación indicados durante el registro se usarán para crear un borrador de acuerdo de licencia con Xsolla y para generar recomendaciones sobre las soluciones que se adaptan a sus necesidades. Puede modificar los datos después, pero si facilita los datos correctos al registrarse, se acelerará el proceso de firma del acuerdo de licencia.
Para registrarse, acceda a Cuenta del editor y cree una cuenta.
La contraseña de Cuenta del editor puede estar compuesta por letras del alfabeto latino, números y caracteres especiales y debe contener al menos:
- 8 caracteres
- un dígito
- una letra mayúscula
- y una letra minúscula
Para maximizar la seguridad de su contraseña, le recomendamos:
- cambiar su contraseña al menos una vez cada 90 días
- utilizar una contraseña nueva que no coincida con las 4 últimas contraseñas de su cuenta
- utilizar una contraseña única que no coincida con contraseñas empleadas en ningún otro lugar
- no almacenar su contraseña en un lugar de fácil acceso
- utilizar gestores de contraseñas para almacenar su contraseña
Cuenta del editor utiliza la autenticación de dos factores y envía un código de confirmación siempre que se produce un intento de autenticación.
Crear proyecto en Cuenta del editor
Si tiene varias aplicaciones, recomendamos crear un proyecto independiente para cada una de ellas. A partir de los datos especificados durante la creación del proyecto, Xsolla genera recomendaciones sobre soluciones que se adaptan a sus necesidades.
Para crear un nuevo proyecto:
- Abra Cuenta del editor.
- En el menú lateral, haga clic en Create project.

- Introduzca el nombre de su proyecto en inglés (obligatorio).
- Seleccione una o varias plataformas de lanzamiento de su juego (obligatorio).
- Agregue un enlace a su juego. Si su juego aún no tiene sitio web, proporcione un enlace a su sitio web principal o sección donde aparezcan los juegos (obligatorio).
- Seleccione el motor del juego.
- Seleccione las opciones de monetización que utiliza o prevé utilizar.
- Especifique si el juego ya se ha lanzado. Si el juego aún no se ha lanzado, especifique la fecha de lanzamiento prevista.
- Haga clic en Create project. Podrá ver una página con los productos de Xsolla que le recomendamos.
Durante el proceso de integración, debe proporcionar el ID del proyecto que se encuentra en su Cuenta del editor junto al nombre del proyecto.

Establecer catálogo
Crear artículos en Cuenta del editor
Tiene que crear un catálogo en el lado de Xsolla. Puede agregar artículos manualmente o importarlos desde Google Play o PlayFab. Cuando haga importaciones desde Google Play, puede importar un máximo de 100 artículos cada vez.
Estas instrucciones indican los pasos para la configuración básica de un artículo virtual. Más tarde, podrá agregar otros artículos a su catálogo (moneda virtual, lotes y claves del juego), crear grupos de artículos, establecer campañas promocionales, precios regionales, etc.
Para agregar un artículo virtual con la configuración básica al catálogo:
- Abra su proyecto en Cuenta del editor.
- Haga clic en Store en el menú lateral.
- En el panel Virtual items, haga clic en Connect.
- En el menú desplegable, seleccione Create item.
- Establezca la configuración básica del artículo en los siguientes campos:
- Image (opcional)
- SKU (ID único del artículo)
- Item name
- Description (opcional)
- Especificar el precio del artículo:
- Establezca el conmutador Price in real currency en On.
- En el campo Default currency, cambie la moneda (opcional) y especifique el precio del artículo.
- Si cambió la moneda en el campo Default currency, seleccione la misma moneda en el campo Price in real currency.
- Cambie el estado del artículo a Available.
- Haga clic en Create item.
Visualizar el catálogo en el lado del cliente de la aplicación
- Descargue la última versión del SDK (recomendada) o elija la versión del SDK requerida desde GitHub y descárguela.
- Descomprima el paquete.
- En el menú principal, acceda a
Assets > Import Package > Custom Package y seleccione el SDK descargado. - En el menú principal, vaya a
Window > Xsolla > Edit Settings . - Vaya al panel
Inspector . En el campoProject ID , especifique el ID del proyecto que se encuentra en Cuenta del editor junto al nombre de su proyecto.

- En el lado del cliente de la aplicación, añada una interfaz de usuario para visualizar el catálogo de artículos.
- Implemente la solicitud de un catálogo de artículos a los servidores de Xsolla.
GetCatalog
. También puede obtener información sobre los artículos del catálogo utilizando otros métodos del SDK.Establecer la compra de artículos
Crear pedido mediante la función de nube
Para crear un pedido con los datos del usuario y del artículo en el lado de Xsolla, agregue al proyecto una función de nube que use la llamada API Crear token de pago para la compra. Esta llamada devolverá un token de pago, el cual es necesario para abrir la interfaz de pago y hacer una compra.
Limitaciones:
- Necesita transmitir el país del usuario o la dirección IP del usuario cuando se solicite el token de pago.
- Si no transmite la moneda en el token, esta se determinaré en función del país.
- Si transmite la moneda en el token, el usuario paga con esta moneda.
Para agregar una función de nube a un proyecto:
- Instale la CLI (interfaz de línea de comandos) de Firebase. Para hacerlo, ejecute el comando CLI:
1npm install -g firebase-tools
- Para vincular su proyecto al proyecto de Firebase, inicialice el proyecto de Firebase ejecutando el comando CLI:
1firebase init functions
- Siga las instrucciones del instalador para configurar los ajustes:
- Seleccione un código base existente.
- Defina JavaScript como el lenguaje empleado para crear funciones de nube.
- Instale las dependencias.
- Abra el
functions/index.js
y modifíquelo:
- javascript
1// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
2const functions = require('firebase-functions/v1');
3
4const projectId = <projectId>;
5const apiKey = <apiKey>;
6
7exports.getXsollaPaymentToken = functions.https.onRequest((req, res) => {
8
9 const requestBody = req.body;
10 if (!requestBody) {
11 res.status(400).send('Request body is missing');
12 return;
13 }
14
15 const userId = requestBody.data.uid;
16 const email = requestBody.data.email;
17 const sku = requestBody.data.sku;
18 const returnUrl = requestBody.data.returnUrl;
19
20 const payload = {
21 user: {
22 id: {value: userId},
23 name: {
24 value: email
25 },
26 email: {
27 value: email
28 },
29 country: {
30 value: 'US',
31 allow_modify: false
32 }
33 },
34 purchase: {
35 items: [
36 {
37 sku: sku,
38 quantity: 1
39 }
40 ]
41 },
42 sandbox: true,
43 settings: {
44 language: 'en',
45 currency: 'USD',
46 return_url: returnUrl,
47 ui: {
48 theme: '63295aab2e47fab76f7708e3'
49 }
50 }
51 }
52
53 let url = "https://store.xsolla.com/api/v3/project/" + projectId.toString() + "/admin/payment/token";
54
55 fetch(
56 url,
57 {
58 method: "POST",
59 headers: {
60 'Content-Type': 'application/json',
61 Authorization: 'Basic ' + btoa(`${projectId}:${apiKey}`)
62 },
63 body: JSON.stringify(payload)
64 },
65 )
66 .then(xsollaRes => {
67 // Handle the response data
68 if (xsollaRes.ok) {
69 return xsollaRes.json();
70 } else {
71 throw new Error(`HTTP request failed with status ${xsollaRes.status} and statusText: ${xsollaRes.statusText}`)
72 }
73 })
74 .then(data => {
75 res.send(JSON.stringify(data));
76 })
77 .catch(error => {
78 res.send("Error = " + error);
79 });
80});
81
82exports.webhookFakeResponse = functions.https.onRequest((request, response) => {
83 response.status(200).send()
84})
- En el script, especifique los valores para las variables:
projectId
: ID del proyecto que puede encontrar en su Cuenta del editor junto al nombre del proyecto.

apiKey
: clave de API. se muestra en la Cuenta del editor solo una vez cuando se crea, y debe almacenarse en su lado. Puede crear una nueva clave en la siguiente sección:- Company settings > API keys
- Project settings > API keys
- Para probar la función de nube con el emulador, ejecute el comando CLI:
1firebase emulators:start
- Después de ejecutar la función de nube, puede hacer una llamada a los siguientes métodos en el lado del cliente de su aplicación:
getXsollaPaymentToken
: devuelve el token de pago para abrir la interfaz de pago.webhookFakeResponse
: envía el código HTTP200
en respuesta al webhook Payment. El método no contiene una lógica de validación de compra: úselo solo para las pruebas. Para obtener la lista completa de webhooks e información general sobre cómo operar con ellos, consulte la documentación de webhooks.
- Para llamar a los métodos de forma local, use las URL
https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
yhttps://localhost:5001/{firebase-project-id}/us-central1/webhookFakeResponse
, en los cuales{firebase-project-id}
es el ID del proyecto de Firebase (Firebase console > Project Settings > Project ID).
- Para implementar la función de nube en producción, ejecute el comando CLI:
1firebase deploy --only functions
- Cuando se haya implementado en producción, puede llamar a los métodos a través de las URL
https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken
yhttps://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse
, el los cuales{firebase-project-id}
es el ID del proyecto de Firebase (Firebase console > Project Settings > Project ID). Para obtener más detalles sobre cómo ejecutar la función en producción, consulte la documentación de Firebase.
Cree el pedido y abra la interfaz de pago en el proyecto de Unity
- Abra su proyecto de Unity.
- Haga cambios en el script de controlador de páginas:
- Agregue el método
MakeCloudFunctionRequest
método para llamar a la función de nube. Para invocar el métodogetXsollaPaymentToken
, facilite una de las siguientes direcciones URL, en las cuales{firebase-project-id}
es el ID del proyecto de Firebase (Firebase console > Project Settings > Project ID):
- Agregue el método
- para acceso local:
https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
- para acceso en la producción:
https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken
- para acceso local:
- C++
1IEnumerator MakeCloudFunctionRequest(string sku)
2 {
3 string url = "https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken";
4
5 using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
6 {
7 var userData = new UserData()
8 {
9 data = new UserData.Data() {
10 uid = user.UserId,
11 email = user.Email,
12 sku = sku,
13 returnUrl = "app://xpayment.com.xsolla.unitysample"
14 }
15 };
16
17 byte[] data = System.Text.Encoding.UTF8.GetBytes(JsonUtility.ToJson(userData, true));
18 UploadHandlerRaw upHandler = new UploadHandlerRaw(data);
19 upHandler.contentType = "application/json";
20 webRequest.uploadHandler = upHandler;
21 webRequest.method = "POST";
22 yield return webRequest.SendWebRequest();
23
24 if (webRequest.result != UnityWebRequest.Result.Success)
25 {
26 Debug.LogError("Error: " + webRequest.error);
27 }
28 else
29 {
30 var paymentToken = "";
31 XsollaWebBrowser.OpenPurchaseUI(
32 paymentToken,
33 false);
34 Debug.Log("Response: " + webRequest.downloadHandler.text);
35 }
36 }
37 }
- Agregue devolución de llamada de función de nube al pulsar el botón de compra:
- C++
1private void OnItemsRequestSuccess(StoreItems storeItems)
2 {
3 foreach (var storeItem in storeItems.items)
4 {
5 var widgetGo = Instantiate(WidgetPrefab, WidgetsContainer, false);
6 var widget = widgetGo.GetComponent<StoreItemWidget>();
7
8 widget.BuyButton.onClick.AddListener(() =>
9 {
10 StartCoroutine(MakeCloudFunctionRequest(storeItem.sku));
11 });
12
13 widget.NameText.text = storeItem.name;
14 widget.DescriptionText.text = storeItem.description;
15
16 if (storeItem.price != null)
17 {
18 var realMoneyPrice = storeItem.price;
19 widget.PriceText.text = $"{realMoneyPrice.amount} {realMoneyPrice.currency}";
20 }
21
22 ImageLoader.LoadSprite(storeItem.image_url, sprite => widget.IconImage.sprite = sprite);
23 }
24 }
Puede usar el proyecto de prueba como ejemplo de implementación. El código fuente del proyecto de Unity está disponible en GitHub.
Ejemplo de script de controlador de páginas:
- C++
1using Firebase.Extensions;
2using System;
3using System.Collections;
4using UnityEngine;
5using UnityEngine.Networking;
6using UnityEngine.UI;
7using Xsolla.Catalog;
8using Xsolla.Core;
9
10[Serializable]
11public class UserData
12{
13 public Data data;
14
15 [Serializable]
16 public class Data
17 {
18 public string uid;
19 public string email;
20 public string sku;
21 public string returnUrl;
22 }
23}
24
25public class FirebaseExamplePage : MonoBehaviour
26{
27 public GameObject LoginContainer;
28 public GameObject StoreItemsContainer;
29
30 public InputField EmailInputField;
31 public InputField PasswordInputField;
32 public Button LoginButton;
33 public Button RegisterButton;
34
35 public Transform WidgetsContainer;
36 public GameObject WidgetPrefab;
37
38 protected Firebase.Auth.FirebaseAuth auth;
39 Firebase.Auth.FirebaseUser user = null;
40
41 Firebase.DependencyStatus dependencyStatus = Firebase.DependencyStatus.UnavailableOther;
42
43 public virtual void Start()
44 {
45 Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
46 dependencyStatus = task.Result;
47 if (dependencyStatus == Firebase.DependencyStatus.Available)
48 {
49 InitializeFirebase();
50 }
51 else
52 {
53 Debug.LogError(
54 "Could not resolve all Firebase dependencies: " + dependencyStatus);
55 }
56 });
57 }
58
59 protected void InitializeFirebase()
60 {
61 StoreItemsContainer.SetActive(false);
62
63 Debug.Log("Setting up Firebase Auth");
64 auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
65 auth.StateChanged += AuthStateChanged;
66 RegisterButton.onClick.AddListener(() =>
67 {
68 auth.CreateUserWithEmailAndPasswordAsync(EmailInputField.text, PasswordInputField.text).ContinueWith(task =>
69 {
70 if (task.IsCanceled)
71 {
72 Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled.");
73 return;
74 }
75 if (task.IsFaulted)
76 {
77 Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
78 return;
79 }
80
81 Firebase.Auth.AuthResult result = task.Result;
82 Debug.LogFormat("Firebase user created successfully: {0} ({1})",
83 result.User.DisplayName, result.User.UserId);
84 });
85 });
86
87 LoginButton.onClick.AddListener(() =>
88 {
89 auth.SignInWithEmailAndPasswordAsync(EmailInputField.text, PasswordInputField.text).ContinueWith(task =>
90 {
91 if (task.IsCanceled)
92 {
93 Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
94 return;
95 }
96 if (task.IsFaulted)
97 {
98 Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
99 return;
100 }
101
102 Firebase.Auth.AuthResult result = task.Result;
103 Debug.LogFormat("Firebase user logged in successfully: {0} ({1})",
104 result.User.DisplayName, result.User.UserId);
105 });
106 });
107 }
108
109 void AuthStateChanged(object sender, System.EventArgs eventArgs)
110 {
111 Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
112 if (senderAuth == auth && senderAuth.CurrentUser != user)
113 {
114 bool signedIn = user != senderAuth.CurrentUser && senderAuth.CurrentUser != null;
115 if (!signedIn && user != null)
116 {
117 Debug.Log("Signed out " + user.UserId);
118 }
119 user = senderAuth.CurrentUser;
120 if (signedIn)
121 {
122 Debug.Log("AuthStateChanged Signed in " + user.UserId);
123 LoadCatalog();
124 }
125 }
126 }
127
128 void OnDestroy()
129 {
130 if (auth != null)
131 {
132 auth.SignOut();
133 auth.StateChanged -= AuthStateChanged;
134 auth = null;
135 }
136 }
137 private void LoadCatalog()
138 {
139 LoginContainer.SetActive(false);
140 StoreItemsContainer.SetActive(true);
141 XsollaCatalog.GetCatalog(OnItemsRequestSuccess, OnError);
142 }
143
144 private void OnItemsRequestSuccess(StoreItems storeItems)
145 {
146
147 foreach (var storeItem in storeItems.items)
148 {
149 var widgetGo = Instantiate(WidgetPrefab, WidgetsContainer, false);
150 var widget = widgetGo.GetComponent<StoreItemWidget>();
151
152 if(widget != null)
153 {
154 widget.NameText.text = storeItem.name;
155 widget.DescriptionText.text = storeItem.description;
156
157 widget.BuyButton.onClick.AddListener(() =>
158 {
159 StartCoroutine(MakeCloudFunctionRequest(storeItem.sku));
160 });
161
162 if (storeItem.price != null)
163 {
164 var realMoneyPrice = storeItem.price;
165 widget.PriceText.text = $"{realMoneyPrice.amount} {realMoneyPrice.currency}";
166 }
167
168 ImageLoader.LoadSprite(storeItem.image_url, sprite => widget.IconImage.sprite = sprite);
169 }
170 }
171 }
172 IEnumerator MakeCloudFunctionRequest(string sku)
173 {
174 string url = "https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken";
175
176 using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
177 {
178 var userData = new UserData()
179 {
180 data = new UserData.Data() {
181 uid = user.UserId,
182 email = user.Email,
183 sku = sku,
184 returnUrl = "app://xpayment.com.xsolla.unitysample"
185 }
186 };
187
188 byte[] data = System.Text.Encoding.UTF8.GetBytes(JsonUtility.ToJson(userData, true));
189 UploadHandlerRaw upHandler = new UploadHandlerRaw(data);
190 upHandler.contentType = "application/json";
191 webRequest.uploadHandler = upHandler;
192 webRequest.method = "POST";
193 yield return webRequest.SendWebRequest();
194
195 if (webRequest.result != UnityWebRequest.Result.Success)
196 {
197 Debug.LogError("Error: " + webRequest.error);
198 }
199 else
200 {
201 string responseJson = webRequest.downloadHandler.text;
202 var responseData = JsonUtility.FromJson<OrderData>(responseJson);
203
204 var paymentToken = responseData.token;
205 int orderId = responseData.order_id;
206
207 XsollaWebBrowser.OpenPurchaseUI(
208 paymentToken,
209 false);
210 Debug.Log("Response: " + webRequest.downloadHandler.text);
211 }
212 }
213 }
214
215 private void OnError(Error error)
216 {
217 Debug.LogError($"Error: {error.errorMessage}");
218 }
219}
Establecer seguimiento del estado del pedido
Se requiere hacer el seguimiento del estado del pedido para garantizar que el pago se realizó correctamente y para conceder artículos al usuario.
Obtener el estado del pedido en el lado del cliente
La lógica de seguimiento del pedido se incluye en el método GetXsollaPaymentToken
. Para procesar una compra correctamente, debe transmitirse una función que se invoca cuando el estado del pedido cambia a done
.
El método del SDK AddOrderForTracking
se utiliza para realizar el seguimiento. Para obtener información detallada sobre cómo funciona el método, consulte Hacer seguimiento del estado del pedido.
Obtener el estado del pedido en el lado del servidor
El SDK le permite hacer un seguimiento del estado del pedido en el lado del cliente de su aplicación. Sin embargo, le recomendamos que establezca un controlador del webhook Payment para recibir información del pedido en el back-end de su aplicación. Esto le permite implementar una validación adicional de las compras realizadas.
Para obtener la lista completa de webhooks e información general sobre cómo operar con ellos, consulte la documentación de webhooks.
Para configurar los webhooks en el lado de Xsolla:
- Abra su proyecto en Cuenta del editor.
- Haga clic en Project settings en el menú lateral y vaya a la sección Webhooks.
- En el campo Webhook URL, ingrese la URL a la que Xsolla enviará los webhooks.
Para realizar pruebas, puede especificarhttps://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse
, en la cual{firebase-project-id}
es el ID del proyecto de Firebase (Firebase console>Project Settings > Project ID). En este caso, Firebase simula el procesamiento eficiente del webhook. Para un proyecto real, necesita agregar lógica de validación de compra.
Para probar los webhooks, también puede elegir cualquier sitio web específico, como webhook.site, o una plataforma, como ngrok.
- Copie y guarde el valor del campo Secret key. Esta clave se genera por defecto y se usa para firmar webhooks. Si desea cambiarla, haga clic en el icono de actualización.
- Haga clic en Enable webhooks.

¿Has encontrado una errata u otro error de texto? Selecciona el texto y pulsa Ctrl+Intro.