Как использовать Pay Station совместно с аутентификацией Firebase

Если вы уже реализовали аутентификацию пользователей в  приложении с использованием Firebase, вы можете формировать платежный токен на стороне Firebase, а затем передавать его в клиентскую часть приложения для открытия платежного интерфейса.

При таком способе интеграции вам потребуется самостоятельно реализовать логику определения страны пользователя и валюты для оплаты покупки.

Сценарий интеграции:

  1. Создайте проект.
  1. Зарегистрируйтесь в Личном кабинете и создайте новый проект. ID созданного проекта потребуется вам на дальнейших шагах.

  1. Настройте каталог товаров:
    • Создайте каталог товаров на стороне Xsolla. Вы можете добавить товары вручную или импортировать их из Google Play или PlayFab.
    • Реализуйте получение каталога с помощью библиотеки Store и его отображение на клиенте приложения.

  1. Настройте покупку товара:
    • Реализуйте создание заказа с данными о пользователе и товаре c помощью облачной функции Firebase.
    • Реализуйте открытие платежного интерфейса на клиентской части приложения с помощью библиотеки Payments.

  1. Настройте отслеживание статуса заказа.

Внимание

Чтобы завершить интеграцию и начать принимать реальные платежи, вам требуется подписать Лицензионный договор с Xsolla.

Вы можете подписать договор на любом этапе интеграции, но обратите внимание, что процесс рассмотрения заявки занимает до 3 рабочих дней.

В качестве примера реализации совместного использования аутентификации Firebase и Pay Station используйте тестовое веб-приложение. Исходный код тестового веб-приложения доступен на GitHub.

Создание проекта

Личный кабинет — основной инструмент для настройки возможностей Xsolla, а также для работы с аналитикой и транзакциями.

Указанные на этапе регистрации данные о компании и вашем приложении будут использоваться для формирования рекомендаций с подходящими для вас решениями и создания черновика договора с Xsolla. Вы сможете изменить данные позже, но указание при регистрации верных данных ускорит процесс согласования договора.

Чтобы создать проект:

  1. Зарегистрируйтесь в Личном кабинете.
Примечание
Правила для формирования пароля

Пароль от Личного кабинета должен содержать не менее:

  • 8 символов;
  • одной цифры;
  • одной прописной буквы латинского алфавита;
  • одной строчной буквы латинского алфавита.

Для обеспечения безопасности пароля рекомендуется:

  • менять пароль не реже одного раза в 90 дней;
  • использовать новый пароль, который не совпадает с последними 4 паролями вашей учетной записи;
  • использовать уникальный пароль, который не совпадает с паролями в других сервисах;
  • не хранить пароль в легкодоступных местах;
  • использовать менеджеры паролей для хранения пароля.

Личный кабинет использует двухфакторную аутентификацию и отправляет код подтверждения при каждой попытке аутентификации.

  1. Укажите основную информацию для создания аккаунта:
    1. Ваши имя и фамилию.
    2. Вашу роль в компании.
    3. Название компании. Если вы регистрируетесь как физическое лицо, укажите полностью ваши имя и фамилию.
    4. Ссылку на подробную информацию о вас и вашей игре или продукте (опционально).
    5. Вашу страну или регион.
  1. Нажмите Далее.
  1. Чтобы автоматически создать ваш первый проект, укажите основную информацию о нем:
    1. Выберите тип проекта: Игра, Игровая платформа или Другое.
    2. Введите название проекта на английском языке.
    3. Выберите одну или несколько платформ релиза.
    4. Выберите способы монетизации, которые вы используете или собираетесь использовать.
    5. Выберите стадию разработки.
    6. Если тип вашего проекта — Игра, выберите ее жанр и игровой движок.
    7. Добавьте ссылку на игру или продукт (опционально).
  1. Нажмите Завершить.

После создания проекта вы будете перенаправлены на страницу компании, где в боковом меню отобразится созданный проект:

  • Нажмите на его название, чтобы перейти к дальнейшей интеграции продуктов и решений Xsolla.
  • Перейдите в раздел Настройки проекта, чтобы добавить дополнительные языки и названия проекта на этих языках (опционально).

Если у вас несколько игр или продуктов, добавьте проект для каждой из них. Для этого на странице компании в боковом меню нажмите Создать проект и укажите необходимую информацию.

В процессе интеграции вам потребуется ID проекта. Вы можете найти его в Личном кабинете рядом с названием проекта.

Настройка каталога товаров

Создание предметов в Личном кабинете

Внимание

Вам потребуется создать каталог товаров на стороне Xsolla. Вы можете добавить товары вручную или импортировать их из App Store, Google Play или PlayFab. При импорте из Google Play можно импортировать не более 100 предметов за раз.

В рамках этой инструкции приведены шаги по базовой настройке виртуального предмета. Позже вы сможете дополнить свой каталог другими товарами (виртуальными валютами, бандлами, игровыми ключами), создать группы товаров, настроить акционные кампании, региональные цены и т. д.

Чтобы добавить в каталог виртуальный предмет с базовыми настройками:

  1. В проекте в Личном кабинете перейдите в раздел Каталог товаров > Виртуальные предметы.
  2. В раскрывающемся меню выберите Создать предмет.

  1. Задайте базовые настройки предмета в следующих полях:
    • Изображение (опционально).
    • Артикул (уникальный ID предмета).
    • Название предмета.
    • Описание (опционально).

  1. Задайте цену предмета:
    1. Установите переключатель Цены в реальной валюте в положение Вкл.
    2. В поле Цена в реальной валюте измените валюту (опционально) и укажите цену предмета.
    3. Если вы изменили валюту в поле Цена в реальной валюте, укажите эту же валюту в поле Валюта по умолчанию.

Примечание
Чтобы методы API для получения каталога товаров работали корректно, для всех создаваемых предметов должны совпадать валюта по умолчанию и перечень валют, в которых указаны цены.

  1. Измените статус предмета на Доступен.

  1. Нажмите Создать предмет.

Отображение каталога в клиентской части приложения

  1. Добавьте в проект библиотеку Store. Для этого откройте файл build.gradle и добавьте следующую строку в раздел зависимостей:

Copy
Full screen
Small screen
    1implementation("com.xsolla.android:store:latest.release")
    

    1. В клиентской части приложения добавьте UI для отображения каталога товаров.
    2. Реализуйте запрос каталога товаров с серверов Xsolla.

    Примечание
    В примере для получения списка виртуальных предметов используется метод XStore.getVirtualItems. Вы также можете получать информацию о товарах из каталога с помощью других методов библиотеки Store.

    Пример (класс StoreActivity тестового веб-приложения):

    Copy
    Full screen
    Small screen
     1package com.xsolla.androidsample
     2
     3import androidx.appcompat.app.AppCompatActivity
     4import android.os.Bundle
     5import android.widget.Toast
     6import androidx.recyclerview.widget.LinearLayoutManager
     7import androidx.recyclerview.widget.RecyclerView
     8import com.xsolla.android.store.XStore
     9import com.xsolla.android.store.callbacks.GetVirtualItemsCallback
    10import com.xsolla.android.store.entity.response.items.VirtualItemsResponse
    11import com.xsolla.androidsample.adapter.BuyItemAdapter
    12
    13class StoreActivity : AppCompatActivity() {
    14
    15    private lateinit var itemsView: RecyclerView
    16
    17    override fun onCreate(savedInstanceState: Bundle?) {
    18        super.onCreate(savedInstanceState)
    19        setContentView(R.layout.activity_store)
    20
    21        XStore.init(<projectId>)
    22
    23        initUI()
    24        loadVirtualItems()
    25    }
    26
    27    private fun initUI() {
    28        itemsView = findViewById(R.id.buy_recycler_view)
    29        itemsView.layoutManager = LinearLayoutManager(this)
    30    }
    31
    32    private fun loadVirtualItems() {
    33        val parentActivity = this
    34        XStore.getVirtualItems(object : GetVirtualItemsCallback {
    35            override fun onSuccess(response: VirtualItemsResponse) {
    36                itemsView.adapter = BuyItemAdapter(parentActivity, response.items.filter { item -> item.virtualPrices.isEmpty() && !item.isFree })
    37            }
    38
    39            override fun onError(throwable: Throwable?, errorMessage: String?) {
    40                showNotificationMessage(errorMessage ?: throwable?.javaClass?.name ?: "Error")
    41            }
    42        })
    43    }
    44
    45    private fun showNotificationMessage(message: String) {
    46        Toast.makeText(
    47            baseContext,
    48            message,
    49            Toast.LENGTH_SHORT,
    50        ).show()
    51    }
    52}
    

    В скрипте в блоке инициализации XStore.init() укажите ID проекта, который можно найти в Личном кабинете рядом с названием проекта.

    Настройка покупки товара

    Создание заказа с помощью облачной функции

    Чтобы на стороне Xsolla сформировать заказ с данными о пользователе и товаре, добавьте в проект облачную функцию, вызывающую метод API Создание платежного токена для покупки. Этот метод вернет платежный токен, который потребуется для открытия платежного интерфейса и совершения оплаты.

    Ограничения:

    • Вам необходимо передать в запросе платежного токена либо страну, либо IP-адрес пользователя.
    • Если вы не передали валюту при запросе платежного токена, она будет определяться согласно стране пользователя.
    • Если вы передали валюту при запросе платежного токена, пользователь будет оплачивать заказ в этой валюте.

    Примечание
    Предварительно у вас должен быть создан и инициализирован проект Firebase, а также активирована аутентификация пользователей с помощью Firebase. Подробные сведения об этих шагах приведены в следующих инструкциях Firebase:

    Добавление облачной функции в проект Firebase

    1. Установите Firebase CLI (Command-Line Interface — командная строка), для этого выполните CLI-команду:

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

      1. Чтобы связать ваш проект с проектом Firebase, инициализируйте проект Firebase, для этого выполните CLI-команду:

      Copy
      Full screen
      Small screen
        1firebase init functions
        

        1. Следуйте указаниям установщика, чтобы задать настройки:
          1. Выберите существующую кодовую базу.
          2. Укажите JavaScript в качестве языка создания облачных функций.
          3. Установите зависимости.

        1. Откройте файл functions/index.js и измените его:

        Copy
        Full screen
        Small screen
         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})
        

        1. В скрипте укажите значения для переменных:
          • projectId — ID проекта, который можно найти в Личном кабинете рядом с названием проекта.

        1. Чтобы протестировать работу облачной функции с помощью эмулятора, используйте CLI-команду:

        Copy
        Full screen
        Small screen
          1firebase emulators:start
          

          1. После запуска облачной функции  вы можете вызывать в клиентской части вашего приложения следующие методы:
            • getXsollaPaymentToken — возвращает платежный токен для открытия платежного интерфейса.
            • webhookFakeResponse — отправляет 200 HTTP-код в ответ на вебхук Успешный платеж. Метод не содержит логику валидации покупки и используется только для тестирования. Полный список вебхуков и общая информация о работе с ними приведена в документации по вебхукам.

          1. Локально методы доступны для вызова по URL-адресам https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken и https://localhost:5001/{firebase-project-id}/us-central1/webhookFakeResponse, где {firebase-project-id} — ID проекта Firebase (консоль Firebase > Project Settings > Project ID).

          1. Чтобы запустить облачную функцию в боевой среде, используйте CLI-команду:

          Copy
          Full screen
          Small screen
            1firebase deploy --only functions
            

            1. После запуска в боевой среде методы станут доступны для вызова по URL-адресам https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken и https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse, где {firebase-project-id} — ID проекта Firebase (консоль Firebase > Project Settings > Project ID). Подробная информация о запуске функции в боевой среде приведена в документации Firebase.

            Реализация открытия платежного интерфейса

            1. Добавьте в проект библиотеку Payments. Для этого откройте файл build.gradle и добавьте следующую строку в раздел зависимостей:

            Copy
            Full screen
            Small screen
              1implementation("com.xsolla.android:payments:latest.release")
              

              1. Откройте файл AndroidManifest.xml и добавьте разрешение для доступа к интернету:

              Copy
              Full screen
              Small screen
              1<uses-permission android:name="android.permission.INTERNET" />
              

              1. Добавьте логику формирования заказа (вызов метода XStore.getXsollaPaymentToken облачной функции) и открытия платежного интерфейса с полученным платежным токеном (класс XPayments.createIntentBuilder()).

              1. Для вызова метода getXsollaPaymentToken укажите один из следующих URL-адресов, где {firebase-project-id} — ID проекта Firebase (консоль Firebase > Project Settings > Project ID):
                • для локального доступа — https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken;
                • для доступа в боевой среде — https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken.

              Пример (класс BuyItemAdapter тестового веб-приложения):

              Copy
              Full screen
              Small screen
                1package com.xsolla.androidsample.adapter
                2
                3import android.R.attr.duration
                4import android.os.Handler
                5import android.os.Looper
                6import android.view.LayoutInflater
                7import android.view.ViewGroup
                8import android.widget.Toast
                9import androidx.recyclerview.widget.RecyclerView
               10import com.bumptech.glide.Glide
               11import com.xsolla.android.payments.XPayments
               12import com.xsolla.android.payments.data.AccessToken
               13import com.xsolla.android.store.entity.response.items.VirtualItemsResponse
               14import com.xsolla.androidsample.R
               15import com.xsolla.androidsample.StoreActivity
               16import org.json.JSONObject
               17import java.io.BufferedReader
               18import java.io.BufferedWriter
               19import java.io.OutputStream
               20import java.io.OutputStreamWriter
               21import java.net.HttpURLConnection
               22import java.net.URL
               23
               24
               25class BuyItemAdapter(private val parentActivity: StoreActivity, private val items: List<VirtualItemsResponse.Item>) :
               26    RecyclerView.Adapter<BuyItemViewHolder>() {
               27    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BuyItemViewHolder {
               28        return BuyItemViewHolder( LayoutInflater.from(parent.context)
               29            .inflate(R.layout.buy_item_sample, parent, false))
               30    }
               31
               32    override fun onBindViewHolder(holder: BuyItemViewHolder, position: Int) {
               33        val item = items[position]
               34        Glide.with(holder.view).load(item.imageUrl).into(holder.itemImage)
               35        holder.itemName.text = item.name
               36        holder.itemDescription.text = item.description
               37        var priceText: String
               38        if(item.virtualPrices.isNotEmpty()) {
               39            priceText = "${item.virtualPrices[0].getAmountRaw()} ${item.virtualPrices[0].name}"
               40        } else {
               41            priceText = "${item.price?.getAmountRaw()} ${item.price?.currency.toString()}"
               42        }
               43
               44        holder.itemPrice.text = priceText
               45
               46        holder.itemButton.setOnClickListener {
               47            Thread {
               48                purchase(item.sku!!)
               49            }.start()
               50        }
               51    }
               52
               53    private fun purchase(sku: String) {
               54
               55        val uid = parentActivity.intent.getStringExtra("uid")
               56        val email = parentActivity.intent.getStringExtra("email")
               57
               58        val jsonBody = JSONObject()
               59        jsonBody.put("data", JSONObject().apply {
               60            put("uid", uid)
               61            put("email", email)
               62            put("sku", sku)
               63            put("returnUrl", "app://xpayment.${parentActivity.packageName}")
               64        })
               65
               66        val connection = URL(https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken).openConnection() as HttpURLConnection
               67        connection.requestMethod = "POST"
               68        connection.setRequestProperty("Content-Type", "application/json")
               69        connection.doOutput = true
               70
               71        val outputStream: OutputStream = connection.outputStream
               72        val writer = BufferedWriter(OutputStreamWriter(outputStream))
               73        writer.write(jsonBody.toString())
               74        writer.flush()
               75        writer.close()
               76
               77        val responseCode = connection.responseCode
               78
               79        if (responseCode == HttpURLConnection.HTTP_OK) {
               80            val response = connection.inputStream.bufferedReader().use(BufferedReader::readText)
               81            connection.disconnect()
               82
               83            val jsonObject = JSONObject(response)
               84            val token = jsonObject.getString("token")
               85            val orderId = jsonObject.getString("order_id")
               86
               87            val intent = XPayments.createIntentBuilder(parentActivity)
               88                .accessToken(AccessToken(token))
               89                .isSandbox(true)
               90                .build()
               91            parentActivity.startActivityForResult(intent, 1)
               92        } else {
               93            Handler(Looper.getMainLooper()).post {
               94                showNotificationMessage("HTTP request failed with error: $responseCode")
               95            }
               96        }
               97    }
               98
               99    override fun getItemCount() = items.size
              100
              101    private fun showNotificationMessage(message: String) {
              102        Toast.makeText(
              103            parentActivity,
              104            message,
              105            Toast.LENGTH_SHORT,
              106        ).show()
              107    }
              108}
              

              1. Добавьте метод onActivityResult() для обработки результата платежа.

              Пример (класс StoreActivity тестового веб-приложения):

              Copy
              Full screen
              Small screen
               1override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
               2        super.onActivityResult(requestCode, resultCode, data)
               3        if (requestCode == 1) {
               4            val (status, _) = XPayments.Result.fromResultIntent(data)
               5            when (status) {
               6                XPayments.Status.COMPLETED -> showNotificationMessage("Payment completed")
               7                XPayments.Status.CANCELLED -> showNotificationMessage("Payment canceled")
               8                XPayments.Status.UNKNOWN -> showNotificationMessage("Payment error")
               9            }
              10        }
              11    }
              

              Отслеживание статуса заказа

              Отслеживание статуса заказа требуется, чтобы убедиться, что оплата прошла успешно, и начислить товары пользователю.

              Получение статуса заказа на клиентской части

              Чтобы подписаться на изменения статуса заказа, используйте в клиентской части приложения метод SDK XStore.getOrderStatus. Передайте в метод следующие параметры:

              • listener — объект слушателя типа OrderStatusListener;
              • orderId — ID заказа, полученный в результате покупки через корзину, покупки в один клик или покупки за виртуальную валюту.

              Подробные сведения о работе метода приведены в разделе Отслеживание статуса заказа.

              Получение статуса заказа на серверной части

              Внимание

              SDK позволяет отслеживать статус заказа на клиентской части вашего приложения. Однако мы рекомендуем настроить обработку вебхука Успешный платеж и получать информацию о заказе на серверной части вашего приложения. Это позволит реализовать дополнительную валидацию совершенных покупок.

              Полный список вебхуков и общая информация о работе с ними приведены в документации по вебхукам.

              Чтобы настроить вебхуки на стороне Xsolla:

              1. В проекте в Личном кабинете перейдите в раздел Настройки проекта > Вебхуки.
              2. В поле Сервер для вебхуков укажите URL-адрес, на который Xsolla будет отправлять вебхуки.

              Примечание

              Для тестирования вы можете указать https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse, где  {firebase-project-id} — ID проекта Firebase (консоль Firebase > Project Settings > Project ID). В этом случае Firebase будет имитировать успешную обработку вебхука. Для реального проекта вам потребуется добавить логику валидации покупки.

              Для тестирования вебхуков вы также можете выбрать любой специализированный сайт, например webhook.site, или платформу, например ngrok.

              1. Скопируйте и сохраните значение из поля Секретный ключ. Этот ключ генерируется по умолчанию и используется для подписи вебхуков. Если вы хотите изменить его, нажмите значок обновления.
              2. Нажмите Получать вебхуки.

              Была ли статья полезна?
              Спасибо!
              Что может сделать страницу еще лучше? Сообщение
              Жаль, что так произошло
              Расскажите, почему статья не была полезна. Сообщение
              Спасибо за обратную связь!
              Ваши мысли и идеи помогут нам улучшить ваш пользовательский опыт.
              Последнее обновление: 5 декабря 2025

              Нашли опечатку или ошибку в тексте? Выделите ее и нажмите Ctrl+Enter.

              Сообщите о проблеме
              Мы постоянно улучшаем качество нашей документации. Ваш отзыв поможет нам в этом.
              Укажите email-адрес, чтобы мы могли связаться с вами
              Спасибо за обратную связь!
              Не получилось отправить ваш комментарий
              Попробуйте еще раз позже или напишите нам на doc_feedback@xsolla.com.