2.2.1
RuStore позволяет интегрировать платежи в мобильное приложение.
Пример реализации
Ознакомьтесь с приложением-примером, чтобы узнать, как правильно интегрировать SDK платежей.
Условия работы платежей
- На устройстве пользователя установлена актуальная версия RuStore.
- Пользователь авторизован в RuStore.
- Пользователь и приложение не должны быть заблокированы в RuStore.
- Для приложения включена возможность покупок в Консоли RuStore.
Сервис имеет некоторые ограничения на работу за пределами России.
Подготовка к работе
Для подключения скачайте RuStore Billing SDK и импортируйте его в проект (Assets > Import Package > Custom Package). Зависимости подключаются автоматически с помощью External Dependency Manager (включен в SDK).
Если вы используете операционную систему macOS, измените настройки утилиты архивации. В настройках Archive Utility снимите флажок Keep expanding if possible. В противном случае архив проекта будет скачан некорректно.
Также вы можете склонировать код с помощью Git.
Для корректной обработки зависимостей SDK установите следующие настройки.
- Edit > Project Settings > Player Settings > Publishing Settings, включите Custom Main Gradle Template и Custom Gradle Properties Template.
- Assets > External Dependencies Manager > Android Resolver > Settings, включите Use Jetifier, Patch
mainTemplate.gradle
, PatchgradleTemplate.properties
.
После настройки обязательно сделать Assets > External Dependencies Manager > Android Resolver > Force Resolve.
Minimum API level должен быть установлен не ниже 24. Минификация приложения (ProGuard/R8) в данный момент не поддерживается, необходимо её отключить в настройках проекта (File > Build Settings > Player Settings > Publishing Settings > Minify).
Обработка deeplink
Для корректной работы оплаты через сторонние приложения (СБП, SberPay и др.) необходимо правильно реализовать обработку deeplink. Укажите в AndroidManifest.xml
intent-filter
с scheme
вашего проекта (см. ниже).
<activity
android:name="ru.rustore.unitysdk.RuStoreUnityActivity" android:theme ="@style/UnityThemeSelector" android:exported ="true">
<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>
Здесь: yourappscheme
— схема вашего deeplink, её можно изменить на другую.
Далее расширьте класс UnityPlayerActivity
и добавьте обработку входящего intent
в onNewIntent
.
package ru.rustore.unitysdk;import android.os.Bundle;import android.content.Intent;import ru.rustore.unitysdk.billingclient.RuStoreUnityBillingClient;import com.unity3d.player.UnityPlayerActivity;public class RuStoreUnityActivity extends UnityPlayerActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
if (savedInstanceState == null ) {
RuStoreUnityBillingClient.onNewIntent(getIntent());
}
}
@Override protected void onNewIntent(Intent intent) {
super .onNewIntent(intent);
RuStoreUnityBillingClient.onNewIntent(intent);
}}
Разместите Java-файл с кодом расширения UnityPlayerActivity
в папке проекта Assets
. Если у вас уже есть своё расширение UnityPlayerActivity
, перенесите в него код функций onCreate
и onNewIntent
.
Инициализация
Перед вызовом методов библиотеки необходимо выполнить её инициализацию.
Выберите в меню редактора пункт Window > RuStoreSDK > Settings > Billing Client.
RuStoreBillingClient.Instance.Init();
Если требуется инициализация с другими настройками, есть возможность передать их непосредственно из кода.
var config = new RuStoreBillingClientConfig() {
consoleApplicationId = "11111" ,
deeplinkPrefix = "yourappscheme" ,
allowNativeErrorHandling = true,
enableLogs = true
};
RuStoreBillingClient.Instance.Init(config);
-
consoleApplicationId
— код приложения из консоли разработчика RuStore (пример:https://console.rustore.ru/apps/123456
). -
deeplinkPrefix
— URL-адрес для использования deeplink. В качестве названия может быть использовано любое уникальное имя (пример: yourappscheme). -
allowNativeErrorHandling
— разрешить обработку ошибок в нативном SDK (см. подробнее в разделе Обработка ошибок). -
enableLogs
— включить ведение журнала событий.
deeplinkPrefix
, должна совпадать со схемой, указанной в AndroidManifest.xml
(подробнее см. Обработка deeplink).Если вам нужно проверить факт инициализации библиотеки, используйте свойство RuStoreBillingClient.Instance.isInitialized
— его значение true
, если библиотека инициализирована, и false
, если Init
еще не был вызван.
var isInitialized = RuStoreBillingClient.Instance.IsIninialized;
Как работают платежи
Проверка доступности работы с платежами
Для проверки доступности платежей используйте методCheckPurchasesAvailability
.
Если все указанные выше условия выполняются, возвращается FeatureAvailabilityResult.isAvailable == true
.
В противном случае возвращается FeatureAvailabilityResult.isAvailable == false
, где FeatureAvailabilityResult.cause
— это ошибка о невыполненном условии.
Все возможные ошибки RuStoreException
описаны в разделе Обработка ошибок. Прочие ошибки возвращаются в onFailure
.
RuStoreBillingClient.Instance.CheckPurchasesAvailability(
onFailure: (error) => {
// Process error
},
onSuccess: (response) => {
if (response.isAvailable) {
// Process purchases available
} else {
// Process purchases unavailable
}
});
Работа с SDK
Получение списка продуктов
Для получения списка пр одуктов используйте метод GetProducts
.
RuStoreBillingClient.Instance.GetProducts(productIds,
onFailure: (error) => {
// Process error
},
onSuccess: (response) => {
// Process response
});
string[] productIds
— список идентификаторов продуктов.
Метод возвращает список продуктов List<Product>
.
Структура продукта
public class Product {
public enum ProductStatus {
ACTIVE,
INACTIVE
}
public enum ProductType {
NON_CONSUMABLE,
CONSUMABLE,
SUBSCRIPTION
}
public string productId;
public ProductType productType;
public ProductStatus productStatus;
public string priceLabel;
public int price;
public string currency;
public string language;
public string title;
public string description;
public string imageUrl;
public string promoImageUrl;
public ProductSubscription subscription;
}
productId
— идентификатор продукта.productType
— тип продукта.productStatus
— статус продукта.priceLable
— отформатированная цена товара, включая валютный знак на языкеlanguage
.price
— цена в минимальных единицах (в копейках).currency
— код валюты ISO 4217.language
— язык, указанный с помощью BCP 47 кодирования.title
— название продукта на языкеlanguage
.description
— описание на языкеlanguage
.imageUrl
— ссылка на картинку.promoImageUrl
— ссылка на промокартинку.subscription
— описание подписки, возвращается только для продуктов с типомsubscription
.
Структура подписки
public class ProductSubscription {
public SubscriptionPeriod subscriptionPeriod;
public SubscriptionPeriod freeTrialPeriod;
public SubscriptionPeriod gracePeriod;
public string introductoryPrice;
public string introductoryPriceAmount;
public SubscriptionPeriod introductoryPricePeriod;
}
subscriptionPeriod
— период подписки.freeTrialPeriod
— пробный период подписки.gracePeriod
— льготный период подписки.introductoryPrice
— отформатированная вступительная цена подписки, включая знак валюты, на языкеproduct:language
.introductoryPriceAmount
— вступительная цена в минимальных единицах валюты (в копейках).introductoryPricePeriod
— расчётный период вступительной цены.
Структура периода подписки
public class SubscriptionPeriod {
public int years;
public int months;
public int days;
}
years
— количество лет.months
— количество месяцев.days
— количество дней.
Получение списка покупок
Метод возвращает только покупки со статусами из таблицы ниже.
Тип/Статус | INVOICE_CREATED | CONFIRMED | PAID |
---|---|---|---|
CONSUMABLE | + | + | |
NON-CONSUMABLE | + | + | |
SUBSCRIPTION | + | + |
Метод возвращает незавершённые состояния покупки и покупки потребляемых товаров, требующих обработки. Помимо этого, он показывает подтверждённые покупки для подписок и непотребляемых товаров — тех, которые не льзя купить повторно.
Для получения списка покупок пользователя используйте метод GetPurchases
.
RuStoreBillingClient.Instance.GetPurchases(
onFailure: (error) => {
// Process error
},
onSuccess: (response) => {
// Process response
});
Метод возвращает List<Purchase> response
— список покупок.
Структура покупки
public class Purchase {
public enum PurchaseState
{
CREATED,
INVOICE_CREATED,
CONFIRMED,
PAID,
CANCELLED,
CONSUMED,
CLOSED
}
public string purchaseId;
public string productId;
public string description;
public string invoiceId;
public string language;
public DateTime purchaseTime;
public string orderId;
public string amountLabel;
public int amount;
public string currency;
public int quantity;
public PurchaseState purchaseState;
public string developerPayload;
public string subscriptionToken;
}
purchaseId
— идентификатор покупки.productId
— идентификатор продукта.description
— описание на языкеlanguage
.invoiceId
— идентификатор счёта.language
— язык, указанный с помощью BCP 47 кодирования.purchaseTime
— время покупки.orderId
— уникальный идентификатор оплаты, сформированный приложением (UUID).amountLable
— отформатированная цена покупки, включая валютный знак на языкеlanguage
.amount
— цена в минимальных единицах валюты.currency
— код валюты ISO 4217.quantity
— количество продукта.purchaseState
— состояние покупки:developerPayload
— указанная разработчиком строка, содержащая дополнительную информацию о заказе.subscriptionToken
— токен для валидации покупки на сервере.
Подтверждение покупки
Продукты, требующие подтверждения
RuStore содержит продукты следующих типов.
SUBSCRIPTION
— подписка (можно купить на период времени, например: подписка в стриминговом сервисе).NON_CONSUMABLE
— непотребляемый (можно купить один раз, например: отключение рекламы в приложении).CONSUMABLE
— потребляемый (можно купить много раз, например: кристаллы в приложении).
Подтверждения требуют только продукты типа CONSUMABLE
, если они находятся в состоянии PurchaseState.PAID
.
Вызов метода подтверждения
Для подтверждения покупки используйте методconfirmPurchase
. Запрос на подтверждение покупки должен сопровождаться выдачей товара. После вызова подтверждения покупка перейдёт в статус CONSUMED
.
RuStoreBillingClient.Instance.ConfirmPurchase(
purchaseId: "purchaseId" ,
onFailure: (error) => {
// Process error
},
onSuccess: () => {
// Process success
}
);
purchaseId
— идентификатор покупки.
Отмена покупки
Для отмены покупки используйте метод DeletePurchase
.
RuStoreBillingClient.Instance.DeletePurchase(
purchaseId: "purchaseId" ,
onFailure: (error) => {
// Process error
},
onSuccess: () => {
// Process success
}
);
purchaseId
— идентификатор покупки.
Используйте этот метод, если у вас есть логика, завязанная на удалении покупки. Покупка отменяется автоматически через таймаут в 20 минут, либо при повторной покупке от того же клиента.
Обработка ошибок
Возможные ошибки
RuStoreNotInstalledException
— на устройстве пользователя не установлен RuStore;RuStoreOutdatedException
— версия RuStore, установленная на устройстве пользователя, не поддерживает платежи;RuStoreUserUnauthorizedException
— пользователь не авторизован в RuStore;RuStoreRequestLimitReached
— с момента последнего отображения процесса прошло слишком мало времени;RuStoreReviewExists
— этот пользователь уже оценил ваше приложение;RuStoreInvalidReviewInfo
— проблемы сReviewInfo
;RuStoreException
— базовая ошибка RuStore, от которой наследуются остальные ошибки.
Возникающие ошибки передаются в обработчик методов SDK onFailure
.
Структура ошибки
public class RuStoreError {
public string name;
public string description;
}
name
– имя ошибки.description
– описание ошибки.
Автоматическая обработка ошибок
При вызове методаPurchaseProduct
ошибки обрабатываются автома тически.
Если при инициализации SDK был передан параметр allowNativeErrorHandling == true
, при возникновении ошибки, кроме вызова соответствующего обработчика Failure
, пользователю будет показан диалог с ошибкой.
public fun RuStoreException.resolveForBilling(context: Context)
Изменить это поведение после инициализации можно установкой свойства AllowNativeErrorHandling
.
RuStoreBillingClient.Instance.AllowNativeErrorHandling = false ;