Kotlin/Java 应用内支付 SDK (版本 10.5.0)
RuStore 支持在移动应用程序中集成支付功能。
-
如果您不知道从哪里开始,请阅读使用场景中的指南。
-
如果您从 billingClient SDK 迁移到 Pay SDK,请参阅迁移指南。 有关 Pay SDK 的详细信息,请参见此处。
准备工作
添加仓库
repositories {
maven {
url = uri("https://nexus-external.vkteam.ru/repository/maven-rustore-exposed/")
}
}
添加依赖
在您的配置文件中添加以下代码以连接依赖项。
dependencies {
implementation(platform("ru.rustore.sdk:bom:2026.06.01"))
implementation("ru.rustore.sdk:pay")
}
处理 deeplink
RuStore SDK 中的 deeplink 处理允许在通过银行应用程序(SBP、SberPay 等)进行支付时,与第三方应用程序高效交互。 这可以将用户引导至支付页面,并在交易完成后将其返回到您的应用程序中 。
为了在您的应用程序和 Pay SDK 中配置 deeplink,请在 AndroidManifest.xml 文件中使用 sdk_pay_scheme_value 指定 deeplinkScheme,
并重写 Activity 的 onNewIntent 方法。
- 使用 deeplinks 时,必须指定方案(scheme)。
- 如果在未指定方案的情况下尝试支付,将会出现错误。
- 仅允许使用 ASCII 编码的字符。 格式必须符合 RFC-3986 规范。
指定 deeplinkScheme:
<?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">
<!-- ... -->
<activity
android:name=".YourPayActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourappscheme" />
</intent-filter>
</activity>
<meta-data
android:name="sdk_pay_scheme_value"
android:value="yourappscheme" />
</application>
</manifest>
请将 yourappscheme 替换为您自己的方案名称。 例如,ru.package.name.rustore.scheme。
然后,在完成支付后需要返回的 Activity(您的应用页面)中添加以下代码:
- Kotlin
- Java
class YourPayActivity : AppCompatActivity() {
private val intentInteractor: IntentInteractor by lazy {
RuStorePayClient.instance.getIntentInteractor()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
intentInteractor.proceedIntent(intent, sdkTheme = SdkTheme.LIGHT) // Опциональная тема
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intentInteractor.proceedIntent(intent, sdkTheme = SdkTheme.LIGHT) // Опциональная тема
}
}
public class YourPayActivity extends AppCompatActivity {
private final IntentInteractor intentInteractor =
RuStorePayClient.Companion.getInstance().getIntentInteractor();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
intentInteractor.proceedIntent(getIntent(), SdkTheme.LIGHT); // Опциональная тема
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
intentInteractor.proceedIntent(intent, SdkTheme.LIGHT); // Опциональная тема
}
}
为了在从 deeplink 返回时恢复应用程序的状态,请在 AndroidManifest.xml 中添加 android:launchMode="singleTop" 属性。
<?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>
<!-- ... -->
<activity
android:name=".YourPayActivity"
android:launchMode="singleTop"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
</activity>
<!-- ... -->
</application>
</manifest>
SDK 初始化
在调用库方法之前,需要对其进行初始化。 初始化过程是自动完成的,但为了使 SDK 正常工作,您需要在 Manifest.xml 文件中指定 console_app_id_value。 该值必须在字符串资源中指定。
可以通过以下方式实现。
<?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_value"
android:value="@string/CONSOLE_APPLICATION_ID" />
<meta-data
android:name="sdk_pay_scheme_value"
android:value="@string/APP_SCHEME" />
</application>
</manifest>
-
示例:CONSOLE_APPLICATION_ID— RuStore 控制台中的应用标识符。https://console.rustore.ru/apps/111111。
在 RuStore 控制台的哪里可以查看应用程序 ID?
- 转到应用程序选项卡并选择所需的应用程序。
- 从应用程序页面的 URL 地址中复制 ID —— 即
apps/和/versions之间的那一组数字。 例如,对于 URL 地址https://console.rustore.ru/apps/123456/versions,应用程序 ID 为123456。

- 在
build.gradle中指定的ApplicationId必须与您在 RuStore 控制台中发布的 APK 文件的applicationId一致。 - 为了使 deeplink 正常工作,AndroidManifest 中必须包含一个名为 "sdk_pay_scheme_value" 的
<meta-data>属性。 其值为您的应用程序方案 (scheme)。 -
keystore签名必须与在 RuStore 控制台发布的应用所使用的签名一致。 请确保所使用的buildType(例如debug)使用的签名与已发布的应用程序(例如release)相同。
必要的权限和安全参数
Pay SDK 会自动在应用程序清单中添加一些必要的权限和参数,以支持与支付安全相关的功能。
其他权限
此外,Pay SDK 可能还需要其他标准权限,例如:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
SDK 方法
可用的公共交互器:
-
PurchaseInteractor- 一个允许处理支付并具有多个公共方法的交互器。getPurchase(purchaseId: PurchaseId): Task<Purchase>- 允许通过 ID 获取购买信息。getPurchases(productType: ProductType? = null, purchaseStatus: PurchaseStatus? = null, acknowledgementState: AcknowledgementState? = null): Task<List<Purchase>>— 允许获取用户的购买记录。 该方法支持根据产品类型(消耗型、非消耗型产品或订阅)、购买状态(支持PAID、CONFIRMEDACTIVE和PAUSED状态)以及产品交付状态 (acknowledgementState) 进行可选过滤。 可能的值:PENDING,ACKNOWLEDGED,UNKNOWN。 默认情况下,过滤器被禁用,将返回用户所有处于PAID、CONFIRMEDACTIVE和PAUSED状态的购买记录(无论商品类型如何)。getPurchaseAvailability(): Task<PurchaseAvailabilityResult>- 返回支付功能可用性检查的结果。purchase(params: ProductPurchaseParams, preferredPurchaseType: PreferredPurchaseType = PreferredPurchaseType.ONE_STEP, sdkTheme: SdkTheme = SdkTheme.LIGHT, purchaseEventListener: PurchaseEventListener? = null): Task<ProductPurchaseResult>- 允许购买产品并指定所需的支付类型:单阶段(ONE_STEP)或双阶段(TWO_STEP)。 对于该支付方法,支付面板中提供所有支付方式。 如果未指定参数,则默认启动单阶段支付。
重要提示!如果指定支付类型为
TWO_STEP,系统将尝试启动双阶段支付,但最终结果将直接取决于用户选择的支付方式(银行卡、SBP 等)。请注意,在以下情况下无法使用
TWO_STEP支付类型:- 选择 SBP 支付方式时。
- 购买订阅时。
双阶段支付仅适用于一组特定的支付方式(目前仅支持银行卡和 SberPay)。 如果选择的支付方式不支持资金预留 (holding),则购买将按照单阶段场景启动。
purchaseTwoStep(params: ProductPurchaseParams, sdkTheme: SdkTheme = SdkTheme.LIGHT, purchaseEventListener: PurchaseEventListener? = null): Task<ProductPurchaseResult>- 启动商品保证的两阶段购买流程。 使用此方法时,用户在支付面板中只能看到有限的支付方式——仅限那些支持双阶段支付的方式。 在支付过程中,首先冻结买家的资金,只有在通过 confirmTwoStepPurchase 方法确认购买后才会扣除。confirmTwoStepPurchase(purchaseId: PurchaseId, developerPayload: DeveloperPayload? = null)- 确认通过两步支付完成的购买。cancelTwoStepPurchase(purchaseId: PurchaseId)- 取消通过双阶段支付完成的购买。updateAcknowledgementState(purchaseId: PurchaseId, state: AcknowledgementState, developerPayload: DeveloperPayload? = null): Task<AcknowledgementState>- 更新商品交付状态。getBillingSubscriptions(): Task<List<BillingSubscription>>— 返回在 SDK Billing Client 中办理的订阅列表。
-
ProductInteractor- 用于操作产品的交互器:getProducts(productsId: List<ProductId>): Task<List<Product>>- 用于获取在 RuStore 控制台中发布的活动商品信息。
重要
该方法最多返回 1000 个产品,且在无需授权且用户设备未安装 RuStore 的情况下即可运行。 :::
UserInteractor- 一个允许获取用户身份验证状态UserAuthorizationStatus的交互器。 该模型可能有 2 种状态:AUTHORIZED— 用户已在 RuStore 中授权UNAUTHORIZED- 用户未在 RuStore 中进行身份验证。
IntentInteractor- 一个允许处理 intent 和 deeplink 的交互器。 用于从银行应用程序正确返回到本应用程序,并正确恢复支付面板的状态。proceedIntent(intent: Intent?, sdkTheme: SdkTheme = SdkTheme.LIGHT)- 用于处理深度链接并在从银行应用程序返回到您的应用程序时恢复支付面板状态的方法。 调用该方法对于从银行应用程序返回到本应用程序时正确显示支付面板至关重要。
RuStoreUtils模块 - 一组公开方法,例如:isRuStoreInstalled- 检查用户设备上是否安装了 RuStore 应用程序。openRuStoreDownloadInstruction- 打开用于下载 RuStore 应用程序的网页。openRuStore- 启动 RuStore 应用程序。openRuStoreAuthorization- 启动 RuStore 应用程序以进行授权。 用户成功授权后,RuStore 应用程序将自动关闭。
获取产品列表
- Kotlin
- Java
要获取通过 RuStore 控制台添加到应用程序中的产品,必须使用 getProducts 方法。
RuStorePayClient.instance.getProductInteractor().getProducts(productsId = listOf(ProductId("id1"), ProductId("id2")))
.addOnSuccessListener { products: List<Product> ->
// Логика работы со списком продуктов
}
.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
productsId: List<ProductId> — 产品标识符列表(在开发者控制台中创建产品时指定)。 产品列表限制在 1000 个元素以内。
在 RuStore 控制台的哪里可以找到产品 ID?
- 转到应用程序选项卡并选择所需的应用程序。
- 在左侧菜单中选择货币化。
- 选择商品类型:订阅或一次性购买。
- 复制所需商品的 ID。

该方法返回一个可用产品列表。 下方显示了产品模型。
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?,
public val subscriptionInfo: SubscriptionInfo?,
)
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。type— 产品类型。CONSUMABLE_PRODUCT/NON_CONSUMABLE_PRODUCT/SUBSCRIPTION(消耗型/非消耗型/订阅)。amountLabel— 格式化后的购买价格,包含货币符号。price— 以最小单位(分)表示的价格。currency— ISO 4217 货币代码。imageUrl— 图片链接。title— 使用language语言显示的产品名称。description— 使用language语言的描述。subscriptionInfo— 订阅信息(如果产品类型为SUBSCRIPTION,则不为null)。
subscriptionInfo 模型包含订阅产品的信息。
字段的存在并不意味着用户仍然可以使用免费试用期或入门期:用户可能之前已经用完了这些期限。
下面是模型本身。
public class SubscriptionInfo internal constructor(
public val periods: List<SubscriptionPeriod>,
)
public sealed interface SubscriptionPeriod
public class TrialPeriod internal constructor(
public val duration: String,
public val currency: String,
public val price: Int,
) : SubscriptionPeriod
public class PromoPeriod internal constructor(
public val duration: String,
public val currency: String,
public val price: Int,
) : SubscriptionPeriod
public class MainPeriod internal constructor(
public val duration: String,
public val currency: String,
public val price: Int,
) : SubscriptionPeriod
public class GracePeriod internal constructor(
public val duration: String,
) : SubscriptionPeriod
public class HoldPeriod internal constructor(
public val duration: String,
) : SubscriptionPeriod
duration- 周期时长,采用 ISO 8601 格式(与 Public API 一致)currency- ISO 4217 货币代码price- 以最小单位(分)计算 的价格。
订阅周期
-
TrialPeriod— 试用期 -
PromoPeriod— 促销期 -
MainPeriod— 标准订阅期 -
GracePeriod— 宽限期 -
HoldPeriod— 暂停期
关于订阅周期运行方式的详细信息请参阅相关文章。
使用 subscriptionInfo 的示例
RuStorePayClient.instance.getProductInteractor().getProducts(productsId = listOf(ProductId("id1"), ProductId("id2")))
.addOnSuccessListener { products: List<Product> ->
products.forEach { product ->
val periods = product.subscriptionInfo?.periods
when (period) {
is TrialPeriod -> {
println("Бесплатный период: ${period.duration} за ${period.price} ${period.currency}")
}
is PromoPeriod -> {
println("Стартовый период: ${period.duration} за ${period.price} ${period.currency}")
}
is MainPeriod -> {
println("Основной период: ${period.duration} за ${period.price} ${period.currency}")
}
is GracePeriod -> {
println("Период отсрочки: ${period.duration}")
}
is HoldPeriod -> {
println("Период удержания: ${period.duration}")
}
null -> {
println("subscriptionInfo is null")
}
}
}
}
.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
响应示例
响应中模型结构的示意图(非可编译代码 —— 模型构造函数在 SDK 外部不可用)。
Product(
productId = ProductId("conProduct1"),
type = ProductType.CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("100.00 руб."),
price = Price(10000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_consumable_product.png"),
title = Title("Наз вание Потребляемого продукта"),
description = Description("Описание потребляемого продукта"),
)
Product(
productId = ProductId("nonConProduct1"),
type = ProductType.NON_CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("200.00 руб."),
price = Price(20000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_non_consumable_product.png"),
title = Title("Название Непотребляемого продукта"),
description = Description("Описание Непотребляемого продукта"),
)
Product(
productId = ProductId("sub_1"),
type = ProductType.SUBSCRIPTION,
amountLabel = AmountLabel("300.00 руб."),
price = Price(30000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_subscription.png"),
title = Title("Название вашей подписки"),
description = Description("Описание вашей подписки"),
subscriptionInfo = SubscriptionInfo(
periods = listOf(
TrialPeriod(
duration = "P1M",
currency = "RUB",
price = 0
),
PromoPeriod(
duration = "P5D",
currency = "RUB",
price = 149
),
MainPeriod(
duration = "P1Y",
currency = "RUB",
price = 299
),
GracePeriod(
duration = "P3D"
),
HoldPeriod(
duration = "P5D"
)
)
)
)
要获取通过 RuStore 控制台添加到应用程序中的产品,必须使用 getProducts 方法。
List<ProductId> productsId = Arrays.asList(new ProductId("id1"), new ProductId("id2"));
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
productInteractor.getProducts(productsId)
.addOnSuccessListener(products -> {
// Логика работы со списком продуктов
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
productsId: List<ProductId> — 产品标识符列表(在开发者控制台中创建产品时指定)。 产品列表限制在 1000 个元素以内。
在 RuStore 控制台的哪里可以找到产品 ID?
- 转到应用程序选项卡并选择所需的应用程序。
- 在左侧菜单中选择货币化。
- 选择商品类型:订阅或一次性购买。
- 复制所需商品的 ID。

该方法返回一个可用产品列表。 下面是产品模型:
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;
private final SubscriptionInfo subscriptionInfo;
public Product(ProductId productId, ProductType type, AmountLabel amountLabel, @Nullable Price price, Currency currency, Url imageUrl, Title title, @Nullable Description description, @Nullable SubscriptionInfo subscriptionInfo) {
this.productId = productId;
this.type = type;
this.amountLabel = amountLabel;
this.price = price;
this.currency = currency;
this.imageUrl = imageUrl;
this.title = title;
this.description = description;
this.subscriptionInfo = subscriptionInfo;
}
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;
}
public @Nullable SubscriptionInfo getSubscriptionInfo() {
return subscriptionInfo;
}
}
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。type— 产品类型。CONSUMABLE_PRODUCT/NON_CONSUMABLE_PRODUCT/SUBSCRIPTION(消耗型/非消耗型/订阅)。amountLabel— 格式化后的购买价格,包含货币符号。price— 以最小单位(分)表示的价格。currency— ISO 4217 货币代码。imageUrl— 图片链接。title— 使用language语言显示的产品名称。description— 使用language语言的描述。subscriptionInfo— 订阅信息(如果产品类型为SUBSCRIPTION,则不为null)。
subscriptionInfo 模型包含订阅产品的信息。
字段的存在并不意味着用户仍然可以使用免费试用期或入门期:用户可能之前已经用完了这些期限。
下面是模型本身。
public final class SubscriptionInfo {
private final List<SubscriptionPeriod> periods;
public SubscriptionInfo(List<SubscriptionPeriod> periods) {
this.periods = periods;
}
public List<SubscriptionPeriod> getPeriods() {
return periods;
}
}
public interface SubscriptionPeriod {
String getDuration();
}
public final class TrialPeriod implements SubscriptionPeriod {
private final String duration;
private final String currency;
private final int price;
public TrialPeriod(String duration, String currency, int price) {
this.duration = duration;
this.currency = currency;
this.price = price;
}
public String getDuration() { return duration; }
public String getCurrency() { return currency; }
public int getPrice() { return price; }
}
public final class PromoPeriod implements SubscriptionPeriod {
private final String duration;
private final String currency;
private final int price;
public PromoPeriod(String duration, String currency, int price) {
this.duration = duration;
this.currency = currency;
this.price = price;
}
public String getDuration() { return duration; }
public String getCurrency() { return currency; }
public int getPrice() { return price; }
}
public final class MainPeriod implements SubscriptionPeriod {
private final String duration;
private final String currency;
private final int price;
public MainPeriod(String duration, String currency, int price) {
this.duration = duration;
this.currency = currency;
this.price = price;
}
public String getDuration() { return duration; }
public String getCurrency() { return currency; }
public int getPrice() { return price; }
}
public final class GracePeriod implements SubscriptionPeriod {
private final String duration;
public GracePeriod(String duration) {
this.duration = duration;
}
public String getDuration() { return duration; }
}
public final class HoldPeriod implements SubscriptionPeriod {
private final String duration;
public HoldPeriod(String duration) {
this.duration = duration;
}
public String getDuration() { return duration; }
}
duration- 周期时长,采用 ISO 8601 格式(与 Public API 一致)currency- ISO 4217 货币代码price- 以最小单位(分)计算的价格。
订阅周期
-
TrialPeriod— 试用期 -
PromoPeriod— 促销期 -
MainPeriod— 标准订阅期 -
GracePeriod— 宽限期 -
HoldPeriod— 暂停期
关于订阅周期运行方式的详细信息请参阅相关文章。
使用 subscriptionInfo 的示例
List<ProductId> productsId = Arrays.asList(new ProductId("id1"), new ProductId("id2"));
ProductInteractor productInteractor = RuStorePayClient.Companion.getInstance().getProductInteractor();
productInteractor.getProducts(productsId)
.addOnSuccessListener(products -> {
for (Product product : products) {
SubscriptionInfo subscriptionInfo = product.getSubscriptionInfo();
if (subscriptionInfo == null) {
println("SubscriptionInfo is null for product: " + product.getProductId());
continue;
}
List<SubscriptionPeriod> periods = subscriptionInfo.getPeriods();
if (periods == null || periods.isEmpty()) {
continue;
}
for (SubscriptionPeriod period : periods) {
switch (period) {
case TrialPeriod trialPeriod ->
println("Бесплатный период: " + trialPeriod.getDuration() +
" за " + trialPeriod.getPrice() + " " + trialPeriod.getCurrency());
case PromoPeriod promoPeriod ->
println("Стартовый период: " + promoPeriod.getDuration() +
" за " + promoPeriod.getPrice() + " " + promoPeriod.getCurrency());
case MainPeriod mainPeriod ->
println("Основной период: " + mainPeriod.getDuration() +
" за " + mainPeriod.getPrice() + " " + mainPeriod.getCurrency());
case GracePeriod gracePeriod ->
println("Период отсрочки: " + gracePeriod.getDuration());
case HoldPeriod holdPeriod ->
println("Период удержания: " + holdPeriod.getDuration());
default ->
println("Unknown period type: " + period.getClass().getSimpleName());
}
}
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
响应示例
响应中模型结构的示意图(非可编译代码 —— 模型构造函数在 SDK 外部不可用)。
Product(
productId = ProductId("conProduct1"),
type = ProductType.CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("100.00 руб."),
price = Price(10000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_consumable_product.png"),
title = Title("Название Потребляемого продукта"),
description = Description("Описание потребляемого продукта"),
)
Product(
productId = ProductId("nonConProduct1"),
type = ProductType.NON_CONSUMABLE_PRODUCT,
amountLabel = AmountLabel("200.00 руб."),
price = Price(20000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_non_consumable_product.png"),
title = Title("Название Непотребляемого продукта"),
description = Description("Описание Непотребляемого продукта"),
)
Product(
productId = ProductId("sub_1"),
type = ProductType.SUBSCRIPTION,
amountLabel = AmountLabel("300.00 руб."),
price = Price(30000),
currency = Currency("RUB"),
imageUrl = Url("https://your_image_subscription.png"),
title = Title("Название вашей подписки"),
description = Description("Описание вашей подписки"),
subscriptionInfo = SubscriptionInfo(
periods = listOf(
TrialPeriod(
duration = "P1M",
currency = "RUB",
price = 0
),
PromoPeriod(
duration = "P5D",
currency = "RUB",
price = 149
),
MainPeriod(
duration = "P1Y",
currency = "RUB",
price = 299
),
GracePeriod(
duration = "P3D"
),
HoldPeriod(
duration = "P5D"
)
)
)
)
确定用户是否已授权
要检查用户的授权状态,请调用 UserInteractor 的 getUserAuthorizationStatus 方法。
该方法的执行结果是一个 UserAuthorizationStatus 类。
仅在需要提前了解用户是否已在 RuStore 中授权(或设备上是否安装了 RuStore)的场景中使用 getUserAuthorizationStatus 方法。 对于启动支付流程,该方法本身并非必选。
共有 2 个可用值:
AUTHORIZED- 用户已在 RuStore 中授权,或在支付面板中通过 VK ID 授权。UNAUTHORIZED- 用户未授权。 如果用户的设备上未安装 RuStore,也将返回此值。
- Kotlin
- Java
RuStorePayClient.instance.getUserInteractor().getUserAuthorizationStatus()
.addOnSuccessListener { result ->
when (result) {
UserAuthorizationStatus.AUTHORIZED -> {
// Логика когда пользователь авторизован в RuStore или на платежной шторке
}
UserAuthorizationStatus.UNAUTHORIZED -> {
// Логика когда пользователь НЕ авторизован
}
}
}.addOnFailureListener { throwable ->
// Обработка ошибки
}
UserInteractor userInteractor = RuStorePayClient.Companion.getInstance().getUserInteractor();
userInteractor.getUserAuthorizationStatus()
.addOnSuccessListener(status -> {
switch (status) {
case AUTHORIZED:
// Логика когда пользователь авторизован в RuStore или на платежной шторке
break;
case UNAUTHORIZED:
// Логика когда пользователь НЕ авторизован
break;
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
检查支付可用性
要检查支付可用性,请调用 PurchaseInteractor 的 getPurchaseAvailability 方法。 调用该方法时将检查以下条件:
- 公司已通过 RuStore 开发者控制台启用货币化。
- 应用程序未在 RuStore 中被封禁。
- 用户未在 RuStore 中被封禁。
如果所有条件均满足,则返回 Available 结果。 否则返回 Unavailable 结果,并附带原因(关于未满足条件的错误)。 可能的错误详见错误处理章节。
- Kotlin
- Java
支付不可用的原因位于 PurchaseAvailabilityResult.Unavailable 结果的 cause: Throwable 字段中。
RuStorePayClient.instance.getPurchaseInteractor().getPurchaseAvailability()
.addOnSuccessListener { result ->
when (result) {
is PurchaseAvailabilityResult.Available -> {
// Обработка результата доступности платежей
}
is PurchaseAvailabilityResult.Unavailable -> {
// Обработка результата недоступности платежей
}
}
}.addOnFailureListener { throwable ->
// Обработка ошибки
}
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchaseAvailability()
.addOnSuccessListener(result -> {
if (result instanceof PurchaseAvailabilityResult.Available) {
// Обработка результата доступности платежей
} else if (result instanceof PurchaseAvailabilityResult.Unavailable) {
// Обработка результата недоступности платежей
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
购买类型
SDK 提供了一个基础 Purchase 接口,它整合了所有购买类型共有的字段。
基于该接口创建了两种实现:
- ProductPurchase:用于可消耗和不可消耗的购买。
- SubscriptionPurchase:用于订阅。
这种划分允许每种购买类型拥有其独特的属性和行为。
- Kotlin
- Java
public interface Purchase {
public val purchaseId: PurchaseId
public val invoiceId: InvoiceId
public val orderId: OrderId?
public val purchaseType: PurchaseType
public val status: PurchaseStatus
public val description: Description
public val purchaseTime: Date?
public val price: Price
public val amountLabel: AmountLabel
public val currency: Currency
public val developerPayload: DeveloperPayload?
public val sandbox: Boolean
}
public interface Purchase {
PurchaseId getPurchaseId();
InvoiceId getInvoiceId();
@Nullable OrderId getOrderId();
PurchaseType getPurchaseType();
PurchaseStatus getStatus();
Description getDescription();
@Nullable Date getPurchaseTime();
Price getPrice();
AmountLabel getAmountLabel();
Currency getCurrency();
@Nullable DeveloperPayload getDeveloperPayload();
boolean isSandbox();
}
一次性购买模型 ProductPurchase
- Kotlin
- Java
public class ProductPurchase internal constructor(
public override val purchaseId: PurchaseId,
public override val invoiceId: InvoiceId,
public override val orderId: OrderId?,
public override val purchaseType: PurchaseType,
public override val status: ProductPurchaseStatus,
public override val description: Description,
public override val purchaseTime: Date?,
public override val price: Price,
public override val amountLabel: AmountLabel,
public override val currency: Currency,
public override val developerPayload: DeveloperPayload?,
public override val sandbox: Boolean,
public val productId: ProductId,
public val quantity: Quantity,
public val productType: ProductType,
public val acknowledgementState: AcknowledgementState,
) : Purchase
public class ProductPurchase implements Purchase {
private final PurchaseId purchaseId;
private final InvoiceId invoiceId;
private final OrderId orderId;
private final PurchaseType purchaseType;
private final ProductPurchaseStatus status;
private final Description description;
private final Date purchaseTime;
private final Price price;
private final AmountLabel amountLabel;
private final Currency currency;
private final DeveloperPayload developerPayload;
private final boolean sandbox;
private final ProductId productId;
private final Quantity quantity;
private final ProductType productType;
private final AcknowledgementState acknowledgementState;
@Override
public PurchaseId getPurchaseId() { return purchaseId; }
@Override
public InvoiceId getInvoiceId() { return invoiceId; }
@Override
public @Nullable OrderId getOrderId() { return orderId; }
@Override
public PurchaseType getPurchaseType() { return purchaseType; }
@Override
public ProductPurchaseStatus getStatus() { return status; }
@Override
public Description getDescription() { return description; }
@Override
public @Nullable Date getPurchaseTime() { return purchaseTime; }
@Override
public Price getPrice() { return price; }
@Override
public AmountLabel getAmountLabel() { return amountLabel; }
@Override
public Currency getCurrency() { return currency; }
@Override
public @Nullable DeveloperPayload getDeveloperPayload() { return developerPayload; }
@Override
public boolean isSandbox() { return sandbox; }
public ProductId getProductId() { return productId; }
public Quantity getQuantity() { return quantity; }
public ProductType getProductType() { return productType; }
public AcknowledgementState getAcknowledgementState() { return acknowledgementState; }
}
purchaseId— 购买 ID。 购买标识符。 用于在 SDK 中通过获取购买信息的方法来获取购买信息。invoiceId— 账单标识符。 账单标识符。 用于支付的服务器端验证、在开发者控制台中搜索支付,并向买家显示在 RuStore 移动应用程序的支付历史记录中。orderId- 唯一的支付标识符,由开发者指定或自动生成 (uuid)。PurchaseType— 购买类型:ONE_STEP- 单阶段购买;TWO_STEP- 双阶段购买;UNDEFINED- 阶段未定义。
status— 购买状态:INVOICE_CREATED— 已创建付款账单,购买等待支付;CANCELLED— 购买已被买家取消;PROCESSING— 支付已启动;REJECTED— 购买被拒绝(例如,由于资金不足);EXPIRED— 购买支付时间已过期;PAID— 仅用于两阶段支付,中间状态,买家账户资金已冻结,购买等待开发者确认;CONFIRMED— 购买已成功支付;REFUNDING— 已启动退款,请求已发送至收单行;REFUNDED— 购买退款请求已成功提交。 资金将在 10 个工作日内退还给用户。;EXECUTING— 购买正在执行过程中;REVERSED— 仅用于两阶段支付,购买已被开发者取消,或在 6 小时内未确认购买,资金冻结已取消。
description- 购买描述。purchaseTime— 购买时间。price— 以最小单位(分)表示的价格。amountLabel— 格式化后的购买价格,包含货币符号。currency— ISO 4217 货币代码。-
developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义) -
sandbox— 测试支付标志。 值为true表示测试支付,false表示真实支付。 productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。 在 RuStore 控制台中分配给该产品的产品 ID(必填参数)。quantity— 产品数量。productType— 产品类型。 (CONSUMABLE_PRODUCT/NON_CONSUMABLE_PRODUCT/SUBSCRIPTION- 消耗型/非消耗型/订阅产品。)acknowledgementState— 商品交付状态。 可能的值:PENDING(等待交付商品)、ACKNOWLEDGED(商品已交付)、UNKNOWN(逻辑不适用于该支付)。
购买状态模型
单阶段支付的状态模 型。
双阶段支付的状态模型。
订阅模型
- Kotlin
- Java
public class SubscriptionPurchase internal constructor(
public override val purchaseId: PurchaseId,
public override val invoiceId: InvoiceId,
public override val orderId: OrderId?,
public override val purchaseType: PurchaseType,
public override val status: SubscriptionPurchaseStatus,
public override val description: Description,
public override val purchaseTime: Date?,
public override val price: Price,
public override val amountLabel: AmountLabel,
public override val currency: Currency,
public override val developerPayload: DeveloperPayload?,
public override val sandbox: Boolean,
public val productId: ProductId,
public val expirationDate: Date,
public val gracePeriodEnabled: Boolean,
public val acknowledgementState: AcknowledgementState,
) : Purchase
public class SubscriptionPurchase implements Purchase {
private final PurchaseId purchaseId;
private final InvoiceId invoiceId;
private final OrderId orderId;
private final PurchaseType purchaseType;
private final SubscriptionPurchaseStatus status;
private final Description description;
private final Date purchaseTime;
private final Price price;
private final AmountLabel amountLabel;
private final Currency currency;
private final DeveloperPayload developerPayload;
private final boolean sandbox;
private final ProductId productId;
private final Date expirationDate;
private final boolean gracePeriodEnabled;
private final AcknowledgementState acknowledgementState;
@Override
public PurchaseId getPurchaseId() { return purchaseId; }
@Override
public InvoiceId getInvoiceId() { return invoiceId; }
@Override
public @Nullable OrderId getOrderId() { return orderId; }
@Override
public PurchaseType getPurchaseType() { return purchaseType; }
@Override
public SubscriptionPurchaseStatus getStatus() { return status; }
@Override
public Description getDescription() { return description; }
@Override
public @Nullable Date getPurchaseTime() { return purchaseTime; }
@Override
public Price getPrice() { return price; }
@Override
public AmountLabel getAmountLabel() { return amountLabel; }
@Override
public Currency getCurrency() { return currency; }
@Override
public @Nullable DeveloperPayload getDeveloperPayload() { return developerPayload; }
@Override
public boolean isSandbox() { return sandbox; }
public ProductId getProductId() { return productId; }
public Date getExpirationDate() { return expirationDate; }
public boolean isGracePeriodEnabled() { return gracePeriodEnabled; }
public AcknowledgementState getAcknowledgementState() { return acknowledgementState; }
}
purchaseId— 购买 ID。 购买标识符。 用于在 SDK 中通过获取购买信息的方法来获取购买信息。invoiceId— 账单标识符。 账单标识符。 用于服务器端支付验证、在开发者控制台中搜索支付,并向买家显示在支付历史记录中。orderId- 唯一的支付标识符,由开发者指定或自动生成 (uuid)。PurchaseType— 购买类型:ONE_STEP- 单阶段购买;TWO_STEP- 双阶段购买;UNDEFINED- 阶段未定义。
status- 订阅状态:INVOICE_CREATED- 已创建支付账单,订阅等待支付。CANCELLED- 订阅支付账单已取消。EXPIRED- 账单支付期限已过期。PROCESSING- 订阅的首次支付正在处理中。REJECTED- 订阅的首次支付被拒绝。 订阅未办理。ACTIVE- 订阅处于激活状态。PAUSED- 订阅由于付款问题而暂停。TERMINATED- 订阅扣款尝试次数已耗尽(所有尝试均失败)。 订阅因支付问题而被自动关闭。CLOSED- 订阅已被用户或开发者取消。 已支付期间到期,订阅已关闭。
description- 购买描述。purchaseTime— 购买时间。price— 以最小单位(分)表示的价格。amountLabel— 格式化后的购买价格,包含货币符号。currency— ISO 4217 货币代码。-
developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义) -
sandbox— 测试支付标志。 值为true表示测试支付,false表示真实支付。 productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。 在 RuStore 控制台中分配给该产品的产品 ID(必填参数)。expirationDate- 订阅到期日期。gracePeriodEnabled- 指示该订阅是否启用宽限期 (Grace-период) 的标志。acknowledgementState— 商品交付状态。 可能的值:PENDING(等待交付商品)、ACKNOWLEDGED(商品已交付)、UNKNOWN(该逻辑不适用于此付款)。
订阅状态模型
购买产品
- 使用单步支付时,购买无需确认,资金立即从买家账户中扣除,并从开发者处扣除佣金。 在这种情况下,如果需要向客户退款(例如,由于某种原因无法提供产品),只能通过 RuStore 控制台进行退款,资金将在几天后退还给买家。 将退还购买的全额费用,但已扣除的开发者佣金不予返还。
- 使用双步支付时,首先在买家账户中冻结资金。 在这种情况下,不扣除佣金。 资金冻结后,购买需要确认或取消。 在确认购买时,从开发者处扣除佣金。 取消购买意味着解除冻结——资金立即重新可用给买家。
目前,购买订阅 (SubscriptionPurchase) 只能使用单阶段支付 (PurchaseType.ONE_STEP) 来完成。
双阶段支付仅适用于一组特定的支付方式(目前仅支持银行卡和 SberPay)。 SBP 技术不支持双阶段支付。 如果选择的支付方式不支持资金预留 (holding),则购买将按照单阶段场景启动。
- Kotlin
- Java
选择购买类型的付款
请使用 purchase 方法来调用可选择支付阶段的产品购买。
val params = ProductPurchaseParams(
productId = ProductId("productId"),
orderId = null,
quantity = null,
developerPayload = null,
appUserId = null,
appUserEmail = null,
)
RuStorePayClient.instance.getPurchaseInteractor()
.purchase(params = params, preferredPurchaseType = PreferredPurchaseType.ONE_STEP, sdkTheme = SdkTheme.LIGHT, purchaseEventListener = null)
.addOnSuccessListener { result ->
// Логика обработки успешного результата покупки
}
.addOnFailureListener { throwable: Throwable ->
when(throwable){
is RuStorePaymentException.ProductPurchaseException -> // Обработка ошибки покупки продукта
is RuStorePaymentException.ProductPurchaseCancelled -> // Обработка отмены покупки продукта
else -> // Обработка ошибки
}
}
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。quantity— 产品数量。 可选参数,默认值为1。 仅适用于购买消耗性商品。orderId— 由应用程序生成的唯一支付标识符(可选参数)。 如果您在系统中指定此参数,将在 API 响应中收到该参数。 如果不指定,则会自动生成 (uuid)。 最大长度为 150 个字符。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最大长度为 250 个字符。 字符不会被转义。-
appUserId— 用户在您应用程序中的内部 ID(可选参数)。 最大长度为 128 个字符的字符串。提示例如,此参数可用于识别您应用程序中的欺诈行为,从而提高其安全性。
appUserEmail是一个可选参数,用于指定您应用程序中用户的电子邮件地址。 如果买家在应用程序注册时提供了电子邮件地址,则可以传递该地址,以便在发送收据时自动填充email字段——无论是在 RuStore 之外进行支付,还是在用户未登录 RuStore 的情况下。 这使用户无需手动输入 email,缩短了购买路径,有助于提高转化率。preferredPurchaseType- 期望的购买类型 - 单阶段 (ONE_STEP) 或双阶段 (TWO_STEP)。sdkTheme- 支付面板的颜色主题。 提供 2 个选项:LIGHT和DARK(分别对应浅色和深色主题)。 为了保持 SDK 版本之间的向后兼容性,该参数的默认值设置为LIGHT。purchaseEventListener- 一组回调函数,用于在购买的不同阶段获取invoiceId和purchaseId的数据(可选)。
preferredPurchaseType— 期望的购买类型:单步 (ONE_STEP) 或两步 (TWO_STEP)。
该方法默认按照单步支付场景 (preferredPurchaseType = PreferredPurchaseType.ONE_STEP) 运行,即不冻结资金。
对于双步支付,需要指定 preferredPurchaseType = PreferredPurchaseType.TWO_STEP。 该方法的双步支付(即带资金冻结的支付)不保证可用,直接取决 于用户选择的支付方式(银行卡、SBP 等)。
在运行该方法(且 preferredPurchaseType = twoStep)时,在用户选择支付方式之前,购买阶段将为 UNDEFINED。 在处理购买取消结果 (ProductPurchaseCancelled) 或购买错误 (ProductPurchaseException) 时,请考虑此行为。
两步支付(冻结资金)
请使用 purchaseTwoStep 方法来调用两阶段场景的产品购买。
调用此方法时,用户将只能看到有限的付款方式——仅限那些支持双阶段付款的方式。
目前,购买订阅 (SubscriptionPurchase) 只能使用单阶段支付 (PurchaseType.ONE_STEP) 来完成。
val params = ProductPurchaseParams(
productId = ProductId("productId"),
orderId = null,
quantity = null,
developerPayload = null,
appUserId = null,
appUserEmail = null,
)
RuStorePayClient.instance.getPurchaseInteractor()
.purchaseTwoStep(params = params, sdkTheme = SdkTheme.LIGHT, purchaseEventListener = null)
.addOnSuccessListener { result ->
// Логика обработки успешного результата покупки
}
.addOnFailureListener { throwable: Throwable ->
when(throwable){
is RuStorePaymentException.ProductPurchaseException -> // Обработка ошибки покупки продукта
is RuStorePaymentException.ProductPurchaseCancelled -> // Обработка отмены покупки продукта
else -> // Обработка ошибки
}
}
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。quantity— 产品数量。 可选参数,默认值为1。 仅适用于购买消耗性商品。orderId— 由应用程序生成的唯一支付标识符(可选参数)。 如果您在系统中指定此参数,将在 API 响应中收到该参数。 如果不指定,则会自动生成 (uuid)。 最大长度为 150 个字符。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最大长度为 250 个字符。 字符不会被转义。-
appUserId— 用户在您应用程序中的内部 ID(可选参数)。 最大长度为 128 个字符的字符串。提示例如,此参数可用于识别您应用程序中的欺诈行为,从而提高其安全性。
appUserEmail是一个可选参数,用于指定您应用程序中用户的电子邮件地址。 如果买家在应用程序注册时提供了电子邮件地址,则可以传递该地址,以便在发送收据时自动填充email字段——无论是在 RuStore 之外进行支付,还是在用户未登录 RuStore 的情况下。 这使用户无需手动输入 email,缩短了购买路径,有助于提高转化率。preferredPurchaseType- 期望的购买类型 - 单阶段 (ONE_STEP) 或双阶段 (TWO_STEP)。sdkTheme- 支付面板的颜色主题。 提供 2 个选项:LIGHT和DARK(分别对应浅色和深色主题)。 为了保持 SDK 版本之间的向后兼容性,该参数的默认值设置为LIGHT。purchaseEventListener- 一组回调函数,用于在购买的不同阶段获取invoiceId和purchaseId的数据(可选)。
购买参数结构
public class ProductPurchaseParams(
public val productId: ProductId,
public val quantity: Quantity? = null,
public val orderId: OrderId? = null,
public val developerPayload: DeveloperPayload? = null,
public val appUserId: AppUserId? = null,
public val appUserEmail: AppUserEmail? = null,
)
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。quantity— 产品数量。 可选参数,默认值为1。 仅适用于购买消耗性商品。orderId— 由应用程序生成的唯一支付标识符(可选参数)。 如果您在系统中指定此参数,将在 API 响应中收到该参数。 如果不指定,则会自动生成 (uuid)。 最大长度为 150 个字符。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最大长度为 250 个字符。 字符不会被转义。-
appUserId— 用户在您应用程序中的内部 ID(可选参数)。 最大长度为 128 个字符的字符串。提示例如,此参数可用于识别您应用程序中的欺诈行为,从而提高其安全性。
appUserEmail是一个可选参数,用于指定您应用程序中用户的电子邮件地址。 如果买家在应用程序注册时提供了电子邮件地址,则可以传递该地址,以便在发送收据时自动填充email字段——无论是在 RuStore 之外进行支付,还是在用户未登录 RuStore 的情况下。 这使用户无需手动输入 email,缩短了购买路径,有助于提高转化率。
使用 PurchaseEventListener
该接口是一组购买事件回调函数,将在购买过程中被调用。
public interface PurchaseEventListener {
public fun onPurchaseCreated(purchaseId: PurchaseId, invoiceId: InvoiceId)
public fun onPaymentStarted(purchaseId: PurchaseId, invoiceId: InvoiceId)
public fun onPaymentCompleted(purchaseId: PurchaseId, invoiceId: InvoiceId)
public fun onPaymentFailed(purchaseId: PurchaseId?, invoiceId: InvoiceId?)
public fun onPurchaseCancelled(purchaseId: PurchaseId?, invoiceId: InvoiceId?)
}
其实现类被传递给 purchase() 和 purchaseTwoStep() 方法。 通过这些通知,可以在购买的不同阶段获取 purchaseId 和 invoiceId 的数据,以便与这些信息进行交互。 例如,将数值传递给分析系统或写入数据库。
val params = ProductPurchaseParams(
productId = ProductId("productId"),
orderId = null,
quantity = null,
developerPayload = null,
appUserId = null,
appUserEmail = null,
)
val purchaseEventListener = object : PurchaseEventListener {
override fun onPurchaseCreated(purchaseId: PurchaseId, invoiceId: InvoiceId) {
// Реализация метода при создании покупки
}
override fun onPaymentStarted(purchaseId: PurchaseId, invoiceId: InvoiceId) {
// Реализация метода при старте покупки
}
override fun onPaymentCompleted(purchaseId: PurchaseId, invoiceId: InvoiceId) {
// Реализация метода при успешном завершении покупки
}
override fun onPaymentFailed(purchaseId: PurchaseId?, invoiceId: InvoiceId?) {
// Реализация метода при неуспешном завершении покупки
}
override fun onPurchaseCancelled(purchaseId: PurchaseId?, invoiceId: InvoiceId?) {
// Реализация метода при отмене покупки
}
}
RuStorePayClient.instance.getPurchaseInteractor()
.purchase(params = params, sdkTheme = SdkTheme.LIGHT, purchaseEventListener = purchaseEventListener)
.addOnSuccessListener { result ->
// Логика обработки успешного результата покупки
}
.addOnFailureListener { throwable: Throwable ->
when(throwable){
is RuStorePaymentException.ProductPurchaseException -> // Обработка ошибки покупки продукта
is RuStorePaymentException.ProductPurchaseCancelled -> // Обработка отмены покупки продукта
else -> // Обработка ошибки
}
}
选择购买类型的付款
请使用 purchase 方法来调用可选择支付阶段的产品购买。
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null, null, null);
RuStorePayClient ruStorePayClient = RuStorePayClient.Companion.getInstance();
PurchaseInteractor purchaseInteractor = ruStorePayClient.getPurchaseInteractor();
purchaseInteractor.purchase(params, PreferredPurchaseType.ONE_STEP, SdkTheme.LIGHT, null)
.addOnSuccessListener(result -> {
// Логика обработки успешного результата покупки
})
.addOnFailureListener(throwable -> {
if (throwable instanceof RuStorePaymentException.ProductPurchaseException) {
// Обработка ошибки покупки продукта
} else if (throwable instanceof RuStorePaymentException.ProductPurchaseCancelled) {
// Обработка отмены покупки продукта
} else {
// Обработка ошибки
}
});
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。quantity— 产品数量。 可选参数,默认值为1。 仅适用于购买消耗性商品。orderId— 由应用程序生成的唯一支付标识符(可选参数)。 如果您在系统中指定此参数,将在 API 响应中收到该参数。 如果不指定,则会自动生成 (uuid)。 最大长度为 150 个字符。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最大长度为 250 个字符。 字符不会被 转义。-
appUserId— 用户在您应用程序中的内部 ID(可选参数)。 最大长度为 128 个字符的字符串。提示例如,此参数可用于识别您应用程序中的欺诈行为,从而提高其安全性。
appUserEmail是一个可选参数,用于指定您应用程序中用户的电子邮件地址。 如果买家在应用程序注册时提供了电子邮件地址,则可以传递该地址,以便在发送收据时自动填充email字段——无论是在 RuStore 之外进行支付,还是在用户未登录 RuStore 的情况下。 这使用户无需手动输入 email,缩短了购买路径,有助于提高转化率。preferredPurchaseType- 期望的购买类型 - 单阶段 (ONE_STEP) 或双阶段 (TWO_STEP)。sdkTheme- 支付面板的颜色主题。 提供 2 个选项:LIGHT和DARK(分别对应浅色和深色主题)。 为了保持 SDK 版本之间的向后兼容性,该参数的默认值设置为LIGHT。purchaseEventListener- 一组回调函数,用于在购买的不同阶段获取invoiceId和purchaseId的数据(可选)。
该方法默认按照单步支付场景 (preferredPurchaseType = PreferredPurchaseType.ONE_STEP) 运行,即不冻结资金。
对于双步支付,需要指定 preferredPurchaseType = PreferredPurchaseType.TWO_STEP。 该方法的双步支付(即带资金冻结的支付)不保证可用,直接取决于用户选择的支付方式(银行卡、SBP 等)。
在运行该方法(且 preferredPurchaseType = twoStep)时,在用户选择支付方式之前,购买阶段将为 UNDEFINED。 在处理购买取消结果 (ProductPurchaseCancelled) 或购买错误 (ProductPurchaseException) 时,请考虑此行为。
两步支付(冻结资金)
请使用 purchaseTwoStep 方法来调用两阶段场景的产品购买。
调用此方法时,用户将只能看到有限的付款方式——仅限那些支持双阶段付款的方式。
目前,购买订阅 (SubscriptionPurchase) 只能使用单阶段支付 (PurchaseType.ONE_STEP) 来完成。
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null, null, null);
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.purchaseTwoStep(params, SdkTheme.LIGHT)
.addOnSuccessListener(result -> {
// Логика обработки успешного результата покупки
})
.addOnFailureListener(throwable -> {
if (throwable instanceof RuStorePaymentException.ProductPurchaseException) {
// Обработка ошибки покупки продукта
} else if (throwable instanceof RuStorePaymentException.ProductPurchaseCancelled) {
// Обработка отмены покупки продукта
} else {
// Обработка ошибки
}
});
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。quantity— 产品数量。 可选参数,默认值为1。 仅适用于购买消耗性商品。orderId— 由应用程序生成的唯一支付标识符(可选参数)。 如果您在系统中指定此参数,将在 API 响应中收到该参数。 如果不指定,则会自动生成 (uuid)。 最大长度为 150 个字符。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最大长度为 250 个字符。 字符不会被转义。-
appUserId— 用户在您应用程序中的内部 ID(可选参数)。 最大长度为 128 个字符的字符串。提示例如,此参数可用于识别您应用程序中的欺诈行为,从而提高其安全性。
appUserEmail是一个可选参数,用于指定您应用程序中用户的电子邮件地址。 如果买家在应用程序注册时提供了电子邮件地址,则可以传递该地址,以便在发送收据时自动填充email字段——无论是在 RuStore 之外进行支付,还是在用户未登录 RuStore 的情况下。 这使用户无需手动输入 email,缩短了购买路径,有助于提高转化率。preferredPurchaseType- 期望的购买类型 - 单阶段 (ONE_STEP) 或双阶段 (TWO_STEP)。sdkTheme- 支付面板的颜色主题。 提供 2 个选项:LIGHT和DARK(分别对应浅色和深色主题)。 为了保持 SDK 版本之间的向后兼容性,该参数的默认值设置为LIGHT。purchaseEventListener- 一组回调函数,用于在购买的不同阶段获取invoiceId和purchaseId的数据(可选)。
购买参数结构
public class ProductPurchaseParams {
private final ProductId productId;
private final Quantity quantity;
private final OrderId orderId;
private final DeveloperPayload developerPayload;
private final AppUserId appUserId;
private final AppUserEmail appUserEmail;
public ProductPurchaseParams(ProductId productId, @Nullable Quantity quantity, @Nullable OrderId orderId, @Nullable DeveloperPayload developerPayload, @Nullable AppUserId appUserId, @Nullable AppUserEmail appUserEmail) {
this.productId = productId;
this.quantity = quantity;
this.orderId = orderId;
this.developerPayload = developerPayload;
this.appUserId = appUserId;
this.appUserEmail = appUserEmail;
}
public ProductId getProductId() {
return productId;
}
public @Nullable Quantity getQuantity() {
return quantity;
}
public @Nullable OrderId getOrderId() {
return orderId;
}
public @Nullable DeveloperPayload getDeveloperPayload() {
return developerPayload;
}
public @Nullable AppUserId getAppUserId() {
return appUserId;
}
public @Nullable AppUserEmail getAppUserEmail() {
return appUserEmail;
}
}
productId— 在 RuStore 控制台中为产品分配的产品标识符(必填参数)。quantity— 产品数量。 可选参数,默认值为1。 仅适用于购买消耗性商品。orderId— 由应用程序生成的唯一支付标识符(可选参数)。 如果您在系统中指定此参数,将在 API 响应中收到该参数。 如果不指定,则会自动生成 (uuid)。 最大长度为 150 个字符。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最大长度为 250 个字符。 字符不会被转义。-
appUserId— 用户在您应用程序中的内部 ID(可选参数)。 最大长度为 128 个字符的字符串。提示例如,此参数可用于识别您应用程序中的欺诈行为,从而提高其安全性。
appUserEmail是一个可选参数,用于指定您应用程序中用户的电子邮件地址。 如果买家在应用程序注册时提供了电子邮件地址,则可以传递该地址,以便在发送收据时自动填充email字段——无论是在 RuStore 之外进行支付,还是在用户未登录 RuStore 的情况下。 这使用户无需手动输入 email,缩短了购买路径,有助于提高转化率。
使用 PurchaseEventListener
该接口是一组购买事件回调函数,将在购买过程中被调用。
public interface PurchaseEventListener {
void onPurchaseCreated(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId);
void onPaymentStarted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId);
void onPaymentCompleted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId);
void onPaymentFailed(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId);
void onPurchaseCancelled(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId);
}
其实现类被传递给 purchase() 和 purchaseTwoStep() 方法。 通过这些通知,可以在购买的不同阶段获取 purchaseId 和 invoiceId 的数据,以便与这些信息进行交互。 例如,将数值传递给分析系统或写入数据库。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null, null, null);
PurchaseEventListener purchaseEventListener = new PurchaseEventListener() {
@Override
public void onPurchaseCreated(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId) {
// Реализация метода при создании покупки
}
@Override
public void onPaymentStarted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId) {
// Реализация метода при старте покупки
}
@Override
public void onPaymentCompleted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId) {
// Реализация метода при успешном завершении покупки
}
@Override
public void onPaymentFailed(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId) {
// Реализация метода при неуспешном завершении покупки
}
@Override
public void onPurchaseCancelled(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId) {
// Реализация метода при отмене покупки
}
};
purchaseInteractor.purchase(params, PreferredPurchaseType.ONE_STEP, SdkTheme.LIGHT, purchaseEventListener)
.addOnSuccessListener(result -> {
// Логика обработки успешного результата покупки
})
.addOnFailureListener(throwable -> {
if (throwable instanceof RuStorePaymentException.ProductPurchaseException) {
// Обработка ошибки покупки продукта
} else if (throwable instanceof RuStorePaymentException.ProductPurchaseCancelled) {
// Обработка отмены покупки продукта
} else {
// Обработка ошибки
}
});
使用 PurchaseEventListener
该接口是一组购买事件回调函数,在购买过程中会被触发。
public interface PurchaseEventListener {
void onPurchaseCreated(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId);
void onPaymentStarted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId);
void onPaymentCompleted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId);
void onPaymentFailed(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId);
void onPurchaseCancelled(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId);
}
其实现类被传递给 purchase() 和 purchaseTwoStep() 方法。 这些通知允许您在购买流程的不同阶段接收 purchaseId 和 invoiceId,并根据需要使用这些信息。 例如,您可以将这些值发送到分析系统或将其存储在数据库中。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null, null, null);
PurchaseEventListener purchaseEventListener = new PurchaseEventListener() {
@Override
public void onPurchaseCreated(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId) {
// Method implementation when a purchase is created
}
@Override
public void onPaymentStarted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId) {
// Method implementation when the payment starts
}
@Override
public void onPaymentCompleted(@NotNull PurchaseId purchaseId, @NotNull InvoiceId invoiceId) {
// Method implementation when the payment is successfully completed
}
@Override
public void onPaymentFailed(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId) {
// Method implementation when the payment fails
}
@Override
public void onPurchaseCancelled(@Nullable PurchaseId purchaseId, @Nullable InvoiceId invoiceId) {
// Method implementation when the purchase is cancelled
}
};
purchaseInteractor.purchase(params, PreferredPurchaseType.ONE_STEP, SdkTheme.LIGHT, purchaseEventListener)
.addOnSuccessListener(result -> {
// Logic for handling a successful purchase result
})
.addOnFailureListener(throwable -> {
if (throwable instanceof RuStorePaymentException.ProductPurchaseException) {
// Handle product purchase error
} else if (throwable instanceof RuStorePaymentException.ProductPurchaseCancelled) {
// Handle product purchase cancellation
} else {
// Handle error
}
});
确认购买
- Kotlin
- Java
只有通过两阶段支付方案(即包含资金冻结)启动的购买才需要确认。 此类购买在资金成功冻结后,其状态将变为 PurchaseStatus.PAID。
要从买家的卡中扣除资金,需要确认购买。 为此,您必须使用 confirmTwoStepPurchase 方法。
RuStorePayClient.instance.getPurchaseInteractor().confirmTwoStepPurchase(
purchaseId = PurchaseId("purchaseId"),
developerPayload = null,
)
.addOnSuccessListener {
// Логика успешного подтверждения покупки
}.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
purchaseId— 购买 ID。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最多 250 个字符(字符不进行转义)。 如果传递了该参数,它将替换在启动购买时通过purchase/purchaseTwoStep方法记录的值。
只有通过两阶段支付方案(即包含资金冻结)启动的购买才需要确认。 此类购买在资金成功冻结后,其状态将变为 PurchaseStatus.PAID。
要从买家的卡中扣除资金,需要确认购买。 为此,您必须使用 confirmTwoStepPurchase 方法。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.confirmTwoStepPurchase(
new PurchaseId("purchaseId"),
null
).addOnSuccessListener( success -> {
// Логика успешного подтверждения покупки
}).addOnFailureListener(throwable -> {
// Обработка ошибки
});
purchaseId— 购买 ID。developerPayload— 包含订单附加信息的字符串,您可以在确认购买时设置 该信息。 此字符串将覆盖初始化时设置的值。 最大长度为 250 个字符。 字符不进行转义(使用引号时需要转义)。 最多 250 个字符(字符不进行转义)。 如果传递了该参数,它将替换在启动购买时通过purchase/purchaseTwoStep方法记录的值。
取消购买
通过 SDK 只能取消那些通过两阶段支付场景启动的购买,即带有资金冻结的购买。 此类购买在成功冻结后将处于 PurchaseStatus.PAID 状态。 取消后,购买将转变为 PurchaseStatus.REVERSED 状态。
如果您在付款(冻结资金)后无法向买家提供商品,请使用取消购买功能。
要取消购买(冻结),请使用 cancelTwoStepPurchase 方法。
- Kotlin
- Java
RuStorePayClient.instance.getPurchaseInteractor().cancelTwoStepPurchase(
purchaseId = PurchaseId("purchaseId"),
)
.addOnSuccessListener {
// Логика обработки успешной отмены покупки
}.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
purchaseId— 购买 ID。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.cancelTwoStepPurchase(
new PurchaseId("purchaseId")
).addOnSuccessListener(success -> {
// Process success
}).addOnFailureListener(throwable -> {
// Process error
});
purchaseId— 购买 ID。
处理商品交付确认
请使用 updateAcknowledgementState 方法来更新购买确认状态。
- Kotlin
- Java
RuStorePayClient.instance.getPurchaseInteractor()
.updateAcknowledgementState(
purchaseId = purchaseId,
state = AcknowledgementState.ACKNOWLEDGED,
developerPayload = null,
)
.addOnSuccessListener { state ->
// Состояние выдачи товара обновлено
}
.addOnFailureListener { throwable ->
// Обработка ошибки
}
该逻辑并非强制要求,且不影响支付的执行。 它允许在 RuStore 端存储购买处理状态,以便随后在获取带有特定过滤条件的购买列表时,仅选择未处理的购买并为其发放商品。
支付成功后,商品发放状态的默认值为 PENDING。
对于在尚未支持此逻辑的早期 SDK 版本中完成的支付,使用状态 UNKNOWN。 如有需要,可以将此状态更改为任何其他状态。
处理状态可以双向更改:例如,将购买状态从 PENDING 转换为 ACKNOWLEDGED,也可以在需要撤回之前发放的商品(例如在支付退款后)时将其恢复到之前的状态。
在调用此方法时,可以更新 developerPayload 的值。 如果传递了该参数,当前值将被覆盖。 如果未传递该参数,则将保留 developerPayload 的当前值。
purchaseInteractor.updateAcknowledgementState(
purchaseId,
AcknowledgementState.ACKNOWLEDGED,
null
)
.addOnSuccessListener(state -> {
// Состояние выдачи товара обновлено
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
该逻辑并非强制要求,且不影响支付的执行。 它允许在 RuStore 端存储购买处理状态,以便随后在获取带有特定过滤条件的购买列表时,仅选择未处理的购买并为其发放商品。
支付成功后,商品发放状态的默认值为 PENDING。
对于在尚未支持此逻辑的早期 SDK 版本中完成的支付,使用状态 UNKNOWN。 如有需要,可以将此状态更改为任何其他状态。
处理状态可以双向更改:例如,将购买状态从 PENDING 转换为 ACKNOWLEDGED,也可以在需要撤回之前发放的商品(例如在支付退款后)时将其恢复到之前的状态。
在调用此方法时,可以更新 developerPayload 的值。 如果传递了该参数,当前值将被覆盖。 如果未传递该参数,则将保留 developerPayload 的当前值。
获取购买详情
- Kotlin
- Java
getPurchase 方法。
RuStorePayClient.instance.getPurchaseInteractor().getPurchase(PurchaseId("purchaseId"))
.addOnSuccessListener { purchase: Purchase ->
when(purchase) {
is ProductPurchase -> {
// Логика обработки результата покупки продукта
}
is SubscriptionPurchase -> {
// Логика обработки результата покупки подписки
}
else -> {
// Логика обработки результата покупки c базовыми полями
}
}
}
.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
该方法将返回关于任何状态下特定购买的信息。
ProductPurchase 和 SubscriptionPurchase 购买模型的详细信息请参阅相应章节。
响应示例 — 所获模型的 toString() 输出(用于展示结构,非可编译代码)。
ProductPurchase(
purchaseId=PurchaseId(value='purchaseId'),
productId=ProductId(value='game_coins_1000'),
invoiceId=InvoiceId(value='invoiceId'),
orderId=OrderId(value='orderId'),
purchaseType=ONE_STEP,
productType=CONSUMABLE_PRODUCT,
description=Description(value='description'),
purchaseTime=123123123124,
price=Price(value='14100'),
amountLabel=AmountLabel(value='141,00 ₽'),
currency=Currency(value='RUB'),
quantity=Quantity(value='1'),
status=CONFIRMED,
developerPayload='DeveloperPayload(value='developerPayload')',
sandbox=false,
acknowledgementState=PENDING
)
SubscriptionPurchase(
purchaseId=PurchaseId(value='sub_purchase_12345'),
invoiceId=InvoiceId(value='inv_sub_67890'),
orderId=OrderId(value='order_sub_abcde'),
purchaseType=ONE_STEP,
description=Description(value='Ежемесячная подписка на «Премиум»'),
purchaseTime=123123123124,
price=Price(value='29900'),
amountLabel=AmountLabel(value='299 ₽'),
currency=Currency(value='RUB'),
status=ACTIVE,
developerPayload='DeveloperPayload(value='user_id:123;source:profile')',
sandbox=false,
productId=ProductId(value='premium_monthly_v1'),
expirationDate='Sat Aug 01 12:00:00 GMT+03:00 2026',
gracePeriodEnabled='true',
acknowledgementState=ACKNOWLEDGED
)
getPurchase 方法。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchase(new PurchaseId("purchaseId"))
.addOnSuccessListener(purchase -> {
if (purchase instanceof ProductPurchase productPurchase) {
// Логика обработки результата покупки продукта
} else if (purchase instanceof SubscriptionPurchase subscriptionPurchase) {
// Логика обработки результата покупки подписки
} else {
// Логика обработки результата покупки c базовыми полями
}
})
.addOnFailureListener(throwable -> {
// Обработка ошибки
});
该方法将返回关于任何状态下特定购买的信息。
ProductPurchase 和 SubscriptionPurchase 购买模型的详细信息请参阅相应章节。
获取购买列表
- Kotlin
- Java
要获取用户的购买列表,请使用 getPurchases 方法。
RuStorePayClient.instance.getPurchaseInteractor().getPurchases()
.addOnSuccessListener { purchases: List<Purchase> ->
// Логика работы со списком покупок пользователя
}
.addOnFailureListener { throwable: Throwable ->
// Обработ ка ошибки
}
该方法允许根据三个参数过滤购买记录:
商品类型 (productType):
CONSUMABLE_PRODUCT— 消耗品;NON_CONSUMABLE_PRODUCT— 非消耗品;SUBSCRIPTION— 订阅。
购买状态 (purchaseStatus):
PAID— 资金已成功冻结,购买记录正在等待开发者的确认(适用于商品);CONFIRMED— 购买已确认,资金已扣除(适用于商品);ACTIVE— 订阅处于激活状态(适用于订阅);PAUSED— 订阅处于冻结期:支付失败(例如卡内余额不足),但系统将继续尝试扣款(适用于订阅)。
商品交付状态 (acknowledgementState):
PENDING— 等待交付商品;ACKNOWLEDGED— 商品已交付;UNKNOWN— 该逻辑不适用于此笔支付。
默认情况下,所有过滤器均关闭,将返回用户的所有购买记录。
RuStorePayClient.instance.getPurchaseInteractor().getPurchases(
productType = ProductType.CONSUMABLE_PRODUCT,
purchaseStatus = ProductPurchaseStatus.PAID,
)
.addOnSuccessListener { purchases: List<Purchase> ->
// Логика работы со списком покупок пользователя
}
.addOnFailureListener { throwable: Throwable ->
// Обработка ошибки
}
要获取用户的购买列表,请使用 getPurchases 方法。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchases(null, null, null)
.addOnSuccessListener(purchases -> {
// Логика работы со списком покупок пользователя
})
.addOnFailureListener(error -> {
// Обработка ошибки
});
该方法允许根据三个参数过滤购买记录:
商品类型 (productType):
CONSUMABLE_PRODUCT— 消耗品;NON_CONSUMABLE_PRODUCT— 非消耗品;SUBSCRIPTION— 订阅。
购买状态 (purchaseStatus):
PAID— 资金已成功冻结,购买记录正在等待开发者的确认(适用于商品);CONFIRMED— 购买已确认,资金已扣除(适用于商品);ACTIVE— 订阅处于激活状态(适用于订阅);PAUSED— 订阅处于冻结期:支付失败(例如卡内余额不足),但系统将继续尝试扣款(适用于订阅)。
商品交付状态 (acknowledgementState):
PENDING— 等待交付商品;ACKNOWLEDGED— 商品已交付;UNKNOWN— 该逻辑不适用于此笔支付。
默认情况下,所有过滤器均关闭,将返回用户的所有购买记录。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchases(ProductType.CONSUMABLE_PRODUCT, ProductPurchaseStatus.PAID, null)
.addOnSuccessListener(purchases -> {
// Логика работы со списком покупок пользователя
})
.addOnFailureListener(error -> {
// Обработка ошибки
});
购买结果结构
ProductPurchaseResult - 数字商品或订阅的成功支付结果(适用于单阶段支付),或资金成功冻结的结果(适用于双阶段支付)。
- Kotlin
- Java
public class ProductPurchaseResult internal constructor(
public val orderId: OrderId?,
public val purchaseId: PurchaseId,
public val productId: ProductId,
public val invoiceId: InvoiceId,
public val purchaseType: PurchaseType,
public val productType: ProductType,
public val quantity: Quantity,
public val sandbox: Boolean,
)
public class ProductPurchaseResult {
private final OrderId orderId;
private final PurchaseId purchaseId;
private final ProductId productId;
private final InvoiceId invoiceId;
private final PurchaseType purchaseType;
private final ProductType productType;
private final Quantity quantity;
private final boolean sandbox;
public ProductPurchaseResult(OrderId orderId,
PurchaseId purchaseId,
ProductId productId,
InvoiceId invoiceId,
PurchaseType purchaseType,
ProductType productType,
Quantity quantity,
boolean sandbox) {
this.orderId = orderId;
this.purchaseId = purchaseId;
this.productId = productId;
this.invoiceId = invoiceId;
this.purchaseType = purchaseType;
this.productType = productType;
this.quantity = quantity;
this.sandbox = sandbox;
}
public OrderId getOrderId() {
return orderId;
}
public PurchaseId getPurchaseId() {
return purchaseId;
}
public ProductId getProductId() {
return productId;
}
public InvoiceId getInvoiceId() {
return invoiceId;
}
public PurchaseType getPurchaseType() {
return purchaseType;
}
public ProductType getProductType() {
return productType;
}
public Quantity getQuantity() {
return quantity;
}
public boolean isSandbox() {
return sandbox;
}
}
-
ProductPurchaseResult— 数字商品成功支付(对于单阶段支付)或资金成功冻结(对于双阶段支付)的结果。purchaseId- 购买标识符。 用于通过 SDK 的获取购买信息方法获取购买信息以及进行服务器端订阅验证。productId- 所购产品的标识符,在 RuStore 开发者控制台创建时指定。invoiceId- 账单标识符。 用于支付的服务器端验证、在开发者控制台中搜索支付,并向买家显示在 RuStore 移动应用程序的支付历史记录中。orderId- 唯一的支付标识符,由开发者指定或自动生成 (uuid)。purchaseType- 购买类型 (ONE_STEP/TWO_STEP/UNDEFINED- 单阶段/双阶段/未定义阶段)。productType- 产品类型 (NON_CONSUMABLE_PRODUCT- 非消耗性商品,CONSUMABLE_PRODUCT- 消耗性商品,SUBSCRIPTION- 订阅)。quantity- 启动购买时指定的商品数量。sandbox- 指示是否为沙 箱测试支付的标志。 如果为TRUE- 则表示购买是在测试模式下完成的。
错误处理
如果在支付过程中发生错误或用户取消购买,支付方法的执行(无论是选择购买类型还是双阶段方法)将以错误结束:
ProductPurchaseException- 产品购买错误。ProductPurchaseCancelled- 由于在获得购买结果前取消产品购买(用户关闭了支付面板)而导致的错误。 在这种情况下,建议通过获取购买信息的方法进一步检查购买状态。
购买错误和取消的结构:
- Kotlin
- Java
public class ProductPurchaseException internal constructor(
public val orderId: OrderId?,
public val purchaseId: PurchaseId?,
public val productId: ProductId?,
public val invoiceId: InvoiceId?,
public val quantity: Quantity?,
public val purchaseType: PurchaseType?,
public val sandbox: Boolean?,
public val productType: ProductType?,
public override val cause: Throwable,
) : RuStorePaymentException(message = "Error purchase product", cause = cause)
public class ProductPurchaseException extends RuStorePaymentException {
private final OrderId orderId;
private final PurchaseId purchaseId;
private final ProductId productId;
private final InvoiceId invoiceId;
private final Quantity quantity;
private final PurchaseType purchaseType;
private final Boolean sandbox;
private final ProductType productType;
public ProductPurchaseException(OrderId orderId,
PurchaseId purchaseId,
ProductId productId,
InvoiceId invoiceId,
Quantity quantity,
PurchaseType purchaseType,
Boolean sandbox,
ProductType productType,
Throwable cause) {
super("Error purchase product", cause);
this.orderId = orderId;
this.purchaseId = purchaseId;
this.productId = productId;
this.invoiceId = invoiceId;
this.quantity = quantity;
this.purchaseType = purchaseType;
this.sandbox = sandbox;
this.productType = productType;
}
public OrderId getOrderId() {
return orderId;
}
public PurchaseId getPurchaseId() {
return purchaseId;
}
public ProductId getProductId() {
return productId;
}
public InvoiceId getInvoiceId() {
return invoiceId;
}
public Quantity getQuantity() {
return quantity;
}
public PurchaseType getPurchaseType() {
return purchaseType;
}
public ProductType getProductType() {
return productType;
}
public Boolean getSandbox() {
return sandbox;
}
}
purchaseId— 购买标识符。 用于在 SDK 中通过获取购买信息的方法来获取购买信息。productId— 所购产品的标识符,在 RuStore 开发者控制台中创建时指定。invoiceId— 账单标识符。 用于支付的服务器端验证、在开发者控制台中搜索支付,并向买家显示在 RuStore 移动应用程序的支付历史记录中。orderId— 唯一的支付标识符,由开发者指定或自动生成 (uuid)。purchaseType— 购买类型 (ONE_STEP/TWO_STEP/UNDEFINED— 单阶段/双阶段/未定义阶段)。productType- 产品类型 (NON_CONSUMABLE_PRODUCT- 非消耗性商品,CONSUMABLE_PRODUCT- 消耗性商品,SUBSCRIPTION- 订阅)。quantity— 在启动购买时指定的商品数量。
ProductPurchaseCancelled — 取消数字商品购买。 支付对话框在获取购买结果之前已关闭,因此购买状态未知。 建议单独使用获取购买信息方法来请求购买状态。
- Kotlin
- Java
public class ProductPurchaseCancelled internal constructor(
public val purchaseId: PurchaseId?,
public val purchaseType: PurchaseType?,
public val productType: ProductType?,
) : RuStorePaymentException(message = "Purchase product is cancelled")
public class ProductPurchaseCancelled extends RuStorePaymentException {
private final PurchaseId purchaseId;
private final PurchaseType purchaseType;
private final ProductType productType;
public ProductPurchaseCancelled(PurchaseId purchaseId, PurchaseType purchaseType, ProductType productType) {
super("Purchase product is cancelled");
this.purchaseId = purchaseId;
this.purchaseType = purchaseType;
this.productType = productType;
}
public PurchaseId getPurchaseId() {
return purchaseId;
}
public PurchaseType getPurchaseType() {
return purchaseType;
}
public ProductType getProductType() {
return productType;
}
}
purchaseId— 购买标识符。 用于在 SDK 中通过获取购买信息的方法来获取购买信息。purchaseType— 购买类型 (ONE_STEP/TWO_STEP/UNDEFINED — 单阶段/双阶段/未定义阶段)。productType- 产品类型 (NON_CONSUMABLE_PRODUCT- 非消耗性商品,CONSUMABLE_PRODUCT- 消耗性商品,SUBSCRIPTION- 订阅)。
在服务器端验证购买
- Kotlin
- Java
如果您需要在 RuStore 中对成功的购买进行验证,可以使用公开的验证 API 接口。 产品和订阅的验证使用不同的方法:
- 验证产品购买时,请使用购买完成后返回的
ProductPurchaseResult模型中的invoiceId。 - 验证订阅购买时,请使用购买完成后返回的
ProductPurchaseResult模型中的purchaseId。
可以通过 ProductPurchaseResult 响应中获取的数据来确定所购产品的类型。
val params = ProductPurchaseParams(ProductId("productId"))
RuStorePayClient.instance.getPurchaseInteractor()
.purchase(params = params, preferredPurchaseType = PreferredPurchaseType.TWO_STEP)
.addOnSuccessListener { purchaseResult ->
when (purchaseResult.productType) {
CONSUMABLE_PRODUCT,
NON_CONSUMABLE_PRODUCT -> {
val invoiceId = purchaseResult.invoiceId.value
yourApi.validateProduct(invoiceId)
}
SUBSCRIPTION -> {
val purchaseId = purchaseResult.purchaseId.value
yourApi.validateSubscription(purchaseId)
}
}
}
也可以在 Purchase 模型中获取 invoiceId。 可以使用 getPurchases() 方法或 getPurchase 方法获取 Purchase 模型。
RuStorePayClient.instance.getPurchaseInteractor().getPurchases()
.addOnSuccessListener { purchases ->
purchases.forEach { purchase ->
if(purchase is SubscriptionPurchase){
val purchaseId = purchase.purchaseId.value
yourApi.validateSubscription(purchaseId)
} else {
val invoiceId = purchase.invoiceId.value
yourApi.validateProduct(invoiceId)
}
}
}
如果您需要在 RuStore 中对成功的购买进行验证,可以使用公开的验证 API 接口。 产品和订阅的验证使用不同的方法:
- 验证产品购买时,请使用购买 完成后返回的
ProductPurchaseResult模型中的invoiceId。 - 验证订阅购买时,请使用购买完成后返回的
ProductPurchaseResult模型中的purchaseId。
可以通过 ProductPurchaseResult 响应中获取的数据来确定所购产品的类型。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
ProductPurchaseParams params = new ProductPurchaseParams(new ProductId("productId"), null, null, null, null, null);
purchaseInteractor.purchase(params, PreferredPurchaseType.TWO_STEP)
.addOnSuccessListener(result -> {
switch (result.getProductType()) {
case CONSUMABLE_PRODUCT:
case NON_CONSUMABLE_PRODUCT:
String invoiceId = result.getInvoiceId().getValue();
yourApi.validateProduct(invoiceId);
break;
case SUBSCRIPTION:
String purchaseId = result.getPurchaseId().getValue();
yourApi.validateSubscription(purchaseId);
break;
}
});
也可以在 Purchase 模型中获取 invoiceId。 可以使用 getPurchases 方法或 getPurchase 方法获取 Purchase 模型。
PurchaseInteractor purchaseInteractor = RuStorePayClient.Companion.getInstance().getPurchaseInteractor();
purchaseInteractor.getPurchases(null, null, null)
.addOnSuccessListener(purchases -> {
for (Purchase purchase : purchases) {
if (purchase instanceof SubscriptionPurchase) {
String purchaseId = purchase.getPurchaseId().getValue();
yourApi.validateSubscription(purchaseId);
} else {
String invoiceId = purchase.getInvoiceId().getValue();
yourApi.validateProduct(invoiceId);
}
}
})
.addOnFailureListener(error -> {
// Обработка ошибки
});
RuStoreUtils
RuStoreUtils 是原生 SDK 中的一个模块,包含一组用于与用户设备上的 RuStore 应用程序进行交互的公共方法。
通过 ru.rustore.sdk.core.util 包中的 object RuStoreUtils 访问这些方法。 所有方法都接收 Context 参数。
isRuStoreInstalled 方法用于检查用户设备上是否安装了 RuStore 应用程序。
- Kotlin
- Java
if (RuStoreUtils.isRuStoreInstalled(context)) {
// RuStore установлен на устройстве пользователя
} else {
// RuStore не установлен на устройстве пользователя
}
if (RuStoreUtils.INSTANCE.isRuStoreInstalled(context)) {
// RuStore установлен на устройстве пользователя
} else {
// RuStore не установлен на устройстве пользователя
}
openRuStoreDownloadInstruction 方法用于打开下载 RuStore 移动应用程序的网页。
- Kotlin
- Java
RuStoreUtils.openRuStoreDownloadInstruction(context)
RuStoreUtils.INSTANCE.openRuStoreDownloadInstruction(context);
openRuStore 方法用于启动 RuStore 移动应用程序。 调用此方法时,如果未安装 RuStore 应用程序,将显示一条内容为“无法打开应用程序”的 Toast 通知。
- Kotlin
- Java
RuStoreUtils.openRuStore(context)
RuStoreUtils.INSTANCE.openRuStore(context);
openRuStoreAuthorization 方法用于启动 RuStore 移动应用程序进行身份验证。 用户成功通过身份验证后,RuStore 应用程序将自动关闭。 调用此方法时,如果未安装 RuStore 应用程序,将显示一条内容为“无法打开应用程序”的 Toast 通知。
- Kotlin
- Java
RuStoreUtils.openRuStoreAuthorization(context)
RuStoreUtils.INSTANCE.openRuStoreAuthorization(context);
使用 RuStoreUtils 验证支付场景
关于使用 RuStoreUtils 检查设备上是否存在 RuStore 以及处理用户身份验证的应用案例,请参阅《无需安装 RuStore 即可接收付款》一文。
文中提供了:
-
在未安装 RuStore 时的购买操作场景;
-
通过 RuStoreUtils 顺序调用安装检查和身份验证方法的示例;
-
SDK 在不同条件下的行为特点(如 RuStore 是否存在、用户是否通过身份验证等)。
错误列表
RuStorePaymentNetworkException - SDK 网络交互错误。
错误模型中返回错误代码(code 字段),可通过该代码确定错误原因。
错误代码表可在错误代码部分找到。
message 字段包含错误原因的描述。
- Kotlin
- Java
public class RuStorePaymentNetworkException internal constructor(
public val code: String?,
public val id: String,
public override val message: String,
public override val cause: Throwable? = null,
) : RuStorePaymentException(message, cause)
public class RuStorePaymentNetworkException extends RuStorePaymentException {
private final String code;
private final String id;
public RuStorePaymentNetworkException(
String code,
String id,
String message,
Throwable cause
) {
super(message, cause);
this.code = code;
this.id = id;
}
public String getCode() {
return code;
}
public String getId() {
return id;
}
}
RuStorePaymentNetworkException— SDK 网络交互错误;RuStorePaymentException—— 支付 SDK 的异常基类,继承自 Exception;RuStorePaymentCommonException— 支付 SDK 的通用错误;RuStorePayClientAlreadyExist— SDK 重复初始化错误;RuStorePayClientNotCreated— 在 SDK 初始化之前尝试调用其公共接口;RuStorePayInvalidActivePurchase— 启动了未知产品类型的支付流程;RuStorePayInvalidConsoleAppId— 未指定用于初始化 SDK 的必填参数console_app_id_value;RuStorePaySignatureException— 响应签名错误。 在尝试进行欺诈操作时触发;EmptyPaymentTokenException— 获取支付令牌错误;InvalidCardBindingIdException— 使用保存的银行卡支付错误;ApplicationSchemeWasNotProvided— 未指定回跳 Deep Link 的 Scheme;ProductPurchaseException- 产品购买错误。 模型结构请参阅购买结果结构章节;ProductPurchaseCancelled- 产品购买已取消(用户关闭了支付面板)。 模型结构请参阅购买结果结构章节。
以下错误属于基础模块 ru.rustore.sdk:core,且继承自 RuStoreException 而非 RuStorePaymentException:
RuStoreNotInstalledException—— 用户设备上未安装 RuStore;RuStoreOutdatedException— 设备上安装的 RuStore 版本不支持支付;RuStoreUserUnauthorizedException—— 用户未在 RuStore 中登录;RuStoreApplicationBannedException— 应用在 RuStore 中被封禁;RuStoreUserBannedException— 用户在 RuStore 中被封禁。
错误代码
| 错误代码 | 描述 |
|---|---|
4000001 | 请求格式不正确:缺少或填写错误的必填参数,或数据格式错误。 |
4000002, 4000016, 4040005 | 未找到该应用。 |
4000003 | 应用已被封禁。 |
4000004 | 应用签名与注册的签名不匹配。 |
4000005 | 未找到该公司。 |
4000006 | 该公司已被封禁。 |
4000007 | 该公司的货币化功能已关闭或未激活。 |
4000014 | 未找到该产品。 |
4000015 | 该产品尚未发布。 |
4000017 | quantity 参数不正确。 |
4000018 | 已超过购买限制。 |
4000020 | 该产品已被购买。 |
4000021 | 产品购买未完成。 |
4000022 | 未找到该笔购买记录。 |
4000025 | 未找到合适的支付方式。 |
4000026 | 确认购买的类型错误(应为两阶段支付)。 |
4000027 | 确认购买的状态错误。 |
4000028 | 取消购买的类型错误(应为两阶段支付)。 |
4000029 | 取消购买的状态错误。 |
4000030 | 已签发的令牌与所购商品不匹配。 |
4000041 | 用户已拥有该产品代码的有效订阅。 |
4000045 | 超过最大尺寸值。 |
4010001 | 禁止访问请求的资源(未授权)。 |
4010002 | 令牌有效期已过期。 |
4010003 | 支付令牌无效。 |
4030001 | 未传递支付令牌。 |
4030002 | 用户因安全要求被封禁。 |
4040002, 4040003, 4040004 | 支付系统错误。 |
5000*** | 内部错误。 |