9.1.0 (актуальная версия)
RuStore позволяет интегрировать платежи в мобильное приложение.
-
Если не знаете с чего начать, прочтите инструкцию в сценариях использования.
-
Если вы переходите на Pay SDK с billingClient SDK, ознакомьтесь с инструкцией по переходу. Подробности о Pay SDK можно узнать тут.
Подключение в проект
- Скопируйте проекты плагина и приложения-примера из официального репозитория RuStore на GitFlic.
- Скопируйте папки
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 Консоль отображаются идентификаторы приложений?
- Перейдите на вкладку Приложен ия и выберите нужное приложение.
- Скопируйте идентификатор из 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
Deeplink в RuStore SDK платежей нужна для корректной работы со сторонними приложениями оплаты. Она помогает пользователям быстрее совершать покупки в стороннем приложении и возвращаться в ваше приложение.
Плагин RuStorePay содержит реализацию RuStoreIntentFilterActivity
, которая обрабатывает входящие intent и возвращается в игровую активити com.dynamo.android.DefoldActivity
.
Для включения в сборку добавьте RuStoreIntentFilterActivity
в AndroidManifest.xml
указав intent-filter
и meta-data
.
<!-- 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
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 с информацией о продуктах (см. ниже).
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
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 с информацией о покупках (см. ниже).
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
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
-- 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
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 символов.tipНапример, данный параметр может использоваться для выявления случаев мошенничества в вашем приложении, что позволит повысить его безопасность.
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
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)
Структура параметров покупки
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 символов.tipНапример, данный параметр может использоваться для выявления случаев мошенничества в вашем приложении, что позволит повысить его безопасность.
appUserEmail
— это необязательный параметр, позволяющий задать адрес электронной почты пользователя в вашем приложении. Если адрес электронной почты покупателя был указан при регистрации в приложении, его можно передать для автоматического заполнения поляemail
при отправке чека — как для платежей вне RuStore, так и для случаев, когда пользователь не авторизован в RuStore. Это избавляет пользователя от необходимости вручную вводить email, сокращает путь до покупки и способствует повышению конверсии.
Структура результата покупки
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 | Выписанный токен не соответствует покупаемому товару. |
4010001 | Доступ к запрашиваему ресурсу запрещен (неавторизовано). |
4010002 | Время жизни токена истекло. |
4010003 | Платежный токен невалиден. |
4030001 | Не передан платежный токен. |
4030002 | Пользователь заблокирован по требованиям безопасности. |
4040002 , 4040003 , 4040004 | Ошибка платежной системы. |
5000*** | Внутренняя ошибка. |