跳到主要内容

9.1.0 (актуальная версия)

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

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

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

Подключение в проект

  1. Скопируйте проекты плагина и приложения-примера из официального репозитория RuStore на GitFlic.
  2. Скопируйте папки billing_example / extension_rustore_billing и billing_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 Консоль отображаются идентификаторы приложений?
  1. Перейдите на вкладку Приложения и выберите нужное приложение.
  2. Скопируйте идентификатор из URL-адреса страницы приложения — это набор цифр между apps/ и /versions. Например, для URL-адреса https://console.rustore.ru/apps/123456/versions ID приложения — 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>

Также, чтобы обеспечить правильное поведение платежной шторки при сворачивании приложения, игровому активити необходимо задать режим запуска android:launchMode="singleTop".

<?xml version="1.0" encoding="utf-8"?>
<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="singleTop">
<meta-data android:name="android.app.lib_name"
android:value="{{exe-name}}" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Важно

Package Name приложения, указанный в game.project → Android → Package, должен совпадать с Package Name APK-файла, который вы публиковали в системе RuStore Консоль.

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

Плагин RuStorePay содержит реализацию RuStoreIntentFilterActivity, которая обрабатывает входящие intent и возвращается в игровую активити com.dynamo.android.DefoldActivity.

Для включения в сборку добавьте RuStoreIntentFilterActivity в AndroidManifest.xml указав intent-filter и meta-data.

AndroidManifest.xml
<!-- Deeplink activity -->
<activity android:name="ru.rustore.defold.pay.RuStoreIntentFilterActivity"
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>

<!-- Deeplink scheme -->
<meta-data
android:name="sdk_pay_scheme_value"
android:value="@string/rustore_PayClientSettings_deeplinkScheme" />
Пример оформления манифеста
<?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"/>

<!-- android:launchMode="singleTop" -->
<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="singleTop">
<meta-data android:name="android.app.lib_name"
android:value="{{exe-name}}" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- Deeplink activity -->
<activity android:name="ru.rustore.defold.pay.RuStoreIntentFilterActivity"
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>

<!-- 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;
import ru.rustore.defold.pay.RuStorePay;

public class RuStoreIntentFilterActivity extends Activity {

private final String defoldActivityClassName = "com.dynamo.android.DefoldActivity";

private Class<?> getActivityClass(String activityClassName) {
Class<?> activityClass = null;
try {
activityClass = Class.forName(activityClassName);
} catch(ClassNotFoundException ex) {
}

return activityClass;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if (savedInstanceState == null) {
RuStorePay.INSTANCE.proceedIntent(getIntent());
}

startGameActivity(getIntent(), defoldActivityClassName);
finish();
}

@Override
public void onNewIntent(Intent newIntent)
{
super.onNewIntent(newIntent);

RuStorePay.INSTANCE.proceedIntent(newIntent);
startGameActivity(newIntent, defoldActivityClassName);
finish();
}

private void startGameActivity(Intent intent, String gameActivityClassName) {
Class<?> gameActivityClass = getActivityClass(gameActivityClassName);
if (gameActivityClass != null) {
Intent newIntent = new Intent(this, gameActivityClass);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (intent != null) newIntent.putExtras(intent.getExtras());
startActivity(newIntent);
}
}
}

Работа с 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_success
  • rustore_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
Вызов метода get_purchase_availability
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
Вызов метода get_user_authorization_status
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
Вызов метода get_products
local PRODUCT_IDS = {
"non_con2",
"non_con1",
"con2",
"con1",
"sub2",
"sub1"}

rustorepay.get_products(PRODUCT_IDS)

local PRODUCT_IDS = {} — список идентификаторов продуктов (задаются при создании продукта в консоли разработчика). Список продуктов имеет ограничение в размере 1000 элементов.

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

Обратный вызов (callback) rustore_pay_on_get_products_success возвращает строку JSON с информацией о продуктах (см. ниже).

Поля JSON с информацией о продукте
amountLabel -- string
currency -- string
description -- string (optional)
imageUrl -- string
price -- number (optional)
productId -- string
title -- string
type -- string
-- APPLICATION
-- NON_CONSUMABLE_PRODUCT
-- CONSUMABLE_PRODUCT
  • productId — идентификатор продукта, который был присвоен продукту в RuStore Консоли (обязательный параметр).
  • type — тип продукта. CONSUMABLE/NON-CONSUMABLE (потребляемый/непотребляемый).
  • amountLabel — отформатированная цена покупки, включая валютный знак.
  • price — цена в минимальных единицах (в копейках).
  • currency — код валюты ISO 4217.
  • title — название продукта на языке language.
  • description — описание на языке language.
  • imageUrl — ссылка на картинку.

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

Для получения списка покупок пользователя используйте метод 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
Вызов метода get_purchases
rustorepay.get_purchases()

Данный метод поддерживает необязательную фильтрацию по типу товаров (потребляемые или непотреблямые товары), а также по статусу покупки (поддерживаются только статусы PAID и CONFIRMED). По умолчанию фильтр выключен и вернет все покупки пользователя (вне зависимости от типа товара) в статусах PAID и CONFIRMED. Статус PAID означает успешное холдирование средств, покупка ожидает подтверждения покупки со стороны разработчика.

Вызов метода get_purchases с фильтром
local filter = {
-- productType = "CONSUMABLE_PRODUCT", -- optional
purchaseStatus = "PAID" -- optional
}

rustorepay.get_purchases(filter)

Обратный вызов (callback) rustore_pay_on_get_purchases_success возвращает строку JSON с информацией о покупках (см. ниже).

Поля JSON с информацией о покупке
amountLabel -- string
currency -- string
description -- string
developerPayload -- string (optional)
invoiceId -- string
orderId -- string (optional)
price -- number
productId -- string
productType -- string
-- APPLICATION
-- NON_CONSUMABLE_PRODUCT
-- CONSUMABLE_PRODUCT
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 — запрос на возврат средств за покупку совершён успешно;
    • REVERSED — только для двухстадийной оплаты, покупка была отменена разработчиком или не было произведено подтверждение покупки в течение 6 часов, холдирование средств отменено.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации
  • sandbox — флаг тестового платежа. Значение true — тестовый платёж, false— реальный платёж.

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

Для получения информации о покупке, используйте метод 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
Вызов метода get_purchase
rustorepay.get_purchase()

Обратный вызов (callback) rustore_pay_on_get_purchase_success возвращает строку JSON с информацией о конкретной покупке в любом статусе (см. ниже).

Поля JSON с информацией о покупке
amountLabel -- string
currency -- string
description -- string
developerPayload -- string (optional)
invoiceId -- string
orderId -- string (optional)
price -- number
productId -- string
productType -- string
-- APPLICATION
-- NON_CONSUMABLE_PRODUCT
-- CONSUMABLE_PRODUCT
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 — запрос на возврат средств за покупку совершён успешно;
    • REVERSED — только для двухстадийной оплаты, покупка была отменена разработчиком или не было произведено подтверждение покупки в течение 6 часов, холдирование средств отменено.
  • developerPayload — строка с дополнительной информацией о заказе, которую вы можете установить при подтверждении покупки. Эта строка переопределяет значение, заданное при инициализации
  • sandbox — флаг тестового платежа. Значение true — тестовый платёж, false— реальный платёж.

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

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

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

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

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

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

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

Для вызова покупки продукта с выбором стадийности оплаты используйте метод 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
Вызов метода purchase
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"

rustorepay.purchase(json_params, preferred_purchase_type)
  • 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) покупки.

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

Для вызова покупки продукта по двухстадийному сценарию используйте метод 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
Вызов метода purchase_two_step
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)

rustorepay.purchase_two_step(json_params)

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

Поля JSON с параметрами покупки
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, сокращает путь до покупки и способствует повышению конверсии.

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

  • ProductPurchaseResult — результат успешной оплаты цифрового товара (для одностадийной оплаты) или успешного холдирования средств (для двухстадийной оплаты).
Поля JSON с информацией о результате покупки
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 — идентификатор счета. Используется для серверной валидации платежа, поиска платежей в консоли разработчика, а также отображается покупателю в истории платежей в мобильном приложении RuStore
  • orderId — уникальный идентификатор оплаты, указанный разработчиком или сформированный автоматически (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

Структура ошибки и отмены покупки:

Поля JSON с информацией об ошибке оплаты
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 — реальный платёж.
Поля JSON с информацией об отмене оплаты
purchaseId - string (optional)
purchaseType - string (optional)
-- ONE_STEP
-- TWO_STEP
-- UNDEFINED
  • purchaseId — идентификатор покупки. Используется для получения информации о покупке в SDK методом получения информации о покупке.
  • purchaseType — тип покупки (ONE_STEP/TWO_STEP/UNDEFINED — одностадийная / двухстадийная / стадийность не определена).

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

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

Получение invoiceId из результата покупки
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
Вызов метода confirm_two_step_purchase
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
Вызов метода confirm_two_step_purchase
local purchase_id = ...
local developer_payload = ...

rustorepay.confirm_two_step_purchase(purchase_id, developer_payload)
Вызов метода cancel_two_step_purchase
local purchase_id = ...

rustorepay.cancel_two_step_purchase()
  • purchaseId — идентификатор покупки.

RuStoreUtils

RuStoreUtils — это блок в нативном SDK, содержащий набор публичных методов, предназначенных для взаимодействия с приложением RuStore на устройстве пользователя.

Для доступа к методам блока в среде Defold используется методы модуля rustorecore.

Метод is_rustore_installed проверяет наличие приложения RuStore на устройстве пользователя.

Вызов метода is_rustore_installed
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.

Вызов метода open_rustore_download_instruction
rustorecore.open_rustore_download_instruction()

Метод open_rustore запускает мобильное приложение RuStore. При вызове данного метода, в случае отсутствия установленного приложения RuStore, будет отображено Toast уведомление с сообщением "Не удалось открыть приложение".

Вызов метода open_rustore
rustorecore.open_rustore()

Метод open_rustore_authorization запускает мобильное приложение RuStore для авторизации. После успешной авторизации пользователя приложение RuStore автоматически закрывается. При вызове данного метода, в случае отсутствия установленного приложения RuStore, будет отображено Toast уведомление с сообщением "Не удалось открыть приложение".

Вызов метода open_rustore_authorization
rustorecore.open_rustore_authorization()

Список ошибок

Throwable — базовый класс ошибки.

Поля JSON базовой ошибки
simpleName -- string
detailMessage -- string
  • simpleName – имя ошибки.
  • detailMessage – описание ошибки.

RuStorePaymentException — базовый класс ошибки платёжного клиента.

Поля JSON базовой ошибки платёжного клиента
cause -- json Throwable
-- simpleName -- string
-- detailMessage -- string
  • cause – дополнительная информация об ошибке.

Унаследованные поля:

  • simpleName – имя ошибки.
  • detailMessage – описание ошибки.

RuStorePaymentNetworkException — ошибка сетевого взаимодействия SDK. В модели ошибки возвращается код ошибки (поле code), по которому можно определить причину ошибки. Таблица с кодами ошибок доступна в разделе коды ошибок.

Поля JSON ошибки RuStorePaymentNetworkException
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Выписанный токен не соответствует покупаемому товару.
4010001Доступ к запрашиваему ресурсу запрещен (неавторизовано).
4010002Время жизни токена истекло.
4010003Платежный токен невалиден.
4030001Не передан платежный токен.
4030002Пользователь заблокирован по требованиям безопасности.
4040002, 4040003, 4040004Ошибка платежной системы.
5000***Внутренняя ошибка.