Skip to main content

4.0.0

RuStore allows you to integrate payments into your mobile app.

Implementation example

Please have a thorough look at the application example to learn how to integrate payments 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:

flutter pub add flutter_rustore_billing

This command adds the following line to pubspec.yaml.

dependencies: flutter_rustore_billing: ^4.0.0

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.initialize() method.
RustoreBillingClient.initialize(
"123456", //consolApplicationId
"yourappscheme://iamback", //deeplinkScheme
true //allowNativeErrorHandling
).then((value) {
print( "initialize success: $value" );
}, onError: (err) {
print( "initialize err: $err" );});
note

The ApplicationId specified in build.gradle must match the applicationId of the APK file you published to the RuStore Console.

  • 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 must match the one specified in AndroidManifest.xml (see Deeplinks handling).
  • allowNativeErrorHandling — allow error handling (see in Error 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.available()method.If all conditions are met, the method returns ture.

RustoreBillingClient.available().then((value) {
print("available success $value");
}, onError: (err) {
print("available err: $err");
});

Working with SDK

Getting products list

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

RustoreBillingClient.products(ids).then((response) {
for ( final product in response.products) {
print(product?.productId);
}
}, onError: (err) {
print("products err: $err");
});

ids: List<String?> — list of products IDs.

The method returns ProductsResponse

class ProductsResponse {
int code;
String? errorMessage;
String? errorDescription;
String? traceId;
List<Product?> products;
List<DigitalShopGeneralError?> errors;
}
  • code — error code..
  • errorMessage — error message for the user..
  • errorDescription — error message decoding..
  • traceId — error ID..
  • errors — list of errors..
  • products — list of products..

Error structure DigitalShopGeneralError

class DigitalShopGeneralError {
String? name;
int ? code;
String? description
}
  • name – error name..
  • code — error code..
  • description – error description..

Product Structure Product

class Product {
String productId;
String? productType;
String productStatus;
String? priceLabel;
int ? price;
String? currency;
String? language;
String? title;
String? description;
String? imageUrl;
String? promoImageUrl;
Subscription? subscription;
}
  • productId — product ID..
  • productType — product type..
  • productStatus — product status..
  • priceLable — 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

class Subscription {
SubscriptionPeriod? subscriptionPeriod;
SubscriptionPeriod? freeTrialPeriod;
SubscriptionPeriod? gracePeriod;
String? introductoryPrice;
String? introductoryPriceAmount;
SubscriptionPeriod? introductoryPricePeriod;
}
  • 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

class SubscriptionPeriod {
int years;
int months;
int days;
}
  • years — number of years..
  • months — number of days..
  • days — number of days..

Purchasing product

Use theRustoreBillingClient.purchase(id)method to call a product purchase.

RustoreBillingClient.purchase(id).then((response) {
print("purchase success: $response");
}, onError: (err) {
print("purchase err: $err");
});

id — product ID.

Structure PaymentResult

class PaymentResult {
SuccessInvoice? successInvoice;
InvalidInvoice? invalidInvoice;
SuccessPurchase? successPurchase;
InvalidPurchase? invalidPurchase;
}

Structure SuccessInvoice

class SuccessInvoice {
String invoiceId;
String finishCode;
}

Structure InvalidInvoice

class InvalidInvoice {
String? invoiceId;
}

Structure SuccessPurchase

class SuccessPurchase {
String finishCode;
String? orderId;
String purchaseId;
String productId;
}

StructureInvalidPurchase

class InvalidPurchase {
String? purchaseId;
String? invoiceId;
String? orderId;
int? quantity;
String? productId;
int? errorCode;
}
  • SuccessInvoice — payment successfully completed;

    .
  • InvalidInvoice — payment completed without an invoice. It may possibly be caused by an error in the invoice (such as an empty line);

    .
  • SuccessPurchase — product has been paid for successfully;

    .
  • InvalidPurchase — failed to complete payment.

    .

**finishCode**may return one the following statuses:

  • SUCCESSFUL_PAYMENT — successful payment.

    .
  • CLOSED_BY_USER — cancelled by the user;

    .
  • UNHANDLED_FORM_ERROR — unknown error.

    .
  • PAYMENT_TIMEOUT — timeout payment error.

    .
  • DECLINED_BY_SERVER— rejected by server;

    .
  • RESULT_UNKNOWN — unknown payment status.

    .

Getting purchases list

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

Type/StatusINVOICE_CREATEDCONFIRMEDPAIDPAUSED
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.purchasesmethod to get the user's list of purchases.

RustoreBillingClient.purchases().then((response) {
for ( final product in response.purchases) {
print(product?.purchaseId);
}
}, onError: (err) {
print( "purchases err: $err" );
});

The method returns PurchasesResponse (see below) below).

class PurchasesResponse {
int code;
String? errorMessage;
String? errorDescription;
String? traceId;
List<Purchase?> purchases;
List<DigitalShopGeneralError?> errors;
}
  • code — error code..
  • errorMessage — error message for the user..
  • errorDescription — error message decoding..
  • errors — list of errors..
  • purchases — list of requested purchases..

Error structure DigitalShopGeneralError (see below) below).

class DigitalShopGeneralError {
String? name;
int ? code;
String? description;
}
  • name – error name..
  • code — error code..
  • description – error description..
class Purchase {
String? purchaseId;
String? productId;
String? description;
String? language;
String? purchaseTime;
String? orderId;
String? amountLabel;
int ? amount;
String? currency;
int ? quantity;
String? purchaseState;
String? developerPayload;
}

Purchase Structure Purchase (see below) below).

  • purchaseId — purchase ID..
  • productId — product 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..

Getting purchase info

Use the purchaseInfo method to retrive purchase details.
RustoreBillingClient.purchaseInfo(purchaseId).then((purchase) {
print(purchase);
}, onError: (err) {
print("Error getPurchaseInfo: $err");
});

Purchase Structure Purchase (see below) below).

class Purchase {
String? purchaseId;
String? productId;
String? description;
String? language;
String? purchaseTime;
String? orderId;
String? amountLabel;
int ? amount;
String? currency;
int ? quantity;
String? purchaseState;
String? developerPayload;
}
  • purchaseId — purchase ID..
  • productId — product 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..

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

Use theRustoreBillingClient.confirm(id) method to call a product purchase. The release of the goods must be accompanied by a purchase confirmation request. Once the confirmation is called, the purchase will have a CONSUMED status.

RustoreBillingClient.confirm(id).then((response) {
print( "confirm success: $response" );
}, onError: (err) {
print( "confirm err: $err" );
});
  • id — purchase ID..

The method returns ConfirmPurchaseResponse (see below) below).

class ConfirmPurchaseResponse {
int code;
String? errorMessage;
String? errorDescription;
String? traceId;
List<DigitalShopGeneralError?> errors;
}
  • code — error code..
  • errorMessage — error message for the user..
  • errorDescription — error message decoding..
  • traceId — error ID..
  • errors — list of errors..

Error structure DigitalShopGeneralError (see below) below).

class DigitalShopGeneralError {
String? name;
int ? code;
String? description;
}
  • name – error name..
  • code — error code..
  • description – error description..

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.

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

Logging

Logging is disabled by default inside flutter sdk. You can view logs using the RuStoreFlutterBillingPlugin tag.

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;
  • RuStoreApplicationBannedException — application blocked in RuStore;
  • RuStoreUserBannedException — user blocked on RuStore;
  • RuStoreException — basic RuStore error, from which all other errors are inherited..

You can enable the allowNativeErrorHandling parameter to show an error dialog to the user:

RustoreBillingClient.initialize(
"123456", //consolApplicationId
"yourappscheme://iamback", //deeplinkScheme
true //allowNativeErrorHandling
).then((value) {
print( "initialize success: $value" );
}, onError: (err) {
print( "initialize err: $err" );});
  • allowNativeErrorHandling — allow error handling (see in Error handling).