Перейти к основному содержимому

6.0.0

RuStore позволяет интегрировать платежи в мобильное приложение.

подсказка

Если не знаете с чего начать, прочтите инструкцию в сценариях использования.

Пример реализации

Ознакомьтесь с приложением-примером чтобы узнать, как правильно интегрировать SDK платежей.

Условия работы платежей

  • Приложение загружено в Консоль RuStore.
  • Приложение прошло модерацию (публиковать приложение необязательно).
Важно
  • Подпись тестируемой сборки (например, debug) приложения должна совпадать с подписью сборки приложения, которая была загружена в консоль и прошла модерацию ранее (например, release).
  • Пользователь и приложение не должны быть заблокированы в RuStore.
  • Для приложения включена возможность покупок в RuStore Консоли.
предупреждение

Сервис имеет некоторые ограничения на работу за пределами России.

Подготовка к работе

предупреждение

Библиотеки плагинов в репозитории собраны для Godot Engine 4.2.1. Если вы используете другую версию Godot Engine, выполните шаги раздела Пересборка плагина.

  1. Скопируйте проекты плагина и приложения-примера из официального репозитория RuStore на GitFlic.
  2. Скопируйте содержимое папки godot_example/android/plugins в папку your_project/android/plugins.
  3. В пресете сборки Android в списке Плагины отметьте плагины Ru Store Godot Billing и Ru Store Godot Core.

Deeplink в RuStore SDK платежей нужна для корректной работы со сторонними приложениями оплаты. Она помогает пользователям быстрее совершать покупки в стороннем приложении и возвращаться в ваше приложение.

Для настройки работы с deeplink в вашем приложении и RuStore SDK, укажите deeplinkScheme внутри вашего AndroidManifest файла и переопределите метод onNewIntent вашего Activity.

<activity
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
android:theme="@style/GodotAppSplashTheme"
android:excludeFromRecents="false"
android:exported="true"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:resizeableActivity="false"
tools:ignore="UnusedAttribute" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- your app scheme -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourappscheme" />
</intent-filter>
</activity>

Вместо yourappscheme из примера выше укажите название своей схемы. Например, ru.package.name.rustore.scheme.

к сведению

Схема, указанная в AndroidManifest файле должна совпадать со схемой, которую вы указываете в методе create RuStore SDK платежей.

Инициализация

Перед вызовом методов библиотеки необходимо выполнить её инициализацию.

Для инициализации вызовите метод init.
const APPLICATION_ID = "123456"
const DEEPLINK_SCHEME = "yourappscheme"
const DEBUG_LOGS = false

var _billing_client: RuStoreGodotBillingClient = null

func _ready():
_billing_client = RuStoreGodotBillingClient.get_instance()
_billing_client.init(APPLICATION_ID, DEEPLINK_SCHEME, DEBUG_LOGS)
Где в RuStore Консоль отображаются идентификаторы приложений?
  1. Перейдите на вкладку Приложения и выберите нужное приложение.
  2. Скопируйте идентификатор из URL-адреса страницы приложения — это набор цифр между apps/ и /versions. Например, для URL-адреса https://console.rustore.ru/apps/123456/versions ID приложения — 123456.

  • DEEPLINK_SCHEME — схема deeplink, необходимая для возврата в ваше приложение после оплаты через стороннее приложение (например, SberPay или СБП). SDK генерирует свой хост к данной схеме.
  • DEBUG_LOGS — флаг, регулирующий ведение журнала событий. Укажите значение true, если хотите, чтобы события попадали в журнал. В ином случае укажите false.
примечание
  • ApplicationId, указанный в build.gradle, должен совпадать с applicationId APK-файла, который вы публиковали в системе RuStore Консоль.
  • Схема deeplink, передаваемая в deeplinkScheme, должна совпадать со схемой, указанной в AndroidManifest.xml в разделе Обработка deeplink.
  • Подпись keystore должна совпадать с подписью, которой было подписано приложение, опубликованное в системе Консоль RuStore. Убедитесь, что используемый buildType (пр. debug) использует такую же подпись, что и опубликованное приложение (пр. release).

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

Как работают платежи

Приложение для оплаты RuStore Сервер RuStore_Billing_Client Ваш сервер Ваше приложение Покупатель Приложение для оплаты RuStore Сервер RuStore_Billing_Client Ваш сервер Ваше приложение ПокупательПроверка доступности работы платежей [Необязательно] Серверная валидация платежа [Обязательно] Покупка потребляемого товара [Обязательно] Обработка deeplink при оплате СБП, SberPay и т.д.Покупка продукта Входит в ваше приложение checkPurchasesAvailability Результат getProducts Список продуктов вашего приложения Показ списка доступных покупок Приобретение товара purchaseProduct Запрос способа оплаты Проведение платежа Способ оплаты Результат проведения платежа Информация о платеже Серверная валидация (public API) Достоверная информация о покупке Начисление товара покупателю Резул�ьтат валидации confirmPurchase Результат потребления purchaseProduct Запрос способа оплаты Указал СБП/SberPay/T-Pay Запуск процесса оплаты Сценарий оплаты Оплата покупки Возврат в приложение OnNewIntent Результат оплаты Отображение платёжной шторки с результатом оплаты

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

Во время проверки доступности платежей проверяются следующие условия.

  • На устройстве пользователя установлена актуальная версия RuStore.
  • Приложение RuStore поддерживает функциональность платежей.
  • Пользователь авторизован в RuStore.
  • Пользователь и приложение не должны быть заблокированы в RuStore.
  • Для приложения включена возможность покупок в RuStore Консоли.
Для проверки доступности платежей используйте метод check_purchases_availability.

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

  • on_check_purchases_availability_success;
  • on_check_purchases_availability_failure.
Подписка на события
func _ready():
# Инициализация _billing_client

_billing_client.on_check_purchases_availability_success(_on_check_purchases_availability_success)
_billing_client.on_check_purchases_availability_failure(_on_check_purchases_availability_failure)

func _on_check_purchases_availability_success(result: RuStoreFeatureAvailabilityResult):
pass

func _on_check_purchases_availability_failure(error: RuStoreError):
pass
Вызов метода check_purchases_availability
_billing_client.check_purchases_availability()

Обратный вызов (callback) on_check_purchases_availability_success возвращает объект RuStoreFeatureAvailabilityResult с информацией о доступности сервиса.

class_name RuStoreFeatureAvailabilityResult extends Object

var isAvailable: bool
var cause: RuStoreError

func _init(json: String = ""):
if json == "":
isAvailable = false
cause = RuStoreError.new()
else:
var obj = JSON.parse_string(json)
isAvailable = obj["isAvailable"]
cause = RuStoreError.new(json)
  • isAvailable — выполнение условий выполнения платежей (true/false).
  • cause — информация об ошибке.

Обратный вызов (callback) on_check_purchases_availability_failure возвращает объект RuStoreError со всеми прочими ошибками, например — «Нет соединения с интернетом».

Работа с SDK

Получение списка продуктов

Вы проверили, что платежи доступны и пользователи могут совершать покупки. Теперь можно получить список продуктов. Используйте метод get_products, чтобы получить информацию о продуктах, добавленных в ваше приложение через RuStore Консоль.

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

  • on_get_products_success;
  • on_get_products_failure.
Подписка на события
func _ready():
# Инициализация _billing_client

_billing_client.on_get_products_success(_on_get_products_success)
_billing_client.on_get_products_failure(_on_get_products_failure)

func _on_get_products_success(products: Array):
pass

func _on_get_products_failure(error: RuStoreError):
pass
Вызов метода get_products
const PRODUCT_IDS = [
"123",
"non_con",
"con",
"sub"]

_billing_client.get_products(PRODUCT_IDS)

PRODUCT_IDS — список идентификаторов продуктов. В нём не должно быть более 100 позиций.

Чтобы указать id продуктов, которые нужны для работы метода, выполните следующие действия.

  1. Откройте RuStore Консоль.
  2. Перейдите на вкладку Приложения.
  3. Выберите нужное приложение.
  4. В левом боковом меню выберите раздел Монетизация.
  5. Выберите тип товара: Подписки или Разовые покупки.
  6. Скопируйте идентификаторы нужных товаров. Это и есть id продуктов.

Максимальная длина — 2083 символа в списке.

Обратный вызов (callback) on_get_products_success возвращает список объектов RuStoreProduct с информацией о продуктах.

class_name RuStoreProduct extends Object

var productId: String = ""
var productStatus: ERuStoreProductStatus.Item = 0
var productType: ERuStoreProductType.Item = 0
var priceLabel: String = ""
var price: int = 0
var currency: String = ""
var language: String = ""
var title: String = ""
var description: String = ""
var imageUrl: String = ""
var promoImageUrl: String = ""
var subscription: RuStoreProductSubscription = null

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
productId = obj["productId"]
productStatus = ERuStoreProductStatus.Item.get(obj["productStatus"])

if obj.has("productType"):
productType = ERuStoreProductType.Item.get(obj["productType"])

if obj.has("priceLabel"):
priceLabel = obj.get("priceLabel")

if obj.has("price"):
price = int(obj["price"])

if obj.has("currency"):
currency = obj.get("currency")

if obj.has("language"):
language = obj.get("language")

if obj.has("title"):
title = obj.get("title")

if obj.has("description"):
description = obj.get("description")

if obj.has("imageUrl"):
imageUrl = ""#obj["imageUrl"]

if obj.has("promoImageUrl"):
promoImageUrl = ""#obj["promoImageUrl"]

if obj.has("subscription"):
subscription = RuStoreProductSubscription.new(str(obj["subscription"]))

Ниже представлены доступные поля продукта.

  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).

  • productType — тип продукта (потребляемый / непотребляемый / подписка): CONSUMABLE/NON-CONSUMABE/SUBSCRIPTION:

    • NON_CONSUMABLE — непотребляемый (можно купить один раз, например: отключение рекламы в приложении);
    • CONSUMABLE — потребляемый (можно купить много раз, например: кристаллы в приложении);
    • SUBSCRIPTION — подписка (можно купить на период времени, например: подписка в стриминговом сервисе).
  • productStatus — статус продукта:

    • ACTIVE — продукт доступен для покупки;
    • INACTIVE — продукт недоступен для покупки.
  • priceLable — отформатированная цена товара, включая валютный знак на языке language.

  • price — цена в минимальных единицах (в копейках).

  • currency — код валюты ISO 4217.

  • language — язык, указанный с помощью BCP 47 кодирования.

  • title — название продукта на языке language.

  • description — описание на языке language.

  • imageUrl — ссылка на картинку.

  • promoImageUrl — ссылка на промокартинку.

  • subscription — описание подписки, возвращается только для продуктов с типом subscription.

Структура подписки

class_name RuStoreProductSubscription extends Object

var subscriptionPeriod: RuStoreSubscriptionPeriod = null
var freeTrialPeriod: RuStoreSubscriptionPeriod = null
var gracePeriod: RuStoreSubscriptionPeriod = null
var introductoryPrice: String = ""
var introductoryPriceAmount: String = ""
var introductoryPricePeriod: RuStoreSubscriptionPeriod = null

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)

if obj.has("subscriptionPeriod"):
subscriptionPeriod = RuStoreSubscriptionPeriod.new(str(obj["subscriptionPeriod"]))

if obj.has("freeTrialPeriod"):
freeTrialPeriod = RuStoreSubscriptionPeriod.new(obj["freeTrialPeriod"])

if obj.has("gracePeriod"):
gracePeriod = RuStoreSubscriptionPeriod.new(obj["gracePeriod"])

if obj.has("introductoryPrice"):
introductoryPrice = obj["introductoryPrice"]

if obj.has("introductoryPriceAmount"):
introductoryPriceAmount = obj["introductoryPriceAmount"]

if obj.has("introductoryPricePeriod"):
introductoryPricePeriod = RuStoreSubscriptionPeriod.new(obj["introductoryPricePeriod"])
  • subscriptionPeriod — период подписки.
  • freeTrialPeriod — пробный период подписки.
  • gracePeriod — льготный период подписки.
  • introductoryPrice — отформатированная вступительная цена подписки, включая знак валюты, на языке product:language.
  • introductoryPriceAmount — вступительная цена в минимальных единицах валюты (в копейках).
  • introductoryPricePeriod — расчётный период вступительной цены.

Структура периода подписки

class_name RuStoreSubscriptionPeriod extends Object

var days: int = 0
var months: int = 0
var years: int = 0

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
days = int(obj["days"])
months = int(obj["months"])
years = int(obj["years"])
  • days — количество дней.
  • months — количество месяцев.
  • years — количество лет.

Обратный вызов (callback) on_get_products_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Покупка продукта

Для вызова покупки продукта используйте метод purchaseProduct.

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

  • on_purchase_product_success;
  • on_purchase_product_failure
Подписка на события
func _ready():
# Инициализация _billing_client

_billing_client.on_purchase_product_success(_on_purchase_product_success)
_billing_client.on_purchase_product_failure(_on_purchase_product_failure)

func _on_purchase_product_success(result: RuStorePaymentResult):
pass

func _on_purchase_product_failure(error: RuStoreError):
pass
Вызов метода purchase_product
const PRODUCT_ID = "123"
const PARAMS = {
"order_id": "example_id",
"quantity": 1,
"payload": "Some payload"
}

_billing_client.purchase_product(PRODUCT_ID, PARAMS)
  • PRODUCT_ID — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр);

  • PARAMS — опциональные параметры:

    • orderId — идентификатор заказа, создаётся на стороне AnyApp. (необязательно — если не указан, то генерируется автоматически);
    • quantity — количество продукта (необязательный параметр — если не указывать, будет подставлено значение 1) (необязательно);
    • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки.

Обратный вызов on_purchase_product_success возвращает объект наследник класса RuStorePaymentResult с информацией о покупке.

  • Success — результат успешного завершения покупки цифрового товара.
  • Failure — при отправке запроса на оплату или получения статуса оплаты возникла проблема, невозможно установить статус покупки.
  • Cancelled — запрос на покупку отправлен, при этом пользователь закрыл «платёжную шторку» на своём устройстве, и результат оплаты неизвестен.
  • InvalidPaymentState — ошибка работы SDK платежей. Может возникнуть, в случае некорректного обратного deeplink.
class_name RuStorePaymentResult extends Object
class Success extends RuStorePaymentResult:

var orderId: String = ""
var purchaseId: String = ""
var productId: String = ""
var invoiceId: String = ""
var subscriptionToken: String = ""
var sandbox: bool = false

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
if obj.has("orderId"):
purchaseId = obj["orderId"]

purchaseId = obj["purchaseId"]
productId = obj["productId"]
invoiceId = obj["invoiceId"]
sandbox = obj["sandbox"]

if obj.has("subscriptionToken"):
purchaseId = obj["subscriptionToken"]
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов (необязательно — если не указан, то генерируется автоматически).
  • purchaseId — идентификатор покупки.
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • invoiceId — идентификатор счёта.
  • subscriptionToken — токен подписки. Состоит из invoiceId покупки и userId RuStore, записанных через точку: invoiceId.userId.
  • sandbox — флаг тестового платежа. Значение true — тестовый платёж, false — реальный платёж.
class Cancelled extends RuStorePaymentResult:

var purchaseId: String
var sandbox: bool = false

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
purchaseId = obj["purchaseId"]
sandbox = obj["sandbox"]
  • purchaseId — идентификатор покупки.
  • sandbox — флаг тестового платежа. Значение true — тестовый платёж, false — реальный платёж.

class Failure extends RuStorePaymentResult:

var purchaseId: String = ""
var invoiceId: String = ""
var orderId: String = ""
var quantity: int = 0
var productId: String = ""
var errorCode: int = 0
var sandbox: bool = false

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
if obj.has("purchaseId"): purchaseId = obj["purchaseId"]
if obj.has("invoiceId"): invoiceId = obj["invoiceId"]
if obj.has("orderId"): orderId = obj["orderId"]
if obj.has("quantity"): quantity = int(obj["quantity"])
if obj.has("productId"): productId = obj["productId"]
if obj.has("errorCode"): errorCode = int(obj["errorCode"])
sandbox = obj["sandbox"]
  • purchaseId — идентификатор покупки.
  • invoiceId — идентификатор счёта.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.
  • quantity — количество продукта (необязательный параметр — если не указывать, будет подставлено значение 1).
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • errorCode — код ошибки.
  • sandbox — флаг тестового платежа. Значение true — тестовый платёж, false — реальный платёж.
class InvalidPaymentState extends RuStorePaymentResult:
pass

Обратный вызов (callback) on_purchase_product_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Получение сведений о покупке

Для получения информации о покупке, используйте метод get_purchase_info.

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

  • on_get_purchase_info_success.
  • on_get_purchase_info_failure.
Подписка на события
func _ready:
# Инициализация _billing_client

_billing_client.on_get_purchase_info_success(_on_get_purchase_info_success)
_billing_client.on_get_purchase_info_failure(_on_get_purchase_info_failure)

func _on_get_purchase_info_success(purchase: RuStorePurchase):
pass

func _on_get_purchase_info_failure(error: RuStoreError):
pass
Вызов метода get_purchase_info
# Ваша реализация UI запроса информации о покупке
func _on_confirm_purchase_pressed(purchase: RuStorePurchase):
_billing_client.get_purchase_info(purchase.purchaseId)

purchase.purchaseId — идентификатор покупки.

Обратный вызов (callback) on_get_purchase_info_success возвращает объект RuStorePurchase с информацией о покупке.

class_name RuStorePurchase extends Node

var purchaseId: String = ""
var productId: String = ""
var productType: ERuStoreProductType.Item = ERuStoreProductType.Item.NON_CONSUMABLE
var invoiceId: String = ""
var language: String = ""
var purchaseTime: String = ""
var orderId: String = ""
var amountLabel: String = ""
var amount: int = 0
var currency: String = ""
var quantity: int = 0
var purchaseState: ERuStorePurchaseState.Item = ERuStorePurchaseState.Item.CANCELLED
var developerPayload: String = ""
var subscriptionToken: String = ""

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
if obj.has("purchaseId"): purchaseId = obj["purchaseId"]
productId = obj["productId"]
if obj.has("productType"): productType = ERuStoreProductType.Item.get(obj["productType"])
if obj.has("invoiceId"): invoiceId = obj["invoiceId"]
if obj.has("language"): language = obj["language"]
if obj.has("purchaseTime"): purchaseTime = obj["purchaseTime"]#RuStoreDateTime
if obj.has("orderId"): orderId = obj["orderId"]
if obj.has("amountLabel"): amountLabel = obj["amountLabel"]
if obj.has("amount"): amount = int(obj["amount"])
if obj.has("currency"): currency = obj["currency"]
if obj.has("quantity"): quantity = int(obj["quantity"])
if obj.has("purchaseState"): purchaseState = ERuStorePurchaseState.Item.get(obj["purchaseState"])
if obj.has("developerPayload"): developerPayload = obj["developerPayload"]
if obj.has("subscriptionToken"): subscriptionToken = obj["subscriptionToken"]
  • purchaseId — идентификатор покупки.

  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).

  • productType — тип продукта (потребляемый / непотребляемый / подписка): CONSUMABLE/NON-CONSUMABE/SUBSCRIPTION:

    • NON_CONSUMABLE — непотребляемый (можно купить один раз, например: отключение рекламы в приложении).
    • CONSUMABLE — потребляемый (можно купить много раз, например: кристаллы в приложении).
    • SUBSCRIPTION — подписка (можно купить на период времени, например: подписка в стриминговом сервисе).
  • invoiceId — идентификатор счёта.

  • language — язык, указанный с помощью BCP 47 кодирования.

  • purchaseTime — время покупки:

    • MMM — сокращенное название месяца (январь — Jan).
    • dd — день месяца.
    • yyyy — год.
    • h — час в 12-часовом формате.
    • mm — минуты.
    • ss — секунды.
    • a — AM/PM индикатор времени.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.

  • amountLable — отформатированная цена покупки, включая валютный знак.

  • amount — цена в минимальных единицах валюты.

  • currency — код валюты ISO 4217.

  • quantity — количество продукта (необязательный параметр — если не указывать, будет подставлено значение 1).

  • purchaseState — состояние покупки:

    • CREATED — покупка создана.
    • INVOICE_CREATED — создан счёт на оплату, покупка ожидает оплаты.
    • PAID — только покупки потребляемого товара — промежуточный статус, средства на счёте покупателя зарезервированы. Покупка ожидает подтверждения от разработчика.
    • CONFIRMED — платеж за непотребляемый товар успешно совершен.
    • CONSUMED — платеж за потребляемый товар успешно совершен.
    • CANCELLED — покупка отменена — оплата не была произведена или был совершен возврат средств покупателю (для подписок после возврата средств покупка не переходит в CANCELLED).
    • PAUSED — для подписок — подписка перешла в HOLD период.
    • TERMINATED — подписка закрылась.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки.

  • subscriptionToken — токен для валидации покупки на сервере.

Статусная модель (purchaseState)

Статусная модель покупки потребляемых продуктов (CONSUMABLES)

img

Статусная модель покупки непотребляемых продуктов (NON-CONSUMABLES)

img

Статусная модель покупки подписок (SUBSCRIPTIONS)

img

Обратный вызов (callback) on_get_purchase_info_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Получение списка покупок

Метод возвращает только покупки со статусами из таблицы ниже. Подробнее о других возможных состояниях покупки смотрите в разделе Получение сведений о покупке.

Тип/СтатусINVOICE_CREATEDCONFIRMEDPAIDPAUSED
CONSUMABLE++
NON-CONSUMABLE++
SUBSCRIPTION+++
примечание

Метод возвращает незавершённые состояния покупки и покупки потребляемых товаров, требующих обработки. Помимо этого, он показывает подтверждённые покупки для подписок и непотребляемых товаров — тех, которые нельзя купить повторно.

Для получения списка покупок пользователя используйте метод get_purchases.

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

  • on_get_purchases_success.
  • on_get_purchases_failure.
Подписка на события
func _ready:
# Инициализация _billing_client

_billing_client.on_get_purchases_success(_on_get_purchases_success)
_billing_client.on_get_purchases_failure(_on_get_purchases_failure)

func _on_get_purchases_success(purchases: Array):
pass

func _on_get_purchases_failure(error: RuStoreError):
pass
Вызов метода get_purchases
_billing_client.get_purchases()

Обратный вызов on_get_purchases_success возвращает массив объектов RuStorePurchase с информацией о покупках.

Обратный вызов (callback) on_get_purchases_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Потребление (подтверждение) покупки

Продукты, требующие потребления (подтверждения)

Учитывайте тип покупки. Метод потребления (подтверждения) необходим, только если у вас потребляемый товар (CONSUMABLE), который можно купить много раз.

Чтобы такие товары начислились пользователям без ошибок, подтвердите потребление (подтверждение) продукта с помощью метода confirmPurchase. При начислении товара в вашем приложении используйте серверную валидацию платежей. Начисляйте товар только когда платёж (счёт) перейдет в финальный статус CONFIRMED. Начисление продуктов пользователям надо делать в callback addOnSuccessListener метода confirmPurchase.

Обратите внимание!

Статус PAID является промежуточным и означает, что средства пользователя захолдированы на карте и вам нужно подтвердить покупку.

Исключение составляют платежи через СБП или мобильное списание — см. пояснения ниже.

При оплате потребляемых (CONSUMABLE) товаров через СБП или мобильное списание используется одностадийный платёж, при этом модель счёта остаётся двухстадийной. Это значит, что при переходе счёта в статус PAID при оплате через СБП или мобильное списание деньги уже списаны со счёта покупателя, а с разработчика удержана комиссия. В этом случае при отмене покупки в состоянии PAID происходит возврат средств (refund), а не отмена холдирования — reverse. Удержанная комиссия разработчику не возвращается. При этом для завершения покупки всё равно нужно выполнить метод подтверждения (потребления) — см. также таблицу ниже.

Платёжный методТип платежаПлатёж в статусе PAID
  • банковские карты;
  • Сбер ID;
  • SberPay;
  • T-Pay;
  • VK Pay.
Двухстадийный
  • Средства захолдированы на счёте покупателя.
  • Комиссия с разработчика не удержана.
  • Возможна отмена платежа.
  • СБП;
  • мобильное списание.
Одностадийный
  • Средства списаны со счёта покупателя.
  • Удержана комиссия с разработчика.
  • При отмене покупки в состоянии PAID происходит возврат средств (refund), а не отмена холдирования — reverse. Удержанная комиссия разработчику не возвращается.

Вызов метода потребления (подтверждения)

Для потребления (подтверждения) покупки используйте метод confirm_purchase. Запрос на потребление (подтверждение) покупки должен сопровождаться выдачей товара. После вызова подтверждения покупка перейдёт в статус CONSUMED.

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

  • on_confirm_purchase_success;
  • on_confirm_purchase_failure.
Подписка на события
func _ready:
# Инициализация _billing_client

_billing_client.on_confirm_purchase_success(_on_confirm_purchase_success)
_billing_client.on_confirm_purchase_failure(_on_confirm_purchase_failure)

func _on_confirm_purchase_success(purchase_id: String):
pass

func _on_confirm_purchase_failure(purchase_id: String, error: RuStoreError):
pass
Вызов метода confirm_purchase
# Ваша реализация UI потребления (подтверждения) покупки
func _on_confirm_purchase_pressed(purchase: RuStorePurchase):
_billing_client.confirm_purchase(purchase.purchaseId)

purchase.purchaseId — идентификатор покупки.

Обратный вызов (callback) on_confirm_purchase_failure возвращает идентификатор покупки типа String и объект RuStoreError с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Отмена покупки

Для отмены покупки используйте метод delete_purchase.

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

  • on_delete_purchase_success;
  • on_delete_purchase_failure.
Подписка на события
func _ready:
# Инициализация _billing_client

_billing_client.on_delete_purchase_success(_on_delete_purchase_success)
_billing_client.on_delete_purchase_failure(_on_delete_purchase_failure)

func _on_delete_purchase_success(purchase_id: String):
pass

func _on_delete_purchase_failure(purchase_id: String, error: RuStoreError):
_core_client.show_toast(purchase_id + " " + error.description)
Вызов метода delete_purchase
# Ваша реализация UI отмены покупки
func _on_delete_purchase_pressed(purchase: RuStorePurchase):
_billing_client.delete_purchase(purchase.purchaseId)
purchase.purchaseId — идентификатор покупки

  • Обратный вызов (callback) on_delete_purchase_info_success возвращает идентификатор покупки.
  • Обратный вызов (callback) on_delete_purchase_info_failure возвращает идентификатор покупки типа String и объект RuStoreError с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Логирование

Если необходимо логировать события библиотеки платежей, добавьте необязательный параметр debugLogs в вызов init и единожды выполните подписку на события:

  • on_payment_logger_debug;
  • on_payment_logger_error;
  • on_payment_logger_info;
  • on_payment_logger_verbose;
  • on_payment_logger_warning.

Логирование будет работать только для Debug-сборок приложения и *.aar пакетов плагинов. Логи будут автоматически отключены для Release-сборок.

func _ready():
_billing_client = RuStoreGodotBillingClient.get_instance()

_billing_client.on_payment_logger_debug.connect(_on_payment_logger_debug)
_billing_client.on_payment_logger_error.connect(_on_payment_logger_error)
_billing_client.on_payment_logger_info.connect(_on_payment_logger_info)
_billing_client.on_payment_logger_verbose.connect(_on_payment_logger_verbose)
_billing_client.on_payment_logger_warning.connect(_on_payment_logger_warning)

# Вызов метода init

func _on_payment_logger_debug(error: RuStoreError, message: String, tag: String):
_core_client.show_toast(tag + ": " + message)

func _on_payment_logger_error(error: RuStoreError, message: String, tag: String):
_core_client.show_toast(tag + ": " + message)

func _on_payment_logger_info(error: RuStoreError, message: String, tag: String):
_core_client.show_toast(tag + ": " + message)

func _on_payment_logger_verbose(error: RuStoreError, message: String, tag: String):
_core_client.show_toast(tag + ": " + message)

func _on_payment_logger_warning(error: RuStoreError, message: String, tag: String):
_core_client.show_toast(tag + ": " + message)

Ниже представлены возвращаемые параметры.

  • error — информация об ошибке. Структура ошибки описана в разделе Обработка ошибок.
  • message — сообщение для логирования.
  • tag — тэг лога.

Динамическая смена темы интерфейса

Для динамической смены темы необходимо использовать метод set_theme.

Вызов метода установки темы

func _ready():
_billing_client = RuStoreGodotBillingClient.get_instance()

var theme = ERuStoreTheme.Item.DARK

Где: theme — тип темы из перечисления ERuStoreTheme:

  • DARK — тёмная тема;
  • LIGHT — светлая тема.

Обработка ошибок

Возможные ошибки

  • RuStoreNotInstalledException — на устройстве пользователя не установлен RuStore;
  • RuStoreOutdatedException — версия RuStore, установленная на устройстве пользователя, не поддерживает данный SDK;
  • RuStoreUserUnauthorizedException — пользователь не авторизован в RuStore;
  • RuStoreRequestLimitReached — с момента последнего отображения процесса прошло слишком мало времени;
  • RuStoreReviewExists — этот пользователь уже оценил ваше приложение;
  • RuStoreInvalidReviewInfo — проблемы с ReviewInfo;
  • RuStoreException — базовая ошибка RuStore, от которой наследуются остальные ошибки.

Структура ошибки

class_name RuStoreError extends Object

var name: String = ""
var description: String = ""

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)

if obj.has("simpleName"):
name = obj["simpleName"]

if obj.has("detailMessage"):
description = obj["detailMessage"]
  • name – имя ошибки.
  • description – описание ошибки.

Автоматическая обработка ошибок

При вызове метода покупки продукта purchase_product ошибки обрабатываются автоматически.

Для показа диалога с ошибкой пользователю используйте метод set_error_handling (см. ниже).

func _ready():
_billing_client = RuStoreGodotBillingClient.get_instance()
_billing_client.set_error_handling(true)
  • true — показывать диалог;
  • false — не показывать диалог.