SDK para Unity (PC, web) / Como usar o Pay Station em combinação com a autenticação Firebase
  Voltar aos Documentos

SDK para Unity (PC, web)

Como usar o Pay Station em combinação com a autenticação Firebase

Se você já implementou a autenticação de usuários no seu aplicativo usando o Firebase, você pode gerar um token de pagamento no lado do Firebase e então passá-lo ao lado do cliente no aplicativo para abrir a interface de pagamento.

Usando essa opção de integração, você deve implementar a lógica para determinar o país e moeda do usuário a ser usado para pagar pela compra de forma independente.

Fluxo de integração:

  1. Crie um projeto.
  1. Cadastre sua Conta de Distribuidor e crie um novo projeto. Você precisará do ID do projeto criado nas próximas etapas.

  1. Configure um catálogo:
    • Crie um catálogo de itens no lado Xsolla. Você pode adicionar itens manualmente ou importá-los do Google Play PlayFab.
    • Implemente a obtenção e exibição do catálogo no lado do cliente do aplicativo usando o SDK.

  1. Configure a compra de um item:
    • Crie um pedido com os dados do usuário e do item no lado do cliente no aplicativo usando a função Firebase cloud.
    • Implemente a abertura da interface de pagamento no lado do cliente no seu aplicativo usando o SDK.

  1. Configure o rastreamento do status do pedido.

Aviso

Para concluir a integração e começar a aceitar pagamentos reais, você precisará assinar um contrato de licenciamento com a Xsolla.

Você pode assinar o contrato de licenciamento em qualquer etapa da integração, mas tenha em mente que o processo de análise pode levar até 3 dias úteis.

Use o aplicativo de amostra como exemplo para implementar o uso combinado da autenticação Firebase e o Pay Station. O código fonte do aplicativo de amostra está disponível no GitHub.

Criar projeto

Cadastre sua Conta de Distribuidor

A Conta de Distribuidor é a ferramenta principal para configurar recursos da Xsolla, bem como trabalhar com análises e transações.

Os dados sobre a empresa e o seu aplicativo especificados durante o cadastro serão usados para criar um rascunho de contrato de licenciamento com a Xsolla e para gerar recomendações sobre soluções que sejam mais adequadas a você. Você pode alterar os dados mais tarde, mas o fornecimento dos dados corretos durante o cadastro acelera o processo de assinatura do contrato de licenciamento.

Para se cadastrar, vá para Conta de Distribuidor e crie um conta.

Observação

A senha da Conta de Distribuidor pode conter letras latinas, números e caracteres especiais e deve conter pelo menos:

  • 8 caracteres
  • um dígito
  • uma letra maiúscula
  • uma letra minúscula

Para garantir a segurança da senha, recomendamos:

  • alterar sua senha pelo menos uma vez a cada 90 dias
  • usar uma nova senha diferente de suas últimas 4 senhas
  • usar uma senha única que não corresponda a outras senhas que você usa
  • não armazenar sua senha num lugar de fácil acesso
  • usar gerenciadores de senha para armazenar a sua senha

A Conta de Distribuidor usa autenticação em duas etapas e envia um código de confirmação a cada tentativa de autenticação.

Crie um projeto na Conta de Distribuidor

Caso tenha múltiplos aplicativos, recomendamos criar um projeto separado para cada aplicativo. Com base nos dados especificados durante a criação do projeto, a Xsolla gera recomendações sobre as soluções mais adequadas a você.

Para criar um novo projeto:

  1. Abra a Conta de Distribuidor.
  2. No menu lateral, clique em Create project.

  1. Insira o nome do seu projeto em inglês (obrigatório).

Observação
Após criar o projeto, será possível adicionar idiomas adicionais e nomes de projeto traduzidos na seção Project settings.

  1. Escolha uma ou várias plataformas de lançamento do seu jogo (obrigatório).
  2. Adicione um link para o seu jogo. Se o seu jogo ainda não tiver um site, adicione um link para a fonte que inclui informações sobre o jogo (obrigatório).
  3. Escolha a engine do jogo.
  4. Escolha suas opções de monetização ou o plano utilizado.
  5. Especifique se o jogo já foi lançado. Se o jogo não tiver sido lançado, especifique a data de lançamento planejada.
  6. Clique em Create project. Você verá uma página com os produtos Xsolla recomendados para você.

Durante o processo de integração, você precisa fornecer o ID do projeto, que pode ser encontrado na Conta de Distribuidor ao lado do nome do seu projeto.

Configure o catálogo

Crie itens a Conta de Distribuidor

Aviso

Você precisa criar um catálogo no lado da Xsolla. Você pode adicionar itens manualmente ou importá-los pelo Google Play ou PlayFab. Ao importar pelo Google Play, você poderá importar no máximo 100 itens por vez.

Essas instruções fornecem etapas para a configuração básica de um item virtual. Mais tarde, você poderá adicionar outros itens ao catálogo (moeda virtual, conjuntos, chaves de jogo), criar grupos de itens, configurar campanhas promocionais, preços regionais, etc.

Para adicionar itens virtuais com configurações básicas ao catálogo:

  1. Abra seu projeto na Conta de Distribuidor.
  2. Clique em Store no menu lateral.
  3. No painel Virtual Items, clique em Connect.
  4. Na lista suspensa, selecione Create item.

  1. Defina as configurações básicas do item nos seguintes campos:
    • Image (opcional)
    • SKU (ID único do item)
    • Item name
    • Description (opcional)

  1. Especifique o preço do item:
    1. Defina a opção Price in real currency como On.
    2. No campo Default currency, altere a moeda (opcional) e especifique o preço do item.
    3. Se você alterou a moeda no campo Default currency, selecione a mesma moeda no campo Price in real currency.

Observação
Para garantir que as chamadas de API da obtenção de catálogo estejam funcionando corretamente, certifique-se de que a moeda padrão e a lista de moedas na qual os preços são especificados correspondam a todos os itens.

  1. Altere o status do item para Available.

  1. Clique em Create item.

Exibição do catálogo no lado do cliente no aplicativo

  1. Baixe o SDK do CDN ou GitHub.
  2. Descompacte o pacote.
  3. No menu principal, vá paraq Assets > Import Package > Custom Package e selecione o SDK baixado.
  4. No menu principal, vá para Window > Xsolla > Edit Settings.
  5. Vá para o painel Inspector. No campo Project ID, especifique o ID do projeto que pode ser encontrado na Conta de Distribuidor próxima ao nome do seu projeto.

  1. No lado do cliente no aplicativo, adicione a interface para exibir o catálogo de produtos.
  2. Implemente a solicitação de catálogos de itens pelos servidores Xsolla.

Observação

Para obter uma lista de itens virtuais, use o método SDK GetCatalog. Você também pode obter informações sobre os itens de catálogo usando outros métodos SDK.

Para um tutorial passo a passo sobre criar uma página de catálogo, consulte Exibição do catálogo de itens.

Configure a compra de itens

Crie um pedido usando a função cloud

Para criar um pedido com dados de usuário e item no lado Xsolla, adicione uma função cloud ao projeto que utiliza a chamada de API Criar token de pagamento para compra. Essa chamada retornará um token de pagamento, que é necessário para abrir a interface de pagamento e fazer uma compra.

Limitações:

  • você precisa passar o país do usuário ou o endereço IP do usuário ao solicitar o token de pagamento.
  • Se você não passar a moeda no token, ela é determinada pelo país.
  • Se você passar a moeda no token, o usuário paga nessa concorrência.

Aviso
Você precisa primeiro criar e inicializar um projeto Firebase e ativar a autenticação de usuários usando o Firebase. Para detalhes sobre essas etapas, consulte as seguintes instruções do Firebase:

Para adicionar uma função cloud a um projeto:

  1. Para instalar o Firebase CLI (Command-Line Interface). Para fazer isso, execute o comando CLI:

Copy
Full screen
Small screen
    npm install -g firebase-tools
    

    1. Para vincular seu projeto ao projeto Firebase, inicialize o projeto Firebase executando o comando CLI:

    Copy
    Full screen
    Small screen
      firebase init functions
      

      1. Siga as instruções do instalador para definir as configurações:
        1. Selecione um código de base existente.
        2. Especifique o JavaScript como idioma para criar funções cloud.
        3. Instale as dependências.

      1. Abra functions/index.js e modifique-a:

      Copy
      Full screen
      Small screen
      // The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
      const functions = require('firebase-functions/v1');
      
      const projectId = <projectId>;
      const apiKey = <apiKey>;
      
      exports.getXsollaPaymentToken = functions.https.onRequest((req, res) => {
      
        const requestBody = req.body;
          if (!requestBody) {
            res.status(400).send('Request body is missing');
            return;
          }
      
        const userId = requestBody.data.uid;
        const email = requestBody.data.email;
        const sku = requestBody.data.sku;
        const returnUrl = requestBody.data.returnUrl;
      
        const payload = {
          user: {
            id: {value: userId},
            name: {
              value: email
            },
            email: {
              value: email
            },
            country: {
              value: 'US',
              allow_modify: false
            }
          },
          purchase: {
            items: [
              {
                sku: sku,
                quantity: 1
              }
            ]
          },
          sandbox: true,
          settings: {
            language: 'en',
            currency: 'USD',
            return_url: returnUrl,
            ui: {
              theme: '63295aab2e47fab76f7708e3'
            }
          }
        }
      
        let url = "https://store.xsolla.com/api/v3/project/" + projectId.toString() + "/admin/payment/token";
      
        fetch(
          url,
          {
            method: "POST",
            headers: {
              'Content-Type': 'application/json',
              Authorization: 'Basic ' + btoa(`${projectId}:${apiKey}`)
            },
            body: JSON.stringify(payload)
          },
        )
        .then(xsollaRes => {
          // Handle the response data
          if (xsollaRes.ok) {
            return xsollaRes.json();
          } else {
            throw new Error(`HTTP request failed with status ${xsollaRes.status} and statusText: ${xsollaRes.statusText}`)
          }
        })
        .then(data => {
          res.send(JSON.stringify(data));
        })
        .catch(error => {
          res.send("Error = " + error);
        });
      });
      
      exports.webhookFakeResponse = functions.https.onRequest((request, response) => {
        response.status(200).send()
      })
      

      1. No script, especifique os valores das variáveis:
        • projectId — ID do projeto que você pode encontrar na sua Conta de Distribuidor próximo ao nome do projeto.

        • apiKey — Chave API. É mostrada na Conta de Distribuidor apenas uma vez, durante a criação, e deve ser armazenada por você. Você pode criar uma nova chave na seguinte seção:
          • Company settings > API keys
          • Project settings > API keys

      1. Para testar a função cloud com o emulador, execute o comando CLI:

      Copy
      Full screen
      Small screen
        firebase emulators:start
        

        1. Depois de executar a função cloud, você poderá chamar os seguintes métodos no lado do cliente do seu aplicativo:
          • getXsollaPaymentToken — retorna o token de pagamento por abrir a interface de pagamento.
          • webhookFakeResponse — envia o código HTTP 200 em resposta ao webook Payment. Esse método não contém uma lógica de validação de compra: use-o apenas para testes. Para uma lista completa de webhooks e informações gerais sobre como trabalhar com eles, consulte a documentação de webhooks.

        1. Para chamar métodos localmente, use os URLs https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken e https://localhost:5001/{firebase-project-id}/us-central1/webhookFakeResponse, onde {firebase-project-id} é o ID do projeto Firebase (Firebase console > Project Settings > Project ID).

        1. Para aplicar a função cloud na produção, execute o comando CLI:

        Copy
        Full screen
        Small screen
          firebase deploy --only functions
          

          1. Uma vez aplicada na produção, você poderá chamar métodos pelos URLs https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken e https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse, onde {firebase-project-id} é o ID do projeto Firebase (Firebase console > Project Settings > Project ID). Para detalhes sobre como executar o recurso em produção, consulte a documentação Firebase.

          Crie um pedido e abra a interface de pagamento no projeto Unity

          1. Abra seu projeto Unity.
          2. Faça alterações no script da página do controlador:
            1. Adicione o método MakeCloudFunctionRequest para chamar a função cloud. Para chamar o método getXsollaPaymentToken, forneça um dos seguintes URLs, onde {firebase-project-id} é o ID de projeto Firebase (Firebase console > Project Settings > Project ID):

              • para acesso local — https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
              • para acesso na produção — https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken

          Copy
          Full screen
          Small screen
          IEnumerator MakeCloudFunctionRequest(string sku)
             {
                 string url = "https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken";
          
                 using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
                 {
                     var userData = new UserData()
                     {
                         data = new UserData.Data() {
                             uid = user.UserId,
                             email = user.Email,
                             sku = sku,
                             returnUrl = "app://xpayment.com.xsolla.unitysample"
                         }
                     };
          
                     byte[] data = System.Text.Encoding.UTF8.GetBytes(JsonUtility.ToJson(userData, true));
                     UploadHandlerRaw upHandler = new UploadHandlerRaw(data);
                     upHandler.contentType = "application/json";
                     webRequest.uploadHandler = upHandler;
                     webRequest.method = "POST";
                     yield return webRequest.SendWebRequest();
          
                     if (webRequest.result != UnityWebRequest.Result.Success)
                     {
                         Debug.LogError("Error: " + webRequest.error);
                     }
                     else
                     {
                         var paymentToken = "";
                         XsollaWebBrowser.OpenPurchaseUI(
                                 paymentToken,
                                 false);
                         Debug.Log("Response: " + webRequest.downloadHandler.text);
                     }
                 }
             }
          

            1. Adicione o retorno de chamada da função cloud ao clicar no botão de compra:

          Copy
          Full screen
          Small screen
          private void OnItemsRequestSuccess(StoreItems storeItems)
              {
                  foreach (var storeItem in storeItems.items)
                  {
                      var widgetGo = Instantiate(WidgetPrefab, WidgetsContainer, false);
                      var widget = widgetGo.GetComponent<StoreItemWidget>();
          
                      widget.BuyButton.onClick.AddListener(() =>
                      {
                          StartCoroutine(MakeCloudFunctionRequest(storeItem.sku));
                      });
          
                      widget.NameText.text = storeItem.name;
                      widget.DescriptionText.text = storeItem.description;
          
                      if (storeItem.price != null)
                      {
                          var realMoneyPrice = storeItem.price;
                          widget.PriceText.text = $"{realMoneyPrice.amount} {realMoneyPrice.currency}";
                      }
          
                      ImageLoader.LoadSprite(storeItem.image_url, sprite => widget.IconImage.sprite = sprite);
                  }
              }
          

          Você pode usar o projeto de teste como exemplo de implementação. O código fonte para o projeto Unity está disponível no GitHub.

          Exemplo de script da página do controlador:

          Copy
          Full screen
          Small screen
          using Firebase.Extensions;
          using System;
          using System.Collections;
          using UnityEngine;
          using UnityEngine.Networking;
          using UnityEngine.UI;
          using Xsolla.Catalog;
          using Xsolla.Core;
          
          [Serializable]
          public class UserData
          {
              public Data data;
          
              [Serializable]
              public class Data
              {
                  public string uid;
                  public string email;
                  public string sku;
                  public string returnUrl;
              }
          }
          
          public class FirebaseExamplePage : MonoBehaviour
          {
              public GameObject LoginContainer;
              public GameObject StoreItemsContainer;
          
              public InputField EmailInputField;
              public InputField PasswordInputField;
              public Button LoginButton;
              public Button RegisterButton;
          
              public Transform WidgetsContainer;
              public GameObject WidgetPrefab;
          
              protected Firebase.Auth.FirebaseAuth auth;
              Firebase.Auth.FirebaseUser user = null;
          
              Firebase.DependencyStatus dependencyStatus = Firebase.DependencyStatus.UnavailableOther;
          
              public virtual void Start()
              {
                  Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
                      dependencyStatus = task.Result;
                      if (dependencyStatus == Firebase.DependencyStatus.Available)
                      {
                          InitializeFirebase();
                      }
                      else
                      {
                          Debug.LogError(
                            "Could not resolve all Firebase dependencies: " + dependencyStatus);
                      }
                  });
              }
          
              protected void InitializeFirebase()
              {
                  StoreItemsContainer.SetActive(false);
          
                  Debug.Log("Setting up Firebase Auth");
                  auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
                  auth.StateChanged += AuthStateChanged;
                  RegisterButton.onClick.AddListener(() =>
                  {
                      auth.CreateUserWithEmailAndPasswordAsync(EmailInputField.text, PasswordInputField.text).ContinueWith(task =>
                      {
                          if (task.IsCanceled)
                          {
                              Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled.");
                              return;
                          }
                          if (task.IsFaulted)
                          {
                              Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
                              return;
                          }
          
                          Firebase.Auth.AuthResult result = task.Result;
                          Debug.LogFormat("Firebase user created successfully: {0} ({1})",
                              result.User.DisplayName, result.User.UserId);
                      });
                  });
          
                  LoginButton.onClick.AddListener(() =>
                  {
                      auth.SignInWithEmailAndPasswordAsync(EmailInputField.text, PasswordInputField.text).ContinueWith(task =>
                      {
                          if (task.IsCanceled)
                          {
                              Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
                              return;
                          }
                          if (task.IsFaulted)
                          {
                              Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
                              return;
                          }
          
                          Firebase.Auth.AuthResult result = task.Result;
                          Debug.LogFormat("Firebase user logged in successfully: {0} ({1})",
                              result.User.DisplayName, result.User.UserId);
                      });
                  });
              }
          
              void AuthStateChanged(object sender, System.EventArgs eventArgs)
              {
                  Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
                  if (senderAuth == auth && senderAuth.CurrentUser != user)
                  {
                      bool signedIn = user != senderAuth.CurrentUser && senderAuth.CurrentUser != null;
                      if (!signedIn && user != null)
                      {
                          Debug.Log("Signed out " + user.UserId);
                      }
                      user = senderAuth.CurrentUser;
                      if (signedIn)
                      {
                          Debug.Log("AuthStateChanged Signed in " + user.UserId);
                          LoadCatalog();
                      }
                  }
              }
          
              void OnDestroy()
              {
                  if (auth != null)
                  {
                      auth.SignOut();
                      auth.StateChanged -= AuthStateChanged;
                      auth = null;
                  }
              }
              private void LoadCatalog()
              {
                  LoginContainer.SetActive(false);
                  StoreItemsContainer.SetActive(true);
                  XsollaCatalog.GetCatalog(OnItemsRequestSuccess, OnError);
              }
          
              private void OnItemsRequestSuccess(StoreItems storeItems)
              {
          
                  foreach (var storeItem in storeItems.items)
                  {
                      var widgetGo = Instantiate(WidgetPrefab, WidgetsContainer, false);
                      var widget = widgetGo.GetComponent<StoreItemWidget>();
          
                      if(widget != null)
                      {
                          widget.NameText.text = storeItem.name;
                          widget.DescriptionText.text = storeItem.description;
          
                          widget.BuyButton.onClick.AddListener(() =>
                          {
                              StartCoroutine(MakeCloudFunctionRequest(storeItem.sku));
                          });
          
                          if (storeItem.price != null)
                          {
                              var realMoneyPrice = storeItem.price;
                              widget.PriceText.text = $"{realMoneyPrice.amount} {realMoneyPrice.currency}";
                          }
          
                          ImageLoader.LoadSprite(storeItem.image_url, sprite => widget.IconImage.sprite = sprite);
                      }
                  }
              }
              IEnumerator MakeCloudFunctionRequest(string sku)
              {
                  string url = "https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken";
          
                  using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
                  {
                      var userData = new UserData()
                      {
                          data = new UserData.Data() {
                              uid = user.UserId,
                              email = user.Email,
                              sku = sku,
                              returnUrl = "app://xpayment.com.xsolla.unitysample"
                          }
                      };
          
                      byte[] data = System.Text.Encoding.UTF8.GetBytes(JsonUtility.ToJson(userData, true));
                      UploadHandlerRaw upHandler = new UploadHandlerRaw(data);
                      upHandler.contentType = "application/json";
                      webRequest.uploadHandler = upHandler;
                      webRequest.method = "POST";
                      yield return webRequest.SendWebRequest();
          
                      if (webRequest.result != UnityWebRequest.Result.Success)
                      {
                          Debug.LogError("Error: " + webRequest.error);
                      }
                      else
                      {
                          string responseJson = webRequest.downloadHandler.text;
                          var responseData = JsonUtility.FromJson<OrderData>(responseJson);
          
                          var paymentToken = responseData.token;
                          int orderId = responseData.order_id;
          
                          XsollaWebBrowser.OpenPurchaseUI(
                                  paymentToken,
                                  false);
                          Debug.Log("Response: " + webRequest.downloadHandler.text);
                      }
                  }
              }
          
              private void OnError(Error error)
              {
                  Debug.LogError($"Error: {error.errorMessage}");
              }
          }
          

          Configure o rastreamento de status de pedidos

          É necessário rastrear o status do pedido para garantir que o pagamento foi bem-sucedido e para conceder itens ao usuário.

          Obter status do pedido no lado do cliente

          A lógica de rastreamento de pedido está incluída no método GetXsollaPaymentToken. Para processar uma compra bem-sucedida, você precisa passar uma função que é chamada quando o status do pedido é alterado para done.

          O método SDK AddOrderForTracking é usado para rastrear. Para obter informações detalhadas sobre como os métodos funcionam, consulte Rastreamento do status do pedido.

          Obter status do pedido no lado do servidor

          Aviso

          O SDK permite que você rastreie o status do pedido no lado do cliente do seu aplicativo. Porém, recomendamos configurar o gerenciador de webhook Payment para receber informações no back-end do seu aplicativo. Isso permite que você implemente validações adicionais das compras concluídas.

          Para obter a lista completa de webhooks e informações gerais sobre trabalhar com eles, consulte a documentação de webhooks.

          Para configurar webhooks no lado Xsolla:

          1. Abra seu projeto na Conta de Distribuidor.
          2. Clique em Project settings no menu lateral e vá para a seção Webhooks.
          3. No campo Webhook server, insira o URL ao qual a Xsolla enviará os webhooks.

          Observação

          Para propósitos de teste, você pode especificar https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse, onde {firebase-project-id} é o ID do projeto Firebase (Firebase console > Project Settings > Project ID). Nesse caso, o Firebase simula o processamento bem-sucedido do webhook. Em um projeto real, você precisará adicionar a lógica de validação da compra.

          Para testar webhooks, você também pode escolher qualquer site dedicado, tal como webhook.site, ou uma plataforma, tal como ngrok.

          1. Copie e salve o valor do campo Secret key. Essa chave é gerada por padrão e é usada para assinar webhooks. Se quiser alterá-la, clique no ícone de atualização.
          2. Clique em Enable webhooks.

          Este artigo foi útil?
          Obrigado!
          Podemos melhorar alguma coisa? Mensagem
          Que pena ouvir isso
          Explique porque este artigo não foi útil para você. Mensagem
          Obrigado pelo seu feedback!
          Avaliaremos sua mensagem e a usaremos para melhorar sua experiência.
          Última atualização: 20 de Dezembro de 2024

          Encontrou um erro de texto ou digitação? Selecione o texto e pressione Ctrl+Enter.

          Relatar um problema
          Nós sempre avaliamos nossos conteúdos. Seu feedback nos ajuda a melhorá-los.
          Forneça um e-mail para que possamos responder
          Obrigado pelo seu feedback!