Skip to main content

6.0.0

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

tip

Сценарий работы с платежами описан в гайде. Изучите его перед началом работы.

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

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

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

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

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

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

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


flutter pub add flutter_rustore_billing

Эта команда добавит строчку в файл pubspec.yaml.


dependencies: flutter_rustore_billing: ^6.0.0

Для корректной работы оплаты через сторонние приложения (СБП, SberPay и др.) необходимо правильно реализовать обработку deeplink. Укажите в AndroidManifest.xml intent-filter с scheme вашего проекта (см. ниже).

AndroidManifest.xml
<activity
android:name=".sample.MainActivity">
<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, её можно изменить на другую.

Эта схема должна совпадать со схемой deeplink, указываемой при инициализации библиотеки billing-клиента.

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

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

Для инициализации вызовите метод RustoreBillingClient.initialize().
RustoreBillingClient.initialize(
"123456", //consolApplicationId
"yourappscheme://iamback", //deeplinkScheme
).then((value) {
print( "initialize success: $value" );
}, onError: (err) {
print( "initialize err: $err" );});
  • consoleApplicationId — код приложения из консоли разработчика RuStore (пример: https://console.rustore.ru/apps/123456).

    Чтобы получить ID приложения, скопируйте цифры из URL-адреса страницы приложения в RuStore Консоли после apps/.

note

ApplicationId, указанный в build.gradle, должен совпадать с applicationId APK-файла, который вы публиковали в Консоли RuStore.

  • deeplinkScheme — схема deeplink, необходимая для возврата в ваше приложение после оплаты через стороннее приложение (например, SberPay или СБП). SDK генерирует свой хост к данной схеме.
note
Схема deeplink, передаваемая в deeplinkScheme, должна совпадать со схемой, указанной в AndroidManifest.xml (подробнее см. Обработка deeplink).

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

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

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

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

Для проверки доступности платежей используйте метод RustoreBillingClient.available().Если все указанные выше условия выполняются, возвращается ture.

RustoreBillingClient.available().then((value) { 
print("available success $value");
}, onError: (err) {
print("available err: $err");
});

Работа с SDK

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

Для получения списка продуктов используйте метод RustoreBillingClient.products(ids).

RustoreBillingClient.products(ids).then((response) {
for ( final product in response.products) {
print(product?.productId);
}
}, onError: (err) {
print("products err: $err");
});

ids: List<String?> — список идентификаторов продуктов. В нём не должно быть более 100 позиций.

Метод возвращает ProductsResponse

class ProductsResponse {
int code;
String? errorMessage;
String? errorDescription;
String? traceId;
List<Product?> products;
List<DigitalShopGeneralError?> errors;
}
  • code — код ответа.
  • errorMessage — сообщение об ошибке для пользователя.
  • errorDescription — расшифровка сообщения об ошибке.
  • traceId — идентификатор ошибки.
  • errors — список ошибок для запрошенных продуктов.
  • products — список продуктов.

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

class DigitalShopGeneralError {
String? name;
int ? code;
String? description
}
  • name – имя ошибки.
  • code — код ошибки.
  • description – описание ошибки.

Структура продукта Product

class Product {
String productId;
String? productType;
String productStatus;
String? priceLabel;
int ? price;
String? currency;
String? language;
String? title;
String? description;
String? imageUrl;
String? promoImageUrl;
Subscription? subscription;
}
  • productId — идентификатор продукта.
  • productType — тип продукта.
  • productStatus — статус продукта.
  • priceLable — отформатированная цена товара, включая валютный знак на языке language.
  • price — цена в минимальных единицах (в копейках).
  • currency — код валюты ISO 4217.
  • language — язык, указанный с помощью BCP 47 кодирования.
  • title — название продукта на языке language.
  • description — описание на языке language.
  • imageUrl — ссылка на картинку.
  • promoImageUrl — ссылка на промокартинку.
  • subscription — описание подписки, возвращается только для продуктов с типом subscription.

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

class Subscription {
SubscriptionPeriod? subscriptionPeriod;
SubscriptionPeriod? freeTrialPeriod;
SubscriptionPeriod? gracePeriod;
String? introductoryPrice;
String? introductoryPriceAmount;
SubscriptionPeriod? introductoryPricePeriod;
}
  • subscriptionPeriod — период подписки.
  • freeTrialPeriod — пробный период подписки.
  • gracePeriod — льготный период подписки.
  • introductoryPrice — отформатированная вступительная цена подписки, включая знак валюты, на языке product:language.
  • introductoryPriceAmount — вступительная цена в минимальных единицах валюты (в копейках).
  • introductoryPricePeriod — расчётный период вступительной цены.

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

class SubscriptionPeriod {
int years;
int months;
int days;
}
  • years — количество лет.
  • months — количество месяцев.
  • days — количество дней.

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

Для вызова покупки продукта используйте метод RustoreBillingClient.purchase(id).

RustoreBillingClient.purchase(id).then((response) {
print("purchase success: $response");
}, onError: (err) {
print("purchase err: $err");
});

id — идентификатор продукта

Структура результата покупки PaymentResult

class PaymentResult {
SuccessInvoice? successInvoice;
InvalidInvoice? invalidInvoice;
SuccessPurchase? successPurchase;
InvalidPurchase? invalidPurchase;
}

Структура SuccessInvoice

class SuccessInvoice {
String invoiceId;
String finishCode;
}

Структура InvalidInvoice

class InvalidInvoice {
String? invoiceId;
}

Структура SuccessPurchase

class SuccessPurchase {
String finishCode;
String? orderId;
String purchaseId;
String productId;
String? invoiceId;
String? subscriptionToken;
bool? sandbox;
}

Структура InvalidPurchase

class InvalidPurchase {
String? purchaseId;
String? invoiceId;
String? orderId;
int? quantity;
String? productId;
int? errorCode;
bool? sandbox;
}
  • SuccessInvoice — платежи завершились с результатом.
  • InvalidInvoice — платежи завершились без указания номера счёта. Вероятно, они были запущены с некорректным номером счёта (пустая строка, например).
  • SuccessPurchase — результат успешного завершения покупки цифрового товара.
  • InvalidPurchase — при оплате цифрового товара платежи завершились с ошибкой.

Возможные статусы, которые может содержать finishCode

  • SUCCESSFUL_PAYMENT — успешная оплата.
  • CLOSED_BY_USER — отменено пользователем.
  • UNHANDLED_FORM_ERROR — неизвестная ошибка.
  • PAYMENT_TIMEOUT — ошибка оплаты по таймауту.
  • DECLINED_BY_SERVER — отклонено сервером.
  • RESULT_UNKNOWN — неизвестный статус оплаты.

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

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

Тип/СтатусINVOICE_CREATEDCONFIRMEDPAIDPAUSED
consumable++
non-consumable++
subscription+++
note

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

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

RustoreBillingClient.purchases().then((response) {
for ( final product in response.purchases) {
print(product?.purchaseId);
}
}, onError: (err) {
print( "purchases err: $err" );
});

Метод возвращает PurchasesResponse (см. ниже).

class PurchasesResponse {
int code;
String? errorMessage;
String? errorDescription;
String? traceId;
List<Purchase?> purchases;
List<DigitalShopGeneralError?> errors;
}
  • code — код ответа.
  • errorMessage — сообщение об ошибке для пользователя.
  • errorDescription — расшифровка сообщения об ошибке.
  • errors — список ошибок для запрошенных продуктов.
  • purchases — список запрошенных покупок.

Структура ошибки DigitalShopGeneralError (см. ниже).

class DigitalShopGeneralError {
String? name;
int ? code;
String? description;
}
  • name – имя ошибки.
  • code — код ошибки.
  • description – описание ошибки.
class Purchase {
String? purchaseId;
String? productId;
String? productType;
String? language;
String? purchaseTime;
String? orderId;
String? amountLabel;
int? amount;
String? currency;
int? quantity;
String? purchaseState;
String? developerPayload;
String? invoiceId;
String? subscriptionToken;
}

Структура покупки Purchase (см. ниже).

  • purchaseId — идентификатор покупки.
  • productId — идентификатор продукта.
  • description — описание на языке language.
  • language — язык, указанный с помощью BCP 47 кодирования.
  • purchaseTime — время покупки.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (UUID).
  • amountLable — отформатированная цена покупки, включая валютный знак на языке language.
  • amount — цена в минимальных единицах валюты.
  • currency — код валюты ISO 4217.
  • quantity — количество продукта.
  • purchaseState — состояние покупки.
  • developerPayload — указанная разработчиком строка, содержащая дополнительную информацию о заказе.

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

Для получения информации о покупке, используйте метод purchaseInfo.
RustoreBillingClient.purchaseInfo(purchaseId).then((purchase) {
print(purchase);
}, onError: (err) {
print("Error getPurchaseInfo: $err");
});

Структура покупки Purchase (см. ниже).

class Purchase {
String? purchaseId;
String? productId;
String? productType;
String? language;
String? purchaseTime;
String? orderId;
String? amountLabel;
int? amount;
String? currency;
int? quantity;
String? purchaseState;
String? developerPayload;
String? invoiceId;
String? subscriptionToken;
}
  • purchaseId — идентификатор покупки.
  • productId — идентификатор продукта.
  • description — описание на языке language.
  • language — язык, указанный с помощью BCP 47 кодирования.
  • purchaseTime — время покупки.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (UUID).
  • amountLable — отформатированная цена покупки, включая валютный знак на языке language.
  • amount — цена в минимальных единицах валюты.
  • currency — код валюты ISO 4217.
  • quantity — количество продукта.
  • purchaseState — состояние покупки.
  • developerPayload — указанная разработчиком строка, содержащая дополнительную информацию о заказе.

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

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

img

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

img

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

img

Подтверждение покупки

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

RuStore содержит продукты следующих типов.

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

Подтверждения требуют только продукты типа CONSUMABLE, если они находятся в состоянии PurchaseState.PAID.

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

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

RustoreBillingClient.confirm(id).then((response) {
print( "confirm success: $response" );
}, onError: (err) {
print( "confirm err: $err" );
});
  • id — идентификатор покупки.

Метод возвращает ConfirmPurchaseResponse (см. ниже).

class ConfirmPurchaseResponse {
int code;
String? errorMessage;
String? errorDescription;
String? traceId;
List<DigitalShopGeneralError?> errors;
}
  • code — код ответа.
  • errorMessage — сообщение об ошибке для пользователя.
  • errorDescription — расшифровка сообщения об ошибке.
  • traceId — идентификатор ошибки.
  • errors — список ошибок для запрошенных продуктов.

Структура ошибки DigitalShopGeneralError (см. ниже).

class DigitalShopGeneralError {
String? name;
int ? code;
String? description;
}
  • name – имя ошибки.
  • code — код ошибки.
  • description – описание ошибки.

Валидация покупок на сервере

Если вам необходимо произвести валидацию успешной покупки на сервере методами API RuStore, вы можете использовать subscriptionToken в PurchaseResult, возвращаемой purchaseProduct при успешной покупке продукта.

SubscriptionToken состоит из invoiceId покупки и userId, записанных через точку: $invoiceId.$userId.

Также можно получить subscriptionToken в сущности Purchase. Сущность Purchase можно получить, используя метод purchases().

Ведение журнала событий

Логирование включено по умолчанию внутри flutter sdk. Логи вы можете смотреть по тегу RuStoreFlutterBillingPlugin.

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

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

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