6.1.0 (Beta)
With RuStore you can integrate payments in your mobile app.
-
If you are in doubt read the instruction in the usage scenarios.
-
If you migrate to Pay SDK from billingClient SDK, please review the migration instructions. For more details, see here.
Prerequisites
- In-app purchases for the app are enabled in RuStore Console.
- The app must not be banned in RuStore.
- The current version of RuStore is installed on the user's device.
- User is authorized in RuStore.
- The user must is not banned in RuStore.
Connect to project
Adding repository
Add our repository as shown in the example below.
repositories {
maven {
url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven")
}
}
Connecting the dependency
Add the following code to your configuration file to add the dependency.
dependencies {
implementation(platform("ru.rustore.sdk:bom:6.1.0"))
implementation("ru.rustore.sdk:pay")
}
Initialization
Initialize the library before calling its methods.
The initialization itself is done automatically, however, for your SDK to work, define console_app_id_key
in your manifest.xml
.
You can so it the following way:
<?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">
...
<meta-data
android:name="console_app_id_key"
android:value="@string/CONSOLE_APPLICATION_ID" />
</application>
</manifest>
-
CONSOLE_APPLICATION_ID
— product ID form the RuStore Console.
Where are app IDs in the RuStore Console?
- Navigate to the Applications tab and selected the needed app.
- 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 addresshttps://console.rustore.ru/apps/123456/versions
the app ID is123456
.
ApplicationId
specified inbuild.gradle
, must matchapplicationId
of the APK file you published in the RuStore Console.-
The
keystore
signature must match the signature that was used to sign the app published in the RuStore Console. Make sure thatbuildType
used (example:debug
) uses the same signature as the published app (example:release
).
Working with SDK
Available public interactiors:
PurchaseInteractor
— interactor that allows working with payments and has several public methods:getPurchase(purchaseId: PurchaseId): Task<Purchase>
— retrieves payment information by its ID.getPurchases(): Task<List<Purchase>>
— retrieves the user's purchases. The returned list contains purchases in theCONFIRMED
status for non-consumable products andPAID
status for consumable products.PAID
— this status means that the money is put on hold. The purchase requires the developer's confirmation.getPurchaseAvailability(): Task<PurchaseAvailabilityResult>
— returns payments availability result.consumePurchase(purchaseId: PurchaseId, developerPayload: DeveloperPayload? = null)
— purchase confirmation (consumption). Only for consumable products.
ProductInteractor
— interactor that allows working with products and has several public methods:getProducts(productsId: List<ProductId>): Task<List<Product>>
— retrieves product information by ID. You can specify up to 1000 items in the products list.purchase(params: ProductPurchaseParams): Task<ProductPurchaseResult>
— allows to purchase product.
- The
RuStoreUtils
block — set of public methods, such as:isRuStoreInstalled
— checks if the RuStore app is installed on the user's device.openRuStoreDownloadInstruction
— opens RuStore app download page.openRuStore
— launches RuStore app.openRuStoreAuthorization
— launches RuStore app for authorization. Automatically closes after user authorization in RuStore.
Payments availability check
- Kotlin
- Java
To check purchase availability, call the getPurchaseAvailability
methods from PurchaseInteractor
. On calling, the following conditions are checked:
- The current version of RuStore is installed on the user's device.
- User is authorized in RuStore.
- The user and the app are not banned in RuStore.
- Monetization is enabled in the RuStore Console.
If all conditions are met, PurchaseAvailabilityResult.Available
is returned.
Otherwise, PurchaseAvailabilityResult.Unavailable(val cause: Throwable)
is returned, where cause
is an error of unmet conditions.
To figure out the cause of the error, check its type for RuStoreException
.
See Error handling.
For example, if you received RuStoreUserUnauthorizedException
, this means that the user is not authorized in RuStore.
IN this case you can call the openRuStoreAuthorization
method that launches the RuStore app for authorization.
See other methods in section SDK.
RuStorePayClient.getPurchaseInteractor().getPurchaseAvailability()
.addOnSuccessListener { result ->
when (result) {
is PurchaseAvailabilityResult.Available -> {
// Process purchases available
}
is PurchaseAvailabilityResult.Unavailable -> {
// Process purchases unavailable
}
}
}.addOnFailureListener { throwable ->
// Process unknown error
}
To check purchase availability, call the getPurchaseAvailability
methods from PurchaseInteractor
. On calling, the following conditions are checked:
- The current version of RuStore is installed on the user's device.
- User is authorized in RuStore.
- The user and the app are not banned in RuStore.
- Monetization is enabled in the RuStore Console.
If all conditions are met, PurchaseAvailabilityResult.Available
is returned.
Otherwise, PurchaseAvailabilityResult.Unavailable(val cause: Throwable)
is returned, where cause
is an error of unmet conditions.
To figure out the cause of the error, check its type for RuStoreException
.
See Error handling.
For example, if you received RuStoreUserUnauthorizedException
, this means that the user is not authorized in RuStore.
IN this case you can call the openRuStoreAuthorization
method that launches the RuStore app for authorization.
See other methods in section SDK.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchaseAvailability()
.addOnSuccessListener(result -> {
if (result instanceof PurchaseAvailabilityResult.Available) {
// Process purchases available
} else if (result instanceof PurchaseAvailabilityResult.Unavailable) {
// Process purchases unavailable
}
})
.addOnFailureListener(throwable -> {
// Process unknown error
});
Working with products
Retrieving products list
- Kotlin
- Java
You checked that payments are available and the users are able to make purchases. Now you can request products list. Use the getProducts
method to request the information about products added to your app in RuStore Console.
RuStorePayClient.instance.getProductInteractor().getProducts(productsId = listOf(ProductId("id1"), ProductId("id2")))
.addOnSuccessListener { products: List<Product> ->
// Process success
}
.addOnFailureListener { throwable: Throwable ->
// Process error
}
productsId: List<ProductId>
— 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?
- Navigate to the Applications tab and selected the needed app.
- Select Monetization in the left menu.
- Select product type: Subscriptions or In-App purchases.
- Copy the IDs of the required products.
The method returns products list. Below is the product pattern.
public class Product internal constructor(
public val productId: ProductId,
public val type: ProductType,
public val amountLabel: AmountLabel,
public val price: Price?,
public val currency: Currency,
public val imageUrl: Url,
public val title: Title,
public val description: Description?,
)
amountLabel
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.description
— descriptions inlanguage
.imageUrl
— image URL.price
— price in minimum currency units.productId
— product ID assigned to product in RuStore Console (mandatory).title
— product name inlanguage
.type
— product type.
Response examples
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("Title of a Consumable product"),
description = Description("Description of a Consumable product"),
)
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("Title of a Non-consumable product"),
description = Description("Description of a Non-consumable product"),
)
You checked that payments are available and the users are able to make purchases. Now you can request products list. Use the getProducts
method to request the information about products added to your app in RuStore Console.
List<ProductId> productIds = Arrays.asList(new ProductId("id1"), new ProductId("id2"));
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
productInteractor.getProducts(productsId)
.addOnSuccessListener(products -> {
// Process success
})
.addOnFailureListener(throwable -> {
// Process error
});
productsId: List<ProductId>
— 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?
- Navigate to the Applications tab and selected the needed app.
- Select Monetization in the left menu.
- Select product type: Subscriptions or In-App purchases.
- Copy the IDs of the required products.
The method returns products list. Below is the product pattern:
public class Product {
private final ProductId productId;
private final ProductType type;
private final AmountLabel amountLabel;
private final Price price;
private final Currency currency;
private final Url imageUrl;
private final Title title;
private final Description description;
public Product(ProductId productId, ProductType type, AmountLabel amountLabel, @Nullable Price price, Currency currency, Url imageUrl, Title title, @Nullable Description description) {
this.productId = productId;
this.type = type;
this.amountLabel = amountLabel;
this.price = price;
this.currency = currency;
this.imageUrl = imageUrl;
this.title = title;
this.description = description;
}
public ProductId getProductId() {
return productId;
}
public ProductType getType() {
return type;
}
public AmountLabel getAmountLabel() {
return amountLabel;
}
public @Nullable Price getPrice() {
return price;
}
public Currency getCurrency() {
return currency;
}
public Url getImageUrl() {
return imageUrl;
}
public Title getTitle() {
return title;
}
public @Nullable Description getDescription() {
return description;
}
}
amountLabel
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.description
— descriptions inlanguage
.imageUrl
— image URL.price
— price in minimum currency units.productId
— product ID assigned to product in RuStore Console (mandatory).title
— product name inlanguage
.type
— product type.
Response examples
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("Title of a Consumable product"),
description = Description("Description of a Consumable product"),
)
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("Title of a Non-consumable product"),
description = Description("Description of a Non-consumable product"),
)
Working with purchases
Getting products list
- Kotlin
- Java
Go get the user's purchases list, use the getPurchases
method.
RuStorePayClient.getPurchaseInteractor().getPurchases()
.addOnSuccessListener { purchases: List<Purchase> ->
// Process success
}
.addOnFailureListener { throwable: Throwable ->
// Process error
}
This method returns the products list in the CONFIRMED
status for non-consumable products and PAID
for consumable products.
Below is the product pattern:
public class Purchase internal constructor(
public val purchaseId: PurchaseId,
public val productId: ProductId,
public val invoiceId: InvoiceId,
public val orderId: OrderId?,
public val type: PurchaseType,
public val description: Description,
public val purchaseTime: Date?,
public val price: Price,
public val amountLabel: AmountLabel,
public val currency: Currency,
public val quantity: Quantity,
public val status: PurchaseStatus,
public val subscriptionToken: SubscriptionToken?,
public val developerPayload: DeveloperPayload?,
)
purchaseId
— product ID.productId
— product ID assigned to product in RuStore Console (mandatory).invoiceId
— invoice ID.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.type
— product type:CONSUMABLE
/NON-CONSUMABE
.description
— purchase description;purchaseTime
— purchase time.price
— price in minimum currency units.amountLable
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.quantity
— product amount (optional, value1
will be used if not specified).purchaseState
— purchase state.developerPayload
— string with additional order information, that you can specify on purchase initialization.
Go get the user's purchases list, use the getPurchases
method.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchases()
.addOnSuccessListener(purchases -> {
// Process PaymentResult
})
.addOnFailureListener(error -> {
// Process error
});
This method returns the products list in the CONFIRMED
status for non-consumable products and PAID
for consumable products.
Below is the product pattern:
public class Purchase {
private final PurchaseId purchaseId;
private final ProductId productId;
private final InvoiceId invoiceId;
private final OrderId orderId;
private final PurchaseType type;
private final Description description;
private final Date purchaseTime;
private final Price price;
private final AmountLabel amountLabel;
private final Currency currency;
private final Quantity quantity;
private final PurchaseStatus status;
private final SubscriptionToken subscriptionToken;
private final DeveloperPayload developerPayload;
public Purchase(PurchaseId purchaseId, ProductId productId, InvoiceId invoiceId, OrderId orderId, PurchaseType type, Description description, Date purchaseTime, Price price, AmountLabel amountLabel, Currency currency, Quantity quantity, PurchaseStatus status, SubscriptionToken subscriptionToken, @Nullable DeveloperPayload developerPayload) {
this.purchaseId = purchaseId;
this.productId = productId;
this.invoiceId = invoiceId;
this.orderId = orderId;
this.type = type;
this.description = description;
this.purchaseTime = purchaseTime;
this.price = price;
this.amountLabel = amountLabel;
this.currency = currency;
this.quantity = quantity;
this.status = status;
this.subscriptionToken = subscriptionToken;
this.developerPayload = developerPayload;
}
public PurchaseId getPurchaseId() {
return purchaseId;
}
public ProductId getProductId() {
return productId;
}
public InvoiceId getInvoiceId() {
return invoiceId;
}
public @Nullable OrderId getOrderId() {
return orderId;
}
public PurchaseType getType() {
return type;
}
public Description getDescription() {
return description;
}
public Date getPurchaseTime() {
return purchaseTime;
}
public Price getPrice() {
return price;
}
public AmountLabel getAmountLabel() {
return amountLabel;
}
public Currency getCurrency() {
return currency;
}
public Quantity getQuantity() {
return quantity;
}
public PurchaseStatus getStatus() {
return status;
}
public @Nullable SubscriptionToken getSubscriptionToken() {
return subscriptionToken;
}
public @Nullable DeveloperPayload getDeveloperPayload() {
return developerPayload;
}
}
purchaseId
— product ID.productId
— product ID assigned to product in RuStore Console (mandatory).invoiceId
— invoice ID.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.type
— product type:CONSUMABLE
/NON-CONSUMABE
.description
— purchase description;purchaseTime
— purchase time.price
— price in minimum currency units.amountLable
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.quantity
— product amount (optional, value1
will be used if not specified).purchaseState
— purchase state.developerPayload
— string with additional order information, that you can specify on purchase initialization.subscriptionToken
— purchase token for server validation .
Getting purchase information
- Kotlin
- Java
getPurchase
method.
RuStorePayClient.getPurchaseInteractor().getPurchase(PurchaseId("purchaseId"))
.addOnSuccessListener { purchase: Purchase ->
// Process success
}
.addOnFailureListener { throwable: Throwable ->
// Process error
}
This method returns information about a specific purchase in any status. Below is the product pattern:
public class Purchase internal constructor(
public val purchaseId: PurchaseId,
public val productId: ProductId,
public val invoiceId: InvoiceId,
public val orderId: OrderId?,
public val type: PurchaseType,
public val description: Description,
public val purchaseTime: Date?,
public val price: Price,
public val amountLabel: AmountLabel,
public val currency: Currency,
public val quantity: Quantity,
public val status: PurchaseStatus,
public val subscriptionToken: SubscriptionToken?,
public val developerPayload: DeveloperPayload?,
)
-
purchaseId
— product ID. -
productId
— product ID assigned to product in RuStore Console (mandatory). -
invoiceId
— invoice ID. -
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. -
type
— product type:CONSUMABLE
/NON-CONSUMABE
. -
description
— purchase description; -
purchaseTime
— purchase time. -
price
— price in minimum currency units. -
amountLable
— formatted purchase price, including currency symbol. -
currency
— ISO 4217 currency code. -
quantity
— product amount (optional, value1
will be used if not specified). -
purchaseState
— purchase state.Intermediate statuses:
INVOICE_CREATED
— purchase invoice is created and awaiting payment.PROCESSING
— payment initiated.PAID
— only for consumable products — intermediate status, the funds on the user's account are put on hold. The purchase is awaiting confirmation from the developer.
Final statuses:
CONSUMED
— payment for consumable product successful.CONFIRMED
— payment for non-consumable product successful.CANCELLED
— purchase canceledm no payment was made.EXPIRED
— payment time expired.REJECTED
— purchase rejected (for example: due to insufficient funds).REVERSED
— purchase was canceled as it was not confirmed within 72 hours (for consumable products).REFUNDED
— purchase successfully refunded.
For more information on status changes, see purchase status model.
-
developerPayload
— string with additional order information, that you can specify on purchase initialization. -
subscriptionToken
— purchase token for server validation .
getPurchase
method.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchase(new PurchaseId("purchaseId"))
.addOnSuccessListener(purchase -> {
// Process success
})
.addOnFailureListener(throwable -> {
// Process error
});
This method returns information about a specific purchase in any status. Below is the product pattern:
public class Purchase {
private final PurchaseId purchaseId;
private final ProductId productId;
private final InvoiceId invoiceId;
private final OrderId orderId;
private final PurchaseType type;
private final Description description;
private final Date purchaseTime;
private final Price price;
private final AmountLabel amountLabel;
private final Currency currency;
private final Quantity quantity;
private final PurchaseStatus status;
private final SubscriptionToken subscriptionToken;
private final DeveloperPayload developerPayload;
public Purchase(PurchaseId purchaseId, ProductId productId, InvoiceId invoiceId, OrderId orderId, PurchaseType type, Description description, Date purchaseTime, Price price, AmountLabel amountLabel, Currency currency, Quantity quantity, PurchaseStatus status, SubscriptionToken subscriptionToken, @Nullable DeveloperPayload developerPayload) {
this.purchaseId = purchaseId;
this.productId = productId;
this.invoiceId = invoiceId;
this.orderId = orderId;
this.type = type;
this.description = description;
this.purchaseTime = purchaseTime;
this.price = price;
this.amountLabel = amountLabel;
this.currency = currency;
this.quantity = quantity;
this.status = status;
this.subscriptionToken = subscriptionToken;
this.developerPayload = developerPayload;
}
public PurchaseId getPurchaseId() {
return purchaseId;
}
public ProductId getProductId() {
return productId;
}
public InvoiceId getInvoiceId() {
return invoiceId;
}
public @Nullable OrderId getOrderId() {
return orderId;
}
public PurchaseType getType() {
return type;
}
public Description getDescription() {
return description;
}
public Date getPurchaseTime() {
return purchaseTime;
}
public Price getPrice() {
return price;
}
public AmountLabel getAmountLabel() {
return amountLabel;
}
public Currency getCurrency() {
return currency;
}
public Quantity getQuantity() {
return quantity;
}
public PurchaseStatus getStatus() {
return status;
}
public @Nullable SubscriptionToken getSubscriptionToken() {
return subscriptionToken;
}
public @Nullable DeveloperPayload getDeveloperPayload() {
return developerPayload;
}
}
-
purchaseId
— product ID. -
productId
— product ID assigned to product in RuStore Console (mandatory). -
invoiceId
— invoice ID. -
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. -
type
— product type:CONSUMABLE
/NON-CONSUMABE
. -
description
— purchase description; -
purchaseTime
— purchase time. -
price
— price in minimum currency units. -
amountLable
— formatted purchase price, including currency symbol. -
currency
— ISO 4217 currency code. -
quantity
— product amount (optional, value1
will be used if not specified). -
purchaseState
— purchase state.Intermediate statuses:
INVOICE_CREATED
— purchase invoice is created and awaiting payment.PROCESSING
— payment initiated.PAID
— only for consumable products — intermediate status, the funds on the user's account are put on hold. The purchase is awaiting confirmation from the developer.
Final statuses:
CONSUMED
— payment for consumable product successful.CONFIRMED
— payment for non-consumable product successful.CANCELLED
— purchase canceledm no payment was made.EXPIRED
— payment time expired.REJECTED
— purchase rejected (for example: due to insufficient funds).REVERSED
— purchase was canceled as it was not confirmed within 72 hours (for consumable products).REFUNDED
— purchase successfully refunded.
For more information on status changes, see purchase status model.
-
developerPayload
— string with additional order information, that you can specify on purchase initialization. -
subscriptionToken
— purchase token for server validation .
Purchase status model (purchaseState)
CONSUMABLES
- purchase state model
NON-CONSUMABLES
- purchase state model
Purchasing product
- Kotlin
- Java
To purchase product, use the purchase
method.
RuStorePayClient.getProductInteractor().purchase(
ProductPurchaseParams(
productId = ProductId("productId"),
orderId = null,
quantity = null,
developerPayload = null,
)
).addOnSuccessListener { paymentResult: PaymentResult ->
when (paymentResult) {
// Process PaymentResult
}
}.addOnFailureListener { throwable: Throwable ->
// Process error
}
public class ProductPurchaseParams(
public val productId: ProductId,
public val quantity: Quantity? = null,
public val orderId: OrderId? = null,
public val developerPayload: DeveloperPayload? = null,
)
productId
— product ID assigned to product in RuStore Console (mandatory).quantity
— product amount (optional, value1
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
— string with additional order information, that you can specify on purchase initialization. 250 characters max.
public sealed interface ProductPurchaseResult {
public class SuccessProductPurchaseResult(
public val orderId: OrderId?,
public val purchaseId: PurchaseId,
public val productId: ProductId,
public val invoiceId: InvoiceId,
public val subscriptionToken: SubscriptionToken?,
) : ProductPurchaseResult
public class CancelProductPurchaseResult(
public val purchaseId: PurchaseId?,
) : ProductPurchaseResult
public class FailureProductPurchaseResult(
public val orderId: OrderId?,
public val purchaseId: PurchaseId?,
public val productId: ProductId?,
public val invoiceId: InvoiceId?,
public val quantity: Quantity?,
public val subscriptionToken: SubscriptionToken?,
public val cause: Throwable,
) : ProductPurchaseResult
}
SuccessProductPurchaseResult
— successful purchase result.FailureProductPurchaseResult
— failed purchase result.CancelProductPurchaseResult
— payment dialog was closed prior to receiving purchase result. Purchase state unknown. We recommend request purchase status using the method for getting purchase information.
To purchase product, use the purchase
method.
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null);
productInteractor.purchase(params)
.addOnSuccessListener(result -> {
// Process PaymentResult
})
.addOnFailureListener(error -> {
// Process error
});
public class ProductPurchaseParams {
private final ProductId productId;
private final Quantity quantity;
private final OrderId orderId;
private final DeveloperPayload developerPayload;
public ProductPurchaseParams(ProductId productId, @Nullable Quantity quantity, @Nullable OrderId orderId, @Nullable DeveloperPayload developerPayload) {
this.productId = productId;
this.quantity = quantity;
this.orderId = orderId;
this.developerPayload = developerPayload;
}
public ProductId getProductId() {
return productId;
}
public @Nullable Quantity getQuantity() {
return quantity;
}
public @Nullable OrderId getOrderId() {
return orderId;
}
public @Nullable DeveloperPayload getDeveloperPayload() {
return developerPayload;
}
}
productId
— product ID assigned to product in RuStore Console (mandatory).quantity
— product amount (optional, value1
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
— string with additional order information, that you can specify on purchase initialization. 250 characters max.
public interface ProductPurchaseResult {
public static class SuccessProductPurchaseResult implements ProductPurchaseResult {
public final OrderId orderId;
public final PurchaseId purchaseId;
public final ProductId productId;
public final InvoiceId invoiceId;
public final SubscriptionToken subscriptionToken;
public SuccessProductPurchaseResult(OrderId orderId, PurchaseId purchaseId, ProductId productId, InvoiceId invoiceId, SubscriptionToken subscriptionToken) {
this.orderId = orderId;
this.purchaseId = purchaseId;
this.productId = productId;
this.invoiceId = invoiceId;
this.subscriptionToken = subscriptionToken;
}
}
public static class CancelProductPurchaseResult implements ProductPurchaseResult {
public final @Nullable PurchaseId purchaseId;
public CancelProductPurchaseResult(@Nullable PurchaseId purchaseId) {
this.purchaseId = purchaseId;
}
}
public static class FailureProductPurchaseResult implements ProductPurchaseResult {
public final @Nullable OrderId orderId;
public final @Nullable PurchaseId purchaseId;
public final @Nullable ProductId productId;
public final @Nullable InvoiceId invoiceId;
public final @Nullable Quantity quantity;
public final @Nullable SubscriptionToken subscriptionToken;
public final Throwable cause;
public FailureProductPurchaseResult(@Nullable OrderId orderId, @Nullable PurchaseId purchaseId, @Nullable ProductId productId, @Nullable InvoiceId invoiceId, @Nullable Quantity quantity, @Nullable SubscriptionToken subscriptionToken, Throwable cause) {
this.orderId = orderId;
this.purchaseId = purchaseId;
this.productId = productId;
this.invoiceId = invoiceId;
this.quantity = quantity;
this.subscriptionToken = subscriptionToken;
this.cause = cause;
}
}
}
SuccessProductPurchaseResult
— successful purchase result.FailureProductPurchaseResult
— failed purchase result.CancelProductPurchaseResult
— payment dialog was closed prior to receiving purchase result. Purchase state unknown. We recommend request purchase status using the method for getting purchase information.
Server purchase validation
- Kotlin
- Java
If you need to validate a purchase on the RuStore server, you can use subscriptionToken
from the ProductPurchaseResult.SuccessProductPurchaseResult
model, that is returned on successful purchase.
You can also validate payments using InvoiceId
.
RuStorePayClient.getProductInteractor().purchase(ProductId("productId"))
.addOnSuccessListener { result ->
if (result is ProductPurchaseResult.SuccessProductPurchaseResult) {
val subscriptionToken = result.subscriptionToken
yourApi.validate(subscriptionToken)
}
}
You can also get a subscriptionToken
from the Purchase
entity. The Purchase
entity can be retrieved using the getPurchases
method.
RuStorePayClient.getPurchaseInteractor().getPurchases()
.addOnSuccessListener { purchases ->
purchases.forEach { purchase ->
yourApi.validate(purchase.subscriptionToken)
}
}
If you need to validate a purchase on the RuStore server, you can use subscriptionToken
from the ProductPurchaseResult.SuccessProductPurchaseResult
model, that is returned on successful purchase.
You can also validate payments using InvoiceId
.
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null);
productInteractor.purchase(params)
.addOnSuccessListener(result -> {
if (result instanceof ProductPurchaseResult.SuccessProductPurchaseResult) {
ProductPurchaseResult.SuccessProductPurchaseResult successResult = (ProductPurchaseResult.SuccessProductPurchaseResult) result;
String subscriptionToken = successResult.getSubscriptionToken().getValue();
yourApi.validate(subscriptionToken);
}
});
You can also get a subscriptionToken
from the Purchase
entity. The Purchase
entity can be retrieved using the getPurchases
method.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchases()
.addOnSuccessListener(purchases -> {
for (Purchase purchase : purchases) {
yourApi.validate(purchase.getSubscriptionToken().getValue());
}
})
.addOnFailureListener(error -> {
// Process error
});
Consume (confirm) purchase
The RuStore application consists of the following types of products:
CONSUMABLE
— consumables (multiple-time purchases, such as crystals in the app).NON_CONSUMABLE
— non-consumables (one-time purchases, such as disabling in-app ads).
Only CONSUMABLE
products need confirmation when they are in the PurchaseState.PAID
status.
- Kotlin
- Java
To consume purchase, use the consumePurchase
method:
RuStorePayClient.getPurchaseInteractor().consumePurchase(
purchaseId = PurchaseId("purchaseId"),
developerPayload = null,
)
.addOnSuccessListener {
// Process success
}.addOnFailureListener { throwable: Throwable ->
// Process error
}
purchaseId
— product ID.developerPayload
— string with additional order information, that you can specify on purchase initialization. 250 characters max. If passed, changes value set on purchase start by thepurchase
method.
To consume purchase, use the consumePurchase
method:
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.consumePurchase(
new PurchaseId("purchaseId"),
null
).addOnSuccessListener(aVoid -> {
// Process success
}).addOnFailureListener(throwable -> {
// Process error
});
purchaseId
— product ID.developerPayload
— string with additional order information, that you can specify on purchase initialization. 250 characters max. If passed, changes value set on purchase start by thepurchase
method.
Handling pending payments
Handling of unfinished payments is done by the developer.
To confirm a purchase of CONSUMABLE
product in the PAID
state, call the [purchase confirmation
method].(#consumepurchase) (see Retrieve purchase details).
Error handling
RuStorePaymentNetworkException
— SDK network communication error;RuStorePaymentCommonException
— general SDK error;RuStorePayClientAlreadyExist
— duplicate initialization error SDK;RuStorePayClientNotCreated
— attempt to access public SDK interface before initialisation;RuStorePayInvalidActivePurchase
— payment initiated for unknown product type;RuStorePayInvalidConsoleAppId
— mandatory parameterсonsole_application_id
for SDK initialisation not set;RuStorePaySignatureException
— invalid signature (occurs because of fraud actions);EmptyPaymentTokenException
— error receiving payment token;RuStoreNotInstalledException
— RuStore is not installed on the user's device;RuStoreOutdatedException
— RuStore version installed on the user's device does not support this SDK;RuStoreUserUnauthorizedException
— user is not authorized in RuStore;RuStoreApplicationBannedException
— app is banned in RuStore RuStore;RuStoreUserBannedException
— user is blocked in RuStore;RuStoreException
— basic RuStore error from which other errors are inherited.