SDK in-app платежей для Godot (версия 6.1.0)
RuStore позволяет интегрировать платежи в мобильное приложение.
Если не знаете с чего начать, прочтите инструкцию в сценариях использования.
Пример реализации
Ознакомьтесь с приложением-примером чтобы узнать, как правильно интегрировать SDK платежей.
Условия работы платежей
- Приложение загружено в Консоль RuStore.
- Приложение прошло модерацию (публиковать приложение необязательно).
- Подпись тестируемой сборки (например,
debug
) приложения должна совпадать с подписью сборки приложения, которая была загружена в консоль и прошла модерацию ранее (например,release
).
- Пользователь и приложение не должны быть заблокированы в RuStore.
- Для приложения включена возможность покупок в RuStore Консоли.
Сервис имеет некоторые ограничения на работу за пределами России.
Подготовка к работе
Библиотеки плагинов в репозитории собраны для Godot Engine 4.2.1. Если вы используете другую версию Godot Engine, выполните шаги раздела Пересборка плагина.
- Скопируйте проекты плагина и приложения-примера из официального репозитория RuStore на GitFlic.
- Скопируйте содержимое папки
godot_example/android/plugins
в папкуyour_project/android/plugins
. - В пресете сборки Android в списке Плагины отметьте плагины Ru Store Godot Billing и Ru Store Godot Core.
Обработка deeplink
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)
-
APPLICATION_ID
— идентификатор приложения из консоли RuStore.
Где в RuStore Консоль отображаются идентификаторы приложений?
- Перейдите на вкладку Приложения и выберите нужное приложение.
- Скопируйте идентификатор из 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 поддерживает функциональность платежей.
- Пользователь авторизован в 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
_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
const PRODUCT_IDS = [
"123",
"non_con",
"con",
"sub"]
_billing_client.get_products(PRODUCT_IDS)
PRODUCT_IDS
— список идентификаторов продуктов. В нём не должно быть более 100 позиций.
Чтобы указать id
продуктов, которые нужны для работы метода, выполните следующие действия.
- Откройте RuStore Консоль.
- Перейдите на вкладку Приложения.
- Выберите нужное приложение.
- В левом боковом меню выберите раздел Монетизация.
- Выберите тип товара: Подписки или Разовые покупки.
- Скопируйте идентификаторы нужных товаров. Это и есть
id
продуктов.
Обратный вызов (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
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
# Ваша реализация 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
)
Статусная модель покупки непотребляемых про дуктов (NON-CONSUMABLES
)
Статусная модель покупки подписок (SUBSCRIPTIONS
)
Обратный вызов (callback) on_get_purchase_info_failure
возвращает объект RuStoreError
с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.
Получение списка покупок
Метод возвращает только покупки со статусами из таблицы ниже. Подробнее о других возможных состояниях покупки смотрите в разделе Получение сведений о покупке.
Тип/Статус | INVOICE_CREATED | CONFIRMED | PAID | PAUSED |
---|---|---|---|---|
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
_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 |
---|---|---|
| Двухстадийный |
|
| Одностадийный |
|
Вызов метода потребления (подтверждения)
Для потребления (подтверждения) покупки используйте метод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
# Ваша реализация 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)
# Ваша реализация 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
— не показывать диалог.