Kebechet.Maui.RevenueCat.InAppBilling
7.4.0
Prefix Reserved
dotnet add package Kebechet.Maui.RevenueCat.InAppBilling --version 7.4.0
NuGet\Install-Package Kebechet.Maui.RevenueCat.InAppBilling -Version 7.4.0
<PackageReference Include="Kebechet.Maui.RevenueCat.InAppBilling" Version="7.4.0" />
<PackageVersion Include="Kebechet.Maui.RevenueCat.InAppBilling" Version="7.4.0" />
<PackageReference Include="Kebechet.Maui.RevenueCat.InAppBilling" />
paket add Kebechet.Maui.RevenueCat.InAppBilling --version 7.4.0
#r "nuget: Kebechet.Maui.RevenueCat.InAppBilling, 7.4.0"
#:package Kebechet.Maui.RevenueCat.InAppBilling@7.4.0
#addin nuget:?package=Kebechet.Maui.RevenueCat.InAppBilling&version=7.4.0
#tool nuget:?package=Kebechet.Maui.RevenueCat.InAppBilling&version=7.4.0
Maui.RevenueCat.InAppBilling
A .NET MAUI wrapper library for RevenueCat in-app purchases. Provides a unified C# API that abstracts away the need for you to use platform-specific code from Android and iOS native bindings.
Features
- Unified API for iOS and Android in-app purchases
- Subscription and one-time purchase support
- User authentication (anonymous and identified users)
- Subscription status and entitlement checking
- Trial/intro discount eligibility
- Subscriber attributes management
- Stub implementation for Windows (for development convenience)
Installation
dotnet add package Kebechet.Maui.RevenueCat.InAppBilling
Quick Start
1. Register the service
In your MauiProgram.cs:
builder.Services.AddRevenueCatBilling();
2. Inject and initialize
In App.xaml.cs, inject IRevenueCatBilling and initialize in OnStart():
public partial class App : Application
{
private readonly IRevenueCatBilling _revenueCat;
public App(IRevenueCatBilling revenueCat)
{
InitializeComponent();
_revenueCat = revenueCat;
}
protected override void OnStart()
{
var revenueCatApiKey = string.Empty;
#if __ANDROID__
revenueCatApiKey = "<your-android-api-key>";
#elif __IOS__
revenueCatApiKey = "<your-ios-api-key>";
#endif
_revenueCat.Initialize(revenueCatApiKey);
base.OnStart();
}
}
Important: Initialize must be called in
OnStart(), not in the constructor.
Test Store API keys (iOS)
RevenueCat's Test Store lets you exercise the full purchase flow without configuring App Store Connect / Play Console products. Test Store keys start with test_.
This wrapper ships an iOS xcframework built from source with the BYPASS_SIMULATED_STORE_RELEASE_CHECK Swift compilation flag, so a test_… key works on iOS Release builds too — it does not force-close the app. No code changes are required on your side; just pass the test_… key to Initialize(...).
On Android no such rebuild is needed: the RevenueCat SDK ships as a normal AAR (Kotlin bytecode), so its test-key check runs against the consuming app's build at runtime rather than being compiled into the library — a prebuilt AAR doesn't carry the always-on guard the prebuilt iOS framework did. Test Store support does require RevenueCat Android SDK 9.9.0+; this binding ships upstream SDK 10.16.1 (binding package 10.16.1), so test_… keys work out of the box (see issue #95, resolved by that SDK bump). The same "don't ship a test_ key to production" guidance applies on both platforms.
See src/Maui.RevenueCat.iOS/README.md for the build-time details and issue #116 for context.
API Reference
Initialization & State
| Method | Description |
|---|---|
Initialize(string apiKey) |
Initialize RevenueCat with your platform-specific API key |
IsInitialized() |
Check if the SDK has been initialized |
IsAnonymous() |
Check if current user is anonymous |
GetAppUserId() |
Get the current user ID |
Offerings & Products
| Method | Description |
|---|---|
GetOfferings(bool forceRefresh = false) |
Fetch available offerings and packages |
CheckTrialOrIntroDiscountEligibility(List<string> identifiers) |
Check eligibility for trials/intro pricing. Apple platforms only (iOS and Mac Catalyst); throws NotImplementedException on Android |
Purchases
| Method | Description |
|---|---|
PurchaseProduct(PackageDto package) |
Initiate a purchase flow |
GetActiveSubscriptions() |
Get list of active subscription identifiers |
GetAllPurchasedIdentifiers() |
Get all purchased product identifiers |
GetPurchaseDateForProductIdentifier(string productSku) |
Get purchase date for a specific product |
RestoreTransactions() |
Restore previous purchases |
User Management
| Method | Description |
|---|---|
Login(string appUserId) |
Log in an identified user |
Logout() |
Log out and create anonymous user |
GetCustomerInfo() |
Get current customer info and entitlements |
GetManagementSubscriptionUrl() |
Get URL for subscription management |
Subscriber Attributes
| Method | Description |
|---|---|
SetEmail(string email) |
Set user's email |
SetDisplayName(string name) |
Set user's display name |
SetPhoneNumber(string phone) |
Set user's phone number |
SetAttributes(IDictionary<string, string> attributes) |
Set custom attributes |
Example: Complete Purchase Flow
public class PurchaseService
{
private readonly IRevenueCatBilling _revenueCat;
public PurchaseService(IRevenueCatBilling revenueCat)
{
_revenueCat = revenueCat;
}
public async Task<bool> PurchaseSubscription()
{
var offerings = await _revenueCat.GetOfferings();
if (offerings.Count == 0)
return false;
var defaultOffering = offerings.FirstOrDefault(o => o.IsCurrent);
var monthlyPackage = defaultOffering?.AvailablePackages
.FirstOrDefault(p => p.Identifier == "monthly");
if (monthlyPackage == null)
return false;
var result = await _revenueCat.PurchaseProduct(monthlyPackage);
if (result.IsSuccess)
{
// Purchase successful
return true;
}
if (result.ErrorStatus == PurchaseErrorStatus.PurchaseCancelledError)
{
// User cancelled - not an error
return false;
}
// Handle other errors
Console.WriteLine($"Purchase failed: {result.ErrorStatus}");
return false;
}
public async Task<bool> HasActiveSubscription(string entitlementId)
{
var customerInfo = await _revenueCat.GetCustomerInfo();
return customerInfo?.ActiveSubscriptions
.Any(e => e == entitlementId) ?? false;
}
}
Platform Support
| Platform | Support |
|---|---|
| Android | Full implementation |
| iOS | Full implementation |
| Windows | Stub (returns defaults) |
| MacCatalyst | Full implementation (shares the iOS implementation) |
Stub implementations return:
truefor boolean methods- Empty collections for list methods
string.Emptyfor string methodsnullfor nullable types
This allows you to build and test on Windows/Mac without platform conditionals.
Error Handling
The library follows a non-throwing approach for runtime errors:
- Exceptions are thrown only for developer mistakes (e.g., calling methods before
Initialize()) - Runtime errors (network issues, store problems, etc.) return:
ErrorStatusin result DTOs (e.g.,PurchaseResultDto.ErrorStatus)- Empty collections for list returns
nullfor nullable types
This design ensures your app never crashes due to store-related issues.
Common Error Codes
| Error | Description |
|---|---|
PurchaseCancelledError |
User cancelled the purchase |
StoreProblemError |
Issue with the app store |
NetworkError |
Network connectivity issue |
ProductAlreadyPurchasedError |
Product was already purchased |
PaymentPendingError |
Payment is pending (e.g., awaiting approval) |
See PurchaseErrorStatus for the complete list.
Credits
- Native bindings for Android and iOS inspired by thisisthekap's Xamarin bindings
- Abstraction layer based on RevenueCatXamarin by BillFulton
Contributing
Feel free to create an issue or pull request. For major changes, please open an issue first to discuss your proposal - large PRs without prior discussion may be rejected.
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-android35.0 is compatible. net9.0-browser was computed. net9.0-ios was computed. net9.0-ios18.0 is compatible. net9.0-maccatalyst was computed. net9.0-maccatalyst18.0 is compatible. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net9.0-windows10.0.19041 is compatible. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Kebechet.Extensions.IsNullOrEmpty (>= 1.0.1)
- Microsoft.Maui.Controls (>= 9.0.0)
-
net9.0-android35.0
- Kebechet.Extensions.IsNullOrEmpty (>= 1.0.1)
- Kebechet.Maui.RevenueCat.Android (>= 10.16.1)
- Microsoft.Maui.Controls (>= 9.0.0)
-
net9.0-ios18.0
- Kebechet.Extensions.IsNullOrEmpty (>= 1.0.1)
- Kebechet.Maui.RevenueCat.iOS (>= 5.83.1)
- Microsoft.Maui.Controls (>= 9.0.0)
-
net9.0-maccatalyst18.0
- Kebechet.Extensions.IsNullOrEmpty (>= 1.0.1)
- Kebechet.Maui.RevenueCat.iOS (>= 5.83.1)
- Microsoft.Maui.Controls (>= 9.0.0)
-
net9.0-windows10.0.19041
- Kebechet.Extensions.IsNullOrEmpty (>= 1.0.1)
- Microsoft.Maui.Controls (>= 9.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Kebechet.Maui.RevenueCat.InAppBilling:
| Package | Downloads |
|---|---|
|
benxu.AppPlatform.Billing.RevenueCat
RevenueCat integration for in-app subscriptions in .NET MAUI. Provides real SDK integration for Android/iOS with optional simulator mode for testing. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 7.4.0 | 73 | 8/7/2026 |
| 7.3.2 | 78 | 8/5/2026 |
| 7.3.1 | 86 | 8/5/2026 |
| 7.3.0 | 83 | 8/5/2026 |
| 7.2.0 | 76 | 8/5/2026 |
| 7.1.0 | 1,060 | 6/17/2026 |
| 7.0.1 | 662 | 6/10/2026 |
| 7.0.0 | 458 | 5/19/2026 |
| 6.0.0 | 389 | 5/13/2026 |
| 5.5.0 | 984 | 2/8/2026 |
| 5.4.4 | 1,059 | 1/10/2026 |
| 5.4.3 | 203 | 1/4/2026 |
| 5.4.2 | 701 | 12/7/2025 |
| 5.4.1 | 542 | 11/3/2025 |
| 5.4.0 | 245 | 11/2/2025 |
| 5.3.2 | 612 | 10/11/2025 |
| 5.3.1 | 211 | 10/11/2025 |
| 5.3.0 | 757 | 8/21/2025 |
| 5.2.1 | 288 | 8/18/2025 |
| 5.2.0 | 282 | 8/11/2025 |
CHANGED
- Android binding updated to `Kebechet.Maui.RevenueCat.Android` 10.16.1 (RevenueCat Android SDK 10.1.2 -> 10.16.1). Notable upstream fixes: BillingClient connection moved off the main thread, showInAppMessages guarded against BillingClient runtime crashes, several OutOfMemory fixes around cached offerings responses. Full changelog: https://github.com/RevenueCat/purchases-android/releases
- iOS binding updated to `Kebechet.Maui.RevenueCat.iOS` 5.83.1 (RevenueCat iOS SDK 5.72.0 -> 5.83.1). Notable upstream changes: Test Store free-trial support, Test Store no longer logs misleading App Store/StoreKit messages, and a T-SAN memory-alignment crash fix. Full changelog: https://github.com/RevenueCat/purchases-ios/releases