Skip to main content

10.1.0

With RuStore you can integrate payments in your mobile app.

tip

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

Look at the example app to learn how to integrate our SDK.

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

Установка плагинов

To connect, download the following packages from the releases page:

  • ru.rustore.core-version.tgz
  • ru.rustore.pay-version.tgz

Import the packages into your project via the Package Manager (Window → Package Manager → + → Add package from tarball...).

tip

If you are using macOS, change the settings of the Archive Utility. In the Archive Utility settings, uncheck Keep expanding if possible. Otherwise, the project archive will be downloaded incorrectly.

To handle SDK dependencies correctly, perform the following settings.

  1. Open the project settings: Edit → Project Settings → Player → Android Settings.

  2. In the Publishing Settings section, enable the following options:

    • Custom Main Manifest.
    • Custom Main Gradle Template.
    • Custom Gradle Properties Template.
  3. In the Other Settings section, configure:

    • package name.
    • Minimum API Level = 24.
    • Target API Level = 34.

Подключение зависимостей

Dependencies for the Android build are automatically connected using the External Dependency Manager tool.

To automatically resolve dependencies, use the command: Assets → External Dependency Manager → Android Resolver → Force Resolve. This operation should be performed every time new versions of plugins are added or when the files Assets/Plugins/Android/mainTemplate.gradle and Assets/Plugins/Android/settingsTemplate.gradle are regenerated.

  • When installing RuStore plugins via a *.unitypackage, the External Dependency Manager does not require any special installation steps.

  • When installing RuStore plugins via the Package Manager, perform the following steps:

    • Open the RuStore Core plugin tab in the Package Manager window: Window → Package Manager → Packages RuStore → RuStore Core.
    • Switch to the Samples tab.
    • Import the External Dependency Manager sample.
  • The latest version of External Dependency Manager can also be obtained from the developer’s repository on GitHub:

    • Open the Package Manager window: Window → Package Manager → + → Add package from git URL....
    • Use the URL https://github.com/googlesamples/unity-jar-resolver.git?path=/upm to add the package.
    • To resolve the error "Google.IOSResolver.dll will not be loaded", install the iOS Build Support module for your Unity version via UnityHub → Installs → Your Unity version → Add modules → iOS Build Support.
<!-- Example of the error message -->
<Assembly 'Packages/com.google.external-dependency-manager/ExternalDependencyManager/Editor/1.2.182/Google.IOSResolver.dll' will not be loaded due to errors:
Unable to resolve reference 'UnityEditor.iOS.Extensions.Xcode'. Is the assembly missing or incompatible with the current platform?
Reference validation can be disabled in the Plugin Inspector.>

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

Initialize the library before calling its methods. The initialization itself is done automatically, however, for your SDK to work, in your Manifest.xml file define console_app_id_value and internal_config_key. Both values must be placed inside the <application> tag.

<!-- 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 — product ID form the RuStore Console.

Where are app IDs in the RuStore Console?
  1. Navigate to the Applications tab and selected the needed app.
  2. Copy the ID from the URL address of the app page — it is a set of numbers between apps/ and /versions. FOr example, for URL address https://console.rustore.ru/apps/123456/versions the app ID is 123456.

Important

The application's Package Name specified in Edit → Project Settings... → Player → Android → Other Settings → Package Name must match the Package Name of the APK file you published in the RuStore Console.

Attention! Test build signature (for example: debug) of the app must match the signature of the app build that was uploaded to the console and passed moderation (for example, release)

The console_app_id_value value is set in the PayClientSettings.assets file. To create PayClientSettings.assets, in the Unity Editor menu select Window → RuStore SDK → Settings → PayClient.

The internal_config_key value is set automatically in the PayClientSettings.assets file.

Attention!

Do not set the console_app_id_value and internal_config_key values directly in the manifest. The strings must be placed in the resources file that is generated automatically based on PayClientSettings.assets.

Deeplink in the RuStore Payments SDK is required for correct integration with third-party payment apps. It helps users complete purchases faster in an external payment app and then return to your app.

To configure a deeplink in your app, follow these three main steps:

1. Create and configure an Activity class to handle the deeplink.

  1. Create the file RuStoreIntentFilterActivity.java and place it in the Assets folder of your project.
  2. Implement the RuStoreIntentFilterActivity class logic using the code below.
Attention
  • The class name must match the Java file name.
  • Only ASCII characters are allowed. The format must comply with the RFC 3986 specification.

The example implementation of RuStoreIntentFilterActivity:

  • Processes the incoming intent containing payment data.
  • Passes control to the main activity (for example, UnityPlayerActivity).
Example implementation of RuStoreIntentFilterActivity.java
package ru.rustore.unitysdk;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.unity3d.player.UnityPlayerActivity;
import ru.rustore.unitysdk.payclient.RuStoreUnityPayClient;
import ru.rustore.sdk.pay.model.SdkTheme;

public class RuStoreIntentFilterActivity extends Activity {

private final Class<?> UNITY_PLAYER_ACTIVITY_CLASS = UnityPlayerActivity.class;

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

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

if (!isTaskRoot()) {
finish();
return;
}

startGameActivity();
finish();
}

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

RuStoreUnityPayClient.INSTANCE.proceedIntent(intent);
}

private void startGameActivity() {
Intent intent = new Intent(this, UNITY_PLAYER_ACTIVITY_CLASS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}

Parameters of the proceedIntent method:

  • Intent intent — the intent that contains payment transaction data.
  • SdkTheme sdkTheme — the color theme of the payment bottom sheet. Two options are available: LIGHT and DARK (light and dark themes respectively). The default is LIGHT (optional).
  • Long maxRetryTimeMs — the maximum time (in milliseconds) for retry attempts to initialize the payment client. The default is 5000 ms (optional).

2. Update AndroidManifest.xml.

  1. Create a deeplink activity ru.rustore.unitysdk.RuStoreIntentFilterActivity with the Theme.NoDisplay theme.
  2. Move the launching intent-filter (MAIN and LAUNCHER) from the game activity to the deeplink activity.
  3. Create an intent-filter tag inside the deeplink activity specifying a link to your Deeplink Scheme.
  4. Create a meta-data tag inside <application> specifying a link to your Deeplink Scheme.
Example: AndroidManifest.xml modifications
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools">
<application>
<!-- 1. Deeplink Activity -->
<activity android:name="ru.rustore.unitysdk.RuStoreIntentFilterActivity"
android:theme="@android:style/Theme.NoDisplay"
android:exported="true">

<!-- 2. Starting intent-filter -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- 3. Deeplink intent-filter -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/rustore_PayClientSettings_deeplinkScheme" />
</intent-filter>
</activity>

<!-- 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" />

<!-- 4. Deeplink Scheme -->
<meta-data android:name="sdk_pay_scheme_value" android:value="@string/rustore_PayClientSettings_deeplinkScheme" />

<!-- Game Activity -->
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:exported="true">
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<!--
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
-->
</activity>
</application>
</manifest>

3. Specify the Deeplink Scheme in Unity settings.

  1. In the Unity Editor, go to: Window → RuStore SDK → Settings → PayClient.
  2. In the opened Inspector, find the Deeplink Scheme field and set a unique scheme for your app (for example, yourappscheme).
Attention!

Do not set deeplinkScheme directly in the manifest. The string must be placed in the resources file that is generated automatically based on PayClientSettings.assets.

Работа с SDK

Available public methods:

  • GetPurchase — allows you to get information about a purchase by its ID.
  • GetPurchases — allows you to retrieve user purchases. This method supports optional filtering by product type (consumable or non-consumable products), as well as by purchase status (statuses PAID and CONFIRMED are supported). By default, the filters are disabled, and all user purchases (regardless of product type) with statuses PAID and CONFIRMED will be returned.
  • GetPurchaseAvailability — returns the result of checking payment availability.
  • Purchase — allows you to make a product purchase with the desired payment type specified: single-stage (ONE_STEP) or two-stage (TWO_STEP). For this method, all payment options are available on the payment sheet. If the parameter is not specified, single-stage payment is used by default.
Important!

If the payment type TWO_STEP is specified, an attempt will be made to initiate a two-stage payment, but the final result will directly depend on the payment method (card, SBP, etc.) selected by the user. Two-stage payment is available only for a specific set of payment methods (currently — only for cards). SBP technologies do not support two-stage payment. If a payment method that does not support holding is selected, the purchase will be processed using the single-stage scenario.

  • PurchaseTwoStep — initiates a guaranteed two-stage purchase scenario. When using this method, the payment sheet presents the user only with payment methods that support two-stage payment. During the payment process, the buyer's funds are first held and are debited only after the purchase is confirmed using the ConfirmTwoStepPurchase method.
  • ConfirmTwoStepPurchase — confirms a purchase made using two-stage payment.
  • CancelTwoStepPurchase — cancels a purchase made using two-stage payment.
  • GetProducts — allows you to get information about active products published in the RuStore console.
Important

This method returns no more than 1000 products and works without authorization or the RuStore app being installed on the user's device.

  • RuStoreCoreClient.Instance block — a set of public methods, such as:
    • IsRuStoreInstalled — checks if the RuStore app is installed on the user's device.
    • OpenRuStoreDownloadInstruction — opens a web page for downloading the RuStore app.
    • OpenRuStore — launches the RuStore app.
    • OpenRuStoreAuthorization — launches the RuStore app for authorization. After successful user authorization, the RuStore app will automatically close.

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

To check purchase availability, call the GetPurchaseAvailability method. On calling, the following conditions are checked.

  • The company has monetization enabled via the RuStore Developer Console.
  • The application must not be banned in RuStore.
  • The user must not be banned in RuStore.
If all above conditions are met, PurchaseAvailabilityResult.isAvailable == true is returned.

Otherwise, PurchaseAvailabilityResult.isAvailable == false and PurchaseAvailabilityResult.cause are returned, where cause is the error indicating the unmet condition (possible errors are described in the Error Handling section).

Calling the GetPurchaseAvailability method
RuStorePayClient.Instance.GetPurchaseAvailability(
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
if (result.isAvailable) {
// Process success
}
else {
// Process result.cause
}
});

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

To check the user's authorization status, call the GetUserAuthorizationStatus method. The result of this method is a value from the UserAuthorizationStatus enumeration. Only two values are possible:

  • AUTHORIZED — the user is authorized in RuStore.
  • UNAUTHORIZED — the user is not authorized in RuStore. This value will also be returned if the user does not have the RuStore app installed on the device.
Calling the GetUserAuthorizationStatus method
RuStorePayClient.Instance.GetUserAuthorizationStatus(
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
if (result == UserAuthorizationStatus.AUTHORIZED) {
// Process success
}
});

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

To retrieve the products added to your application via the RuStore Console, you must use the method:s GetProducts.

Calling the GetProducts method
ProductId[] ids = ...

RuStorePayClient.Instance.GetProducts(
productIds: ids,
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
// Process success
});

ProductId[] productIds — the list of product IDs that are set when products are created in the RuStore Console. The list is limited by 1000 items.

Where are product IDs in the RuStore Console?
  1. Navigate to the Applications tab and selected the needed app.
  2. Select Monetization in the left menu.
  3. Select product type: Subscriptions or In-App purchases.
  4. Copy the IDs of the required products.

The method returns a list of products. The product model is shown below.

Product model
public class Product : BaseFields {
public ProductId productId { get; }
public ProductType type { get; }
public AmountLabel amountLabel { get; }
public Price? price { get; }
public Currency currency { get; }
public Title title { get; }
public Description? description { get; }
public Url imageUrl { get; }
public SubscriptionInfo? subscriptionInfo { get; }
}
  • productId — product ID assigned to product in RuStore Console (mandatory).
  • type — product type. CONSUMABLE/NON-CONSUMABLE/SUBSCRIPTION (consumable/non-consumable/subscription).
  • amountLabel — formatted purchase price, including currency symbol.
  • price — price in minimum currency units.
  • currency — ISO 4217 currency code.
  • title — product name in language.
  • description — descriptions in language.
  • imageUrl — image URL.
  • subscriptionInfo — subscription information (will be not null if the product type is SUBSCRIPTION).
Subscription info model
public class SubscriptionInfo {
public List<SubscriptionPeriod> periods { get; }
}
  • periods — a list of subscription periods.
Subscription period model
public interface SubscriptionPeriod { }

public sealed class TrialPeriod : SubscriptionPeriod {
public string duration { get; }
public string currency { get; }
public int price { get; }
}

public sealed class PromoPeriod : SubscriptionPeriod {
public string duration { get; }
public string currency { get; }
public int price { get; }
}

public sealed class MainPeriod : SubscriptionPeriod {
public string duration { get; }
public string currency { get; }
public int price { get; }
}

public sealed class GracePeriod : SubscriptionPeriod {
public string duration { get; }
}

public sealed class HoldPeriod : SubscriptionPeriod {
public string duration { get; }
}
  • duration — period duration in ISO 8601 format.
  • currency — ISO 4217 currency code.
  • price — the price in the smallest currency units.

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

Go get the user's purchases list, use the GetPurchases method.

Calling the method to get the user's purchase list
RuStorePayClient.Instance.GetPurchases(
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
result.ForEach(purchase => {
if (purchase is ProductPurchase productPurchase) {
// Process success
// productPurchase.productId
}
if (purchase is SubscriptionPurchase subscriptionPurchase) {
// Process success
// subscriptionPurchase.productId
}
});
});

This method allows you to filter purchases by product type and purchase status:

Product types:

  • Consumable productsProductType.CONSUMABLE_PRODUCT
  • Non-consumable productsProductType.NON_CONSUMABLE_PRODUCT
  • SubscriptionsProductType.SUBSCRIPTION

Purchase statuses:

  • For products:

    • PAID: Funds successfully held, purchase is awaiting confirmation from the developer.
    • CONFIRMED: Purchase confirmed, funds have been debited.
  • For subscriptions:

    • ACTIVE: Subscription is active.
    • PAUSED: Subscription is in Hold period (for example, due to insufficient funds on the card), attempts to debit continue according to the subscription tariff settings.

By default, filters are disabled. If values are not specified, the method will return all user purchases with statuses PAID, CONFIRMED, ACTIVE, and PAUSED, regardless of product type.

Calling the method to get the user's purchase list
RuStorePayClient.Instance.GetPurchases(
productType: ProductType.CONSUMABLE_PRODUCT,
purchaseStatus: ProductPurchaseStatus.CONFIRMED,
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
// Process success
});

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

Go get purchase information, use the getPurchase method.
Calling the method to get the user's purchase list
RuStorePayClient.Instance.GetPurchase(
purchaseId: purchase.purchaseId,
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
result.ForEach(purchase => {
if (purchase is ProductPurchase productPurchase) {
// Process success
// productPurchase.productId
}
if (purchase is SubscriptionPurchase subscriptionPurchase) {
// Process success
// subscriptionPurchase.productId
}
});
});

Типы покупок

The SDK provides a basic interface IPurchase, which combines the common fields of all purchase types. Based on it, two implementations have been created:

  • ProductPurchase: for consumable and non-consumable purchases.
  • SubscriptionPurchase: for subscriptions.

This separation allows each purchase type to have its own unique properties and behavior.

Purchase Interface
public interface IPurchase {
PurchaseId purchaseId { get; }
InvoiceId invoiceId { get; }
OrderId? orderId { get; }
PurchaseType purchaseType { get; }
Enum status { get; }
Description description { get; }
DateTime? purchaseTime { get; }
Price price { get; }
AmountLabel amountLabel { get; }
Currency currency { get; }
DeveloperPayload? developerPayload { get; }
bool sandbox { get; }
}

Модель разовой покупки ProductPurchase

ProductPurchase Model
public class ProductPurchase : BaseFields, IPurchaseStatus<ProductPurchaseStatus> {
public AmountLabel amountLabel { get; }
public Currency currency { get; }
public Description description { get; }
public DeveloperPayload? developerPayload { get; }
public InvoiceId invoiceId { get; }
public OrderId? orderId { get; }
public Price price { get; }
public ProductId productId { get; }
public ProductType productType { get; }
public PurchaseId purchaseId { get; }
public DateTime? purchaseTime { get; }
public PurchaseType purchaseType { get; }
public Quantity quantity { get; }
public ProductPurchaseStatus status { get; }
public bool sandbox { get; }

...
}
  • amountLabel — formatted purchase price, including currency symbol.
  • currency — ISO 4217 currency code.
  • description - purchase description.
  • developerPayload — a string with additional order information that you can set when confirming the purchase. This string overrides the value set during initialization
  • invoiceId — invoice ID. Invoice identifier. Used for server-side payment validation, searching payments in the developer console, and is also displayed to the user in the payment history in the RuStore mobile app.
  • orderId - unique payment identifier specified by the developer or generated automatically (uuid).
  • price — price in minimum currency units.
  • productId — product ID assigned to product in RuStore Console (mandatory). Product identifier assigned to the product in the RuStore Console (required parameter).
  • productType — product type. (CONSUMABLE/NON-CONSUMABLE - consumable/non-consumable.)
  • purchaseId — product ID. Purchase identifier. Used to obtain purchase information in the SDK via the purchase information retrieval method.
  • purchaseTime — purchase time.
  • PurchaseType — purchase type:
    • ONE_STEP - one-stage payment;
    • TWO_STEP - two-stage payment;
    • UNDEFINED — number of payment stages is undefined.
  • quantity — product quantity.
  • status — purchase state:
    • INVOICE_CREATED — purchase invoice is created and awaiting payment;
    • CANCELLED — purchase canceled by the user;
    • PROCESSING — payment initiated;
    • REJECTED — purchase rejected (for example: due to insufficient funds);
    • EXPIRED — payment time expired;
    • PAID — only for two-stage payments, intermediate status, funds are put on hold on the user's account, the purchase is awaiting confirmation from the developer;
    • CONFIRMED — purchase successfully paid for;
    • REFUNDING — refund initiated, request sent to acquirer ;
    • REFUNDED — purchase successfully refunded;
    • REVERSED — only for two-stage payment: wither the purchase was canceled by the developer or there was no payment within 6 hours, the funds on the user's account are put off hold.
  • — test payment flag. true — test payment, false — actual payment

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

One-stage payment status model.

Two-stage payment status model.

Модель подписки SubscriptionPurchase

SubscriptionPurchase Model
public class SubscriptionPurchase : BaseFields, IPurchaseStatus<SubscriptionPurchaseStatus> {
public PurchaseId purchaseId { get; }
public InvoiceId invoiceId { get; }
public OrderId? orderId { get; }
public PurchaseType purchaseType { get; }
public SubscriptionPurchaseStatus status { get; }
public Description description { get; }
public DateTime? purchaseTime { get; }
public Price price { get; }
public AmountLabel amountLabel { get; }
public Currency currency { get; }
public DeveloperPayload? developerPayload { get; }
public bool sandbox { get; }
public ProductId productId { get; }
public DateTime? expirationDate { get; }
public bool gracePeriodEnabled { get; }

...
}
  • purchaseId — product ID. Purchase identifier. Used to obtain purchase information in the SDK via the purchase information retrieval method.
  • invoiceId — invoice ID. Invoice identifier. Used for server-side payment validation, searching payments in the developer console, and is also displayed to the user in the payment history.
  • orderId - unique payment identifier specified by the developer or generated automatically (uuid).
  • purchaseType — purchase type:
    • ONE_STEP - one-stage payment;
    • TWO_STEP - two-stage payment;
    • UNDEFINED — number of payment stages is undefined.
  • status — subscription status:
    • INVOICE_CREATED — invoice created, subscription is awaiting payment.
    • CANCELLED — subscription invoice cancelled.
    • EXPIRED — invoice payment period expired.
    • PROCESSING — first subscription payment is being processed.
    • REJECTED — first subscription payment was rejected. Subscription not activated.
    • ACTIVE — subscription is active.
    • EXPIRED — subscription period expired. (Same as above: not the subscription, but the time to pay the first invoice for subscription activation expired, so no subscription was created.)
    • PAUSED — subscription is paused due to payment issues.
    • TERMINATED — all attempts to charge the subscription failed. Subscription automatically closed due to payment issues.
    • CLOSED — subscription was cancelled by the user or developer. The paid period expired, subscription is closed.
  • description — purchase description.
  • purchaseTime — purchase time.
  • price — price in minimum currency units.
  • amountLabel — formatted purchase price, including currency symbol.
  • currency — ISO 4217 currency code.
  • developerPayload — a string with additional order information that you can set when confirming the purchase. This string overrides the value set during initialization
  • — test payment flag. true — test payment, false — actual payment
  • productId — product ID assigned to product in RuStore Console (mandatory). Product identifier assigned to the product in the RuStore Console (required parameter).
  • expirationDate — subscription expiration date.
  • gracePeriodEnabled — flag indicating whether the grace period is active for the subscription.

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

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

Пояснения по работе с одностадийными и двухстадийными оплатами
  • When using a single-stage payment, the purchase does not require confirmation; the funds are immediately debited from the buyer’s account, and a commission is charged to the developer. In this case, if a refund to the customer is required (for example, if the product cannot be delivered for some reason), a refund can only be processed via the RuStore Console, and the funds will be returned to the buyer within a few days. The full purchase amount is refunded, but the commission previously withheld from the developer is not reimbursed.
  • In the case of a two-stage payment, the funds are first held (authorized) on the buyer’s account. No commission is charged at this stage. After the hold, the purchase requires either confirmation or cancellation. The commission is charged to the developer upon purchase confirmation. Cancelling the purchase releases the hold, and the funds instantly become available to the buyer again.
Важно

Two-stage payment is available only for a specific set of payment methods (currently — only for cards). SBP technologies do not support two-stage payment. If a payment method that does not support holding funds is selected, the purchase will be processed using the single-stage scenario.

Payment with purchase type selection

To start a product purchase with the ability to choose the purchase flow (one-step or two-step), use the Purchase method:

Calling the product purchase method
var parameters = new ProductPurchaseParams(
productId: new ProductId("product_id"),
appUserEmail: null,
appUserId: null,
developerPayload: null,
orderId: null,
quantity: new Quantity(1)
);

var sdkTheme = SdkTheme.DARK;

RuStorePayClient.Instance.Purchase(
parameters: parameters,
preferredPurchaseType: PreferredPurchaseType.ONE_STEP,
sdkTheme,
onFailure: (error) => {
switch (error) {
case RuStorePaymentException.ProductPurchaseCancelled cancelled:
// Handle cancelled purchase
break;
case RuStorePaymentException.ProductPurchaseException exception:
// Handle failed purchase
break;
default:
// Handle other error
break;
}
},
onSuccess: (result) => {
// Process success
});
  • productId — product ID assigned to product in RuStore Console (mandatory).
  • quantity — product amount (optional, value 1 will be used if not specified).
  • orderId — payment ID generated by the app (optional). If you specify this parameter in your system, you will receive it via our API. If not specified, will be generated automatically (uuid). 150 characters max.
  • developerPayload — a string with additional order information that you can set when confirming the purchase. This string overrides the value set during initialization. Maximum length is 250 characters.
  • appUserId — the internal user ID in your application (optional parameter). A string with a maximum length of 128 characters.
    tip

    For example, this parameter can be used to detect cases of fraud in your application, which will help improve its security.

  • appUserEmail — this is an optional parameter that allows you to specify the user's email address in your application. If the buyer's email address was provided during registration in the app, it can be passed for automatic filling of the email field when sending a receipt — both for payments outside RuStore and in cases where the user is not authorized in RuStore. This saves the user from having to manually enter their email, shortens the purchase flow, and helps increase conversion.
  • preferredPurchaseType — the desired purchase type: single-stage (ONE_STEP) or two-stage (TWO_STEP).
  • sdkTheme — the color theme of the payment bottom sheet. Two options are available: LIGHT and DARK (light and dark themes respectively). The default is LIGHT.
Important

This method is launched by default using the single-stage payment scenario (preferredPurchaseType = PreferredPurchaseType.ONE_STEP), i.e., without funds being held.

For two-stage payment, you need to specify preferredPurchaseType = PreferredPurchaseType.TWO_STEP. Two-stage payment (i.e., payment with funds being held) is not guaranteed for this method and directly depends on the payment method (card, SPB, etc.) selected by the user.

When launching this method (with the preferred preferredPurchaseType = twoStep), until the user selects a payment method, the purchase stage will be UNDEFINED. Please take this behavior into account when handling purchase cancellation results (ProductPurchaseCancelled) or purchase errors (ProductPurchaseException).

Two-step payment (with funds hold)

To start a product purchase using the two-step flow, use the PurchaseTwoStep method:

Calling the product purchase method
var parameters = new ProductPurchaseParams(
productId: new ProductId("product_id"),
appUserEmail: null,
appUserId: null,
developerPayload: null,
orderId: null,
quantity: new Quantity(1)
);

var sdkTheme = SdkTheme.DARK;

RuStorePayClient.Instance.PurchaseTwoStep(
parameters: parameters,
sdkTheme,
onFailure: (error) => {
switch (error) {
case RuStorePaymentException.ProductPurchaseCancelled cancelled:
// Handle cancelled purchase
break;
case RuStorePaymentException.ProductPurchaseException exception:
// Handle failed purchase
break;
default:
// Handle other error
break;
}
},
onSuccess: (result) => {
// Process success
});

Purchase parameters structure

Purchase parameters structure
public class ProductPurchaseParams : BaseFields {
public ProductId productId { get; }
public AppUserEmail? appUserEmail { get; }
public AppUserId? appUserId { get; }
public Quantity? quantity { get; }
public OrderId? orderId { get; }
public DeveloperPayload? developerPayload { get; }
}
  • productId — product ID assigned to product in RuStore Console (mandatory).
  • quantity — product amount (optional, value 1 will be used if not specified).
  • orderId — payment ID generated by the app (optional). If you specify this parameter in your system, you will receive it via our API. If not specified, will be generated automatically (uuid). 150 characters max.
  • developerPayload — a string with additional order information that you can set when confirming the purchase. This string overrides the value set during initialization. Maximum length is 250 characters.
  • appUserId — the internal user ID in your application (optional parameter). A string with a maximum length of 128 characters.
    tip

    For example, this parameter can be used to detect cases of fraud in your application, which will help improve its security.

  • appUserEmail — this is an optional parameter that allows you to specify the user's email address in your application. If the buyer's email address was provided during registration in the app, it can be passed for automatic filling of the email field when sending a receipt — both for payments outside RuStore and in cases where the user is not authorized in RuStore. This saves the user from having to manually enter their email, shortens the purchase flow, and helps increase conversion.
  • sdkTheme — the color theme of the payment bottom sheet. Two options are available: LIGHT and DARK (light and dark themes respectively). The default is LIGHT.

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

public sealed class ProductPurchaseResult : BaseFields {

public InvoiceId invoiceId { get; }
public OrderId? orderId { get; }
public ProductId productId { get; }
public ProductType productType { get; }
public PurchaseId purchaseId { get; }
public PurchaseType purchaseType { get; }
public Quantity quantity { get; }
public bool sandbox { get; }

...
}
  • ProductPurchaseResult — the result of a successful digital product payment (for single-stage payment) or successful funds holding (for two-stage payment).
    • invoiceId — invoice identifier. Used for server-side payment validation, searching payments in the developer console, and is also displayed to the user in the payment history in the RuStore mobile app.
    • orderId — unique payment identifier specified by the developer or generated automatically (uuid).
    • productId — identifier of the purchased product, specified when created in the RuStore developer console.
    • productType — product type NON-CONSUMABLE/CONSUMABLE/SUBSCRIPTION (non-consumable/consumable/subscription).
    • purchaseId — purchase identifier. Used to obtain purchase information in the SDK via the purchase information retrieval method.
    • purchaseType — purchase type (ONE_STEP/TWO_STEP/UNDEFINED — single-stage/two-stage/undefined).
    • quantity — quantity of the purchased product.
    • sandbox — flag indicating a test payment in the sandbox. If TRUE, the purchase was made in test mode.

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

If an error occurs during payment or the user cancels the purchase,
the execution of the payment method (both with purchase type selection and the two-stage method) ends with an error:

  • ProductPurchaseException — product purchase error.
  • ProductPurchaseCancelled — error caused by product purchase cancellation (the user closed the payment sheet) before receiving the purchase result.
    In such cases, it is recommended to additionally check the purchase status using the method for retrieving purchase information.

Payment Error Model

public sealed class ProductPurchaseException : RuStorePaymentException {

public InvoiceId? invoiceId { get; }
public OrderId? orderId { get; }
public ProductId? productId { get; }
public ProductType? productType { get; }
public PurchaseId? purchaseId { get; }
public PurchaseType? purchaseType { get; }
public Quantity? quantity { get; }
public bool? sandbox { get; }

...
}
  • invoiceId — invoice identifier. Used for server-side payment validation, searching payments in the developer console, and is also displayed to the user in the payment history in the RuStore mobile app.
  • orderId — unique payment identifier specified by the developer or generated automatically (uuid).
  • productId — identifier of the purchased product, specified when created in the RuStore developer console.
  • productType - product type (NON_CONSUMABLE_PRODUCT - non-consumable product, CONSUMABLE_PRODUCT - consumable product, SUBSCRIPTION - subscription).
  • purchaseId — purchase identifier. Used to obtain purchase information in the SDK via the purchase information retrieval method.
  • purchaseType — purchase type (ONE_STEP/TWO_STEP/UNDEFINED — single-stage/two-stage/undefined).
  • quantity — quantity of the product specified at the start of the purchase.
  • sandbox — flag indicating a test payment in the sandbox. If TRUE, the purchase was made in test mode.

Payment Cancellation Model

public sealed class ProductPurchaseCancelled : RuStorePaymentException {

public ProductType? productType { get; }
public PurchaseId? purchaseId { get; }
public PurchaseType? purchaseType { get; }

...
}
  • purchaseId — purchase identifier. Used to obtain purchase information in the SDK via the purchase information retrieval method.
  • purchaseType — purchase type (ONE_STEP/TWO_STEP/UNDEFINED — single-stage/two-stage/undefined).
  • productType — product type (NON_CONSUMABLE_PRODUCT - non-consumable product, CONSUMABLE_PRODUCT - consumable product, SUBSCRIPTION - subscription).

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

If you need to validate a successful purchase on the RuStore server, you can use the invoiceId from the SuccessProductPurchaseResult model returned after a successful product purchase.

Getting invoiceId from the purchase result
var parameters = new ProductPurchaseParams(
productId: new ProductId("product_id"));

RuStorePayClient.Instance.Purchase(
parameters: parameters,
preferredPurchaseType: PreferredPurchaseType.TWO_STEP,
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
var invoiceId = result.invoiceId.value;
yourApi.validate(invoiceId);
});

You can also get the invoiceId from the Purchase model. The Purchase model can be obtained using the GetPurchases() method or the GetPurchase method.

RuStorePayClient.Instance.GetPurchases(
onFailure: (error) => {
// Process error
},
onSuccess: (result) => {
result.ForEach(item => {
yourApi.validate(item.subscriptionToken);
});
});

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

Only purchases initiated using the two-stage payment scenario, i.e., with funds being held, require confirmation. After successful holding, such purchases will have the status ProductPurchaseStatus.PAID.

To debit funds from the buyer's card, purchase confirmation is required. For this, you must use the ConfirmTwoStepPurchase method.

Calling the confirmation method
PurchaseId id = ...
DeveloperPayload payload = ...

RuStorePayClient.Instance.ConfirmTwoStepPurchase(
purchaseId: purchaseId,
developerPayload: payload,
onFailure: (error) => {
// Process error
},
onSuccess: () => {
// Process success
});
  • purchaseId — product ID.
  • developerPayload — a string with additional order information that you can set when confirming the purchase. This string overrides the value set during initialization (optional). Maximum 250 characters. If provided, it overrides the value set at the start of the purchase using the Purchase/PurchaseTwoStep method.

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

With our SDK you can cancel only the purchases that undergo a two-stage payment process, i.e. when the user's money is put on hold. After a successful hold, such purchases are in the ProductPurchaseStatus.PAID status. If a purchase is canceled it has the ProductPurchaseStatus.REVERSED status.

tip

Cancel purchases if you cannot deliver your product after payment is made (when the user's money is put on hold).

To cancel a purchase (put the user's money off hold), use the CancelTwoStepPurchase method.

Calling the CancelTwoStepPurchase method
PurchaseId id = ...

RuStoreBillingClient.Instance.CancelTwoStepPurchase(
purchaseId: id,
onFailure: (error) => {
// Process error
},
onSuccess: () => {
// Process success
}
);
  • purchaseId — product ID.

RuStoreUtils

RuStoreUtils is a block in the native SDK containing a set of public methods intended for interacting with the RuStore app on the user's device.

To access the block's methods in the Unity environment, use the singleton class RuStoreCoreClient.

The IsRuStoreInstalled method checks if the RuStore app is installed on the user's device.

Calling the IsRuStoreInstalled method
if (RuStorePayClient.Instance.IsRuStoreInstalled()) {
// RuStore is installed on the user's device
} else {
// RuStore is not installed on the user's device
}

The openRuStoreDownloadInstruction method opens a web page for downloading the RuStore mobile application.

Calling the openRuStoreDownloadInstruction method
RuStoreCoreClient.Instance.openRuStoreDownloadInstruction();

The openRuStore method launches the RuStore mobile application. When this method is called, if the RuStore app is not installed, a Toast notification with the message "Failed to open the application" will be displayed.

Calling the openRuStore method
RuStoreCoreClient.Instance.openRuStore();

The openRuStoreAuthorization method launches the RuStore mobile application for authorization. After successful user authorization, the RuStore app will automatically close. When this method is called, if the RuStore app is not installed, a Toast notification with the message "Failed to open the application" will be displayed.

Calling the openRuStoreAuthorization method
RuStoreCoreClient.Instance.openRuStoreAuthorization();

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

RuStoreError — base class for errors.

RuStoreError Class
public class RuStoreError {
public string name;
public string description;
}
  • name – error name.
  • description – error description.

RuStorePaymentException — base class for payment client errors.

public class RuStorePaymentException : RuStoreError {
public virtual RuStoreError? cause { get; }
...
}
  • cause – additional error information.

Inherited fields:

  • name – error name.
  • description – error description.

RuStorePaymentNetworkException — SDK network interaction error. The error model returns an error code (field code), which can be used to determine the cause of the error. The table with error codes is available in the error codes section.

RuStorePaymentNetworkException Class
public class RuStorePaymentNetworkException : RuStorePaymentException {
public string? code { get; }
public string id { get; }
...
}
  • code — error code.
  • id — unique identifier.

Inherited fields:

  • name – error name.
  • description – error description.
  • cause – additional error information.

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

  • RuStorePaymentNetworkException — SDK network communication error;
  • RuStorePaymentCommonException — general SDK error;
  • RuStorePayClientAlreadyExist — SDK re-initialization error;
  • RuStorePayClientNotCreated — attempt to access public SDK interfaces before initialization;
  • RuStorePayInvalidActivePurchase — payment initiated for unknown product type;
  • RuStorePayInvalidConsoleAppId — the required parameter console_application_id for SDK initialization is not specified;
  • RuStorePaySignatureException — invalid response signature. Occurs when attempting fraudulent actions;
  • EmptyPaymentTokenException — error obtaining payment token;
  • InvalidCardBindingIdException — error when paying with a saved card;
  • ApplicationSchemeWasNotProvided — scheme for the return deeplink is not specified;
  • ProductPurchaseException — product purchase error. The model structure is described in the section purchase result structure;
  • ProductPurchaseCancelled — product purchase was cancelled (the user closed the payment sheet). The model structure is described in the section purchase result structure;
  • ProductPurchaseException — product purchase error;
  • RuStoreNotInstalledException — RuStore is not installed on the user's device;
  • RuStoreOutdatedException — the installed version of RuStore on the device does not support payments;
  • RuStoreUserUnauthorizedException — the user is not authorized in RuStore;
  • RuStoreApplicationBannedException — the application is banned in RuStore;
  • RuStoreUserBannedException — the user is banned in RuStore.

Error Codes

Error CodeDescription
4000001The request is malformed: a required parameter is missing or incorrectly filled, or the data format is invalid.
4000002, 4000016, 4040005Application not found.
4000003Application is banned.
4000004Application signature does not match the registered one.
4000005Company not found.
4000006Company is banned.
4000007Company monetization is disabled or inactive.
4000014Product not found.
4000015Product not published.
4000017Invalid quantity parameter.
4000018Purchase limit exceeded.
4000020Product already purchased.
4000021Unfinished product purchase.
4000022Purchase not found.
4000025No suitable payment method found.
4000026Invalid purchase type for confirmation (should be two-stage payment).
4000027Invalid purchase status for confirmation.
4000028Invalid purchase type for cancellation (should be two-stage payment).
4000029Invalid purchase status for cancellation.
4000030The issued token does not match the purchased product.
4000041An active subscription already exists for this product code.
4000045Maximum size limit exceeded.
4010001Access to the requested resource is forbidden (unauthorized).
4010002Token lifetime has expired.
4010003Payment token is invalid.
4030001Payment token not provided.
4030002User is blocked due to security requirements.
4040002, 4040003, 4040004Payment system error.
5000***Internal error.