Comment intégrer Pay Station avec l’authentification Firebase
Après avoir implémenté l’authentification utilisateur via Firebase dans votre application, générez un jeton de paiement côté Firebase, puis passez-le au client de l’application pour ouvrir l’interface de paiement.
Cette option d’intégration implique l’implémentation indépendante de la logique pour déterminer le pays de l’utilisateur et la devise de paiement.
Flux d’intégration :
- Inscrivez un Compte éditeur et créez un nouveau projet. L'ID du projet créé sera nécessaire aux étapes suivantes.
- Configurez un catalogue :
- Créez un catalogue des objets côté Xsolla. Ajoutez des objets manuellement ou importez-les depuis Google Play ou PlayFab.
- En utilisant le SDK, implémentez la récupération et l'affichage du catalogue côté client de l'application.
- Configurez l'achat d'un objet :
- À l'aide de Cloud Functions Firebase, créez une commande avec les données utilisateur et les données de l'objet côté client de l'application.
- Implémentez l'ouverture de l'interface de paiement côté client de l'application en utilisant le SDK.
Pour compléter l’intégration et commencer à accepter les paiements réels, vous devez signer un contrat de licence avec Xsolla.
Vous pouvez signer le contrat de licence à n’importe quelle étape de l’intégration, mais gardez à l’esprit que le processus d’examen peut prendre jusqu’à trois jours ouvrables.
Utilisez le modèle de l’application comme référence pour implémenter l’intégration de l’authentification Firebase avec Pay Station. Le code source du modèle se trouve sur GitHub.
Créer un projet
S'inscrire au Compte éditeur
Le Compte éditeur est l’outil principal pour configurer les fonctionnalités Xsolla, ainsi que pour gérer les analyses et les transactions.
Les informations relatives à votre entreprise et à votre application fournies lors de l’inscription seront utilisées pour créer un projet de contrat de licence avec Xsolla et pour générer des recommandations sur les solutions adaptées à vos besoins. Bien que vous puissiez modifier ces informations ultérieurement, les fournir correctement lors de l’inscription accélérera le processus de signature du contrat de licence.
Pour vous inscrire, accédez au Compte éditeur et créez un compte.
Le mot de passe du Compte éditeur peut comprendre des lettres latines, des chiffres et des caractères spéciaux et doit contenir au moins :
- 8 caractères ;
- un chiffre ;
- une lettre majuscule ;
- une lettre minuscule.
Pour garantir la sécurité du mot de passe, nous recommandons de :
- changer de mot de passe au moins tous les 90 jours ;
- créer un nouveau mot de passe différent aux 4 derniers mots de passe utilisés pour votre compte ;
- créer un mot de passe unique différent des mots de passe utilisés ailleurs ;
- ne pas conserver votre mot de passe dans un endroit où il est facilement accessible ;
- utiliser des gestionnaires de mots de passe pour stocker votre mot de passe.
Le Compte éditeur utilise une authentification à deux facteurs, qui consiste à envoyer un code de confirmation à chaque tentative d’authentification.
Créer un projet dans le Compte éditeur
Si vous gérez plusieurs applications, nous vous recommandons de créer un projet distinct pour chacune d’entre elles. En fonction des informations fournies lors de la création du projet, Xsolla génère des recommandations adaptées à vos besoins.
Pour créer un nouveau projet :
- Ouvrez votre Compte éditeur.
- Dans le menu latéral, cliquez sur Create project.

- Entrez le nom de votre projet en anglais (obligatoire).
- Sélectionnez un ou plusieurs plateformes de sortie pour votre jeu (obligatoire).
- Ajoutez un lien vers votre jeu. Si votre jeu n'a pas encore de site, ajoutez un lien vers votre site principal ou vers la section où vos jeux sont répertoriés (obligatoire).
- Choisissez le moteur de jeu.
- Sélectionnez les options de monétisation que vous utilisez ou prévoyez d'utiliser.
- Spécifiez si le jeu est déjà publié. Si le jeu n'a pas encore été publié, indiquez la date de sortie prévue.
- Cliquez sur Create project. Une page avec les produits Xsolla recommandés pour vous s'affiche.
Au cours du processus d’intégration, vous devez fournir l’ID de projet. Il se trouve dans le Compte éditeur à côté du nom du projet.

Configurer le catalogue
Créer des objets dans le Compte éditeur
Pour ce faire, créez un catalogue côté Xsolla. Ajoutez des objets manuellement ou importez-les depuis Google Play ou PlayFab. Notez que vous pouvez importer un maximum de 100 objets à la fois depuis Google Play.
Ces instructions décrivent les étapes de la configuration de base d’un objet virtuel. Par la suite, vous pourrez ajouter d’autres objets au catalogue (monnaie virtuelle, lots, clés de jeu), créer des groupes d’objets, configurer des campagnes promotionnelles, des prix régionaux, etc.
Pour ajouter un objet virtuel avec des paramètres de base au catalogue :
- Ouvrez le projet dans le Compte éditeur.
- Dans le menu latéral, cliquez sur Store.
- Dans le volet Virtual Items, cliquez sur Connect.
- Dans le menu déroulant, sélectionnez Create item.
- Configurez les paramètres de base de l'objet dans les champs suivants :
- Image (facultatif) ;
- SKU (ID unique de l'objet) ;
- Item name ;
- Description (facultatif).
- Spécifiez le prix de l'objet :
- Réglez la bascule Price in real currency sur On.
- Dans le champ Default currency, modifiez la devise (facultatif) et spécifiez le prix de l'objet.
- Si vous avez changé la devise dans le champ Default currency, sélectionnez la même devise dans le champ Price in real currency.
- Changez le statut de l'objet en Available.
- Cliquez sur Create item.
Afficher le catalogue côté client de l'application
- Téléchargez la dernière version du SDK (recommandé) ou choisissez la version requise sur GitHub et téléchargez-la.
- Décompressez le package.
- Dans le menu principal, accédez à
Assets > Import Package > Custom Package et sélectionnez le SDK téléchargé. - Dans le menu principal, allez à
Window > Xsolla > Edit Settings . - Accédez au panneau
Inspector . Dans le champProject ID , spécifiez l'ID du projet, qui se trouve dans le Compte éditeur à côté du nom de votre projet.

- Côté client de l'application, ajoutez une interface pour afficher le catalogue des objets.
- Implémentez la demande du catalogue des objets depuis les serveurs Xsolla.
GetCatalog
. Vous pouvez également utiliser d’autres méthodes SDK pour récupérer les informations sur les objets du catalogue.Configurer l'achat d'objets
Créer une commande à l'aide d'une Cloud Function
Pour créer une commande avec les données utilisateur et les données de l’objet côté Xsolla, ajoutez une Cloud Function au projet qui utilise l’appel API Créer un jeton de paiement pour un achat. Cet appel renverra un jeton de paiement, nécessaire pour ouvrir l’interface de paiement et effectuer un achat.
Limites :
- Lors de la demande du jeton de paiement, vous devez passer soit le pays de l’utilisateur, soit l’adresse IP.
- Si vous ne passez pas la devise dans le jeton, elle se détermine en fonction du pays.
- Si vous passez la devise dans le jeton, l’utilisateur paie dans cette devise.
Pour ajouter une Cloud Fonction à un projet :
- Installez l'interface CLI (Command-Line Interface) de Firebase. Pour ce faire, exécutez la commande CLI :
1npm install -g firebase-tools
- Pour lier votre projet au projet Firebase, initialisez le projet Firebase en exécutant la commande CLI :
1firebase init functions
- Suivez les instructions de l'installateur pour configurer les paramètres :
- Sélectionnez une base de code existante ;
- Spécifiez JavaScript comme langage pour créer des Cloud Functions.
- Installez les dépendances.
- Ouvrez le fichier
functions/index.js
et modifiez-le :
- 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})
- Dans le script, spécifiez les valeurs pour les variables :
projectId
— l'ID du projet, qui se trouve dans le Compte éditeur à côté du nom du projet.

apiKey
– Clé API. Elle ne s'affiche dans le Compte éditeur qu'une seule fois lors de sa création, vous devez donc la conserver de votre côté. Vous pouvez créer une nouvelle clé dans les sections suivantes :- Company settings > API keys ;
- Project settings > API keys.
- Pour tester la Cloud Function avec l'émulateur, exécutez la commande CLI :
1firebase emulators:start
- Après avoir exécuté la Cloud Function, vous pouvez appeler les méthodes suivantes côté client de l'application :
getXsollaPaymentToken
— renvoie le jeton de paiement pour ouvrir l'interface de paiement ;webhookFakeResponse
— envoie le code HTTP200
en réponse au webhook Paiement. La méthode ne contient pas de logique de validation d'achat : utilisez-la uniquement à des fins de test. Pour accéder à la liste complète des webhooks et obtenir des informations générales sur leur utilisation, consultez la documentation sur les webhooks.
- Pour appeler les méthodes localement, utilisez les URL suivantes :
https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
ethttps://localhost:5001/{firebase-project-id}/us-central1/webhookFakeResponse
, où{firebase-project-id}
est l'ID du projet Firebase (Firebase console > Project Settings > Project ID).
- Pour déployer la Cloud Function en production, exécutez la commande CLI :
1firebase deploy --only functions
- Une fois le déploiement en production effectué, vous pouvez appeler les méthodes via les URL
https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken
ethttps://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse
, où{firebase-project-id}
est l'ID du projet Firebase (Firebase console > Project Settings > Project ID). Pour plus de détails sur l'exécution de cette fonctionnalité en production, consultez la documentation Firebase.
Créer une commande et ouvrir l'interface de paiement dans le projet Unity
- Ouvrez votre projet Unity.
- Apportez des modifications au script du contrôleur de page :
- Ajoutez la méthode
MakeCloudFunctionRequest
pour appeler Cloud Functions. Pour appeler la méthodegetXsollaPaymentToken
, fournissez l'une des URL suivantes, où{firebase-project-id}
est l'ID du projet Firebase (Firebase console > Project Settings > Project ID):
- Ajoutez la méthode
- pour un accès local —
https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
, - pour un accès en production —
https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken
;
- pour un accès 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 }
- Ajoutez l'appel à la fonction cloud de rappel en cas de clic sur le bouton d'achat :
- 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 }
Utilisez le projet de test comme exemple d’implémentation. Le code source du projet Unity se trouve sur GitHub.
Exemple de script de contrôleur de page :
- 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}
Configurer le suivi de l'état de la commande
Le suivi de l’état de la commande est requis pour s’assurer de la réussite du paiement et pour octroyer les objets à l’utilisateur.
Obtenir l'état de la commande côté client
La logique de suivi de commande est intégrée dans la méthode GetXsollaPaymentToken
. Afin de traiter un achat réussi, passez une fonction qui est appelée lorsque le statut de la commande change à done
.
La méthode SDK AddOrderForTracking
s’utilise pour le suivi des commandes. Pour des informations détaillées sur le fonctionnement de cette méthode, référez-vous à Suivi du statut de la commande.
Obtenir l'état de la commande côté serveur
Le SDK vous permet de suivre l’état de la commande côté client de l’application. Cependant, nous vous recommandons d’implémenter le gestionnaire du webhook Paiement pour recevoir des informations sur la commande dans le back-end de l’application. Cela vous permet d’implémenter une validation supplémentaire des achats effectués.
Pour accéder à la liste complète des webhooks et obtenir des informations générales sur leur utilisation, consultez la documentation sur les webhooks.
Pour configurer les webhooks côté Xsolla :
- Ouvrez le projet dans le Compte éditeur.
- Dans le menu latéral, cliquez sur Project settings et accédez à la section Webhooks.
- Dans le champ Webhook server, entrez l’URL vers laquelle Xsolla enverra les webhooks.
Pour les tests, vous pouvez spécifier https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse
, où {firebase-project-id}
est l’ID du projet Firebase (Firebase console > Project Settings > Project ID). Dans ce cas, Firebase simule le traitement réussi du webhook. Pour un projet réel, l’ajout d’une logique de validation des achats est requis.
Pour tester les webhooks, vous pouvez également choisir n’importe quel site dédié, tel que webhook.site, ou une plateforme, telle que ngrok.
- Copiez et enregistrez la valeur du champ Secret key. Cette clé générée par défaut s'utilise pour signer les webhooks. Si vous souhaitez la modifier, cliquez sur l'icône de mise à jour.
- Cliquez sur Enable webhooks.

Faute de frappe ou autre erreur dans le texte ? Sélectionnez le texte concerné et appuyez sur Ctrl+Entée.