Skip to main content

In-app Payments SDK for React Native (версия 10.0.1)

With RuStore you can integrate payments in your mobile app.

tip

Getting Started

Add the following lines to android/app/build.gradle.

android/app/build.gradle
dependencies {
implementation("com.facebook.react:react-android")
implementation("ru.rustore.sdk-wrapper.react-native:pay:10.1.0")

// ... other dependencies
}

To download dependencies, add the repository:

maven {
url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven")
}

Project setup

  • Application ID: ru.rustore.react.pay.example
  • Minimum SDK version: Android API 24
  • Target SDK version: Android API 36

Registering the native module

To use the library, register the native module in MainApplication.java:

import ru.rustore.react.pay.RuStoreReactPayPackage;

// ...

@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new RuStoreReactPayPackage());
return packages;
}

JavaScript interface

The project includes a JavaScript interface for working with the Android native module.
All methods are located in the src/libs/RuStoreReactPay/ directory of the example implementation repository — copy them into your project.

Key files

  • index.tsx — the main module with methods for working with payments
  • types.ts — TypeScript types for working with payments

Deeplink handling in the RuStore SDK enables efficient interaction with third-party applications when processing payments through banking apps (SBP, SberPay, T-Pay, etc.). This allows you to redirect the user to the payment screen and, after the transaction is completed, return them to your application.

To set up deeplink support in your application and Pay SDK, specify the deeplinkScheme using sdk_pay_scheme_value
in your AndroidManifest.xml file and override the onNewIntent method of your Activity.

Attention
  • When using deeplinks, specifying the scheme is mandatory.
  • If a payment is attempted without specifying the scheme, an error will occur.
  • Only ASCII characters are allowed. The format must comply with RFC 3986.

Specifying deeplinkScheme:

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your.app.package.name">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App"
tools:targetApi="n">
<!-- ... -->

<activity
android:name=".YourPayActivity">

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

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourappscheme" />
</intent-filter>

</activity>

<meta-data
android:name="sdk_pay_scheme_value"
android:value="yourappscheme" />

</application>
</manifest>
tip

Replace yourappscheme with the name of your scheme. For example, ru.package.name.rustore.scheme.

Next, add the following code to the Activity you want to return to after the payment is completed (your application page):

class YourPayActivity: AppCompatActivity() {

private val intentInteractor: IntentInteractor by lazy {
RuStorePayClient.instance.getIntentInteractor()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
intentInteractor.proceedIntent(intent)
}
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intentInteractor.proceedIntent(intent)
}
}

To restore the state of your application when returning via deeplink, add the android:launchMode="singleTop" attribute to your AndroidManifest.xml.

Specifying launchMode:

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your.app.package.name">
<!-- ... -->

<application>
<!-- ... -->
<activity
android:name=".YourPayActivity"
android:launchMode="singleTop"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">

<!-- ... -->

</activity>
<!-- ... -->
</application>

</manifest>

SDK Initialization

Initialize the library before calling its methods. The initialization itself is done automatically, however, for your SDK to work, in your AndroidManifest.xml file define console_app_id_value.

AndroidManifest.xml
<meta-data
android:name="console_app_id_value"
android:value="@string/CONSOLE_APPLICATION_ID" />

В strings.xml замените строку с вашим app_id.

strings.xml
<string name="CONSOLE_APPLICATION_ID">your_app_id</string>

CONSOLE_APPLICATION_ID — 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 ApplicationId in build.gradle, must match the applicationId APK-файла, of the APK you published in RuStore Console.
  • The keystore signature must match the signature that was used to sign the app published in the RuStore Console. Make sure that buildType used (example: debug) uses the same signature as the published app (example: release).

info

For security, the SDK sets android:usesCleartextTraffic="false" by default to prevent transmitting data over unsecured HTTP and to protect against man-in-the-middle attacks. If your app requires HTTP, you can set this attribute to true, but do so at your own risk as it increases the chance of data interception and tampering. We recommend allowing cleartext traffic only in exceptional cases and for trusted domains, and preferring HTTPS for all network interactions.

SDK Methods

Available public interactors:

  • PurchaseInteractor - work with payments; public methods include:

    • RuStoreReactPay.getPurchase(purchaseId: string): Promise<{ productPurchase?: ProductPurchase; subscriptionPurchase?: SubscriptionPurchase }> - fetch purchase info by ID.

    • RuStoreReactPay.getPurchases(params?: { productType?: ProductType; purchaseStatus?: ProductPurchaseStatus | SubscriptionPurchaseStatus; }): Promise<Array<{ productPurchase?: ProductPurchase; subscriptionPurchase?: SubscriptionPurchase }>> — fetch user purchases. Optional filtering by product type (consumables, non-consumables, subscriptions) and purchase status (PAID, CONFIRMED, ACTIVE, PAUSED). By default filters are off and all purchases in these statuses are returned regardless of product type.

    • RuStoreReactPay.getPurchaseAvailability(): Promise<PurchaseAvailability> - returns whether payments are available.

    • RuStoreReactPay.purchase(params: { productId: string; orderId?: string; quantity?: number; developerPayload?: string; appUserId?: string; appUserEmail?: string; preferredPurchaseType?: PreferredPurchaseType; }): Promise<ProductPurchaseResult> - start a purchase with a preferred type — one-step (ONE_STEP) or two-step (TWO_STEP). On the payment sheet all methods are available. If not specified, defaults to one-step.

      Important

      If TWO_STEP is specified, the SDK will attempt a two-step flow, but the final result depends on the payment method chosen by the user (card, SBP, etc.)

      Note that TWO_STEP is unavailable:

      • When paying via SBP.

      • When purchasing subscriptions.

      • Two-step payment is available only for certain methods (currently cards and SberPay). If the selected method doesn’t support holds, the purchase will run as a one-step payment..

    • RuStoreReactPay.purchaseTwoStep(params: { productId: string; orderId?: string; quantity?: number; developerPayload?: string; appUserId?: string; appUserEmail?: string; }): Promise<ProductPurchaseResult> - starts a guaranteed two-step purchase. The payment sheet will show only methods that support two-step payments. The payment first places a hold on the buyer’s funds, and funds are captured only after confirmTwoStepPurchase.

    • RuStoreReactPay.confirmTwoStepPurchase(params: { purchaseId: string; developerPayload?: string; }): Promise<void> - confirm a two-step purchase.

    • RuStoreReactPay.cancelTwoStepPurchase(purchaseId: string): Promise<void> - cancel a two-step purchase..

  • ProductInteractor - work with products:

    • RuStoreReactPay.getProducts(ids: string[]): Promise<Product[]> - get info for active products published in RuStore Console.
      Important

      Returns no more than 1000 products and works without authorization and without RuStore being installed on the device.

  • UserInteractor - get UserAuthorizationStatus.

    • AUTHORIZED - the user is authorized in RuStore
    • UNAUTHORIZED - the user is not authorized in RuStore.
      Additional method: RuStoreReactPay.getUserAuthorizationStatus(): Promise<boolean>true corresponds to AUTHORIZED, falseUNAUTHORIZED.
  • IntentInteractor - handle intents:

    • proceedIntent(intent) — process deeplinks used to pay in banking apps. Call this method to properly return to the payment sheet when coming back from the bank app.
  • RuStoreUtils - a set of utility methods:

    • isRuStoreInstalled - check whether the RuStore app is installed on the user’s device.
    • openRuStoreDownloadInstruction - open the page to download RuStore.
    • openRuStore - launch the RuStore app.
    • openRuStoreAuthorization - launch RuStore for authorization. After a successful sign-in, the RuStore app closes automatically.

Purchase types

In the SDK, there is a base Purchase interface that unifies the common fields for all purchase types. It has two implementations:

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

This separation allows each purchase type to expose its own specific properties and behavior.

Purchase interface
interface Purchase {
purchaseId: string;
invoiceId: string;
orderId?: string;
purchaseType: PurchaseType;
status: PurchaseStatus;
description: string;
purchaseTime?: string; /** Purchase time in ISO‑8601 format */
price: number;
amountLabel: string;
currency: string; /** Currency code in ISO 4217 format */
developerPayload?: string;
sandbox: boolean;
}

Retrieving purchase information

Go get purchase information, use the getPurchase method.
// Retrieve specific purchase information
RuStoreReactPay.getPurchase(purchaseId: string): Promise<{
productPurchase?: ProductPurchase;
subscriptionPurchase?: SubscriptionPurchase;
}>

// Retrieve purchase list with with filtration
RuStoreReactPay.getPurchases(params?: {
productType?: ProductType;
purchaseStatus?: ProductPurchaseStatus | SubscriptionPurchaseStatus;
}): Promise<Array<{
productPurchase?: ProductPurchase;
subscriptionPurchase?: SubscriptionPurchase;
}>>

The method returns information about a specific purchase in any status. The purchase model is specified in the purchase types section.

Retrieving purchase list

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

Calling retrieving purchases list method
RuStoreReactPay.getPurchases()
.then((purchases) => {
purchases.forEach((purchase) => {
// Each purchase could include either `productPurchase` array, or `subscriptionPurchase`
const { productPurchase, subscriptionPurchase } = purchase;
if (productPurchase) {
console.log(`Product ID: ${productPurchase.productId}, Status: ${productPurchase.status}`);
} else if (subscriptionPurchase) {
console.log(`Product ID: ${subscriptionPurchase.productId}, Status: ${subscriptionPurchase.status}`);
}
});
})
.catch((error) => {
// Handling errors
});

This method lets you filter purchases by product type and purchase status.

Product types:

  • Consumable products - ProductType.CONSUMABLE_PRODUCT
  • Non-consumable products - ProductType.NON_CONSUMABLE_PRODUCT
  • ПSubscriptions - ProductType.SUBSCRIPTION

Purchase statuses:

  • For products:

    • PAID: Funds are successfully held; the purchase awaits developer confirmation.
    • CONFIRMED: The purchase is confirmed; funds have been captured.
  • For subscriptions:

    • ACTIVE: The subscription is active.
    • PAUSED: The subscription is in a hold/grace period (for example, due to insufficient funds); retries continue as per the subscription tariff settings.

By default, filters are disabled. If values are not provided, the method returns all user purchases in thePAID, CONFIRMED, ACTIVE и PAUSED statuses, regardless of product type.

Calling retrieving purchases list method with filtration
// Example of calling with enabled product type and purchase status filters 
// Pass an object with the relevant fields: productType and status
RuStoreReactPay.getPurchases({
// productType: ProductType.consumable,
// status: ProductPurchaseStatus.paid,
})
.then((purchases) => {
purchases.forEach((purchase) => {
const { productPurchase, subscriptionPurchase } = purchase;
if (productPurchase) {
console.log(`Product ID: ${productPurchase.productId}, Status: ${productPurchase.status}`);
} else if (subscriptionPurchase) {
console.log(`Product ID: ${subscriptionPurchase.productId}, Status: ${subscriptionPurchase.status}`);
}
});
})
.catch((error) => {
// Handling errors
});

Retrieving product list

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

// Getting a list of products
RuStoreReactPay.getProducts(productIds)
.then((response) => {
// response.products — an array of products
response.products.forEach((product) => {
console.log(product.productId);
});
})
.catch((err) => {
console.log('products err:', err);
});

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.

export type Product = {
productId: string;
type: ProductType;
amountLabel: string;
price?: number;
currency: string;
imageUrl: string;
title: string;
description?: string;
subscriptionInfo?: SubscriptionInfo;
};
  • productId — product ID assigned to product in RuStore Console (mandatory).
  • type — product type. CONSUMABLE/NON-CONSUMABLE
  • 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.

Response examples

Consumable product model example
Product(
productId = ProductId("conProduct1"),
type = ProductType.CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("100.00 rub"),
price = Price(10000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_consumable_product.png"),
title = Title("Consumable product name"),
description = Description("Consumable product description"),
)
Non-consumable product model example
Product(
productId = ProductId("nonConProduct1"),
type = ProductType.NON_CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("200.00 rub"),
price = Price(20000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_non_consumable_product.png"),
title = Title("Non-consumable product name"),
description = Description("Non-consumable product description"),
)
Subscription model example
Product(
productId = ProductId("sub_1"),
type = ProductType.SUBSCRIPTION,
amountLabel = AmountLabel("300.00 rub"),
price = Price(30000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_subscription.png"),
title = Title("Subscription name"),
description = Description("Subscription description"),
)

Determine user authorization status

To check the user's authorization status, call the getUserAuthorizationStatus method on the RuStoreReactPay. The result of this method is the Promise<boolean>: true — user is authorized in RuStore, false — user is not authorized in RuStore (or RuStore is not installed on the user's device).

RuStoreReactPay.getUserAuthorizationStatus()
.then((isAuthorized) => {
if (isAuthorized) {
// Logic for when the user is authorized in RuStore
} else {
// Logic for when the user is NOT authorized in RuStore
}
})
.catch((error) => {
// Handling error
});

Check payment availability

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

  • The app has purchases enabled in RuStore Console.
  • The user and the app must not be blocked in RuStore.
Calling getPurchaseAvailability method
// Retrieving purchasing availability information
RuStoreReactPay.getPurchaseAvailability().then((value) => {
// value.isAvailable — purchasing availability indicator
if (value.isAvailable) {
// Purchasing available
} else {
// Purchasing unavailable
}
}).catch((error) => {
// handling errors
});

One-time purchase model ProductPurchase

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
RuStoreReactPay.purchase(params: {
productId: string;
orderId?: string;
quantity?: number;
developerPayload?: string;
appUserId?: string;
appUserEmail?: string;
preferredPurchaseType?: PreferredPurchaseType;
sdkTheme?: string;
}): Promise<ProductPurchaseResult>
  • preferredPurchaseType — the desired purchase type: single-stage (ONE_STEP) or two-stage (TWO_STEP).
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.

Payment type limitations for subscriptions

At the moment, a subscription purchase (SubscriptionPurchase) can only be made using a one-step payment (PurchaseType.ONE_STEP).

Calling the product purchase method
RuStoreReactPay.purchaseTwoStep(params: {
productId: string;
orderId?: string;
quantity?: number;
developerPayload?: string;
appUserId?: string;
appUserEmail?: string;
sdkTheme?: string;
}): Promise<ProductPurchaseResult>

Purchase parameters structure

Purchase parameters structure
export type ProductPurchase = {
purchaseId: string;
invoiceId: string;
orderId?: string;
purchaseType: PurchaseType;
status: ProductPurchaseStatus;
description: string;
purchaseTime?: string;
price: number;
amountLabel: string;
currency: string;
developerPayload?: string;
sandbox: boolean;
productId: string;
quantity: number;
productType: ProductType;
};
  • 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.

Purchase status model

One-stage payment status model.

Two-stage payment status model.

Subscription model SubscriptionPurchase

Subscription model SubscriptionPurchase
export type SubscriptionPurchase = {
purchaseId: string;
invoiceId: string;
orderId?: string;
purchaseType: PurchaseType;
status: SubscriptionPurchaseStatus;
description: string;
purchaseTime?: string;
price: number;
amountLabel: string;
currency: string;
developerPayload?: string;
sandbox: boolean;
productId: string;
expirationDate: string;
gracePeriodEnabled: boolean;
};
  • purchaseId — product ID — the purchase identifier. Used to retrieve purchase details in the SDK via the purchase info method.

  • invoiceId — invoice ID — the invoice identifier. Used for server-side payment validation, for searching payments in the Developer Console, and is shown to the buyer in their payment history.

  • orderId — a unique payment identifier provided 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 flow status:

    • INVOICE_CREATED — an invoice has been created; the subscription is waiting for payment.
    • CANCELLED — the subscription invoice was canceled.
    • EXPIRED — the time to pay the initial invoice has expired; no subscription was created.
    • PROCESSING — the first subscription payment is being processed.
    • REJECTED — the first subscription payment was rejected. The subscription was not created.
    • ACTIVE — the subscription is active.
    • PAUSED — the subscription is paused due to payment issues.
    • TERMINATED — all retry attempts for the subscription failed. The subscription was automatically closed due to payment issues.
    • CLOSED — the subscription was canceled by the user or the developer. After the paid period ended, the subscription was 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) — the product identifier assigned in RuStore Console (required).

  • expirationDate — the subscription end date.

  • gracePeriodEnabled — a flag indicating whether the grace period is enabled for the subscription.

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

Purchase product

Explanation of one-step and two-step payments
  • 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.
Payment method restrictions for subscriptions

At this time, a subscription purchase (SubscriptionPurchase) can only be made using the one-step payment flow (PurchaseType.ONE_STEP).

Important

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
RuStoreReactPay.purchase(params: {
productId: string;
orderId?: string;
quantity?: number;
developerPayload?: string;
appUserId?: string;
appUserEmail?: string;
preferredPurchaseType?: PreferredPurchaseType;
sdkTheme?: string;
}): Promise<ProductPurchaseResult>
  • preferredPurchaseType — the desired purchase type: single-stage (ONE_STEP) or two-stage (TWO_STEP).
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.

Payment type limitations for subscriptions

At the moment, a subscription purchase (SubscriptionPurchase) can only be made using a one-step payment (PurchaseType.ONE_STEP).

Calling the product purchase method
RuStoreReactPay.purchaseTwoStep(params: {
productId: string;
orderId?: string;
quantity?: number;
developerPayload?: string;
appUserId?: string;
appUserEmail?: string;
sdkTheme?: string;
}): Promise<ProductPurchaseResult>

Purchase parameters structure

Purchase parameters structure
export type ProductPurchase = {
purchaseId: string;
invoiceId: string;
orderId?: string;
purchaseType: PurchaseType;
status: ProductPurchaseStatus;
description: string;
purchaseTime?: string;
price: number;
amountLabel: string;
currency: string;
developerPayload?: string;
sandbox: boolean;
productId: string;
quantity: number;
productType: ProductType;
};
  • 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.

Confirming purchase

Only purchases launched with the two-step payment flow (i.e., with a funds hold) require confirmation. After a successful hold, such purchases are in the PurchaseStatus.paid status.

To charge the buyer’s card, the purchase must be confirmed. Use the confirmTwoStepPurchase method to confirm.

// Confirming two-step payment
RuStoreReactPay.confirmTwoStepPurchase(id)
.then(() => {
// Process success
})
.catch((error) => {
// Process error
});
  • id — 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

Cancelling purchase

Only purchases launched with the two-step payment flow (i.e., with a funds hold) can be canceled via the SDK.

Such purchases will be in the PurchaseStatus.paid status after a successful authorization/hold. After cancellation they will switch to PurchaseStatus.reversed.

Use purchase cancellation when, after payment (funds hold), you cannot provide the item to the buyer.

To cancel a two-step purchase (the hold), use cancelTwoStepPurchase.

RuStoreReactPay.cancelTwoStepPurchase(id)
.then(() => {
// Process success
})
.catch((error) => {
// Process error
});
  • id — product ID.

Purchase result structure

ProductPurchaseResult — the result of a successful digital product payment (for one-step payments) or a successful fund hold (for two-step payments).

interface ProductPurchaseResult {
orderId?: string;
purchaseId: string;
productId: string;
invoiceId: string;
purchaseType: PurchaseType;
productType: ProductType;
quantity: number;
sandbox: boolean;
}
  • ProductPurchaseResult — the result of a successful digital product payment (for one-step payments) or a successful fund hold (for two-step payments).

    • purchaseId - purchase identifier. Used to get purchase information in the SDK using the get purchase information method.
    • productId - identifier of the purchased product, specified when creating it in the RuStore developer console.
    • invoiceId - invoice identifier. Used for server-side payment validation, searching for payments in the developer console, and is also displayed to the buyer in the payment history in the RuStore mobile app.
    • orderId - unique payment identifier, specified by the developer or generated automatically (uuid).
    • purchaseType - purchase type (ONE_STEP/TWO_STEP/UNDEFINED - one-step/two-step/undefined).
    • quantity - product quantity - optional. If not specified, the value will be set to 1. Applicable only for purchasing consumable products.
    • sandbox - a flag indicating a test payment in the sandbox. If TRUE - the purchase was made in test mode.

Error handling

If an error occurs during the payment process or the user cancels the purchase, the execution of the payment method (both with the choice of purchase type and the two-step method) terminates with an error:

  • ProductPurchaseException — product purchase error.
  • ProductPurchaseCancelled — an error caused by cancelling a product purchase (the user closed the payment sheet) before receiving the purchase result. In this case, it is recommended to additionally check the purchase status using the get purchase information method.

Error and purchase cancellation structure

export type ProductPurchase = {
purchaseId: string;
invoiceId: string;
orderId?: string;
purchaseType: PurchaseType;
status: ProductPurchaseStatus;
description: string;
purchaseTime?: string;
price: number;
amountLabel: string;
currency: string;
developerPayload?: string;
sandbox: boolean;
productId: string;
quantity: number;
productType: ProductType;
};
  • purchaseId — purchase identifier. Used to get purchase information in the SDK using the get purchase information method.
  • productId — identifier of the purchased product, specified when creating it in the RuStore developer console.
  • invoiceId — invoice identifier. Used for server-side payment validation, searching for payments in the developer console, and is also displayed to the buyer in the payment history in the RuStore mobile app.
  • orderId — unique payment identifier, specified by the developer or generated automatically (uuid).
  • purchaseType — purchase type (ONE_STEP/TWO_STEP/UNDEFINED — one-step/two-step/undefined).
  • productType — type of product (NON_CONSUMABLE_PRODUCT — non-consumable product, CONSUMABLE_PRODUCT — consumable product, SUBSCRIPTION — subscription).
  • quantity — product quantity - optional. If not specified, the value will be set to 1. Applicable only for purchasing consumable products.

Server-side purchase validation

If you need to validate a purchase on the RuStore server, you can use subscriptionToken in ProductPurchaseResult.SuccessProductPurchaseResult, that is returned on successful purchase.

If you need to validate a successful purchase in RuStore, you can use the public validation APIs. Different methods are used to validate products and subscriptions:

  • To validate a product purchase, use the invoiceId from ProductPurchaseResult returned after the purchase is completed.

  • To validate a subscription purchase, use the purchaseId from ProductPurchaseResult returned after the purchase is completed.

You can determine the purchased item type from the ProductPurchaseResult.

You can also get a subscriptionToken in the Purchase entity. Retrieve Purchase by calling getPurchases().

Retrieving invoiceId from the purchase result
// Example of retrieving `invoiceId` or `purchaseId` from the purchase result for the server validation
const params = {
productId: 'productId',
preferredPurchaseType: PreferredPurchaseType.twoStep,
};

RuStoreReactPay.purchase(params)
.then((result) => {
// result.productType could be consumable, nonConsumable or subscription
if (
result.productType === ProductType.consumable ||
result.productType === ProductType.nonConsumable
) {
const invoiceId = result.invoiceId;
yourApi.validateProduct(invoiceId);
} else if (result.productType === ProductType.subscription) {
const purchaseId = result.purchaseId;
yourApi.validateSubscription(purchaseId);
} else {
// optional handling of unspecified type
}
})
.catch((error) => {
// Handling purchase errors
});
Retrieving subscriptionToken from the purchase result
// Example of retrieving `purchaseId` (`subscriptionToken`) for subscription validation
RuStoreReactPay.getPurchases()
.then((purchases) => {
purchases.forEach((purchase) => {
// each purchase could be either product or subscription
const { productPurchase, subscriptionPurchase } = purchase;
if (subscriptionPurchase) {
const purchaseId = subscriptionPurchase.purchaseId;
yourApi.validateSubscription(purchaseId);
} else if (productPurchase) {
const invoiceId = productPurchase.invoiceId;
yourApi.validateProduct(invoiceId);
}
});
})
.catch((error) => {
// Handling errors
});

RuStoreUtils

RuStoreUtils is a block in the native SDK that contains public methods for interacting with the RuStore app on the user’s device.

Use the RustoreReactPay singleton to access these methods.

The IsRuStoreInstalled method checks whether the RuStore app is installed on the user’s device.

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

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

Calling the openRuStoreDownloadInstruction method
RustoreReactPay.openRuStoreDownloadInstruction();

The openRuStore method launches the RuStore mobile app. If RuStore is not installed, a Toast is shown with the message “Failed to open the app”.

Calling the openRuStore method
RustoreReactPay.openRuStore();

The openRuStoreAuthorization method launches RuStore for authorization. After successful authorization, the RuStore app closes automatically. If RuStore is not installed, a Toast is shown with the message “Failed to open the app”.

Calling the openRuStoreAuthorization method
RustoreReactPay.openRuStoreAuthorization();

Using RuStoreUtils to check payment scenarios

A practical case for checking whether RuStore is installed and handling user authorization is covered in Accepting payments without the RuStore app.

That article includes::

  • Scenarios for purchases when RuStore is not installed;

  • Examples of sequential checks for installation and authorization using RuStoreUtils;

  • SDK behavior under different conditions (RuStore present/absent, user authorization, etc.).

Error list

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

The message field contains a description of the error's cause.

export type RuStorePayError = {
code: RuStoreErrorCode;
message: string;
}
  • 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.