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.

All operations with the client are also accessible from Blueprints. Below is a Initialization example.

img

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.
  • Unreal Engine 4.26 and later.
caution

The service has some restrictions to work outside of Russia.

Getting started

  1. In your IDE, open the Android project from the unreal_plugin_libraries.
  2. Build your project with the command gradle assemble.

If the build is successful, the following files will be created in unreal_example/Plugins/RuStoreBilling/Source/RuStoreBilling/ThirdParty/Android/libs and unreal_example / Plugins / RuStoreCore / Source / RuStoreCore / ThirdParty / Android / libs.

  • RuStoreUnityBillingClient.aar
  • RuStoreUnityCore.aar
  1. Copy the contents of the Plugins folder from the official RuStore repository on GitFlic to the Plugins of your project.
  2. Restart Unreal Engine.
  3. Then, in (Edit > Plugins > Project > Mobile) check plug-ins RuStoreBilling and RuStoreCore.
  4. In the YourProject.Build.cs file in the PublicDependencyModuleNames list connect modules RuStoreCore and RuStoreBilling.
  5. In the project settings (Edit > Project Settings > Android) set the Minimum SDK Version parameter to 24 or later and the Target SDK Version parameter: 31 or later.

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. To proces plug-in RuStore Billing automatically adds the AndroidManifest.xml attribute for the main activity and the next intent-filter You can change this behavior in the RuStoreBilling_UPL_Android.xml.

AndroidManifest.xml
<activity android:name="com.Plugins.RuStoreBilling.RuStoreIntentFilterActivity" android:exported="true" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Set your appscheme -->
<data android:scheme="@string/rustore_app_scheme" />
</intent-filter>
</activity>
caution

@string/rustore_app_scheme implementation is necessary for your project.

@string/rustore_app_scheme — your deeplink scheme. This scheme must match the deeplinkSheme value specified during the billing client library initialization.

Initialization

Initialize the library before calling its methods.

Вызов метода Init
FURuStoreBillingClientConfig config;
config.consoleApplicationId = "123456";
config.deeplinkScheme = "yourscheme";
config.allowNativeErrorHandling = false;
config.enableLogs = false;

URuStoreBillingClient::Instance()->Init(config);

All operations with the client are also accessible from Blueprints. Below is a Initialization example.

img
  • consoleApplicationId — application code from RuStore Console (example: https://console.rustore.ru/apps/123456).
  • deeplinkSheme — an url used for deeplink. Make sure your use a unique name, for exampl: yourappscheme).

  • allowNativeErrorHandling — allow error handling (see in Error handling).
  • enableLogs — enable event logging.

The Init() call ties the object to the scene root, and, If no further work with the object is needed, execute the Dispose() method to free memory.

Deinitialization

Вызов метода Dispose
URuStoreBillingClient::Instance()->Dispose();
img

Initialization check

If you need to check whether the library is initialized, use the GetIsInitialized() method. The method will return true if the library is initialized and false if Init hasn't been called yet.

Вызов метода GetIsIninialized
bool isInitialized = URuStoreBillingClient::Instance()->GetIsIninialized();
img

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 CheckPurchasesAvailabilitymethod.

Each request returns requestId that is unique per app launch. Each event returns requestId of the request that triggered this event.

Вызов метода CheckPurchasesAvailability
long requestId = URuStoreBillingClient::Instance()->CheckPurchasesAvailability(
[]( long requestId, TSharedPtr<FURuStoreFeatureAvailabilityResult, ESPMode::ThreadSafe> response) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

The Success callback returns the FURuStoreFeatureAvailabilityResult structure in the Response parameter (see below) below).

USTRUCT(BlueprintType)
struct RUSTORECORE_API FURuStoreFeatureAvailabilityResult
{
GENERATED_USTRUCT_BODY()

FURuStoreFeatureAvailabilityResult()
{
isAvailable = false;
}

UPROPERTY(BlueprintReadWrite)
bool isAvailable;

UPROPERTY(BlueprintReadWrite)
FURuStoreError cause;
};
  • isAvailable — whether payment conditions are met (true/false).
  • cause — error information.

All possiblecause errors are described in Error Handling.. Other errors are processed in on Failure.

The Failure callback returns the FURuStoreError structure with the error information in the Error parameter. All possible FURuStoreError errors are described in Error Handling.

Working with SDK

Getting products list

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

Вызов метода GetProducts
long requestId = URuStoreBillingClient::Instance()->GetProducts(
productIds,
[]( long requestId, TSharedPtr<FURuStoreProductsResponse, ESPMode::ThreadSafe> response) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

TArray<FString> productIds — list of products IDs.

The Success callback returns the FURuStoreProductsResponse structure in the Response parameter (see below).

GetProducts response

USTRUCT(BlueprintType)
struct FURuStoreProductsResponse
{
GENERATED_USTRUCT_BODY()

UPROPERTY(BlueprintReadOnly)
TArray<FURuStoreProduct> products;
};

products — list of products.

Product structure

USTRUCT(BlueprintType)
struct FURuStoreProduct
{
GENERATED_USTRUCT_BODY()

FURuStoreProduct()
{
productId = "";
productType = EURuStoreProductType::NON_CONSUMABLE;
productStatus = EURuStoreProductStatus::INACTIVE;
priceLabel = "";
price = 0;
currency = "";
language = "";
title = "";
description = "";
imageUrl = "";
promoImageUrl = "";
}

UPROPERTY(BlueprintReadOnly)
FString productId;

UPROPERTY(BlueprintReadOnly)
EURuStoreProductType productType;

UPROPERTY(BlueprintReadOnly)
EURuStoreProductStatus productStatus;

UPROPERTY(BlueprintReadOnly)
FString priceLabel;

UPROPERTY(BlueprintReadOnly)
int price;

UPROPERTY(BlueprintReadOnly)
FString currency;

UPROPERTY(BlueprintReadOnly)
FString language;

UPROPERTY(BlueprintReadOnly)
FString title;

UPROPERTY(BlueprintReadOnly)
FString description;

UPROPERTY(BlueprintReadOnly)
FString imageUrl;

UPROPERTY(BlueprintReadOnly)
FString promoImageUrl;

UPROPERTY(BlueprintReadOnly)
FURuStoreProductSubscription 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.

Product type

UENUM(BlueprintType)
enum class EURuStoreProductType : uint8
{
NON_CONSUMABLE UMETA(DisplayName = "NON_CONSUMABLE"),
CONSUMABLE UMETA(DisplayName = "CONSUMABLE"),
SUBSCRIPTION UMETA(DisplayName = "SUBSCRIPTION")
};

Product status

UENUM(BlueprintType)
enum class EURuStoreProductStatus : uint8
{
ACTIVE UMETA(DisplayName = "ACTIVE"),
INACTIVE UMETA(DisplayName = "INACTIVE")
};

Subscription structure

USTRUCT(BlueprintType)
struct FURuStoreProductSubscription
{
GENERATED_USTRUCT_BODY()

FURuStoreProductSubscription()
{
introductoryPrice = "";
introductoryPriceAmount = "";
}

UPROPERTY(BlueprintReadOnly)
FURuStoreSubscriptionPeriod subscriptionPeriod;

UPROPERTY(BlueprintReadOnly)
FURuStoreSubscriptionPeriod freeTrialPeriod;

UPROPERTY(BlueprintReadOnly)
FURuStoreSubscriptionPeriod gracePeriod;

UPROPERTY(BlueprintReadOnly)
FString introductoryPrice;

UPROPERTY(BlueprintReadOnly)
FString introductoryPriceAmount;

UPROPERTY(BlueprintReadOnly)
FURuStoreSubscriptionPeriod 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

USTRUCT(BlueprintType)
struct FURuStoreSubscriptionPeriod
{
GENERATED_USTRUCT_BODY()

FURuStoreSubscriptionPeriod()
{
years = 1970;
months = 1;
days = 1;
}

UPROPERTY(BlueprintReadOnly)
int years;

UPROPERTY(BlueprintReadOnly)
int months;

UPROPERTY(BlueprintReadOnly)
int days;
};
  • years — number of years..
  • months — number of days..
  • days — number of days..

The Failure callback returns the FURuStoreError structure with the error information in the Error parameter.

All possible FURuStoreError errors are described in Error Handling.

Purchasing product

Use thePurchaseProduct()method to call a product purchase.

Purchase product request

Вызов метода PurchaseProduct
long requestId = URuStoreBillingClient::Instance()->PurchaseProduct(
productId,
orderId,
quantity,
developerPayload,
[]( long requestId, TShardPtr<FURuStorePaymentResult, ESPMode::ThreadSafe> response) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • productId — product ID..
  • orderId: String — 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 Success callback returns the smart thread safe (ESPMode::ThreadSafe) pointer to an object of the structure's heir FURuStorePaymentResult in the Response parameter.

The type of the heir object can be obtained using the GetTypeName() method. The type cast can be done via StaticCastSharedPtr<>.

Вызов методов GetTypeName и StaticCastSharedPtr
// TShardPtr<FURuStorePaymentResult, ESPMode::ThreadSafe> response
FString typeName = response->GetTypeName();
if (typeName == "FURuStoreSuccess")
{
auto success = *StaticCastSharedPtr<FURuStoreSuccess>(response);
}

Possible types values:

  • FURuStoreSuccess - successful purchase result..
  • FURuStoreFailure - error occurred when sending a payment request or receiving a payment status, it is not possible to set the purchase status..
  • FURuStoreCancelled — a purchase request has been sent, but the user has closed the "payment window" on their device, so the payment result is unknown..
  • FURuStoreInvalidPaymentState — Billing SDK error.. May occur in case of an incorrect reverse deeplink.

    .

The Success callback returns a managed UE pointer for the URuStorePaymentResultClass class in the Response parameter. Casting to a heir type can be done through a cascade of Cast To calls.

img

Purchase result structure

UCLASS(BlueprintType)
class RUSTOREBILLING_API URuStorePaymentResultClass : public UObject
{
GENERATED_BODY()
};

USTRUCT(BlueprintType)
struct RUSTOREBILLING_API FURuStorePaymentResult
{
GENERATED_USTRUCT_BODY()

virtual ~FURuStorePaymentResult() {}

virtual FString GetTypeName() { return "FURuStorePaymentResult"; }
};

Payment Result StructureSuccess

UCLASS(BlueprintType)
class RUSTOREBILLING_API URuStoreSuccess : public URuStorePaymentResultClass
{
GENERATED_BODY()

public:
UPROPERTY(BlueprintReadOnly)
FURuStoreSuccess value;
};

USTRUCT(BlueprintType)
struct RUSTOREBILLING_API FURuStoreSuccess : public FURuStorePaymentResult
{
GENERATED_USTRUCT_BODY()

FURuStoreSuccess()
{
orderId = "";
purchaseId = "";
productId = "";
invoiceId = "";
subscriptionToken = "";
}

UPROPERTY(BlueprintReadOnly)
FString orderId;

UPROPERTY(BlueprintReadOnly)
FString purchaseId;

UPROPERTY(BlueprintReadOnly)
FString productId;

UPROPERTY(BlueprintReadOnly)
FString invoiceId;

UPROPERTY(BlueprintReadOnly)
FString subscriptionToken;

virtual FString GetTypeName() override { return "FURuStoreSuccess"; }
};

Payment Result StructureCancelled

UCLASS(BlueprintType)
class RUSTOREBILLING_API URuStoreCancelled : public URuStorePaymentResultClass
{
GENERATED_BODY()

public:
UPROPERTY(BlueprintReadOnly)
FURuStoreCancelled value;
};

USTRUCT(BlueprintType)
struct RUSTOREBILLING_API FURuStoreCancelled : public FURuStorePaymentResult
{
GENERATED_USTRUCT_BODY()

FURuStoreCancelled()
{
purchaseId = "";
}

UPROPERTY(BlueprintReadOnly)
FString purchaseId;

virtual FString GetTypeName() override { return "FURuStoreCancelled"; }
};

Payment Result StructureFailure

UCLASS(BlueprintType)
class RUSTOREBILLING_API URuStoreFailure : public URuStorePaymentResultClass
{
GENERATED_BODY()

public:
UPROPERTY(BlueprintReadOnly)
FURuStoreFailure value;
};

USTRUCT(BlueprintType)
struct RUSTOREBILLING_API FURuStoreFailure : public FURuStorePaymentResult
{
GENERATED_USTRUCT_BODY()

public:
FURuStoreFailure()
{
purchaseId = "";
invoiceId = "";
orderId = "";
quantity = 0;
productId = "";
errorCode = 0;
}

UPROPERTY(BlueprintReadOnly)
FString purchaseId;

UPROPERTY(BlueprintReadOnly)
FString invoiceId;

UPROPERTY(BlueprintReadOnly)
FString orderId;

UPROPERTY(BlueprintReadOnly)
int quantity;

UPROPERTY(BlueprintReadOnly)
FString productId;

UPROPERTY(BlueprintReadOnly)
int errorCode;

virtual FString GetTypeName() override { return "FURuStoreFailure"; }
};

PaymentResult StructureInvalidPaymentState

UCLASS(BlueprintType)
class RUSTOREBILLING_API URuStoreInvalidPaymentState : public URuStorePaymentResultBase
{
GENERATED_BODY()

public:
UPROPERTY(BlueprintReadOnly)
FURuStoreInvalidPaymentState value;
};

USTRUCT(BlueprintType)
struct RUSTOREBILLING_API FURuStoreInvalidPaymentState : public FURuStorePaymentResult
{
GENERATED_USTRUCT_BODY()

virtual FString GetTypeName() override { return "FURuStoreInvalidPaymentState"; }
};

The Failure callback returns the FURuStoreError structure with the error information in the Error parameter. All possible FURuStoreError errors are described in Error Handling.

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 theGetPurchases()method to get the user's list of purchases.

Вызов метода GetPurchases
long requestId = URuStoreBillingClient::Instance()->GetPurchases(
[]( long requestId, TSharedPtr<FURuStorePurchasesResponse, ESPMode::ThreadSafe> response) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreRuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

The Success callback returns the FURuStorePurchasesResponse structure in the Response parameter (see below). below).

ResponseGetPurchases

USTRUCT(BlueprintType)
struct FURuStorePurchasesResponse: public FURuStoreResponseWithCode
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadOnly)
TArray<FURuStorePurchase> purchases;
};

purchases — list of requested purchases.

Purchase Structure

USTRUCT(BlueprintType)
struct FURuStorePurchase
{
GENERATED_USTRUCT_BODY()

FURuStorePurchase()
{
purchaseId = "";
productId = "";
invoiceId = "";
description = "";
language = "";
purchaseTime = FDateTime(0);
orderId = "";
amountLabel = "";
amount = 0;
currency = "";
quantity = 0;
purchaseState = EURuStorePurchaseState::CANCELLED;
developerPayload = "";
subscriptionToken = "";
}

UPROPERTY(BlueprintReadOnly)
FString purchaseId;

UPROPERTY(BlueprintReadOnly)
FString productId;

UPROPERTY(BlueprintReadOnly)
FString invoiceId;

UPROPERTY(BlueprintReadOnly)
FString description;

UPROPERTY(BlueprintReadOnly)
FString language;

UPROPERTY(BlueprintReadOnly)
FDateTime purchaseTime;

UPROPERTY(BlueprintReadOnly)
FString purchaseTimeLabel;

UPROPERTY(BlueprintReadOnly)
FString orderId;

UPROPERTY(BlueprintReadOnly)
FString amountLabel;

UPROPERTY(BlueprintReadOnly)
int amount;

UPROPERTY(BlueprintReadOnly)
FString currency;

UPROPERTY(BlueprintReadOnly)
int quantity;

UPROPERTY(BlueprintReadOnly)
EURuStorePurchaseState purchaseState;

UPROPERTY(BlueprintReadOnly)
FString developerPayload;

UPROPERTY(BlueprintReadOnly)
FString subscriptionToken;
};

Purchase state

UENUM(BlueprintType)
enum class EURuStorePurchaseState : uint8
{
CREATED UMETA(DisplayName = "CREATED"),
INVOICE_CREATED UMETA(DisplayName = "INVOICE_CREATED"),
CONFIRMED UMETA(DisplayName = "CONFIRMED"),
PAID UMETA(DisplayName = "PAID UMETA"),
CANCELLED UMETA(DisplayName = "CANCELLED"),
CONSUMED UMETA(DisplayName = "CONSUMED"),
PAUSED UMETA(DisplayName = "PAUSED"),
CLOSED UMETA(DisplayName = "CLOSED")
};
  • purchaseId — purchase ID..

  • productId — product ID..

  • description — product description in language.

  • invoiceId — invoice ID..

  • 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.:

    • CREATED - purchase created.

      ;
    • INVOICE_CREATED — created, waiting for payment.;
    • PAID — consumable purchases only - intermediate status, funds reserved in buyer's account. Purchase pending confirmation from developer.

      ;
    • CONFIRMED — final status, purchase confirmed (for subscriptions and non-consumable items). Funds sent to the developer. Repeat item purchase is blocked by the store;
    • CONSUMED — for consumable items - final status, purchase consumption confirmed. You can re-purchase an item.

      ;
    • CANCELLED — purchase cancelled - payment has not been made or a refund has been made to the buyer (for subscriptions, once refunded, the purchase does not become CANCELLED);
    • PAUSED - for subscriptions - subscription shifted to HOLD period.

      ;
    • TERMINATED — subscription closed.

      .
  • developerPayload — уline specified by the developer that contains additional information about the order..

  • subscriptionToken — token for server validation..

The Failure callback returns the FURuStoreError structure with the error information in the Error parameter.

All possible FURuStoreError errors are described in Error Handling.

Getting purchase info

Use the GetPurchaseInfo method to retrive purchase details.
long requestId = URuStoreBillingClient::Instance()->GetPurchaseInfo(
purchaseId,
[]( long requestId, TSharedPtr<FURuStorePurchaseInfoResponse, ESPMode::ThreadSafe> response) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img

purchaseId — purchase ID.

The Success callback returns the FURuStorePurchase structure in the Response parameter (see below).

Purchase Structure

USTRUCT(BlueprintType)
struct FURuStorePurchase
{
GENERATED_USTRUCT_BODY()

FURuStorePurchase()
{
purchaseId = "";
productId = "";
invoiceId = "";
description = "";
language = "";
purchaseTime = FDateTime(0);
orderId = "";
amountLabel = "";
amount = 0;
currency = "";
quantity = 0;
purchaseState = EURuStorePurchaseState::CANCELLED;
developerPayload = "";
subscriptionToken = "";
}

UPROPERTY(BlueprintReadOnly)
FString purchaseId;

UPROPERTY(BlueprintReadOnly)
FString productId;

UPROPERTY(BlueprintReadOnly)
FString invoiceId;

UPROPERTY(BlueprintReadOnly)
FString description;

UPROPERTY(BlueprintReadOnly)
FString language;

UPROPERTY(BlueprintReadOnly)
FDateTime purchaseTime;

UPROPERTY(BlueprintReadOnly)
FString purchaseTimeLabel;

UPROPERTY(BlueprintReadOnly)
FString orderId;

UPROPERTY(BlueprintReadOnly)
FString amountLabel;

UPROPERTY(BlueprintReadOnly)
int amount;

UPROPERTY(BlueprintReadOnly)
FString currency;

UPROPERTY(BlueprintReadOnly)
int quantity;

UPROPERTY(BlueprintReadOnly)
EURuStorePurchaseState purchaseState;

UPROPERTY(BlueprintReadOnly)
FString developerPayload;

UPROPERTY(BlueprintReadOnly)
FString subscriptionToken;
};

Purchase state

UENUM(BlueprintType)
enum class EURuStorePurchaseState : uint8
{
CREATED UMETA(DisplayName = "CREATED"),
INVOICE_CREATED UMETA(DisplayName = "INVOICE_CREATED"),
CONFIRMED UMETA(DisplayName = "CONFIRMED"),
PAID UMETA(DisplayName = "PAID UMETA"),
CANCELLED UMETA(DisplayName = "CANCELLED"),
CONSUMED UMETA(DisplayName = "CONSUMED"),
PAUSED UMETA(DisplayName = "PAUSED"),
CLOSED UMETA(DisplayName = "CLOSED")
};
  • purchaseId — purchase ID..

  • productId — product ID..

  • description — product description in language.

  • invoiceId — invoice ID..

  • 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.:

    • CREATED - purchase created.

      ;
    • INVOICE_CREATED — created, waiting for payment.;
    • PAID — consumable purchases only - intermediate status, funds reserved in buyer's account. Purchase pending confirmation from developer.

      ;
    • CONFIRMED — final status, purchase confirmed (for subscriptions and non-consumable items). Funds sent to the developer. Repeat item purchase is blocked by the store;
    • CONSUMED — for consumable items - final status, purchase consumption confirmed. You can re-purchase an item.

      ;
    • CANCELLED — purchase cancelled - payment has not been made or a refund has been made to the buyer (for subscriptions, once refunded, the purchase does not become CANCELLED);
    • PAUSED - for subscriptions - subscription shifted to HOLD period.

      ;
    • TERMINATED — subscription closed.

      .
  • developerPayload — уline specified by the developer that contains additional information about the order..

  • subscriptionToken — token for server validation..

The Failure callback returns the FURuStoreError structure with the error information. All possible FURuStoreError errors are described in Error Handling.

Status model (purchaseState)

  • A status-based consumables subscription (CONSUMABLES)
img
  • A status-based non-consumables subscription (NON-CONSUMABLES):
img
  • A status-based subscription purchase model (SUBSCRIPTIONS)
img

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 theConfirmPurchase 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.

Вызов метода ConfirmPurchase
long requestId = RuStoreBillingClient::Instance()->ConfirmPurchase(
purchaseId,
[]( long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
},
[]( long requestId, TSharedPtr<FURuStoreConfirmPurchaseResponse, ESPMode::ThreadSafe> response) {
// Process response
}
);
img
  • purchaseId — purchase ID..

The Failure callback returns the FURuStoreError structure with the error information in the Error parameter. All possible FURuStoreError errors are described in Error Handling.

Canceling purchase

Use theDeletePurchase method to cancel a purchase.

** Purchase cancellation request**

Вызов метода DeletePurchase
long requestId = URuStoreBillingClient::Instance()->DeletePurchase(
purchaseId,
[]( long requestId, TSharedPtr<FURuStoreDeletePurchaseResponse, ESPMode::ThreadSafe> response) {
// Process response
},
[]( long requestId, TSharedPtr<FURuStoreRuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • purchaseId — purchase ID..
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.

The Failure callback returns the FURuStoreError structure with the error information in the Error parameter. All possible FURuStoreError errors are described in Error Handling.

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.

Logging

If you want to log payment library events, add parameter enableLogs = true in the FURuStoreBillingClientConfig structure when calling the Init method.

Вызов метода Init
FURuStoreBillingClientConfig config;
config.consoleApplicationId = "123456";
config.deeplinkScheme = "yourscheme";
config.allowNativeErrorHandling = false;
config.enableLogs = true;

URuStoreBillingClient::Instance()->Init(config);
img

In this case, the BillingClientLogger object will be used, which implements the output of messages to Logcat.

class BillingClientLogger(private val tag: String) : ExternalPaymentLogger {

override fun d(e: Throwable?, message: () -> String) {
Log.d(tag, message.invoke(), e)
}

override fun e(e: Throwable?, message: () -> String) {
Log.e(tag, message.invoke(), e)
}

override fun i(e: Throwable?, message: () -> String) {
Log.i(tag, message.invoke(), e)
}

override fun v(e: Throwable?, message: () -> String) {
Log.v(tag, message.invoke(), e)
}

override fun w(e: Throwable?, message: () -> String) {
Log.w(tag, message.invoke(), e)
}
}

Changing UI theme

To dynamically change theme, use SetTheme.

Вызов метода SetTheme
EURuStoreTheme theme = EURuStoreTheme::DARK;
URuStoreBillingClient::Instance()->SetTheme(theme);
img
  • theme - theme type from the EURuStoreTheme enumeration.

Theme type

UENUM(BlueprintType)
enum class EURuStoreTheme : uint8
{
DARK UMETA(DisplayName = "DARK"),
LIGHT UMETA(DisplayName = "LIGHT")
};
  • DARK — dark theme.
  • LIGHT — light theme.

To retrieve the information about the set theme, use the GetTheme method.

Вызов метода GetTheme
EURuStoreTheme theme = URuStoreBillingClient::Instance()->GetTheme();
img

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..

Error structure

USTRUCT(BlueprintType)
struct RUSTORECORE_API FURuStoreRuStoreError
{
GENERATED_USTRUCT_BODY()
FURuStoreRuStoreError()
{
name = "" ;
description = "" ;
}

UPROPERTY(BlueprintReadOnly)
FString name;

UPROPERTY(BlueprintReadOnly)
FString description;
};
  • name – error name..
  • description – error description..

Auto error handling

When the PurchaseProduct method is called, errors are handled automatically.

If the allowNativeErrorHandling == true parameter was passed during SDK initialisation, an error dialog will be displayed to the user when an error occurs, apart from calling the appropriate Failure handler.

You can change this behavior at any time using the SetAllowNativeErrorHandling() method.

Вызов метода SetAllowNativeErrorHandling
RuStoreBillingClient::Instance()->SetAllowNativeErrorHandling(false);
img
  • true — show dialogue.
  • false — hide dialogue.

Error codes

The following is a description of possible errors in errorCode.

HTTP codeError codeDescription
40040001Incorrect request parameters: mandatory parameters are not filled in/incorrect parameters format
40040003No application found
40040004inactive application status
40040005Product not found
40040006inactive product status
40040007Invalid product type. Supported types: consumable, non-consumable, subscription.
40040008A purchase with this order_id already exists
40040009The current client has a purchase of this product with the status invoice_created. Your are required to offer the client to pay for/cancel the purchase
40040010For consumable product type. The current customer already has purchased this product with the status paid. First you need to confirm the purchase on the device, and then you can send the following purchase request for this product
40040011For non-consumable product type. The current client already has purchased this product with the status pre_confirmed/confirmed. Such product has already been purchased. This product cannot be sold more than once.
40040012Forsubscription product type. The current client already has purchased this product with the status pre_confirmed/confirmed. Such product has already been purchased. This product cannot be sold more than once.
40040013Forsubscription product type. When requesting the subscription service for a list of products GET/products (serviceId, user_id) data were not received
40040014The required attribute(s) was not received in the request.
40040015Failed to change status when updating purchase (no transition allowed).
40040016When purchasing a subscription for a non-consumable product, the number quantity > 1 is specified
40040017Product removed, no new purchases available.
40040018You cannot consume type product.
40140101Invalid token.
40140102Token lifetime has expired.
40340301Access to the requested resource is denied (unauthorized).
40340302The current call is not authorized (method prohibited) for the token.
40340303The application ID in the request does not match the one specified in the token.
40340305Incorrect token type.
40440401Not found.
40840801The notification timeout period specified in the request has expired.
50050***Internal payment service error.