rustore_billing_api 0.8.0
rustore_billing_api: ^0.8.0 copied to clipboard
Unofficial plugin for RuStore billing integration
RuStore Billing API (WIP) #
Note: this package is a work in progress and is not ready for production use.
A Flutter plugin for integrating RuStore billing functionality into your Flutter applications. This plugin provides a comprehensive interface to the RuStore billing SDK, allowing you to handle in-app purchases, subscriptions, and payment flows.
Installation #
Add this dependency to your pubspec.yaml:
dependencies:
rustore_billing_api: ^1.0.0
Setup #
1. Android Configuration #
Add the RuStore repository to your android/build.gradle:
allprojects {
repositories {
maven { url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven") }
}
}
Add the RuStore BOM dependency to your android/app/build.gradle:
dependencies {
implementation(platform("ru.rustore.sdk:bom:2025.06.01"))
implementation("ru.rustore.sdk:billingclient")
}
2. AndroidManifest.xml Configuration #
Add deep link handling to your android/app/src/main/AndroidManifest.xml:
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourappscheme" />
</intent-filter>
</activity>
3. Activity Configuration #
Update your main activity to handle deep links:
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
// Handle deep link intent
rustoreBillingClient.onNewIntent(intent)
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Handle deep link intent
rustoreBillingClient.onNewIntent(intent)
}
}
Usage #
1. Initialize the Billing Client #
import 'package:rustore_billing_api/rustore_billing_api.dart';
final client = RustoreBillingClient.instance;
await client.initialize(
RustoreBillingConfig(
consoleApplicationId: 'your_app_id_here',
deeplinkScheme: 'yourappscheme',
debugLogs: true,
theme: RustoreBillingTheme.light,
enableLogging: true,
),
);
2. Check RuStore Installation and Availability #
// Check if RuStore is installed
final isAuthorized = await client.isRustoreUserAuthorized();
// Check if purchases are available
final availability = await client.checkPurchasesAvailability();
switch (availability.resultType) {
case RustorePurchaseAvailabilityType.available:
print('Purchases are available');
break;
case RustorePurchaseAvailabilityType.unavailable:
print('Purchases unavailable: ${availability.cause?.message}');
break;
case RustorePurchaseAvailabilityType.unknown:
print('Purchase availability unknown');
break;
}
3. Load Products #
final products = await client.getProducts([
'product_id_1',
'product_id_2',
'subscription_id_1',
]);
for (final product in products) {
print('Product: ${product.title} - ${product.priceLabel}');
}
4. Load Purchases #
final purchases = await client.getPurchases();
for (final purchase in purchases) {
print('Purchase: ${purchase.productId} - ${purchase.purchaseState}');
}
5. Start Purchase Flow #
final result = await client.purchaseProduct(
'product_id_1',
developerPayload: 'custom_payload_${DateTime.now().millisecondsSinceEpoch}',
);
switch (result.resultType) {
case RustorePaymentResultType.success:
print('Purchase successful: ${result.purchaseId}');
// Confirm the purchase
await client.confirmPurchase(result.purchaseId!);
break;
case RustorePaymentResultType.cancelled:
print('Purchase cancelled');
break;
case RustorePaymentResultType.failure:
print('Purchase failed: ${result.errorMessage}');
break;
case RustorePaymentResultType.invalid_payment_state:
print('Invalid payment state: ${result.errorMessage}');
break;
}
6. Listen to Purchase Results #
// Listen to purchase results
client.purchaseResults.listen((result) {
print('Purchase result: ${result.resultType}');
});
// Listen to errors
client.errors.listen((error) {
print('Error: ${error.message} (${error.code})');
});
7. Theme Management #
// Change theme dynamically
await client.setTheme(RustoreBillingTheme.dark);
8. Handle Deep Links #
In your main activity, call onNewIntent when receiving deep links:
// This should be called from your Android activity's onNewIntent method
client.onNewIntent(intentData);
API Reference #
RustoreBillingConfig #
Configuration for the RuStore billing client.
class RustoreBillingConfig {
final String consoleApplicationId; // Your app ID from RuStore console
final String deeplinkScheme; // Deep link scheme for payment flows
final bool debugLogs; // Enable debug logging
final RustoreBillingTheme theme; // Billing client theme
final bool enableLogging; // Enable external payment logging
}
RustoreProduct #
Represents a product available for purchase.
class RustoreProduct {
final String productId;
final String productType;
final String? title;
final String? description;
final int? price;
final String? priceLabel;
final String? currency;
final String? language;
}
RustorePurchase #
Represents a purchase made by the user.
class RustorePurchase {
final String? purchaseId;
final String? productId;
final String? invoiceId;
final String? description;
final String? language;
final String? purchaseTime;
final String? orderId;
final String? amountLabel;
final int? amount;
final String? currency;
final int? quantity;
final RustorePurchaseState? purchaseState;
final String? developerPayload;
}
RustorePaymentResult #
Result of a purchase operation.
class RustorePaymentResult {
final RustorePaymentResultType resultType;
final String? purchaseId;
final String? errorCode;
final String? errorMessage;
}
Error Handling #
The plugin provides comprehensive error handling with specific error types:
enum RustoreExceptionType {
notInstalled, // RuStore is not installed
outdated, // RuStore version is outdated
userUnauthorized, // User is not authorized
requestLimitReached, // Request limit reached
reviewExists, // Review already exists
invalidReviewInfo, // Invalid review information
general, // General error
}
Error Codes #
The plugin handles various error codes from the RuStore SDK:
| HTTP Code | Error Code | Description |
|---|---|---|
| 400 | 40001 | Incorrect request parameters |
| 400 | 40003 | App not found |
| 400 | 40004 | App status: inactive |
| 400 | 40005 | Product not found |
| 400 | 40006 | Product status: inactive |
| 400 | 40007 | Invalid product type |
| 400 | 40008 | Order with this order_id already exists |
| 400 | 40009 | Active order exists for this product |
| 400 | 40010 | Order in paid state needs to be consumed |
| 400 | 40011 | Non-consumable product already purchased |
| 400 | 40012 | Subscription already purchased |
| 400 | 40013 | Service data not received |
| 400 | 40014 | Mandatory attribute missing |
| 400 | 40015 | Failed to change order status |
| 400 | 40016 | Quantity > 1 for non-consumable product |
| 400 | 40017 | Product deleted |
| 400 | 40018 | Cannot consume products with this type |
| 401 | 40101 | Invalid token |
| 401 | 40102 | Token lifetime expired |
| 403 | 40301 | Access denied |
| 403 | 40302 | Method not allowed |
| 403 | 40303 | App ID doesn't match token |
| 403 | 40305 | Incorrect token type |
| 404 | 40401 | Not found |
| 408 | 40801 | Notification timeout expired |
| 500 | 50*** | Payment service internal error |
Best Practices #
- Always check RuStore installation before attempting billing operations
- Verify purchase availability to ensure the device supports purchases
- Handle all purchase result types including cancellations and failures
- Confirm purchases after receiving successful payment results
- Use developer payloads for tracking and verification
- Implement proper error handling for all billing operations
- Listen to purchase result streams for real-time updates
- Test with debug logging enabled during development
Troubleshooting #
Common Issues #
-
"Billing client not initialized"
- Ensure you call
initialize()before any other operations - Check that your
consoleApplicationIdis correct
- Ensure you call
-
"Purchases unavailable"
- Verify RuStore is installed on the device
- Check that your app is properly configured in RuStore Console
- Ensure the device supports purchases
-
Deep link issues
- Verify the scheme in
AndroidManifest.xmlmatches your config - Ensure your activity handles
onNewIntentproperly
- Verify the scheme in
-
Product not found
- Check that product IDs exist in RuStore Console
- Verify product status is active
- Ensure product type is supported
Debug Logging #
Enable debug logging to troubleshoot issues:
await client.initialize(
RustoreBillingConfig(
consoleApplicationId: 'your_app_id',
deeplinkScheme: 'yourappscheme',
debugLogs: true, // Enable debug logs
enableLogging: true, // Enable external logging
),
);
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
Support #
For issues and questions:
- Check the RuStore documentation
- Open an issue on GitHub
- Contact the maintainers