7.0.0 (Beta)
With RuStore you can integrate payments in your mobile app.
-
If you don't know where to start read the instruction.
-
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:7.0.0"))
implementation("ru.rustore.sdk:pay")
}
SDK 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
).
SDK methods
Available public interactiors:
PurchaseInteractor
- interactor that works with payments and has several public methods.getPurchase(purchaseId: PurchaseId): Task<Purchase>
- gets purchase information by its ID.getPurchases(productType: ProductType? = null): Task<List<Purchase>>
- retrieves the user's purchases. This method supports an optional product type filter (consumable and non-consumable goods). By default, this filter is disabled (regardless of the product type) — that means that all user purchases in thePAID
andCONFIRMED
will be returned.PAID
- the money on the user's account is put on hold, the developer's action is required: purchase confirmation or cancellation.getPurchaseAvailability(): Task<PurchaseAvailabilityResult>
- retrieves purchase availability status: whether the user can make a purchase.purchaseOneStep(params: Produc tPurchaseParams): Task<ProductPurchaseResult>
- starts a one-stage payment. With this method, the transaction is done without putting the user's money on hold on their account. If a payment is successful, the money is taken from the user's account instantly. You cannot cancel the payment, you can only refund the purchase from the RuStore Console.purchaseTwoStep(params: ProductPurchaseParams): Task<ProductPurchaseResult>
- start a two-stage payment. With this method, the money is put on hold on the user's account. If a purchase is successful, the money is taken from the user's account only after the developer's confirmation.confirmTwoStepPurchase(purchaseId: PurchaseId, developerPayload: DeveloperPayload? = null)
- confirm a two-stage payment.cancelTwoStepPurchase(purchaseId: PurchaseId)
- cancel a two-stage payment.
ProductInteractor
- interactor that works with products and has several public methods:getProducts(productsId: List<ProductId>): Task<List<Product>>
- retrieves information about active products published in the RuStore Console.
ImportantThis method returns up to 1000 products.
- the
RuStoreUtils
block - a set of public methods, such as:isRuStoreInstalled
- checks if the RuStore app is installed on the user's device.openRuStoreDownloadInstruction
- opens RuStore download page.openRuStore
- starts the RuStore app.openRuStoreAuthorization
- starts the RuStore for authorization. The RuStore app will be automatically closed after successful authorization.
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.
RuStorePayClient.instance.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.
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
});
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"),
)
Getting purchases list
- Kotlin
- Java
Go get the user's purchases list, use the getPurchases
method.
RuStorePayClient.instance.getPurchaseInteractor().getPurchases()
.addOnSuccessListener { purchases: List<Purchase> ->
// Process success
}
.addOnFailureListener { throwable: Throwable ->
// Process error
}
This method supports an optional product type filter (consumable and non-consumable goods). By default, this filter is disabled (regardless of the product type) — that means that all user purchases in the PAID
and CONFIRMED
will be returned. Purchase PAID
status means that the money is put on hold on the user's account, the purchase waits for the developer's confirmation.
RuStorePayClient.instance.getPurchaseInteractor().getPurchases(productType = ProductType.CONSUMABLE_PRODUCT)
.addOnSuccessListener { purchases: List<Purchase> ->
// Process success
}
.addOnFailureListener { throwable: Throwable ->
// Process error
}
Below is the purchase pattern:
public class Purchase internal constructor(
public val purchaseId: PurchaseId,
public val productId: ProductId,
public val invoiceId: InvoiceId,
public val orderId: OrderId?,
public val purchaseType: PurchaseType,
public val productType: ProductType,
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.
amountLabel
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.description
— descriptions inlanguage
.-
developerPayload
— string with additional order information, that you can specify on purchase initialization 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.price
— price in minimum currency units.productId
— product ID assigned to product in RuStore Console (mandatory).productType
— product type.
purchaseId
— product ID.purchaseTime
— purchase time.PurchaseType
— purchase type:ONE_PHASE
- one-stage payment;TWO_PHASE
- two-stage payment.
quantity
— product amount (optional, value1
will be used if not specified).status
— purchase state:INVOICE_CREATED
— purchase invoice is created and awaiting payment;CANCELLED
— purchase canceled by the user;PROCESSING
— payment initiated;REJECTED
— purchase rejected (for example: due to insufficient funds);PAID
— only for two-stage payments, intermediate status, funds are put on hold on the user's account, the purchase is awaiting confirmation from the developer;CONFIRMED
— purchase successfully paid for;REFUNDED
— purchase successfully refunded;REVERSED
— only for two-stage payment: wither the purchase was canceled by the developer or there was no payment within 6 hours, the funds on the user's account are put off hold.
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 supports an optional product type filter (consumable and non-consumable goods). By default, this filter is disabled (regardless of the product type) — that means that all user purchases in the PAID
and CONFIRMED
will be returned. Purchase PAID
status means that the money is put on hold on the user's account, the purchase waits for the developer's confirmation.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchases(ProductType.CONSUMABLE_PRODUCT)
.addOnSuccessListener(purchases -> {
// Process PaymentResult
})
.addOnFailureListener(error -> {
// Process error
});
Below is the purchase pattern:
public class Purchase {
private final PurchaseId purchaseId;
private final ProductId productId;
private final InvoiceId invoiceId;
private final OrderId orderId;
private final PurchaseType purchaseType;
private final ProductType productType;
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 purchaseType, ProductType productType, 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 getPurchaseType() {
return purchaseType;
}
public ProductType getProductType() {
return productType;
}
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;
}
}
amountLabel
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.description
— descriptions inlanguage
.-
developerPayload
— string with additional order information, that you can specify on purchase initialization 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.price
— price in minimum currency units.productId
— product ID assigned to product in RuStore Console (mandatory).productType
— product type.
purchaseId
— product ID.purchaseTime
— purchase time.PurchaseType
— purchase type:ONE_PHASE
- one-stage payment;TWO_PHASE
- two-stage payment.
quantity
— product amount (optional, value1
will be used if not specified).status
— purchase state:INVOICE_CREATED
— purchase invoice is created and awaiting payment;CANCELLED
— purchase canceled by the user;PROCESSING
— payment initiated;REJECTED
— purchase rejected (for example: due to insufficient funds);PAID
— only for two-stage payments, intermediate status, funds are put on hold on the user's account, the purchase is awaiting confirmation from the developer;CONFIRMED
— purchase successfully paid for;REFUNDED
— purchase successfully refunded;REVERSED
— only for two-stage payment: wither the purchase was canceled by the developer or there was no payment within 6 hours, the funds on the user's account are put off hold.
Getting purchase information
- Kotlin
- Java
getPurchase
method.
RuStorePayClient.instance.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 purchaseType: PurchaseType,
public val productType: ProductType,
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?,
)
amountLabel
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.description
— descriptions inlanguage
.-
developerPayload
— string with additional order information, that you can specify on purchase initialization 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.price
— price in minimum currency units.productId
— product ID assigned to product in RuStore Console (mandatory).productType
— product type.
purchaseId
— product ID.purchaseTime
— purchase time.PurchaseType
— purchase type:ONE_PHASE
- one-stage payment;TWO_PHASE
- two-stage payment.
quantity
— product amount (optional, value1
will be used if not specified).status
— purchase state:INVOICE_CREATED
— purchase invoice is created and awaiting payment;CANCELLED
— purchase canceled by the user;PROCESSING
— payment initiated;REJECTED
— purchase rejected (for example: due to insufficient funds);PAID
— only for two-stage payments, intermediate status, funds are put on hold on the user's account, the purchase is awaiting confirmation from the developer;CONFIRMED
— purchase successfully paid for;REFUNDED
— purchase successfully refunded;REVERSED
— only for two-stage payment: wither the purchase was canceled by the developer or there was no payment within 6 hours, the funds on the user's account are put off hold.
Response example.
Purchase(
purchaseId = PurchaseId("purchaseId"),
productId = ProductId("productId"),
invoiceId = InvoiceId("invoiceId"),
orderId = OrderId("orderId"),
purchaseType = PurchaseType.ONE_STEP,
productType = ProductType.CONSUMABLE_PRODUCT,
description = Description("description"),
purchaseTime = Date(123123123124),
price = Price(14100),
amountLabel = AmountLabel("141,00 ₽"),
currency = Currency("RUB"),
quantity = Quantity(1),
status = PurchaseStatus.CONFIRMED,
subscriptionToken = SubscriptionToken("subscriptionToken"),
developerPayload = DeveloperPayload("developerPayload"),
)
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 purchaseType;
private final ProductType productType;
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 purchaseType, ProductType productType, 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 getPurchaseType() {
return purchaseType;
}
public ProductType getProductType() {
return productType;
}
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;
}
}
amountLabel
— formatted purchase price, including currency symbol.currency
— ISO 4217 currency code.description
— descriptions inlanguage
.-
developerPayload
— string with additional order information, that you can specify on purchase initialization 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.price
— price in minimum currency units.productId
— product ID assigned to product in RuStore Console (mandatory).productType
— product type.
purchaseId
— product ID.purchaseTime
— purchase time.PurchaseType
— purchase type:ONE_PHASE
- one-stage payment;TWO_PHASE
- two-stage payment.
quantity
— product amount (optional, value1
will be used if not specified).status
— purchase state:INVOICE_CREATED
— purchase invoice is created and awaiting payment;CANCELLED
— purchase canceled by the user;PROCESSING
— payment initiated;REJECTED
— purchase rejected (for example: due to insufficient funds);PAID
— only for two-stage payments, intermediate status, funds are put on hold on the user's account, the purchase is awaiting confirmation from the developer;CONFIRMED
— purchase successfully paid for;REFUNDED
— purchase successfully refunded;REVERSED
— only for two-stage payment: wither the purchase was canceled by the developer or there was no payment within 6 hours, the funds on the user's account are put off hold.
Response example.
Purchase(
purchaseId = PurchaseId("purchaseId"),
productId = ProductId("productId"),
invoiceId = InvoiceId("invoiceId"),
orderId = OrderId("orderId"),
purchaseType = PurchaseType.ONE_STEP,
productType = ProductType.CONSUMABLE_PRODUCT,
description = Description("description"),
purchaseTime = Date(123123123124),
price = Price(14100),
amountLabel = AmountLabel("141,00 ₽"),
currency = Currency("RUB"),
quantity = Quantity(1),
status = PurchaseStatus.CONFIRMED,
subscriptionToken = SubscriptionToken("subscriptionToken"),
developerPayload = DeveloperPayload("developerPayload"),
)
Purchase status model
One-stage payment status model.
Two-stage payment status model.
Purchasing product
- Kotlin
- Java
One-stage payment (without hold)
To purchase product, use thepurchaseOneStep
method.
RuStorePayClient.instance.getPurchaseInteractor().purchaseOneStep(
ProductPurchaseParams(
productId = ProductId("productId"),
orderId = null,
quantity = null,
developerPayload = null,
)
).addOnSuccessListener { paymentResult: PaymentResult ->
when (paymentResult) {
// Process PaymentResult
}
}.addOnFailureListener { throwable: Throwable ->
// Process error
}
Two-stage payment (with hold)
To purchase product, use thepurchaseTwoStep
method.
RuStorePayClient.instance.getPurchaseInteractor().purchaseTwoStep(
ProductPurchaseParams(
productId = ProductId("productId"),
orderId = null,
quantity = null,
developerPayload = null,
)
).addOnSuccessListener { paymentResult: PaymentResult ->
when (paymentResult) {
// Process PaymentResult
}
}.addOnFailureListener { throwable: Throwable ->
// Process error
}
Purchase parameters structure
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. -
purchaseId
- purchase identifier. It is used to retrieve purchase information when using the method to retrieve purchase information -
productId
- product identifier specified during the product creation in the RuStore Console. -
invoiceId
- invoice identifier. It is used for server validation, searching payments in the RuStore Console, also, it is displayed to the buyer in the RuStore app -
orderId
- unique order identifier specified by the developer or generated automatically (uuid). -
subscriptionToken
- purchase server validation token.
One-stage payment (without hold)
To purchase product, use thepurchaseOneStep
method.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null);
purchaseInteractor.purchaseOneStep(params)
.addOnSuccessListener(result -> {
// Process PaymentResult
})
.addOnFailureListener(error -> {
// Process error
});
Two-stage payment (with hold)
To purchase product, use thepurchaseTwoStep
method.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null);
purchaseInteractor.purchaseTwoStep(params)
.addOnSuccessListener(result -> {
// Process PaymentResult
})
.addOnFailureListener(error -> {
// Process error
});
Purchase parameters structure
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.
Purchase result structure
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. -
purchaseId
- purchase identifier. It is used to retrieve purchase information when using the method to retrieve purchase information -
productId
- product identifier specified during the product creation in the RuStore Console. -
invoiceId
- invoice identifier. It is used for server validation, searching payments in the RuStore Console, also, it is displayed to the buyer in the RuStore app -
orderId
- unique order identifier specified by the developer or generated automatically (uuid). -
subscriptionToken
- purchase server validation token.
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
.
val params = ProductPurchaseParams(ProductId("productId"))
RuStorePayClient.getProductInteractor().purchase(params)
.addOnSuccessListener { result ->
if (result is ProductPurchaseResult.SuccessProductPurchaseResult) {
val invoiceId = result.invoiceId.value
yourApi.validate(invoiceId)
}
}
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 invoiceId = successResult.getinvoiceId().getValue();
yourApi.validate(invoiceId);
}
});
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.getinvoiceId().getValue());
}
})
.addOnFailureListener(error -> {
// Process error
});
Confirm (consume) purchase
- Kotlin
- Java
Confirmation is required only for two-stage payments (when the money is put on hold on the user's account). After a successful hold, such purchases will be in the PurchaseStatus.PAID
status.
Purchase confirmation is required for a success transaction. To do this, use the confirmTwoStepPurchase
method.
RuStorePayClient.getPurchaseInteractor().confirmTwoStepPurchase(
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.
Confirmation is required only for two-stage payments (when the money is put on hold on the user's account). After a successful hold, such purchases will be in the PurchaseStatus.PAID
status.
Purchase confirmation is required for a success transaction. To do this, use the confirmTwoStepPurchase
method.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.confirmTwoStepPurchase(
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.
Purchase cancellation
With our SDK you can cancel only the purchases that undergo a two-stage payment process, i.e. when the user's money is put on hold. After a successful hold, such purchases are in the PurchaseStatus.PAID
status. If a purchase is canceled it has the PurchaseStatus.REVERSED
status.
Cancel purchases if you cannot deliver your product after payment is made (when the user's money is put on hold).
To cancel a purchase (put the user's money off hold), use the cancelTwoStepPurchase
method.
- Kotlin
- Java
RuStorePayClient.getPurchaseInteractor().cancelTwoStepPurchase(
purchaseId = PurchaseId("purchaseId"),
)
.addOnSuccessListener {
// Process success
}.addOnFailureListener { throwable: Throwable ->
// Process error
}
purchaseId
— product ID.
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.cancelTwoStepPurchase(
new PurchaseId("purchaseId")
).addOnSuccessListener(aVoid -> {
// Process success
}).addOnFailureListener(throwable -> {
// Process error
});
purchaseId
— product ID.
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.
List of dependencies
androidx.core:core-ktx:1.7.0
— The Apache Software License, Version 2.0;androidx.activity:activity-ktx:1.7.0
— The Apache Software License, Version 2.0;androidx.fragment:fragment-ktx:1.4.0
— The Apache Software License, Version 2.0;androidx.lifecycle:lifecycle-runtime-ktx:2.4.1
— The Apache Software License, Version 2.0;androidx.lifecycle:lifecycle-common-java8:2.4.1
— The Apache Software License, Version 2.0;androidx.recyclerview:recyclerview:1.2.1
— The Apache Software License, Version 2.0;androidx.security:security-crypto:1.0.0
— The Apache Software License, Version 2.0;com.google.android.material:material:1.3.0
— The Apache Software License, Version 2.0;io.coil-kt:coil:2.6.0
— The Apache Software License, Version 2.0.