SDK Платежи in-app для Kotlin/Java (версия 10.1.0)
RuStore позволяет интегрировать платежи в мобильное приложение.
-
Если не знаете с чего начать, прочтите инструкцию в сценариях использования.
-
Если вы переходите на Pay SDK с billingClient SDK, ознакомьтесь с инструкцией по переходу. Подробности о Pay SDK можно узнать тут.
Подготовка к работе
Добавление репозитория
repositories {
maven {
url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven")
}
}
Подключение зависимости
Добавьте следующий код в свой конфигурационный файл для подключения зависимости.
dependencies {
implementation(platform("ru.rustore.sdk:bom:2025.11.01"))
implementation("ru.rustore.sdk:pay")
}
Обработка deeplink
Обработка deeplink в RuStore SDK позволяет эффективно взаимодействовать со сторонними приложениями, при проведении платежей через банковские приложения (СБП, SberPay и др.). Это позволяет перевести пользователя на экран оплаты, а после завершения транзакции — вернуть в ваше приложение.
Для настройки работы с deeplink в вашем приложении и Pay SDK, укажите deeplinkScheme с помощью sdk_pay_scheme_value
в вашем AndroidManifest.xml файле и переопределите метод onNewIntent вашего Activity
- При использовании deeplinks указание схемы является обязательным.
- При попытке платежа без указания схемы будет возникать ошибка.
- Допускаются только символы в кодировке ASCII. Формат должен соответствовать спецификации RFC-3986.
Указание deeplinkScheme:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your.app.package.name">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App"
tools:targetApi="n">
<!-- ... -->
<activity
android:name=".YourPayActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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>
<meta-data
android:name="sdk_pay_scheme_value"
android:value="yourappscheme" />
</application>
</manifest>
Замените yourappscheme на название своей схемы. Например, ru.package.name.rustore.scheme.
Затем, добавьте следующий код в Activity, в которую необходимо вернуться
после совершения оплаты (ваша страница приложения):
сlass YourBillingActivity: AppCompatActivity() {
private val intentInteractor: IntentInteractor by lazy {
RuStorePayClient.instance.getIntentInteractor()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
intentInteractor.proceedIntent(intent, sdkTheme = SdkTheme.LIGHT) // Опциональная тема
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intentInteractor.proceedIntent(intent, sdkTheme = SdkTheme.LIGHT) // Опциональная тема
}
}
Для восстановления состояния вашего приложения при возврате с deeplink добавьте в
AndroidManifest.xml атрибут android:launchMode="singleTop".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your.app.package.name">
<!-- ... -->
<application>
<!-- ... -->
<activity
android:name=".YourPayActivity"
android:launchMode="singleTop"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
</activity>
<!-- ... -->
</application>
</manifest>
Инициализация SDK
Перед вызовом методов библиотеки необходимо выполнить её ини циализацию. Сама инициализация происходит автоматически, но для работы SDK в вашем файле Manifest.xml необходимо прописать console_app_id_value. Значение необходимо указать в строковых ресурсах.
Сделать это можно следующим образом.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your.app.package.name">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App"
tools:targetApi="n">
...
<meta-data
android:name="console_app_id_value"
android:value="@string/CONSOLE_APPLICATION_ID" />
</application>
</manifest>
-
Пример:CONSOLE_APPLICATION_ID— идентификатор приложения из RuStore консоли.https://console.rustore.ru/apps/111111.
Где в RuStore Консоль отображаются идентификаторы приложений?
- Перейдите на вкладку Приложения и выберите нужное приложение.
- Скопируйте идентификатор из URL-адреса страницы приложения — это набор цифр между
apps/и/versions. Например, для URL-адресаhttps://console.rustore.ru/apps/123456/versionsID приложения —123456.

ApplicationId, указанный вbuild.gradle, должен совпадать сapplicationIdAPK-файла, который вы публиковали в RuStore Консоль.-
Подпись
keystoreдолжна совпадать с подписью, которой было подписано приложение, опубликованное в RuStore Консоль. Убедитесь, что используемыйbuildType(пр.debug) использует такую же подпись, что и опубликованное приложение (пр.release).
В целях безопасности, SDK устанавливает android:usesCleartextTraffic="false" по умолчанию, чтобы предотвратить передачу данных по незащищённому HTTP и защитить от атак типа "Man-in-the-Middle". Если ваше приложение требует использования HTTP, вы можете изменить этот атрибут на true, но делайте это на свой страх и риск, так как это увелич ивает шанс перехвата и подмены данных. Мы рекомендуем разрешать незащищённый трафик только в исключительных случаях и для доверенных доменов, предпочитая HTTPS для всех сетевых взаимодействий.
Если необходимо переопределить значение этого атрибута, укажите в манифесте tools:replace="android:usesCleartextTraffic".
Необходимые разрешения и параметры безопасности
Pay SDK автоматически добавляет в манифест приложения некоторые разрешения и параметры, необходимые для работы функциональности, связанной с безопасностью платежей.
Разрешения BLUETOOTH и BLUETOOTH_CONNECT
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Эти разрешения требуются для работы сессионного антифрода — системы, защищающей платежи пользователей. Сбор подобных данных может быть полезен для анализа инцидентов, например, при расследовании кражи учетной записи.
Если вы не хотите предоставлять доступ к Bluetooth, эти разрешения можно удалить из манифеста — Pay SDK продолжит работу, просто не будет собирать эти дополнительные данные для скоринга.
Прочие разрешения
Также Pay SDK может потребовать другие стандартные разрешения, такие как:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Методы SDK
Доступные публичные интеракторы:
-
PurchaseInteractor- интерактор, который позволяет работать с платежами и имеет несколько публичных методов.getPurchase(purchaseId: PurchaseId): Task<Purchase>- позволяет получить информацию о покупке по её ID.getPurchases(productType: ProductType? = null, purchaseStatus: PurchaseStatus? = null): Task<List<Purchase>>— позволяет получить покупки пользователя. Данный метод поддерживает опциональную фильтрацию по типу товаров (потребляемые, непотребляемые товары или подписки), а также по статусу покупки (поддерживаются статусыPAID,CONFIRMEDACTIVEиPAUSED). По умолчанию фильтры отключены, и вернутся все покупки пользователя (независимо от типа товара) в статусахPAID,CONFIRMEDACTIVEиPAUSED.getPurchaseAvailability(): Task<PurchaseAvailabilityResult>- возвращает результат проверки доступности работы с платежами.purchase(params: ProductPurchaseParams, preferredPurchaseType: PreferredPurchaseType = PreferredPurchaseType.ONE_STEP,sdkTheme: SdkTheme = SdkTheme.LIGHT): Task<ProductPurchaseResult>- позволяет совершить покупку продукта с указанием желаемого типа оплаты - одностадийной (ONE_STEP) или двухстадийной (TWO_STEP). Для данного метода оплаты на платёжной шторке доступны все способы оплаты. Если параметр не задан, по умолчанию запускается с оплатой в одну стадию.
Важно!Если указан тип оплаты
TWO_STEP, будет произведена попытка запустить двухстадийную оплату, но итоговый результат напрямую будет зависеть от того, какой способ оплаты (карта, СБП и др.) будет выбран пользователем.Обратите внимание, что тип оплаты
TWO_STEPнедоступен:-
При выборе способа оплаты СБП.
-
При покупке подписок.
Двухстадийная оплата доступна только для определенного набора способов оплаты (на текущий момент — только для карт и SberPay). Если выбран способ оплаты, который не поддерживает холдирование, то покупка будет запущена по сценарию с одной стадией.
purchaseTwoStep(params: ProductPurchaseParams,sdkTheme: SdkTheme = SdkTheme.LIGHT): Task<ProductPurchaseResult>- запускает сценарий гарантированной двухстадийной покупки товара. При использовании данного метода пользователю на платёжной шторке доступен ограниченный набор способов оплаты - только те, которые поддерживают двухстадийную оплату. В процессе платежа сначала осуществляется холдирование денежных средств покупателя, которые списываются только после подтверждения покупки методомconfirmTwoStepPurchase.confirmTwoStepPurchase(purchaseId: PurchaseId, developerPayload: DeveloperPayload? = null)- подтверждение покупки, совершенной по двухстадийной оплате.cancelTwoStepPurchase(purchaseId: PurchaseId)- отмена покупки, совершённой по двухстадийной оплате.
-
ProductInteractor- интерактор, который позволяет работать с продуктами:getProducts(productsId: List<ProductId>): Task<List<Product>>- позволяет получить информацию по активным продуктам, опубликованным в RuStore консоль.
ВажноДанный метод возвращает не более 1000 продуктов и работает без авторизации и наличия установленного RuStore на устройстве пользователя.
-
UserInteractor- интерактор, который позволяет получить статус авторизации пользователяUserAuthorizationStatus. У данной модели может быть 2 состояния:Authorized- пользователь авторизован в RuStoreUnauthorized- пользователь неавторизован в RuStore.
-
IntentInteractor- интерактор, который позволяет обрабатывать intent-ы и deeplink-и. Необходим для корректного возвращения из приложения банка обратно в приложение и корректного восстановления состояния платежной шторки.proceedIntent(intent: Intent?, sdkTheme: SdkTheme = SdkTheme.LIGHT)- метод для обработки диплинков и восстановление состояния платежной шторки при возвращении в Ваше приложение из приложения банка. Вызов данного метода необходим для корректного отображения шторки оплаты при возвращении в приложение из приложения банка.
-
блок
RuStoreUtils- набор открытых методов, таких как:isRuStoreInstalled- проверки наличия приложения RuStore на устройстве пользователя.openRuStoreDownloadInstruction- открывает веб-страницу для скачивания приложения RuStore.openRuStore- запускает приложение RuStore.openRuStoreAuthorization- запускает приложение RuStore для автор изации. После успешной авторизации пользователя приложение RuStore автоматически закроется.
Получение списка продуктов
- Kotlin
- Java
Для получения продуктов, добавленных в ваше приложение через RuStore консоль, необходимо использовать метод getProducts.
RuStorePayClient.instance.getProductInteractor().getProducts(productsId = listOf(ProductId("id1"), ProductId("id2")))
.addOnSuccessListener { products: List<Product> ->
// Логика работы со списком продуктов
}
.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
productsId: List<ProductId> — список идентификаторов продуктов (задаются при создании продукта в консоли разработчика). Список продуктов имеет ограничение в размере 1000 элементов.
Где в RuStore Консоль отображаются идентификаторы продуктов?
- Перейдите на вкладку Приложения и выберите нужное приложение.
- Выберите Монетизация в меню слева.
- Выберите тип товара: Подписки или Разовые покупки.
- Скопируйте идентификаторы нужных товаров.

Метод возвращает список активных продуктов. Ниже представлена модель продукта.
public class Product internal constructor(
public val productId: ProductId,
public val type: ProductType,
public val amountLabel: AmountLabel,
public val price: Price?,
public val currency: Currency,
public val imageUrl: Url,
public val title: Title,
public val description: Description?,
public val subscriptionInfo: SubscriptionInfo?,
)
productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).type— тип продукта.CONSUMABLE/NON-CONSUMABLE/SUBSCRIPTION(потребляемый/непотребляемый/подписка).amountLabel— отформатированная цена покупки, включая валютный знак.price— цена в минимальных единицах (в копейках).currency— код валюты ISO 4217.title— название продукта на языкеlanguage.description— описание на языкеlanguage.imageUrl— ссылка на картинку.subscriptionInfo— информация о подписке (будет неnull, если тип продуктаSUBSCRIPTION).
Модель subscriptionInfo содержит информацию о продукте подписки.
Наличие полей не означает, что пользователю по-прежнему доступен бесплатный или стартовый период: он мог ранее уже исчерпать эти периоды.
Ниже представлена сама модель.
public class SubscriptionInfo internal constructor(
public val periods: List<SubscriptionPeriod>,
)
public sealed interface SubscriptionPeriod
public class TrialPeriod internal constructor(
public val duration: String,
public val currency: String,
public val price: Int,
) : SubscriptionPeriod {
public class PromoPeriod internal constructor(
public val duration: String,
public val currency: String,
public val price: Int,
) : SubscriptionPeriod
public class MainPeriod internal constructor(
public val duration: String,
public val currency: String,
public val price: Int,
) : SubscriptionPeriod
public class GracePeriod internal constructor(
public val duration: String,
) : SubscriptionPeriod
public class HoldPeriod internal constructor(
public val duration: String,
) : SubscriptionPeriod
duration- длительность периода в формате ISO 8601 (как в Public API)currency- код валюты ISO 4217price- цена в минимальных единицах (копейках).
Пример работы с subscriptionInfo
RuStorePayClient.instance.getProductInteractor().getProducts(productsId = listOf(ProductId("id1"), ProductId("id2")))
.addOnSuccessListener { products: List<Product> ->
products.forEach { product ->
val periods = product.subscriptionInfo?.periods
when (period) {
is TrialPeriod -> {
println("Бесплатный период: ${period.duration} за ${period.price} ${period.currency}")
}
is PromoPeriod -> {
println("Стартовый период: ${period.duration} за ${period.price} ${period.currency}")
}
is MainPeriod -> {
println("Основной период: ${period.duration} за ${period.price} ${period.currency}")
}
is GracePeriod -> {
println("Период отсрочки: ${period.duration}")
}
is HoldPeriod -> {
println("Период удержания: ${period.duration}")
}
null -> {
println("subscriptionInfo is null")
}
}
}
}
.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
Примеры ответа
Product(
productId = ProductId("conProduct1"),
type = ProductType.CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("100.00 руб."),
price = Price(10000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_consumable_product.png"),
title = Title("Название Потребляемого продукта"),
description = Description("Описание потребляемого продукта"),
)
Product(
productId = ProductId("nonConProduct1"),
type = ProductType.NON_CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("200.00 руб."),
price = Price(20000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_non_consumable_product.png"),
title = Title("Название Непотребляемого продукта"),
description = Description("Описание Непотребляемого продукта"),
)
Product(
productId = ProductId("sub_1"),
type = ProductType.SUBSCRIPTION,
amountLabel = AmountLabel("300.00 руб."),
price = Price(30000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_subscription.png"),
title = Title("Название вашей подписки"),
description = Description("Описание вашей подписки"),
subscriptionInfo = SubscriptionInfo(
periods = listOf(
TrialPeriod(
duration = "P1M",
currency = "RUB",
price = 0
),
PromoPeriod(
duration = "P5D",
currency = "RUB",
price = 149
),
MainPeriod(
duration = "P1Y",
currency = "RUB",
price = 299
),
GracePeriod(
duration = "P3D"
),
HoldPeriod(
duration = "P5D"
)
)
)
)
Для получения продуктов, добавленных в ваше приложение через RuStore консоль, необходимо использовать метод getProducts.
List<ProductId> productsId = Arrays.asList(new ProductId("id1"), new ProductId("id2"));
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
productInteractor.getProducts(productsId)
.addOnSuccessListener(products -> {
// Логика работы со списком продуктов
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
productsId: List<ProductId> — список идентификаторов продуктов (задаются при создании продукта в консоли разработчика). Список продуктов имеет ограничение в размере 1000 элементов.
Где в RuStore Консоль отображаются идентификаторы продуктов?
- Перейдите на вкладку Приложения и выберите нужное приложение.
- Выберите Монетизация в меню слева.
- Выберите тип товара: Подписки или Разовые покупки.
- Скопируйте идентификаторы нужных товаров.

Метод возвращает список активных продуктов. Ниже представлена модель продукта:
public class Product {
private final ProductId productId;
private final ProductType type;
private final AmountLabel amountLabel;
private final Price price;
private final Currency currency;
private final Url imageUrl;
private final Title title;
private final Description description;
private final SubscriptionInfo subscriptionInfo;
public Product(ProductId productId, ProductType type, AmountLabel amountLabel, @Nullable Price price, Currency currency, Url imageUrl, Title title, @Nullable Description description, @Nullable SubscriptionInfo subscriptionInfo) {
this.productId = productId;
this.type = type;
this.amountLabel = amountLabel;
this.price = price;
this.currency = currency;
this.imageUrl = imageUrl;
this.title = title;
this.description = description;
this.subscriptionInfo = subscriptionInfo;
}
public ProductId getProductId() {
return productId;
}
public ProductType getType() {
return type;
}
public AmountLabel getAmountLabel() {
return amountLabel;
}
public @Nullable Price getPrice() {
return price;
}
public Currency getCurrency() {
return currency;
}
public Url getImageUrl() {
return imageUrl;
}
public Title getTitle() {
return title;
}
public @Nullable Description getDescription() {
return description;
}
public @Nullable SubscriptionInfo getSubscriptionInfo() {
return subscriptionInfo;
}
}
productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).type— тип продукта.CONSUMABLE/NON-CONSUMABLE/SUBSCRIPTION(потребляемый/непотребляемый/подписка).amountLabel— отформатированная цена покупки, включая валютный знак.price— цена в минимальн ых единицах (в копейках).currency— код валюты ISO 4217.title— название продукта на языкеlanguage.description— описание на языкеlanguage.imageUrl— ссылка на картинку.subscriptionInfo— информация о подписке (будет неnull, если тип продуктаSUBSCRIPTION).
Модель subscriptionInfo содержит информацию о продукте подписки.
Наличие полей не означает, что пользователю по-прежнему доступен бесплатный или стартовый период: он мог ранее уже исчерпать эти периоды.
Ниже представлена сама модель.
public final class SubscriptionInfo {
private final List<SubscriptionPeriod> periods;
public SubscriptionInfo(List<SubscriptionPeriod> periods) {
this.periods = periods;
}
public List<SubscriptionPeriod> getPeriods() {
return periods;
}
}
public interface SubscriptionPeriod {
String getDuration();
}
public final class TrialPeriod implements SubscriptionPeriod {
private final String duration;
private final String currency;
private final int price;
public TrialPeriod(String duration, String currency, int price) {
this.duration = duration;
this.currency = currency;
this.price = price;
}
public String getDuration() { return duration; }
public String getCurrency() { return currency; }
public int getPrice() { return price; }
}
public final class PromoPeriod implements SubscriptionPeriod {
private final String duration;
private final String currency;
private final int price;
public PromoPeriod(String duration, String currency, int price) {
this.duration = duration;
this.currency = currency;
this.price = price;
}
public String getDuration() { return duration; }
public String getCurrency() { return currency; }
public int getPrice() { return price; }
}
public final class MainPeriod implements SubscriptionPeriod {
private final String duration;
private final String currency;
private final int price;
public MainPeriod(String duration, String currency, int price) {
this.duration = duration;
this.currency = currency;
this.price = price;
}
public String getDuration() { return duration; }
public String getCurrency() { return currency; }
public int getPrice() { return price; }
}
public final class GracePeriod implements SubscriptionPeriod {
private final String duration;
public GracePeriod(String duration) {
this.duration = duration;
}
public String getDuration() { return duration; }
}
public final class HoldPeriod implements SubscriptionPeriod {
private final String duration;
public HoldPeriod(String duration) {
this.duration = duration;
}
public String getDuration() { return duration; }
}
duration- длительность периода в формате ISO 8601 (как в Public API)currency- код валюты ISO 4217price- цена в минимальных единицах (копейках).
Пример работы с subscriptionInfo
List<ProductId> productsId = Arrays.asList(new ProductId("id1"), new ProductId("id2"));
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
productInteractor.getProducts(productsId)
.addOnSuccessListener(products -> {
for (Product product : products) {
SubscriptionInfo subscriptionInfo = product.getSubscriptionInfo();
if (subscriptionInfo == null) {
println("SubscriptionInfo is null for product: " + product.getProductId());
continue;
}
List<SubscriptionPeriod> periods = subscriptionInfo.getPeriods();
if (periods == null || periods.isEmpty()) {
continue;
}
for (SubscriptionPeriod period : periods) {
switch (period) {
case TrialPeriod trialPeriod ->
println("Бесплатный период: " + trialPeriod.getDuration() +
" за " + trialPeriod.getPrice() + " " + trialPeriod.getCurrency());
case PromoPeriod promoPeriod ->
println("Стартовый период: " + promoPeriod.getDuration() +
" за " + promoPeriod.getPrice() + " " + promoPeriod.getCurrency());
case MainPeriod mainPeriod ->
println("Основной период: " + mainPeriod.getDuration() +
" за " + mainPeriod.getPrice() + " " + mainPeriod.getCurrency());
case GracePeriod gracePeriod ->
println("Период отсрочки: " + gracePeriod.getDuration());
case HoldPeriod holdPeriod ->
println("Период удержания: " + holdPeriod.getDuration());
default ->
println("Unknown period type: " + period.getClass().getSimpleName());
}
}
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
Примеры ответа
Product(
productId = ProductId("conProduct1"),
type = ProductType.CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("100.00 руб."),
price = Price(10000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_consumable_product.png"),
title = Title("Название Потребляемого продукта"),
description = Description("Описание потребляемого продукта"),
)
Product(
productId = ProductId("nonConProduct1"),
type = ProductType.NON_CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("200.00 руб."),
price = Price(20000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_non_consumable_product.png"),
title = Title("Название Непотребляемого продукта"),
description = Description("Описание Непотребляемого продукта"),
)
Product(
productId = ProductId("sub_1"),
type = ProductType.SUBSCRIPTION,
amountLabel = AmountLabel("300.00 руб."),
price = Price(30000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_subscription.png"),
title = Title("Название вашей подписки"),
description = Description("Описание вашей подписки"),
subscriptionInfo = SubscriptionInfo(
periods = listOf(
TrialPeriod(
duration = "P1M",
currency = "RUB",
price = 0
),
PromoPeriod(
duration = "P5D",
currency = "RUB",
price = 149
),
MainPeriod(
duration = "P1Y",
currency = "RUB",
price = 299
),
GracePeriod(
duration = "P3D"
),
HoldPeriod(
duration = "P5D"
)
)
)
)
Определение наличия авторизации у пользователя
Для проверки статуса авторизации пользователя, вызовите метод getUserAuthorizationStatus у UserInteractor.
Результатом вып олнения метода является класс UserAuthorizationStatus. Доступно 2 значения:
AUTHORIZED- пользователь авторизован в RuStore или через VK ID на платежной шторке.UNAUTHORIZED- пользователь не авторизован. Данное значение также вернется если у пользователя нет установленного RuStore на устройстве.
- Kotlin
- Java
RuStorePayClient.instance.getUserInteractor().getUserAuthorizationStatus()
.addOnSuccessListener { result ->
when (result) {
UserAuthorizationStatus.AUTHORIZED -> {
// Логика когда пользователь авторизован в RuStore или на платежной шторке
}
UserAuthorizationStatus.UNAUTHORIZED -> {
// огика когда пользователь НЕ авторизован
}
}
}.addOnFailureListener { throwable ->
// Обработка ошибки
}
UserInteractor userInteractor = RuStorePayClient.Companion.getInstance().getUserInteractor();
userInteractor.getUserAuthorizationStatus()
.addOnSuccessListener(status -> {
switch (status) {
case AUTHORIZED:
// Логика когда пользователь авторизован в RuStore или на платежной шторке
break;
case UNAUTHORIZED:
// Логика когда пользователь НЕ авторизован
break;
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
Проверка доступности работы с платежами
Для проверки доступности платежей, вызовите метод getPurchaseAvailability у PurchaseInteractor. При его вызове проверяются следующие условия.
- У компании подключена монетизация через консоль разработчика RuStore.
- Приложение не должно быть заблокировано в RuStore.
- Пользователь не должен быть заблокирован в RuStore.
Если все условия выполняются, возвращается PurchaseAvailabilityResult.Available. Иначе, возвращается PurchaseAvailabilityResult.Unavailable(val cause: Throwable), где cause - это ошибка о невыполненном условии. Для проверки причины возвращения такого результата нужно проверить тип ошибки на RuStoreException (данные ошибки описаны в разделе Обработка ошибок).
- Kotlin
- Java
RuStorePayClient.instance.getPurchaseInteractor().getPurchaseAvailability()
.addOnSuccessListener { result ->
when (result) {
is PurchaseAvailabilityResult.Available -> {
// Обработка результата доступности платежей
}
is PurchaseAvailabilityResult.Unavailable -> {
// Обработка результата недоступности платежей
}
}
}.addOnFailureListener { throwable ->
// Обработка ошибки
}
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchaseAvailability()
.addOnSuccessListener(result -> {
if (result instanceof PurchaseAvailabilityResult.Available) {
// Обработка результата доступности платежей
} else if (result instanceof PurchaseAvailabilityResult.Unavailable) {
// Обработка результата недоступности платежей
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
Типы покупок
В SDK предусмотрен базовый интерфейс Purchase, который объединяет общие поля всех типов покупок.
На его основе созданы две реализации:
- ProductPurchase: для потребляемых и непотребляемых покупок.
- SubscriptionPurchase: для подписок.
Данное разделение позволяет каждому типу покупки иметь свои уникальные свойства и поведение.
- Kotlin
- Java
public interface Purchase {
public val purchaseId: PurchaseId
public val invoiceId: InvoiceId
public val orderId: OrderId?
public val purchaseType: PurchaseType
public val status: PurchaseStatus
public val description: Description
public val purchaseTime: Date?
public val price: Price
public val amountLabel: AmountLabel
public val currency: Currency
public val developerPayload: DeveloperPayload?
public val sandbox: Boolean
}
public interface Purchase {
PurchaseId getPurchaseId();
InvoiceId getInvoiceId();
@Nullable OrderId getOrderId();
PurchaseType getPurchaseType();
PurchaseStatus getStatus();
Description getDescription();
@Nullable Date getPurchaseTime();
Price getPrice();
AmountLabel getAmountLabel();
Currency getCurrency();
@Nullable DeveloperPayload getDeveloperPayload();
boolean isSandbox();
}