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

9.0.1

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

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

  • Если вы переходите на Pay SDK с billingClient SDK, ознакомьтесь с инструкцией по переходу. Подробности о Pay SDK можно узнать тут.

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

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

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

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

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

  1. Скопируйте проекты плагина и приложения-примера из официального репозитория RuStore на GitFlic.
  2. Скопируйте содержимое папки unreal_example/Plugins в папку Pluginsвнутри своего проекта. Перезапустите Unreal Engine.
  3. В списке плагинов (Edit > Plugins > Mobile) отметьте плагины RuStorePay и RuStoreCore.
  4. В файле YourProject.Build.cs в списке PublicDependencyModuleNames подключите модули RuStoreCore и RuStorePay.
  5. В настройках проекта (Edit > Project Settings > Android) установите параметры:
    • Minimum SDK Version — не ниже 24;
    • Target SDK Version — не ниже 31.

Настройка Unreal Engine

Для версий Unreal Engine младше 5.4 должно быть выполнено обновление gradle и gradle-wrapper.

  1. Перейдите в корневую директорию установки Unreal Engine (например: C:\Program Files\Epic Games\UE_4.26).
  2. В файле \Engine\Build\Android\Java\gradle\build.gradle задайте версию пакета com.android.tools.build:gradle не ниже 4.2.2.
  3. В файле \Engine\Build\Android\Java\gradle\gradle\wrapper\gradle-wrapper.properties задайте версию пакета gradle не ниже 7.5-all.
build.gradle
buildscript {
repositories {
google()
mavenCentral()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.2'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
apply from: 'buildscriptAdditions.gradle', to: buildscript
}

apply from: 'baseBuildAdditions.gradle'

allprojects {
repositories {
google()
mavenCentral()
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

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

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

Вызов метода GetIsIninialized
URuStorePayClient::Instance()->Init();
img

Для работы SDK в вашем AndroidManifest.xml плагин RuStorePay через файл RuStorePay_UPL_Android.xml добавит в манифест приложения данные console_app_id_value, internal_config_key и sdk_pay_scheme_value. Все значения располагаются внутри тэга <application>.

<application>
...

<meta-data android:name="console_app_id_value" android:value="@string/rustore_PayClientSettings_consoleApplicationId" />
<meta-data android:name="internal_config_key" android:value="@string/rustore_PayClientSettings_internalConfigKey" />
<meta-data android:name="sdk_pay_scheme_value" android:value="@string/rustore_PayClientSettings_deeplinkScheme" />

</application>
  • console_app_id_key — идентификатор приложения из RuStore консоли.

  • internal_config_key — всегда имеет значение unreal.
  • sdk_pay_scheme_value — схема deeplink.
Где в RuStore Консоль отображаются идентификаторы приложений?
  1. Перейдите на вкладку Приложения и выберите нужное приложение.
  2. Скопируйте идентификатор из URL-адреса страницы приложения — это набор цифр между apps/ и /versions. Например, для URL-адреса https://console.rustore.ru/apps/123456/versions ID приложения — 123456.

Важно

Package Name приложения, указанный в Edit ➝ Project Settings... ➝ Player ➝ Android ➝ Other Settings ➝ Package Name, должен совпадать с Package Name APK-файла, который вы публиковали в системе RuStore Консоль.

Подпись keystore должна совпадать с подписью, которой было подписано приложение, опубликованное в системе RuStore Консоль. Убедитесь, что используемый buildType (пр. debug) использует такую же подпись, что и опубликованное приложение (пр. release).

Все значения должны быть заданы в файле ресурсов, например: rustore_pay_values.xml.

rustore_pay_values.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="rustore_PayClientSettings_consoleApplicationId">198332</string>
<string name="rustore_PayClientSettings_internalConfigKey" translatable="false">unreal</string>
<string name="rustore_PayClientSettings_deeplinkScheme" translatable="false">yourappscheme</string>
</resources>

Файл ресурсов может быть включен в проект через UPL-файл вашего проекта, в следующем примере копирование файла rustore_pay_values.xml будет выполняться из директории Source/YOUUR_PROJECT_NAME.

rustore_pay_values.xml
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:android="http://schemas.android.com/apk/res/android">

<resourceCopies>
<copyFile src="$S(PluginDir)/rustore_pay_values.xml" dst="$S(BuildDir)/res/values/rustore_pay_values.xml" />
</resourceCopies>

</root>

Деинициализация

Вызов метода Init для URuStorePayClient привязывает объекты к корню сцены. Если дальнейшая работа с объектами больше не планируется, для освобождения памяти необходимо выполнить метод Dispose. Вызов Dispose отвяжет объект от корня и безопасно завершит все отправленные запросы.

Вызов метода Dispose
bool isInitialized = URuStorePayClient::Instance()->Dispose();
img

Проверка инициализации

Если вам нужно проверить факт инициализации библиотеки, используйте метод GetIsInitialized. Метод вернет true, если библиотека инициализирована, и false, если Init еще не был вызван.

Вызов метода GetIsIninialized
bool isInitialized = URuStorePayClient::Instance()->GetIsIninialized();
img

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

Плагин RuStore Pay автоматически добавит в AndroidManifest.xml дополнительную activity с необходимым intent-filter (см. ниже). Изменить это поведение можно в файле RuStorePay_UPL_Android.xml.

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<activity android:name="com.Plugins.RuStorePay.RuStorePayIntentFilterActivity" android:exported="true" android:launchMode="singleTask">
<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="@string/rustore_PayClientSettings_deeplinkScheme" />
</intent-filter>
</activity>
<meta-data android:name="sdk_pay_scheme_value" android:value="@string/rustore_PayClientSettings_deeplinkScheme" />

Работа с SDK

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

Для проверки доступности платежей, вызовите метод GetPurchaseAvailability. При его вызове проверяются следующие условия.

  • У компании подключена монетизация через консоль разработчика RuStore.
  • Приложение не должно быть заблокировано в RuStore.
  • Пользователь не должен быть заблокирован в RuStore.
Если все указанные выше условия выполняются, возвращается PurchaseAvailabilityResult.Available.

В противном случае возвращается PurchaseAvailabilityResult.Unavailable(val cause: Throwable), где cause — это ошибка о невыполненном условии. Для проверки причины возвращения такого результата нужно проверить тип ошибки на RuStoreException (данные ошибки описаны в разделе Обработка ошибок).

Вызов метода GetPurchaseAvailability
long requestId = URuStorePayClient::Instance()->GetPurchaseAvailability(
[](long requestId, TSharedPtr<FURuStorePayPurchaseAvailabilityResult, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

Проверка статуса авторизации пользователя

Для проверки статуса авторизации пользователя, вызовите метод GetUserAuthorizationStatus. Результатом выполнения метода является значение перечисления UserAuthorizationStatus. Возможно только 2 значения:

  • AUTHORIZED — пользователь авторизован в RuStore.
  • UNAUTHORIZED — пользователь неавторизован в RuStore. Данное значение также вернется если у пользователя нет установленного МП RuStore на девайсе.
Вызов метода GetUserAuthorizationStatus
RuStorePayClient.Instance.GetUserAuthorizationStatus(
onSuccess: (result) => {
if (result == UserAuthorizationStatus.AUTHORIZED) {
// Process result
}
});
onFailure: (error) => {
// Process error
},
img

Проверка установки приложения RuStore

Чтобы проверить установлен ли на устройстве пользователя RuStore необходимо вызвать метод IsRuStoreInstalled.

bool bIsRuStoreInstalled = URuStorePayClient::Instance()->IsRuStoreInstalled();
img
  • true – RuStore установлен.

  • false – RuStore не установлен.

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

Для получения продуктов, добавленных в ваше приложение через RuStore консоль, необходимо использовать метод GetProducts.

Вызов метода GetProducts
TArray<URuStorePayProductId*> productIds;

long requestId = URuStorePayClient::Instance()->GetProducts(
productsId,
[](long requestId, TSharedPtr<TArray<FURuStorePayProduct>, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

TArray<URuStorePayProductId*> productIds — список идентификаторов продуктов (задаются при создании продукта в консоли разработчика). Список продуктов имеет ограничение в размере 1000 элементов.

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

Метод возвращает список продуктов. Ниже представлена модель продукта.

Структура продукта
USTRUCT(BlueprintType)
struct FURuStorePayProduct
{
GENERATED_USTRUCT_BODY()

UPROPERTY(BlueprintReadOnly)
URuStorePayAmountLabel* amountLabel;

UPROPERTY(BlueprintReadOnly)
URuStorePayCurrency* currency;

UPROPERTY(BlueprintReadOnly)
URuStorePayDescription* description; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayUrl* imageUrl;

UPROPERTY(BlueprintReadOnly)
URuStorePayPrice* price; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayProductId* productId;

UPROPERTY(BlueprintReadOnly)
URuStorePayTitle* title;

UPROPERTY(BlueprintReadOnly)
EURuStorePayProductType type;

FURuStorePayProduct()
{
amountLabel = NewObject<URuStorePayAmountLabel>();
currency = NewObject<URuStorePayCurrency>();
description = nullptr;
imageUrl = NewObject<URuStorePayUrl>();
price = nullptr;
productId = NewObject<URuStorePayProductId>();
title = NewObject<URuStorePayTitle>();
type = static_cast<EURuStorePayProductType>(0);
}
};
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • type — тип продукта. CONSUMABLE/NON-CONSUMABE (потребляемый/непотребляемый).
  • amountLabel — отформатированная цена покупки, включая валютный знак.
  • price — цена в минимальных единицах (в копейках).
  • currency — код валюты ISO 4217.
  • title — название продукта на языке language.
  • description — описание на языке language.
  • imageUrl — ссылка на картинку.

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

Пояснения по работе с одностадийными и двухстадийными оплатами
  • При использовании одностадийного платежа покупка не требует подтверждения, денежные средства сразу списываются со счёта покупателя, а с разработчика удерживается комиссия. В таком случае, если требуется вернуть денежные средства клиенту (например, по какой-то причине нет возможности поставить продукт), возможен только возврат средств через RuStore Консоль, денежные средства возвращаются покупателю через несколько дней. Возвращается полная стоимость покупки, при этом удержанная комиссия разработчику не возмещается.
  • В случае использования двухстадийного платежа сначала производится холдирование средств на счете покупателя. Комиссия в этом случае не удерживается. После холдирования покупка требует подтверждения или отмены. Комиссия с разработчика удерживается при подтверждении покупки. Отмена покупки означает снятие холда - денежные средства мгновенно снова доступны покупателю.
Важно

Двустадийная оплата доступна только для определенного набора способов оплаты (на текущий момент — только для карт). Технологии СБП не поддерживают двухстадийную оплату. Если выбран способ оплаты, который не поддерживает холдирование, то покупка будет запущена по сценарию с одной стадией.

Оплата с выбором типа покупки

Для вызова покупки продукта с выбором стадийности оплаты используйте метод Purchase:

Вызов метода покупки продукта
FURuStorePayProductPurchaseParams productPurchaseParams;
EURuStorePayPreferredPurchaseType preferredPurchaseType;

...

long requestId = URuStorePayClient::Instance()->Purchase(
productPurchaseParams,
preferredPurchaseType,
[](long requestId, TSharedPtr<FURuStorePayProductPurchaseResult, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • quantity — количество продукта. Необязательный параметр со стандартным значением 1. Применим только к покупке потребляемых товаров.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки. Максимальная длина 250 символов.
  • appUserId — внутренний ID пользователя в вашем приложении (опциональный параметр). Строка с максимальной длиной в 128 символов.
    подсказка

    Например, данный параметр может использоваться для выявления случаев мошенничества в вашем приложении, что позволит повысить его безопасность.

  • appUserEmail - это необязательный параметр, позволяющий задать адрес электронной почты пользователя в вашем приложении. Если адрес электронной почты покупателя был указан при регистрации в приложении, его можно передать для автоматического заполнения поля email при отправке чека — как для платежей вне RuStore, так и для случаев, когда пользователь не авторизован в RuStore. Это избавляет пользователя от необходимости вручную вводить email, сокращает путь до покупки и способствует повышению конверсии.
  • preferredPurchaseType — желаемый тип покупки: одностадийная (ONE_STEP) или двухстадийная (TWO_STEP).
Важно

Данный метод по умолчанию запускается по одностадийному сценарию оплаты (preferredPurchaseType = PreferredPurchaseType.ONE_STEP), т.е. без холдирования средств.

Для двухстадийной оплаты нужно указать preferredPurchaseType = PreferredPurchaseType.TWO_STEP. Двухстадийная оплата (т.е. оплата с холдированием средств) для данного метода не гарантирована и напрямую зависит от того, какой способ оплаты (карта, СПБ и др.) выбрал пользователь.

При запуске данного метода (с предпочитаемым preferredPurchaseType = twoStep), до тех пор пока пользователь не выберет способ оплаты, стадийность покупки будет UNDEFINED. Учитывайте данное поведение при обработке результатов отмены (ProductPurchaseCancelled) или ошибки (ProductPurchaseException) покупки.

Двустадийна оплата (с холдированием средств)

Вызов метода покупки продукта
FURuStorePayProductPurchaseParams productPurchaseParams;

...

long requestId = URuStorePushClient::Instance()->PurchaseTwoStep(
productPurchaseParams,
[](long requestId, TSharedPtr<FURuStorePayProductPurchaseResult, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

Структура параметров покупки:

Структура параметров покупки
USTRUCT(BlueprintType)
struct FURuStorePayProductPurchaseParams
{
GENERATED_USTRUCT_BODY()

UPROPERTY(BlueprintReadOnly)
URuStorePayProductId* productId;

URuStorePayAppUserEmail* appUserEmail; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayAppUserId* appUserId; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayDeveloperPayload* developerPayload; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayOrderId* orderId; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayQuantity* quantity; // nullable

FURuStorePayProductPurchaseParams()
{
productId = NewObject<URuStorePayProductId>();
appUserEmail = nullptr;
appUserId = nullptr;
developerPayload = nullptr;
orderId = nullptr;
quantity = nullptr;
}
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • quantity — количество продукта. Необязательный параметр со стандартным значением 1. Применим только к покупке потребляемых товаров.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки. Максимальная длина 250 символов.
  • appUserId — внутренний ID пользователя в вашем приложении (опциональный параметр). Строка с максимальной длиной в 128 символов.
    подсказка

    Например, данный параметр может использоваться для выявления случаев мошенничества в вашем приложении, что позволит повысить его безопасность.

  • appUserEmail — это необязательный параметр, позволяющий задать адрес электронной почты пользователя в вашем приложении. Если адрес электронной почты покупателя был указан при регистрации в приложении, его можно передать для автоматического заполнения поля email при отправке чека — как для платежей вне RuStore, так и для случаев, когда пользователь не авторизован в RuStore. Это избавляет пользователя от необходимости вручную вводить email, сокращает путь до покупки и способствует повышению конверсии.

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

Структура результата покупки
USTRUCT(BlueprintType)
struct RUSTOREPAY_API FURuStorePayProductPurchaseResult
{
GENERATED_USTRUCT_BODY()

UPROPERTY(BlueprintReadOnly)
URuStorePayOrderId* orderId; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayPurchaseId* purchaseId;

UPROPERTY(BlueprintReadOnly)
URuStorePayProductId* productId;

UPROPERTY(BlueprintReadOnly)
URuStorePayInvoiceId* invoiceId;

UPROPERTY(BlueprintReadOnly)
EURuStorePayPurchaseType purchaseType;

UPROPERTY(BlueprintReadOnly)
URuStorePayQuantity* quantity;

UPROPERTY(BlueprintReadOnly)
bool sandbox;

FURuStorePayProductPurchaseResult()
{
orderId = nullptr;
purchaseId = NewObject<URuStorePayPurchaseId>(GetTransientPackage());
productId = NewObject<URuStorePayProductId>(GetTransientPackage());
invoiceId = NewObject<URuStorePayInvoiceId>(GetTransientPackage());
purchaseType = static_cast<EURuStorePayPurchaseType>(0);
quantity = NewObject<URuStorePayQuantity>(GetTransientPackage());
sandbox = false;
}
};

Обработка ошибки оплаты:

Если в процессе оплаты возникает ошибка или пользователь отменяет покупку, выполнение метода оплаты (как с выбором типа покупки, так и двустадийного метода) завершается с ошибкой:

  • ProductPurchaseCancelled — запрос на покупку отправлен, при этом пользователь закрыл «платёжную шторку» на своём устройстве, и результат оплаты неизвестен.
  • ProductPurchaseException — при отправке запроса на оплату или получения статуса оплаты возникла проблема, невозможно установить статус покупки.

Структура ошибки FURuStoreError описана в разделе Обработка ошибок.

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

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

Вызов метода получения списка покупок пользователя
long requestId = URuStorePayClient::Instance()->GetPurchases(
[](long requestId, TSharedPtr<TArray<FURuStorePayPurchase>, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

Метод поддерживает опциональную фильтрацию по типу товаров (потребляемые или непотреблямые товары) и по статусу покупки (поддерживаются статусы PAID и CONFIRMED).

Вызов метода получения списка покупок пользователя
EURuStorePayProductType productType = EURuStorePayProductType::CONSUMABLE_PRODUCT;
EURuStorePayPurchaseStatus purchaseStatus = EURuStorePayPurchaseStatus::CONFIRMED;

long requestId = URuStorePayClient::Instance()->GetPurchases(
productType,
purchaseStatus,
[](long requestId, TSharedPtr<TArray<FURuStorePayPurchase>, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

Метод возвращает список покупок в статусах CONFIRMED (для непотребляемых товаров) и PAID (для потребляемых товаров). Ниже представлена модель покупки.

Структура с информацией о покупке
USTRUCT(BlueprintType)
struct FURuStorePayPurchase
{
GENERATED_USTRUCT_BODY()

UPROPERTY(BlueprintReadOnly)
URuStorePayAmountLabel* amountLabel;

UPROPERTY(BlueprintReadOnly)
URuStorePayCurrency* currency;

UPROPERTY(BlueprintReadOnly)
URuStorePayDescription* description;

UPROPERTY(BlueprintReadOnly)
URuStorePayDeveloperPayload* developerPayload; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayInvoiceId* invoiceId;

UPROPERTY(BlueprintReadOnly)
URuStorePayOrderId* orderId; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayPrice* price;

UPROPERTY(BlueprintReadOnly)
URuStorePayProductId* productId;

UPROPERTY(BlueprintReadOnly)
EURuStorePayProductType productType;

UPROPERTY(BlueprintReadOnly)
URuStorePayPurchaseId* purchaseId;

UPROPERTY(BlueprintReadOnly)
URuStorePayDate* purchaseTime; // nullable

UPROPERTY(BlueprintReadOnly)
EURuStorePayPurchaseType purchaseType;

UPROPERTY(BlueprintReadOnly)
URuStorePayQuantity* quantity;

UPROPERTY(BlueprintReadOnly)
EURuStorePayPurchaseStatus status;

UPROPERTY(BlueprintReadOnly)
URuStorePaySubscriptionToken* subscriptionToken; // nullable

FURuStorePayPurchase()
{
amountLabel = NewObject<URuStorePayAmountLabel>(GetTransientPackage());
currency = NewObject<URuStorePayCurrency>(GetTransientPackage());
description = NewObject<URuStorePayDescription>(GetTransientPackage());
developerPayload = nullptr;
invoiceId = NewObject<URuStorePayInvoiceId>(GetTransientPackage());
orderId = nullptr;
price = NewObject<URuStorePayPrice>();
productId = NewObject<URuStorePayProductId>(GetTransientPackage());
productType = static_cast<EURuStorePayProductType>(0);
purchaseId = NewObject<URuStorePayPurchaseId>(GetTransientPackage());
purchaseTime = nullptr;
purchaseType = static_cast<EURuStorePayPurchaseType>(0);
quantity = NewObject<URuStorePayQuantity>(GetTransientPackage());
status = static_cast<EURuStorePayPurchaseStatus>(0);
subscriptionToken = nullptr;
}
};
  • amountLabel — отформатированная цена покупки, включая валютный знак.
  • currency — код валюты ISO 4217.
  • description — описание на языке language.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки
  • invoiceId — идентификатор счёта.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.
  • price — цена в минимальных единицах (в копейках).
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • productType — тип продукта.
  • purchaseId — идентификатор покупки.
  • purchaseTime — время покупки.
  • PurchaseType — тип покупки:
    • ONE_PHASE - одностадийная покупка;
    • TWO_PHASE - двухстадийная покупка;
    • UNDEFINED - стадийность не определена.
  • quantity — количество продукта. Необязательный параметр со стандартным значением 1. Применим только к покупке потребляемых товаров.
  • status — состояние покупки:
    • INVOICE_CREATED — создан счёт на оплату, покупка ожидает оплаты;
    • CANCELLED — покупка отменена покупателем;
    • PROCESSING — запущена оплата;
    • REJECTED — покупка отклонена (например, ввиду недостатка средств);
    • EXPIRED — истекло время на оплату покупки;
    • PAID — только для двухстадийной оплаты, промежуточный статус, средства на счёте покупателя захолдированы, покупка ожидает подтверждения от разработчика;
    • CONFIRMED — покупка успешно оплачена;
    • REFUNDED — запрос на возврат средств за покупку совершён успешно;
    • REVERSED — только для двухстадийной оплаты, покупка была отменена разработчиком или не было произведено подтверждение покупки в течение 6 часов, холдирование средств отменено.

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

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

Вызов метода получения списка покупок пользователя
URuStorePayPurchaseId* purchaseId = ...

long requestId = URuStorePushClient::Instance()->GetPurchase(
purchaseId,
[](long requestId, TSharedPtr<FURuStorePayPurchase, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

Метод возвращает информацию о конкретной покупке в любом статусе. Ниже представлена модель покупки.

Структура с информацией о покупке
USTRUCT(BlueprintType)
struct FURuStorePayPurchase
{
GENERATED_USTRUCT_BODY()

UPROPERTY(BlueprintReadOnly)
URuStorePayAmountLabel* amountLabel;

UPROPERTY(BlueprintReadOnly)
URuStorePayCurrency* currency;

UPROPERTY(BlueprintReadOnly)
URuStorePayDescription* description;

UPROPERTY(BlueprintReadOnly)
URuStorePayDeveloperPayload* developerPayload; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayInvoiceId* invoiceId;

UPROPERTY(BlueprintReadOnly)
URuStorePayOrderId* orderId; // nullable

UPROPERTY(BlueprintReadOnly)
URuStorePayPrice* price;

UPROPERTY(BlueprintReadOnly)
URuStorePayProductId* productId;

UPROPERTY(BlueprintReadOnly)
EURuStorePayProductType productType;

UPROPERTY(BlueprintReadOnly)
URuStorePayPurchaseId* purchaseId;

UPROPERTY(BlueprintReadOnly)
URuStorePayDate* purchaseTime; // nullable

UPROPERTY(BlueprintReadOnly)
EURuStorePayPurchaseType purchaseType;

UPROPERTY(BlueprintReadOnly)
URuStorePayQuantity* quantity;

UPROPERTY(BlueprintReadOnly)
EURuStorePayPurchaseStatus status;

FURuStorePayPurchase()
{
amountLabel = NewObject<URuStorePayAmountLabel>(GetTransientPackage());
currency = NewObject<URuStorePayCurrency>(GetTransientPackage());
description = NewObject<URuStorePayDescription>(GetTransientPackage());
developerPayload = nullptr;
invoiceId = NewObject<URuStorePayInvoiceId>(GetTransientPackage());
orderId = nullptr;
price = NewObject<URuStorePayPrice>();
productId = NewObject<URuStorePayProductId>(GetTransientPackage());
productType = static_cast<EURuStorePayProductType>(0);
purchaseId = NewObject<URuStorePayPurchaseId>(GetTransientPackage());
purchaseTime = nullptr;
purchaseType = static_cast<EURuStorePayPurchaseType>(0);
quantity = NewObject<URuStorePayQuantity>(GetTransientPackage());
status = static_cast<EURuStorePayPurchaseStatus>(0);
}
};
  • amountLabel — отформатированная цена покупки, включая валютный знак.
  • currency — код валюты ISO 4217.
  • description — описание на языке language.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки
  • invoiceId — идентификатор счёта.
  • orderId — уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.
  • price — цена в минимальных единицах (в копейках).
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • productType — тип продукта.
  • purchaseId — идентификатор покупки.
  • purchaseTime — время покупки.
  • PurchaseType — тип покупки:
    • ONE_PHASE - одностадийная покупка;
    • TWO_PHASE - двухстадийная покупка;
    • UNDEFINED - стадийность не определена.
  • quantity — количество продукта. Необязательный параметр со стандартным значением 1. Применим только к покупке потребляемых товаров.
  • status — состояние покупки:
    • INVOICE_CREATED — создан счёт на оплату, покупка ожидает оплаты;
    • CANCELLED — покупка отменена покупателем;
    • PROCESSING — запущена оплата;
    • REJECTED — покупка отклонена (например, ввиду недостатка средств);
    • EXPIRED — истекло время на оплату покупки;
    • PAID — только для двухстадийной оплаты, промежуточный статус, средства на счёте покупателя захолдированы, покупка ожидает подтверждения от разработчика;
    • CONFIRMED — покупка успешно оплачена;
    • REFUNDED — запрос на возврат средств за покупку совершён успешно;
    • REVERSED — только для двухстадийной оплаты, покупка была отменена разработчиком или не было произведено подтверждение покупки в течение 6 часов, холдирование средств отменено.

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

Статусная модель одностадийного платежа.



Статусная модель двухстадийного платежа.



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

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

Получение invoiceId из результата покупки
long requestId = URuStorePushClient::Instance()->PurchaseTwoStep(
productPurchaseParams,
[](long requestId, TSharedPtr<FURuStorePayProductPurchaseResult, ESPMode::ThreadSafe> response) {
auto type = response->GetTypeName();
if (type.Equals("FURuStorePaySuccessProductPurchaseResult")) {
auto success = *StaticCastSharedPtr<FURuStorePaySuccessProductPurchaseResult>(response);

FString invoiceId = success.invoiceId->value;
yourApi.validate(invoiceId);
}
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

Также можно получить invoiceId в модели Purchase. Модель Purchase можно получить используя метод GetPurchases или GetPurchase.

long requestId = URuStorePushClient::Instance()->GetPurchases(
[](long requestId, TSharedPtr<TArray<FURuStorePayPurchase>, ESPMode::ThreadSafe> response) {
for (const auto& item : *response) {
yourApi.validate(item.invoiceId);
}
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

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

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

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

Вызов метода подтверждения
URuStorePayPurchaseId* purchaseId = ...
URuStorePayDeveloperPayload* developerPayload = ...

long requestId = URuStoreBillingClient::Instance()->ConfirmTwoStepPurchase(
purchaseId,
developerPayload,
[](long requestId) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • purchaseId — идентификатор покупки.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при инициализации процесса покупки

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

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

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

Вызов метода CancelTwoStepPurchase
URuStorePayPurchaseId* purchaseId = ...

long requestId = URuStoreBillingClient::Instance()->CancelTwoStepPurchase(
purchaseId,
[]( long requestId) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreRuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • purchaseId — идентификатор покупки.
к сведению

Используйте метод отмены покупки с осторожностью и только в исключительных случаях, только если покупка осталась в статусе PAID, а вы не можете выдать товар пользователю. В остальных случаях не рекомендуется вручную отменять покупки, так как RuStore автоматически обрабатывает незавершённые покупки (например, таймаут в 20 минут или повторная покупка от того же клиента).

При оплате покупки через СБП или со счета мобильного телефона отмена покупки в статусе PAID не отменяет холдирование, а приводит к возврату средств (refund). При этом с разработчика удерживается комиссия, которая не возвращается.

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

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

  • RuStorePaymentNetworkException — ошибка сетевого взаимодействия SDK;
  • RuStorePaymentCommonException — общая ошибка SDK;
  • RuStorePayClientAlreadyExist — ошибка повторной инициализации SDK;
  • RuStorePayClientNotCreated — попытка обратиться к публичным интерфейсам SDK до момента её инициализации;
  • RuStorePayInvalidActivePurchase — запущен процесс оплаты неизвестного типа продукта;
  • RuStorePayInvalidConsoleAppId — не задан обязательный параметр console_application_id для инициализации SDK;
  • RuStorePaySignatureException — неверная сигнатура ответа. Возникает при попытке совершить мошеннические действия;
  • EmptyPaymentTokenException — ошибка получения платёжного токена;
  • InvalidCardBindingIdException — ошибка оплаты сохранённой картой;
  • ApplicationSchemeWasNotProvided — не указана схема для обратного диплинка;
  • ProductPurchaseException - ошибка покупки продукта. Структура модели представлена в разделе структура результата покупки;
  • ProductPurchaseCancelled - произошла отмена покупки продукта (пользователь закрыл платёжную шторку). Структура модели представлена в разделе структура результата покупки;
  • ProductPurchaseException — ошибка покупки продукта;
  • RuStoreNotInstalledException — на устройстве пользователя не установлен RuStore;
  • RuStoreOutdatedException — установленная на устройстве версия RuStore не поддерживает платежи;
  • RuStoreUserUnauthorizedException — пользователь не авторизован в RuStore;
  • RuStoreApplicationBannedException — приложение заблокировано в RuStore;
  • RuStoreUserBannedException — пользователь заблокирован в RuStore.

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

USTRUCT(BlueprintType)
struct RUSTORECORE_API FURuStoreRuStoreError
{
GENERATED_USTRUCT_BODY()
FURuStoreRuStoreError()
{
name = "" ;
description = "" ;
}

UPROPERTY(BlueprintReadOnly)
FString name;

UPROPERTY(BlueprintReadOnly)
FString description;
};
  • name – имя ошибки.
  • description – описание ошибки.