Skip to main content

5.0.0

RuStore allows you to integrate payments into your mobile app.

Implementation example

See the example app to learn how to integrate rating and feedback SDK correctly.

Prerequisites

  • The current version of RuStore is installed on the user's device.
  • The user is authorized in RuStore.
  • The user and the app should not be blocked in RuStore.
  • In-app purchases should be enabled for the app in RuStore Console.
caution

The service has some restrictions to work outside of Russia.

Getting started

Run the command below to add the application package to your project:

// HTTPS
npm install git+https://git@gitflic.ru/project/rustore/react-native-rustore-billing-sdk.git

// SSH
npm install git+ssh://git@gitflic.ru/project/rustore/react-native-rustore-billing-sdk.git

To redirect a user to your app after payment via third-party apps (the Faster Payments System (SBP), SberPay and others), you need to properly implement deep linking in your app. Specify the intent-filter in AndroidManifest.xml with schemeof your project (see below).

AndroidManifest.xml
<activity
android:name=".sample.MainActivity">
<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>

where yourappscheme — your deeplink scheme, it can be changed to another one.

This scheme must match the deeplinkSheme value specified during the billing client library initialization.

Initialization

Initialize the library before calling its methods.

For initialisation, call the RustoreBillingClient.init() method.
try {  
RustoreBillingClient.init({
consoleApplicationId: 'appId' ,
deeplinkScheme: 'scheme' ,
});
console.log(initialize success: ${result});
} catch (err) {
console.log(initialize err: ${err});
}
  • consoleApplicationId — application code from RuStore Console (example: https://console.rustore.ru/apps/123456).
  • deeplinkScheme — deeplink scheme required to return to your app upon payment via a third-party application (for example, SberPay or SBP). SDK generates its host for this scheme.
note
The deeplink scheme passed in deeplinkScheme must match the one specified in AndroidManifest.xml (see Deeplinks handling).

How payments work

Checking purchases availability

Please ensure compliance with the conditions below to check whether your app supports payment functions.

  • The current version of RuStore is installed on the user's device.
  • RuStore app supports payment functionality.
  • The user is authorized in RuStore.
  • The user and the app should not be blocked in RuStore.
  • In-app purchases should be enabled for the app in RuStore Console.

To check whether your app supports payment functions, call the RustoreBillingClient.checkPurchasesAvailability()method.If all conditions are met, the method returns true.

try {
const isAvailable = await RustoreBillingClient.checkPurchasesAvailability();
console.log(available success ${isAvailable});
} catch (err) {
console.log(available error ${err});
}

Working with SDK

Getting products list

Use the RustoreBillingClient.getProducts(productIds) method to get a list of products.

try {
const products = await RustoreBillingClient.getProducts(productIds);
for (const product of products) {
console.log(product?.productId);
}
} catch (err) {
console.log(products err: ${err});
}

productIds — list of products IDs.

This method returns Product[]. Below is the product pattern:

interface Product {
productId: string;
productType?: ProductType;
productStatus: ProductStatus;
priceLabel?: string;
price?: number;
currency?: string;
language?: string;
title?: string;
description?: string;
imageUrl?: string;
promoImageUrl?: string;
subscription?: ProductSubscription;
}
  • productId — product ID..
  • productType — product type..
  • productStatus — product status..
  • priceLabel — formatted purchase price, including the currency symbol in language.
  • price — price in minor units (in kopecks)..
  • currency — ISO 4217 currency code.
  • language — language specified with the BCP 47 encoding..
  • title — product name in language.
  • description — product description in language.
  • imageUrl — link to an image..
  • promoImageUrl — promotional picture link..
  • subscription — subscription description, returned only for products with subscription.

Subscription Structure Subscription

interface ProductSubscription {
subscriptionPeriod?: SubscriptionPeriod;
freeTrialPeriod?: SubscriptionPeriod;
gracePeriod?: SubscriptionPeriod;
introductoryPrice?: string;
introductoryPriceAmount?: string;
introductoryPricePeriod?: SubscriptionPeriod;
}
  • subscriptionPeriod — subscription period..
  • freeTrialPeriod — trial subscription period..
  • gracePeriod — grace period..
  • introductoryPrice — formatted introductory subscription price, including the currency symbol, in product:language.
  • introductoryPriceAmount — introductory price in minor units of currency (in kopecks).
  • introductoryPricePeriod — calculated period of the introductory price..

>Subscription Period structure SubscriptionPeriod

interface SubscriptionPeriod {
years: number;
months: number;
days: number;
}
  • years — number of years..
  • months — number of days..
  • days — number of days..

Purchasing product

Use theRustoreBillingClient.purchaseProduct({...})method to call a product purchase.

try {
const response = await RustoreBillingClient.purchaseProduct({
productId: 'productId' ,
orderId: 'orderId' ,
quantity: 0,
developerPayload: 'developerPayload'
});
console.log(purchase success: ${response});
} catch (err) {
console.log(purchase err: ${err});
}
  • productId — product ID..
  • orderId — unique payment identifier generated by the application (uuid);.
  • quantity — product quantity..
  • developerPayload — уline specified by the developer that contains additional information about the order..

The purchase result can be represented as one of the following interfaces:SuccessPayment, CancelledPayment or FailurePayment.

enum PaymentResult {
SUCCESS = 'SUCCESS' ,
CANCELLED = 'CANCELLED' ,
FAILURE = 'FAILURE' ,
}
interface SuccessPaymentResult {
orderId?: string;
purchaseId: string;
productId: string;
invoiceId: string;
subscriptionToken?: string;
}
interface SuccessPayment {
type: PaymentResult.SUCCESS;
result: SuccessPaymentResult;
}
interface CancelledPaymentResult {
purchaseId: string;
}
interface CancelledPayment {
type: PaymentResult.CANCELLED;
result: CancelledPaymentResult;
}
interface FailurePaymentResult {
purchaseId?: string;
invoiceId?: string;
orderId?: string;
quantity?: number;
productId?: string;
errorCode?: number;
}
interface FailurePayment {
type: PaymentResult.FAILURE;
result: FailurePaymentResult;
}
  • SuccessPayment - successful purchase result..
  • FailurePayment - error occurred when sending a payment request or receiving a payment status, it is not possible to set the purchase status..
  • CancelledPayment — a purchase request has been sent, but the user has closed the "payment window" on their device, so the payment result is unknown..

Getting purchases list

The method only returns purchases with statuses from the table below.

Type/StatusINVOICE_CREATEDCONFIRMEDPAID
CONSUMABLE++
NON-CONSUMABLE++
SUBSCRIPTION++
note

The method returns incomplete purchase and purchase consumable states that require processing. Apart from that, it shows confirmed purchases for subscriptions and non-consumable items - those that cannot be purchased again.

Use theRustoreBillingClient.getPurchases()method to get the user's list of purchases.

try {
const purchases = await RustoreBillingClient.getPurchases();
for (const purchase of purchases) {
console.log(purchase?.purchaseId);
}
} catch (err) {
console.log(purchase err: ${err});
}

This method returns Purchase[]. Below is the product pattern:

interface Purchase {  
purchaseId?: string;
productId: string;
productType?: ProductType;
invoiceId?: string;
description?: string;
language?: string;
purchaseTime?: string;
orderId?: string;
amountLabel?: string;
amount?: number;
currency?: string;
quantity?: number;
purchaseState?: PurchaseState;
developerPayload?: string;
subscriptionToken?: string;
}
  • purchaseId — purchase ID..
  • productId — product ID..
  • productType — product type..
  • invoiceId — invoice ID..
  • description — product description in language.
  • language — language specified with the BCP 47 encoding..
  • purchaseTime— time of purchase.

    .
  • orderId — unique payment identifier generated by the application (uuid);.
  • amountLable — formatted purchase price, including the currency symbol in language.
  • amount — price in minor units of currency..
  • currency — ISO 4217 currency code.
  • quantity — product quantity..
  • purchaseState — purchase state.:
  • developerPayload — уline specified by the developer that contains additional information about the order..
  • subscriptionToken — token for server validation..

Getting purchase info

Use the getPurchaseInfo method to retrive purchase details.
try {
const purchaseInfo = await RustoreBillingClient.getPurchaseInfo(purchaseId);
console.log(purchase info ${purchaseInfo});
} catch (err) {
console.log(purchase error ${err});
}

purchaseId — purchase ID..

This method returns Purchase, which is described above.

Server validation

For server purchase validation using API RuStore methods, you can use the subscriptionToken, in the PurchaseResult, returned by purchaseProduct in case of a successful purchase.

SubscriptionToken consists of invoiceId of purchase and userId, written with a dot: $invoiceId.$userId.

try {
const paymentResult = await RustoreBillingClient.purchaseProduct({
productId,
});

if (paymentResult.type == PaymentResult.SUCCESS) {
const subscriptionToken = paymentResult.response.subscriptionToken
yourApi.validate(subscriptionToken)
}
setPayment(paymentResult);
} catch (err: any) {
setError(JSON.stringify(err));
}

You can also get a subscriptionToken in the Purchase entity. Purchase entity can be retrieved using the getPurchases() method.

const purchases = RustoreBillingClient.getPurchases();
for (const purchase of purchases) {
yourApi.validate(purchase.subscriptionToken)
}

Confirming purchase

Products that require confirmation

The RuStore application consists of the following types of products:

  • SUBSCRIPTION— subscription (can be purchased for a period of time, such as a streaming service subscription)..
  • NON_CONSUMABLE — non-consumables (one-time purchases, such as disabling ads in an app).
  • CONSUMABLE — consumables (multiple-time purchases, such as crystals in the app);

    .

Only CONSUMABLE type products require confirmation if they are in PurchaseState.PAID state.

Calling confirmation method

Canceling purchase

Use theRustoreBillingClient.deletePurchase(purchaseId) method to cancel a purchase.

try {
const isDeleted = await RustoreBillingClient.deletePurchase(purchaseId)
console.log(delete success: ${isDeleted});
} catch (err) {
console.log(delete err: ${err});
}
  • purchaseId — purchase ID..

Provided that all conditions are met, the RustoreBillingClient.deletePurchase() method returns true.

info

Note. Use this method if your app logic is related to purchase cancellation. The purchase is canceled automatically after a 20-min timeout, or upon a second purchase from the same customer.

Processing unfinished payments

Uncompleted payments must be processed by the developer.

To confirm a CONSUMABLE purchase type in PAID status, you can call the confirm-purchase method (see Getting purchase info).

In the case of purchase cancellations, consider your internal process when using payment processing methods. As for some developers, it provides for pre-consumption checks or purchase cancellation. In this case, request the status of such purchase separately.

tip

For example, if a user has paid for an item you can't supply to them for some reason, call the cancel purchase method on the PAID status to cancel the purchase.

In cases where the receive shopping list method returns a purchase with INVOICE_CREATED status, you can use the cancel purchase method. For example, if you don't want to see a purchase with these statuses in your shopping list. You don't have to do it yourself, as RuStore handles the cancellation of such purchases on its side.

info

In some cases, after paying through a banking app (SBP, SberPay, TinkoffPay, etc.), the purchase status may still return INVOICE_CREATED, when you subsequently return to app. This is caused by the purchase processing time by the bank. Therefore, the developer needs to correctly link the shopping list obtaining function to the life cycle on the screen.

You acn also cancel a purchase in INVOICE_CREATED status only through user interaction with the app. For example, create a separate button for this purpose.

Errors processing

Possible errors

  • RuStoreNotInstalledException — RuStore not installed on user's device;
  • RuStoreOutdatedException — RuStore, installed on the user's device, does not support payment processing functions.;
  • RuStoreUserUnauthorizedException — user not authorized on RuStore;
  • RuStoreRequestLimitReached — not enough time has passed since the process was last shown.;
  • RuStoreReviewExists — this user has already rated your app.;
  • RuStoreInvalidReviewInfo — problems with ReviewInfo;
  • RuStoreException — basic RuStore error, from which all other errors are inherited..