10.1.0 (актуальная версия)
RuStore позволяет интегрировать платежи в мобильное приложение.
-
Если не знаете с чего начать, прочтите инструкцию в сценариях использования.
-
Если вы переходите на Pay SDK с billingClient SDK, ознакомьтесь с инструкцией по переходу. Подробности о Pay SDK можно узнать тут.
Подключение в проект
- Скопируйте проекты плагина и приложения-примера из официального репозитория RuStore на GitFlic.
- Скопируйте папки
pay_example / extension_rustore_payиpay_example / extension_rustore_coreв корень вашего проекта.
Инициализация
Перед вызовом методов библиотеки необходимо выполнить её инициализацию. Сама инициализация происходит автоматически, но для работы SDK в вашем файле Manifest.xml необходимо прописать console_app_id_value и internal_config_key. Оба значения должны располагаться внутри тега <application>
<!-- Initializing sdk -->
<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" />
console_app_id_value — идентификатор приложения из RuStore консоли.
Где в RuStore Консоль отображаются идентификаторы приложений?
- Перейдите на вкладку Приложения и выберите нужное приложение.
- Скопируйте идентификатор из URL-адреса страницы приложения — это набор цифр между
apps/и/versions. Например, для URL-адресаhttps://console.rustore.ru/apps/123456/versionsID приложения —123456.

Не задавайте значения console_app_id_value и internal_config_key напрямую в манифесте. Строки должны располагаться в файле ресурсов.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="rustore_PayClientSettings_consoleApplicationId" translatable="false">2063572661</string>
<string name="rustore_PayClientSettings_internalConfigKey" translatable="false">defold</string>
<string name="rustore_PayClientSettings_deeplinkScheme" translatable="false">yourappscheme</string>
</resources>
Package Name приложения, указанный в game.project → Android → Package, должен совпадать с Package Name APK-файла, который вы публиковали в системе RuStore Консоль.
Обработка deeplink
Для корректной работы оплаты через сторонние приложения (СБП, SberPay и др.) необходимо правильно реализовать обработку deeplink.
Допускаются только символы в кодировке ASCII. Формат должен соответствовать спецификации RFC-3986.
Плагин extension_rustore_pay содержит реализацию RuStoreIntentFilterActivity, которая обрабатывает входящие intent и возвращается в игровую активити com.dynamo.android.DefoldActivity.
Для включения в сборку добавьте RuStoreIntentFilterActivity в AndroidManifest.xml с указанием двух intent-filter.
<activity android:name="ru.rustore.defold.pay.RuStoreIntentFilterActivity"
android:theme="@android:style/Theme.NoDisplay"
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" />
<!-- Deeplink scheme -->
<data android:scheme="@string/rustore_PayClientSettings_deeplinkScheme" />
</intent-filter>
</activity>
К игровому активити добавьте атрибут android:launchMode="singleTask" и удалите intent-filter с android.intent.action.MAIN.
<activity android:name="com.dynamo.android.DefoldActivity"
android:label="{{project.title}}"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="{{orientation-support}}"
android:exported="true"
android:launchMode="singleTask">
<meta-data android:name="android.app.lib_name"
android:value="{{exe-name}}" />
</activity>
Пример приложения содержит модифицированный манифест в файле pay_example/extension_rustore_pay/manifests/android/AndroidManifest.xml
Пример оформления манифеста
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="{{android.package}}"
android:versionCode="{{android.version_code}}"
android:versionName="{{project.version}}"
android:installLocation="auto">
<uses-feature android:required="true" android:glEsVersion="0x00020000" />
<uses-sdk android:minSdkVersion="{{android.minimum_sdk_version}}" android:targetSdkVersion="{{android.target_sdk_version}}" />
<application
{{#has-icons?}}
android:icon="@drawable/icon"
{{/has-icons?}}
android:extractNativeLibs="{{android.extract_native_libs}}"
android:label="{{project.title}}"
tools:replace="android:label"
android:hasCode="true"
android:name="android.support.multidex.MultiDexApplication"
android:enableOnBackInvokedCallback="true"
android:debuggable="{{android.debuggable}}">
<meta-data android:name="android.max_aspect" android:value="2.1" />
<meta-data android:name="android.notch_support" android:value="true"/>
<activity android:name="com.dynamo.android.DefoldActivity"
android:label="{{project.title}}"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="{{orientation-support}}"
android:exported="true"
android:launchMode="singleTask">
<meta-data android:name="android.app.lib_name"
android:value="{{exe-name}}" />
</activity>
<!-- Deeplink activity -->
<activity android:name="ru.rustore.defold.pay.RuStoreIntentFilterActivity"
android:theme="@android:style/Theme.NoDisplay"
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" />
<!-- Deeplink scheme -->
<data android:scheme="@string/rustore_PayClientSettings_deeplinkScheme" />
</intent-filter>
</activity>
<!-- Deeplink scheme -->
<meta-data
android:name="sdk_pay_scheme_value"
android:value="@string/rustore_PayClientSettings_deeplinkScheme" />
<!-- Initializing sdk -->
<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" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
<!-- END_INCLUDE(manifest) -->
Реализация RuStoreIntentFilterActivity
package ru.rustore.defold.pay;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class RuStoreIntentFilterActivity extends Activity {
private final String defoldActivityClassName = "com.dynamo.android.DefoldActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
RuStorePay.INSTANCE.proceedIntent(getIntent());
}
startGameActivity(defoldActivityClassName);
finish();
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
RuStorePay.INSTANCE.proceedIntent(intent);
}
private void startGameActivity(String gameActivityClassName) {
Class<?> gameActivityClass = getActivityClass(gameActivityClassName);
if (gameActivityClass != null) {
Intent intent = new Intent(this, gameActivityClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
private Class<?> getActivityClass(String activityClassName) {
try {
return Class.forName(activityClassName);
} catch(ClassNotFoundException ex) {
return null;
}
}
}
Метод proceedIntent имеет перегрузку с дополнительным параметром maxRetryTimeMs: Long.
long maxRetryTimeMs = 5000L;
RuStorePay.INSTANCE.proceedIntent(intent, maxRetryTimeMs);
maxRetryTimeMs— максимальное время (в миллисекундах) для повторных попыток инициализации платёжного клиента (по умолчанию 5000 мс).
Работа с SDK
Доступные публичные методы:
get_purchase— позволяет получить информацию о покупке по её ID.get_purchases— позволяет получить покупки пользователя. Данный метод поддерживает опциональную фильтрацию по типу товаров (потребляемые или непотребляемые товары), а также по статусу покупки (поддерживаются статусыPAIDиCONFIRMED). По умолчанию фильтры отключены, и вернутся все покупки пользователя (независимо от типа товара) в статусахPAIDиCONFIRMED.get_purchase_availability— возвращает результат доступности работы с платежами.purchase— позволяет совершить покупку продукта с указанием желаемого типа оплаты - одностадийной (ONE_STEP) или двухстадийной (TWO_STEP). Для данного метода оплаты на платёжной шторке доступны все способы оплаты. Если параметр не задан, по умолчанию запускается с оплатой в одну стадию.
Если указан тип оплаты TWO_STEP, будет произведена попытка запустить двухстадийную оплату, но итоговый результат напрямую будет зависеть от того, какой способ оплаты (карта, СБП и др.) будет выбран пользователем. Двухстадийная оплата доступна только для определенного набора способов оплаты (на текущий момент — только для карт). Технологии СБП не поддерживают двухстадийную оплату. Если выб ран способ оплаты, который не поддерживает холдирование, то покупка будет запущена по сценарию с одной стадией.
purchase_two_step— запускает сценарий гарантированной двухстадийной покупки товара. При использовании данного метода пользователю на платёжной шторке доступен ограниченный набор способов оплаты — только те, которые поддерживают двухстадийную оплату. В процессе платежа сначала осуществляется холдирование денежных средств покупателя, которые списываются только после подтверждения покупки методомConfirmTwoStepPurchase.confirm_two_step_purchase— подтверждение покупки, совершенной по двухстадийной оплате.cancel_two_step_purchase— отмена покупки, совершённой по двухстадийной оплате.get_products— позволяет получить информацию по активным продуктам, опубликованным в RuStore консоль.
Данный метод возвращает не более 1000 продуктов и работает без авторизации и наличия установленного RuStore на устройстве пользователя.
- модуль
rustorecore— набор открытых методов, таких как:is_rustore_installed— проверки наличия приложения RuStore на устройстве пользователя.open_rustore_download_instruction— открывает веб-страницу для скачивания приложения RuStore.open_rustore— запускает приложение RuStore.open_rustore_authorization— запускает приложение RuStore для авторизации. После успешной авторизации пользователя приложение RuStore автоматически закроется.
Проверка доступности работы с платежами
Для проверки доступности платежей, вызовите метод get_purchase_availability. При его вызове проверяются следующие условия.
- У компании подключена монетизация через консоль разработчика RuStore.
- Приложение не должно быть заблокировано в RuStore.
- Пользователь не должен быть заблокирован в RuStore.
Перед использованием метода необходимо единожды выполнить подписку на события:
rustore_pay_on_get_purchase_availability_successrustore_pay_on_get_purchase_availability_failure
function init(self)
rustorecore.connect("rustore_pay_on_get_purchase_availability_success", _on_get_purchase_availability_success)
rustorecore.connect("rustore_pay_on_get_purchase_availability_failure", _on_get_purchase_availability_failure)
end
function _on_get_purchase_availability_success(self, channel, value)
local data = json.decode(value)
if data.isAvailable == true then
-- Process purchase available
else
-- Process purchase unavailable
end
end
function _on_get_purchase_availability_failure(self, channel, value)
local data = json.decode(value)
end
rustorepay.get_purchase_availability()
data.isAvailable == true.
В противном случае возвращается data.isAvailable == false и data.cause, где cause — это ошибка о невыполненном условии (возможные ошибки описаны в разделе Список ошибок).
Проверка статуса авторизации пользователя
Для проверки статуса авторизации пользователя, вызовите метод get_user_authorization_status. Результатом выполнения метода является значение перечисления get_user_authorization_status. Возможно только 2 значения:
AUTHORIZED— пользователь авторизован в RuStore.UNAUTHORIZED— пользователь неавтори зован в RuStore. Данное значение также вернется если у пользователя нет установленного МП RuStore на девайсе.
function init(self)
rustorecore.connect("rustore_pay_on_get_user_authorization_status_success", _on_get_user_authorization_status_success)
rustorecore.connect("rustore_pay_on_get_user_authorization_status_failure", _on_get_user_authorization_status_failure)
end
function _on_get_user_authorization_status_success(self, channel, value)
if value == "AUTHORIZED" then
-- Process AUTHORIZED
elseif value == "UNAUTHORIZED" then
-- Process UNAUTHORIZED
end
end
function _on_get_user_authorization_status_failure(self, channel, value)
local data = json.decode(value)
end
rustorepay.get_user_authorization_status()
Получение списка продуктов
Для получения продуктов, добавленных в ваше приложение через RuStore консоль, необходимо использовать метод get_products.
function init(self)
rustorecore.connect("rustore_pay_on_get_products_success", _on_get_products_success)
rustorecore.connect("rustore_pay_on_get_products_failure", _on_get_products_failure)
end
function _on_get_products_success(self, channel, value)
local data = json.decode(value)
for key, val in pairs(data) do
local product_id = val.productId
-- Optional field
local description
if data.description then
description = data.description
else
description = nil
end
end
end
function _on_get_products_failure(self, channel, value)
local data = json.decode(value)
end
local PRODUCT_IDS = {
"non_con2",
"non_con1",
"con2",
"con1",
"sub2",
"sub1"}
rustorepay.get_products(PRODUCT_IDS)
local PRODUCT_IDS = {} — список идентификаторов продуктов (задаются при создании продукта в консоли разработчика). Список продуктов имеет ограничение в размере 1000 элементов.
Где в RuStore Консоль отображаются идентификаторы продуктов?
- Перейдите на вкладку Приложения и выберите нужное приложение.
- Выберите Монетизация в меню слева.
- Выберите тип товара: Подписки или Разовые покупки.
- Скопируйте идентификаторы нужных товаров.

Обратный вызов (callback) rustore_pay_on_get_products_success возвращает строку JSON с информацией о продуктах (см. ниже).
productId -- string
type -- string
-- NON_CONSUMABLE_PRODUCT
-- CONSUMABLE_PRODUCT
-- SUBSCRIPTION
amountLabel -- string
price -- number (optional)
currency -- string
title -- string
description -- string (optional)
imageUrl -- string
subscriptionInfo -- array of SubscriptionPeriod
productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).type— тип продукта.CONSUMABLE/NON-CONSUMABLE/SUBSCRIPTION(потребляемый/непотребляемый/подписка).amountLabel— отформатированная цена покупки, включая валютный знак.price— цена в минимальных единицах (в копейках).currency— код валюты ISO 4217.title— название продукта на языкеlanguage.description— о писание на языкеlanguage.imageUrl— ссылка на картинку.subscriptionInfo— информация о подписке (будет неnull, если тип продуктаSUBSCRIPTION).
simpleName -- string
-- TrialPeriod
-- PromoPeriod
-- MainPeriod
-- GracePeriod
-- HoldPeriod
duration -- string
currency -- string (optional)
price -- number (optional)
simpleName— тип периода.duration— длительность периода в формате ISO 8601.currency— код валюты ISO 4217.price— цена в минимальных единицах валюты.
Получение списка покупок
Для получения списка покупок пользователя используйте методget_purchases.
function init(self)
rustorecore.connect("rustore_pay_on_get_purchases_success", _on_get_purchases_success)
rustorecore.connect("rustore_pay_on_get_purchases_failure", _on_get_purchases_failure)
end
function _on_get_purchases_success(self, channel, value)
local data = json.decode(value)
for key, val in pairs(data) do
local purchase_id = val.purchaseId
-- Optional field
local purchase_time
if data.purchaseTime then
purchase_time = data.purchaseTime -- UTC MMM dd, yyyy h:mm:ss a
else
purchase_time = nil
end
end
end
function _on_get_purchases_failure(self, channel, value)
local data = json.decode(value)
end
rustorepay.get_purchases()
Данный метод поддерживает необязательную фильтрацию по типу товаров (потребляемые или непотреблямые товары), а также по статусу покупки (поддерживаются только статусы PAID и CONFIRMED). По умолчанию фильтр выключен и вернет все покупки пользователя (вне зависимости от типа товара) в статусах PAID и CONFIRMED. Статус PAID означает успешное холдирование средств, покупка ожидает подтверждения покупки со стороны разработчика.
local filter = {
-- productType = "CONSUMABLE_PRODUCT", -- optional
purchaseStatus = "PAID" -- optional
}
rustorepay.get_purchases(filter)
Обратный вызов (callback) rustore_pay_on_get_purchases_success возвращает строку JSON с информацией о покупках (см. ниже).
purchaseId -- string
invoiceId -- string
orderId -- string (optional)
purchaseType
-- ONE_STEP
-- TWO_STEP
-- UNDEFINED
status -- string
-- INVOICE_CREATED
-- CANCELLED
-- PROCESSING
-- REJECTED
-- CONFIRMED
-- REFUNDING
-- REFUNDED
-- EXECUTING
-- EXPIRED
-- PAID
-- REVERSED
description -- string
purchaseTime -- string (optional) MMM dd, yyyy h:mm:ss a
price -- number
amountLabel -- string
currency -- string
developerPayload -- string (optional)
sandbox -- boolean
productId -- string
quantity -- number
productType -- string
-- NON_CONSUMABLE_PRODUCT
-- CONSUMABLE_PRODUCT
-- SUBSCRIPTION
purchaseId— идентификатор покупки. Идентификатор покупки. Используется для получения информации о покупке в SDK методом получения информации о покупке.invoiceId— идентификатор счёта. Идентификатор счёта. Используется для серверной валидации платежа, поиска платежей в консоли разработчика, а также отображается покупателю в истории платежей в мобильном приложении RuStore.orderId- уникальный идентификатор оплаты, указанный разработчиком или сформированный автоматически (uuid).PurchaseType— тип покупки:ONE_STEP- одностадийная покупка;TWO_STEP- двухстадийная покупка;UNDEFINED- стадийность не определена.
status— состояние покупки:INVOICE_CREATED— создан счёт на оплату, покупка ожидает оплаты;CANCELLED— покупка отменена покупателем;PROCESSING— запущена оплата;REJECTED— покупка отклонена (например, ввиду недостатка средств);EXPIRED— истекло время на оплату покупки;PAID— только для двухстадийной оплаты, промежуточный статус, средства на счёте покупателя захолдированы, покупка ожидает подтверждения от разработчика;CONFIRMED— покупка успешно оплачена;REFUNDING— инициирован возврат средств, запрос отправлен в эквайер;REFUNDED— запрос на возврат средств за покупку совершён успешно. Деньги будут возвращены пользователю в течение 10 рабочих дней.;REVERSED— только для двухстадийной оплаты, покупка была отменена разработчиком или не было произведено подтверждение покупки в течение 6 часов, холдирование средств отменено.
description- описание покупки.purchaseTime— время покупки.price— цена в минимальных единицах (в копейках).amountLabel— отформатированная цена покупки, включая валютный знак.currency— код валюты ISO 4217.-
developerPayload— строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации -
sandbox— флаг тестового платежа. Значениеtrue— тестовый платёж,false— реальный платёж. productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр). Идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).quantity— количество продукта.productType— тип продукта. (CONSUMABLE/NON-CONSUMABLE- потребляемый/непотребляемый.)
Получение сведений о покупке
Для получения информации о покупке, используйте методgetPurchase.
function init(self)
rustorecore.connect("rustore_pay_on_get_purchase_success", _on_get_purchase_success)
rustorecore.connect("rustore_pay_on_get_purchase_failure", _on_get_purchase_failure)
end
function _on_get_purchase_success(self, channel, value)
local data = json.decode(value)
local purchase_id = data.purchaseId
-- Optional field
local purchase_time
if data.purchaseTime then
purchase_time = data.purchaseTime -- UTC MMM dd, yyyy h:mm:ss a
else
purchase_time = nil
end
end
function _on_get_purchase_failure(self, channel, error, id)
local data = json.decode(error)
local purchase_id = id
end
rustorepay.get_purchase()
Обратный вызов (callback) rustore_pay_on_get_purchase_success возвращает строку JSON с информацией о конкретной покупке в любом статусе (см. ниже).
amountLabel -- string
currency -- string
description -- string
developerPayload -- string (optional)
invoiceId -- string
orderId -- string (optional)
price -- number
productId -- string
productType -- string
-- NON_CONSUMABLE_PRODUCT
-- CONSUMABLE_PRODUCT
-- SUBSCRIPTION
purchaseId -- string
purchaseTime -- string (optional) MMM dd, yyyy h:mm:ss a
purchaseType
-- ONE_STEP
-- TWO_STEP
-- UNDEFINED
quantity -- number
sandbox -- boolean
status -- string
-- INVOICE_CREATED
-- CANCELLED
-- PROCESSING
-- REJECTED
-- CONFIRMED
-- REFUNDING
-- REFUNDED
-- EXECUTING
-- EXPIRED
-- PAID
-- REVERSED
purchaseId— идентификатор покупки. Используется для получения информации о покупке в SDK методом получения информации о покупке.productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).invoiceId— идентификатор счёта. Используется для серверной валидации платежа, поиска платежей в консоли разработчика, а также отображается покупателю в истории платежей в мобильном приложении RuStore.orderId- уникальный идентификатор оплаты, указанный разработчиком или сформированный автоматически (uuid).PurchaseType— тип покупки:ONE_STEP- одностадийная покупка;TWO_STEP- двухстадийная покупка;UNDEFINED- стадийность не определена.
productType— тип продукта. (CONSUMABLE/NON-CONSUMABLE- потребляемый/непотребляемый.)description- описание покупки.purchaseTime— время покупки.price— цена в минимальных единицах (в копейках).amountLabel— отформатированная цена покупки, включая валютный знак.currency— код валюты ISO 4217.quantity— количество продукта.status— состояние покупки:INVOICE_CREATED— создан счёт на оплату, покупка ожидает оплаты;CANCELLED— покупка отменена покупателем;PROCESSING— запущена оплата;REJECTED— покупка отклонена (например, ввиду недостатка средств);EXPIRED— истекло время на оплату покупки;PAID— только для двухстадийной оплаты, промежуточный статус, средства на счёте покупателя захолдированы, покупка ожидает подтверждения от разработчика;CONFIRMED— покупка успешно оплачена;REFUNDING— инициирован возврат, запрос отправлен в эквайер;REFUNDED— запрос на возврат средств за покупку совершён успешно. Деньги будут возвращены пользователю в течение 10 рабочих дней.;REVERSED— только для двухстадийной оплаты, покупка была отменена разработчиком или не было произведено подтверждение покупки в течение 6 часов, холдирование средств отменено.
-
developerPayload— строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации -
sandbox— флаг тестового платежа. Значениеtrue— тестовый платёж,false— реальный платёж.
Статусная модель покупки
Статусная модель одностадийного платежа.
Статусная модель двухстадийного платежа.
Покупка продукта
- При использовании одностадийного платежа покупка не требует подтверждения, денежные средства сразу списываются со счёта покупателя, а с разработчика удерживается комиссия. В таком случае, если требуется вернуть денежные средства клиенту (например, по какой-то причине нет возможности поставить продукт), возможен только возврат средств через RuStore Консоль, денежные средства возвращаются покупателю через несколько дней. Возвращается полная стоимость покупки, при этом удержанная комиссия разработчику не возмещается.
- В случае использования двухстадийного платежа сначала производится холдирование ср едств на счете покупателя. Комиссия в этом случае не удерживается. После холдирования покупка требует подтверждения или отмены. Комиссия с разработчика удерживается при подтверждении покупки. Отмена покупки означает снятие холда - денежные средства мгновенно снова доступны покупателю.
Двухстадийная оплата доступна только для определенного набора способов оплаты (на текущий момент — только для карт и SberPay). Технологии СБП не поддерживают двухстадийную оплату. Если выбран способ оплаты, который не поддерживает холдирование, то покупка будет запущена по сценарию с одной стадией.
Оплата с выбором типа покупки
Для вызова покупки продукта с выбором стадийности оплаты используйте метод purchase:
function init(self)
rustorecore.connect("rustore_pay_on_purchase_success", _on_purchase_success)
rustorecore.connect("rustore_pay_on_purchase_failure", _on_purchase_failure)
end
function _on_purchase_success(self, channel, value)
-- ProductPurchaseResult
local data = json.decode(value)
local product_id = data.productId
local purchase_id = data.purchaseId
-- Optional field
local order_id
if data.orderId then
order_id = data.orderId
else
order_id = nil
end
end
function _on_purchase_failure(self, channel, error, id)
local data = json.decode(error)
local product_id = id
end
local params = {
-- appUserEmail = "user@example.com", -- (optional)
-- appUserId = "user123", -- (optional)
-- developerPayload = "payload_data", -- (optional)
-- orderId = "order_456", -- (optional)
-- quantity = 1, -- (optional)
productId = "product_id"
}
local json_params = json.encode(params)
local preferred_purchase_type = "ONE_STEP" -- "TWO_STEP"
local sdk_theme = "LIGHT" -- "DARK"
rustorepay.purchase(json_params, preferred_purchase_type, sdk_theme)
productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).quantity— количество продукта. Необязательный параметр со стандартным значением1. Применим только к покупке потребляемых товаров.orderId— уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.developerPayload— строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации. Максимальная длина 250 символов. Символы не экранируются.-
appUserId— внутренний ID пользователя в вашем приложении (опциональный параметр). Строка с максимальной длиной в 128 символов.подсказкаНапример, данный параметр может использоваться для выявления случаев мошенничества в вашем приложении, что позволит повысить его безопасность.
appUserEmail- это необязательный параметр, позволяющий задать адрес электронной почты пользователя в вашем приложении. Если адрес электронной почты покупателя был указан при регистрации в приложении, его можно передать для автоматического заполнения поляemailпри отправке чека — как для платежей вне RuStore, так и для случаев, когда пользователь не авторизован в RuStore. Это избавляет пользователя от необходимости вручную вводить email, сокращает путь до покупки и способствует повышению конверсии.preferredPurchaseType— желаемый тип покупки: одностадийная (ONE_STEP) или двухстадийная (TWO_STEP).
sdk_theme— цветовая тема платежной шторки. Доступны два вариантаLIGHTиDARK(светлая и темная тема соотвественно), по умолчаниюLIGHT.
Данный метод по умолчанию запускается по одностадийному сценарию оплаты (preferredPurchaseType = PreferredPurchaseType.ONE_STEP), т.е. без холдирования средств.
Для двухстадийной оплаты нужно указать preferredPurchaseType = PreferredPurchaseType.TWO_STEP. Двухстадийная оплата (т.е. оплата с холдированием средств) для данного метода не гарантирована и напрямую зависит от того, какой способ оплаты (карта, СПБ и др.) выбрал пользователь.
При запуске данного метода (с предпочитаемым preferredPurchaseType = twoStep), до тех пор пока пользователь не выберет способ оплаты, стадийность покупки будет UNDEFINED. Учитывайте данное поведение при обработке результатов отмены (ProductPurchaseCancelled) или ошибки (ProductPurchaseException) покупки.
Двухстадийная оплата (с холдированием средств)
Для вызова покупки продукта по двухстадийному сценарию используйте метод PurchaseTwoStep:
При вызове данного метода пользователю будет доступен ограниченный набор способов оплаты — только те, которые поддерживают двухстадийную оплату.
function init(self)
rustorecore.connect("rustore_pay_on_purchase_two_step_success", _on_purchase_two_step_success)
rustorecore.connect("rustore_pay_on_purchase_two_step_failure", _on_purchase_two_step_failure)
end
function _on_purchase_two_step_success(self, channel, value)
-- ProductPurchaseResult
local data = json.decode(value)
local product_id = data.productId
local purchase_id = data.purchaseId
-- Optional field
local order_id
if data.orderId then
order_id = data.orderId
else
order_id = nil
end
end
function _on_purchase_two_step_failure(self, channel, error, id)
local data = json.decode(error)
local product_id = id
end
local params = {
-- appUserEmail = "user@example.com", -- (optional)
-- appUserId = "user123", -- (optional)
-- developerPayload = "payload_data", -- (optional)
-- orderId = "order_456", -- (optional)
-- quantity = 1, -- (optional)
productId = "product_id"
}
local json_params = json.encode(params)
local sdk_theme = "LIGHT" -- "DARK"
rustorepay.purchase_two_step(json_params)
Структура параметров покупки
appUserEmail -- string (optional)
appUserId -- string (optional)
developerPayload -- string (optional)
orderId -- string (optional)
quantity -- number (optional)
productId -- string
productId— идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).quantity— количество продукта. Необязательный параметр со стандартным значением1. Применим только к покупке потребляемых товаров.orderId— уникальный идентификатор оплаты, сформированный приложением (опциональный параметр). Если вы укажете этот параметр в вашей системе, вы получите его в ответе при работе с API. Если не укажете, он будет сгенерирован автоматически (uuid). Максимальная длина 150 символов.developerPayload— строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации. Максимальная длина 250 символов. Символы не экранируются.-
appUserId— внутренний ID пользователя в вашем приложении (опциональный параметр). Строка с максимальной длиной в 128 символов.подсказкаНапример, данный параметр может использоваться для выявления случаев мошенничества в вашем приложении, что позволит повысить его безопасность.
appUserEmail— это необязательный параметр, позволяющий задать адрес электронной почты пользователя в вашем приложении. Если адрес электронной почты покупателя был указан при регистрации в приложении, его можно передать для автоматического заполнения поляemailпри отправке чека — как для платежей в не RuStore, так и для случаев, когда пользователь не авторизован в RuStore. Это избавляет пользователя от необходимости вручную вводить email, сокращает путь до покупки и способствует повышению конверсии.
sdk_theme— цветовая тема платежной шторки. Доступны два вариантаLIGHTиDARK(светлая и темная тема соотвественно), по умолчаниюLIGHT.
Структура результата покупки
ProductPurchaseResult— результат успешной оплаты цифрового товара (для одностадийной оплаты) или успешного холдирования средств (для двухстадийной оплаты).
invoiceId -- string
orderId -- string (optional)
productId -- string
purchaseId -- string
purchaseType -- string
-- ONE_STEP
-- TWO_STEP
-- UNDEFINED
quantity -- number
sandbox -- boolean
purchaseId— идентификатор покупки. Используется для получения информации о покупке в SDK методом получения информации о покупкеproductId— идентификатор приобретенного продукта, указанный при создании в консоли разработчика RuStore.invoiceId— идентификатор счета. Используется для серверной валидации платежа, поиска платежей в консоли разработчика, а также отображается покупателю в истории платежей в мобильном приложении RuStoreorderId— уникальный идентификатор оплаты, указанный разработчиком или сформированный автоматически (uuid).purchaseType— тип покупки (ONE_STEP/TWO_STEP/UNDEFINED— одностадийная/двухстадийная/стадийность не определена).quantity— количество купленного продукта.sandbox— флаг, указывающий признак тестового платежа в песочнице. ЕслиTRUE- покупка совершена в режиме тестирования.
Обработка ошибки оплаты
Если в процессе оплаты возникает ошибка или поль зователь отменяет покупку, выполнение метода оплаты (как с выбором типа покупки, так и двухстадийного метода) завершается с ошибкой:
ProductPurchaseException— ошибка покупки продукта.ProductPurchaseCancelled— ошибка, вызванная отменой покупки продукта (пользователь закрыл платежную шторку) до получения результата покупки. В таком случае рекомендуется дополнительно проверить статус покупки методом получения информации о покупке.
function _on_failure(self, channel, value)
local error = json.decode(value)
if error.simpleName == "ProductPurchaseException" then
-- Process ProductPurchaseException
elseif error.simpleName == "ProductPurchaseCancelled" then
-- Process ProductPurchaseCancelled
end
end
Структура ошибки и отмены покупки:
invoiceId -- string (optional)
orderId -- string (optional)
productId -- string (optional)
purchaseId -- string (optional)
purchaseType -- string (optional)
-- ONE_STEP
-- TWO_STEP
-- UNDEFINED
quantity -- integer (optional)
sandbox -- boolean (optional)
invoiceId— идентификатор счёта. Используется для серверной валидации платежа, поиска платежей в консоли разработчика, а также отображается покупателю в истории платежей в моби льном приложении RuStore.orderId— уникальный идентификатор оплаты, указанный разработчиком или сформированный автоматически (uuid).productId— идентификатор приобретённого продукта, указанный при создании в консоли разработчика RuStore.purchaseId— идентификатор покупки. Используется для получения информации о покупке в SDK методом получения информации о покупке.purchaseType— тип покупки (ONE_STEP/TWO_STEP/UNDEFINED— одностадийная / двухстадийная / стадийность не определена).quantity— количество продуктов - опционально. Если не указывать, то будет подставлено значение 1. Применимо только для покупки потребляемых товаров.sandbox— флаг тестового платежа. Значениеtrue— тестовый платёж,false— реальный платёж.
purchaseId - string (optional)
purchaseType - string (optional)
-- ONE_STEP
-- TWO_STEP
-- UNDEFINED
purchaseId— идентификатор покупки. Используется для получения информации о покупке в SDK методом получения информации о покупке.purchaseType— тип покупки (ONE_STEP/TWO_STEP/UNDEFINED— одностадийная / двухстадийная / стадийность не о пределена).
Серверная валидация покупки
Если вам необходимо произвести валидацию успешной покупки на сервере RuStore, вы можете использовать invoiceId из JSON, возвращаемом при успешной покупке продукта.
local params = {
-- appUserEmail = "user@example.com", -- (optional)
-- appUserId = "user123", -- (optional)
-- developerPayload = "payload_data", -- (optional)
-- orderId = "order_456", -- (optional)
-- quantity = 1, -- (optional)
productId = "product_id"
}
local json_params = json.encode(params)
local preferred_purchase_type = "ONE_STEP" -- "TWO_STEP"
rustorecore.connect("rustore_pay_on_purchase_success", _on_purchase_success)
rustorepay.purchase(json_params, preferred_purchase_type)
function _on_purchase_success(self, channel, value)
-- ProductPurchaseResult
local data = json.decode(value)
local invoice_id = data.invoiceId
your_api.validate(invoice_id);
end
Также можно получить invoiceId из модели покупки в обратных вызовах (callback) методов get_purchases или get_purchase.
function _on_get_purchase_success(self, channel, value)
-- Purchase
local data = json.decode(value)
local invoice_id = data.invoiceId
your_api.validate(invoice_id);
end
Подтверждение покупки
Подтверждения требуют только покупки, которые были запущены по двухстадийному сценарию оплаты, т.е. с холдированием средств. Такие покупки, после успешного холдирования будут находиться в статусе status == "PAID".
Для списания средств с карты покупателя требуется подтверждение покупки. Для этого вы должны использовать метод confirm_two_step_purchase.
function init(self)
rustorecore.connect("rustore_pay_on_confirm_two_step_purchase_success", _on_confirm_two_step_purchase_success)
rustorecore.connect("rustore_pay_on_confirm_two_step_purchase_failure", _on_confirm_two_step_purchase_failure)
end
function _on_confirm_two_step_purchase_success(self, channel, value)
local purchase_id = value
end
function _on_confirm_two_step_purchase_failure(self, channel, error, id)
local data = json.decode(error)
local purchase_id = id
end
local purchase_id = ...
local developer_payload = ...
rustorepay.confirm_two_step_purchase(purchase_id, developer_payload)
purchase_id— идентификатор покупки.developer_payload— строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации (опционально). Максимум 250 символов (символы не экранируются). Если передан, заменяет значение, записанное при старте покупки методомpurchase/purchase_two_step.
Отмена покупки
Через SDK можно отменять только те покупки, которые были запущены по двухстадийному сценарию оплаты, т.е. с холдированием средств. Такие покупки после успешного холдирования будут находиться в статусе status = "PAID". После отмены покупки будут переходить в статус status = "REVERSED".
Используйте отмену покупки в случаях, если после оплаты (холдирования средств) вы не можете предоставить покупателю товар.
Для отмены покупки (холда) используйте метод cancel_two_step_purchase.
function init(self)
rustorecore.connect("rustore_pay_on_cancel_two_step_purchase_success", _on_cancel_two_step_purchase_success)
rustorecore.connect("rustore_pay_on_cancel_two_step_purchase_failure", _on_cancel_two_step_purchase_failure)
end
function _on_cancel_two_step_purchase_success(self, channel, value)
local purchase_id = value
end
function _on_cancel_two_step_purchase_failure(self, channel, error, id)
local data = json.decode(error)
local purchase_id = id
end
local purchase_id = ...
local developer_payload = ...
rustorepay.confirm_two_step_purchase(purchase_id, developer_payload)
local purchase_id = ...
rustorepay.cancel_two_step_purchase()
purchaseId— идентификатор покупки.
RuStoreUtils
RuStoreUtils — это блок в нативном SDK, содержащий набор публичных методов, предназначенных для взаимодействия с приложением RuStore на устройстве пользователя.
Для доступа к методам блока в среде Defold используется методы модуля rustorecore.
Метод is_rustore_installed проверяет наличие приложения RuStore на устройстве пользователя.
local is_installed = rustorecore.is_rustore_installed()
if is_installed then
-- RuStore is installed
else
-- RuStore is not installed
end
Метод open_rustore_download_instruction открывает веб-страницу для скачивания мобильного приложения RuStore.
rustorecore.open_rustore_download_instruction()
Метод open_rustore запускает мобильное приложение RuStore. При вызове данного метода, в случае отсутствия установленного приложения RuStore, будет отображено Toast уведомление с сообщением "Не удалось открыть приложение".
rustorecore.open_rustore()
Метод open_rustore_authorization запускает мобильное приложение RuStore для авторизации. После успешной авторизации пользователя приложение RuStore автоматически закрывается. При вызове данного метода, в случае отсутствия установленного приложения RuStore, будет отображено Toast уведомление с сообщением "Не удалось открыть приложение".
rustorecore.open_rustore_authorization()
Список ошибок
Throwable — базовый класс ошибки.
simpleName -- string
detailMessage -- string
simpleName– имя ошибки.detailMessage– описание ошибки.
RuStorePaymentException — базовый класс ошибки платёжного клиента.
cause -- json Throwable
-- simpleName -- string
-- detailMessage -- string
cause– дополнительная информация об ошибке.
Унаследованные поля:
simpleName– имя ошибки.detailMessage– описание ошибки.
RuStorePaymentNetworkException — ошибка сетевого взаимодействия SDK. В модели ошибки возвращается код ошибки (поле code), по которому можно определить причину ошибки. Таблица с кодами ошибок доступна в разделе коды ошибок.
code -- string (optional)
id -- string
code— код ошибки.id— уникальный идентификатор.
Унаследованные поля:
simpleName– имя ошибки.detailMessage– описание ошибки.cause– дополнительная информация об ошибке.
function _on_failure(self, channel, error)
local _error = json.decode(error)
-- Required field
local simple_name = _error.simpleName
local detail_message = _error.detailMessage
if _error.simpleName == "RuStorePaymentNetworkException" then
-- Required field
local id = _error.id
-- Optional field
local code
if _error.code then
code = _error.code
else
code = nil
end
elseif _error.simpleName == "ProductPurchaseCancelled" then
-- Process ProductPurchaseCancelled
elseif _error.simpleName == "ProductPurchaseException" then
-- Process ProductPurchaseException
end
end
Возможные ошибки
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.
Коды ошибок
| Код ошибки | Описание |
|---|---|
4000001 | Запрос сформирован некор ректно: отсутствует или неверно заполнен обязательный параметр, неверный формат данных. |
4000002, 4000016, 4040005 | Приложение не найдено. |
4000003 | Приложение заблокировано. |
4000004 | Подпись приложения не совпадает с зарегистрированной. |
4000005 | Компания не найдена. |
4000006 | Компания заблокирована. |
4000007 | Монетизация компании отключена или неактивна. |
4000014 | Продукт не найден. |
4000015 | Продукт не опубликован. |
4000017 | Некорректный параметр quantity. |
4000018 | Превышен лимит покупок. |
4000020 | Продукт уже приобретен. |
4000021 | Незавершенная покупка продукта. |
4000022 | Покупка не найдена. |
4000025 | Не найден подходящий способ оплаты. |
4000026 | Неверный тип покупки для подтверждения (должна быть двухстадийная оплата). |
4000027 | Неверный статус покупки для подтверждения. |
4000028 | Неверный тип покупки для отмены (должна быть двухстадийная оплата). |
4000029 | Неверный статус покупки для отмены. |
4000030 | Выписанный токен не соответствует покупаемому товару. |
4000041 | У пользователя уже есть активная подписка для данного кода продукта. |
4000045 | Превышено максимальное значение размера. |
4010001 | Доступ к запрашиваему ресурсу запрещен (неавторизовано). |
4010002 | Время жизни токена истекло. |
4010003 | Платежный токен невалиден. |
4030001 | Не передан платежный токен. |
4030002 | Пользователь заблокирован по требованиям безопасности. |
4040002, 4040003, 4040004 | Ошибка платежной системы. |
5000*** | Внутренняя ошибка. |