![]() |
VOOZH | about |
dotnet add package MZikmund.Uno.RevenueCat --version 0.1.2
NuGet\Install-Package MZikmund.Uno.RevenueCat -Version 0.1.2
<PackageReference Include="MZikmund.Uno.RevenueCat" Version="0.1.2" />
<PackageVersion Include="MZikmund.Uno.RevenueCat" Version="0.1.2" />Directory.Packages.props
<PackageReference Include="MZikmund.Uno.RevenueCat" />Project file
paket add MZikmund.Uno.RevenueCat --version 0.1.2
#r "nuget: MZikmund.Uno.RevenueCat, 0.1.2"
#:package MZikmund.Uno.RevenueCat@0.1.2
#addin nuget:?package=MZikmund.Uno.RevenueCat&version=0.1.2Install as a Cake Addin
#tool nuget:?package=MZikmund.Uno.RevenueCat&version=0.1.2Install as a Cake Tool
A .NET wrapper around RevenueCat SDK for Uno Platform applications, providing in-app purchase and subscription management for Android and iOS.
This library is based on Kebechet/Maui.RevenueCat.InAppBilling and adapted specifically for Uno Platform.
| Platform | Status |
|---|---|
| Android | Supported (API 21+) |
| iOS | Supported (14.2+) |
dotnet add package MZikmund.Uno.RevenueCat
Add the RevenueCat billing service to your dependency injection container:
using Uno.RevenueCat;
// In your service configuration
services.AddRevenueCat();
// Or with debug logging enabled
services.AddRevenueCat(forceEnableDebugLogs: true);
Initialize RevenueCat early in your app lifecycle. Inject IRevenueCatBilling and call Initialize():
public sealed partial class MainPage : Page
{
private readonly IRevenueCatBilling _billing;
public MainPage(IRevenueCatBilling billing)
{
_billing = billing;
InitializeComponent();
// Initialize with your RevenueCat API key
_billing.Initialize("your_revenuecat_api_key");
// Or initialize with a specific user ID
_billing.Initialize("your_revenuecat_api_key", "user_id");
}
}
You can find your API keys in the RevenueCat dashboard under Project Settings > API Keys.
Retrieve available product offerings configured in RevenueCat:
var offerings = await _billing.GetOfferingsAsync();
var currentOffering = offerings.FirstOrDefault(o => o.IsCurrent);
if (currentOffering != null)
{
foreach (var package in currentOffering.AvailablePackages)
{
var product = package.Product;
Console.WriteLine($"{product.Sku}: {product.Pricing.PriceLocalized}");
}
}
// Get a package to purchase
var offerings = await _billing.GetOfferingsAsync();
var package = offerings
.FirstOrDefault(o => o.IsCurrent)?
.AvailablePackages
.FirstOrDefault(p => p.Identifier == "monthly");
if (package == null) return;
// Make the purchase
var result = await _billing.PurchaseProductAsync(package);
if (result.IsSuccess)
{
// Purchase successful
var transaction = result.Transaction;
Console.WriteLine($"Purchased: {transaction?.ProductIdentifier}");
}
else if (result.ErrorStatus == PurchaseErrorStatus.PurchaseCancelledError)
{
// User cancelled - not an error
}
else
{
// Handle error
Console.WriteLine($"Purchase failed: {result.ErrorStatus}");
}
// Get active subscriptions
var activeSubscriptions = await _billing.GetActiveSubscriptionsAsync();
// Get detailed customer info with entitlements
var customerInfo = await _billing.GetCustomerInfoAsync();
if (customerInfo != null)
{
foreach (var entitlement in customerInfo.Entitlements)
{
if (entitlement.IsActive)
{
Console.WriteLine($"Active entitlement: {entitlement.Identifier}");
Console.WriteLine($"Expires: {entitlement.ExpirationDate}");
}
}
}
var customerInfo = await _billing.RestoreTransactionsAsync();
if (customerInfo != null)
{
Console.WriteLine($"Restored {customerInfo.AllPurchasedIdentifiers.Count} purchases");
}
// Login with a user ID
var customerInfo = await _billing.LoginAsync("user_123");
// Check if user is anonymous
if (_billing.IsAnonymous)
{
Console.WriteLine("User is anonymous");
}
// Set subscriber attributes
_billing.SetEmail("user@example.com");
_billing.SetDisplayName("John Doe");
_billing.SetPhoneNumber("+1234567890");
// Set custom attributes
_billing.SetAttributes(new Dictionary<string, string>
{
{ "favorite_color", "blue" }
});
// Logout
await _billing.LogoutAsync();
// Get URL to manage subscriptions (App Store / Play Store)
var managementUrl = await _billing.GetManagementSubscriptionUrlAsync();
if (!string.IsNullOrEmpty(managementUrl))
{
// Open the URL in browser
await Launcher.LaunchUriAsync(new Uri(managementUrl));
}
var eligibilities = await _billing.CheckTrialOrIntroDiscountEligibilityAsync(
new[] { "product_monthly", "product_yearly" });
foreach (var (productId, status) in eligibilities)
{
if (status == IntroElegibilityStatus.Eligible)
{
Console.WriteLine($"{productId} is eligible for intro offer");
}
}
Note: This method returns an empty dictionary on Android.
| Property | Description |
|---|---|
IsInitialized |
Whether the SDK has been initialized |
IsAnonymous |
Whether the current user is anonymous |
AppUserId |
The current user's ID |
| Method | Description |
|---|---|
Initialize(apiKey) |
Initialize with API key (anonymous user) |
Initialize(apiKey, appUserId) |
Initialize with API key and user ID |
GetOfferingsAsync() |
Fetch available offerings |
PurchaseProductAsync(package) |
Purchase a package |
GetActiveSubscriptionsAsync() |
Get active subscription identifiers |
GetAllPurchasedIdentifiersAsync() |
Get all purchased product identifiers |
GetCustomerInfoAsync() |
Get customer info with entitlements |
LoginAsync(appUserId) |
Login with a user ID |
LogoutAsync() |
Logout current user |
RestoreTransactionsAsync() |
Restore previous purchases |
GetManagementSubscriptionUrlAsync() |
Get subscription management URL |
CheckTrialOrIntroDiscountEligibilityAsync() |
Check intro offer eligibility (iOS) |
SetEmail(email) |
Set subscriber email |
SetDisplayName(name) |
Set subscriber display name |
SetPhoneNumber(phone) |
Set subscriber phone number |
SetAttributes(attributes) |
Set custom subscriber attributes |
The library uses a non-throwing approach for runtime errors. Methods return result objects with error status codes rather than throwing exceptions:
var result = await _billing.PurchaseProductAsync(package);
if (result.IsError)
{
switch (result.ErrorStatus)
{
case PurchaseErrorStatus.PurchaseCancelledError:
// User cancelled - handle gracefully
break;
case PurchaseErrorStatus.NetworkError:
// Network issue - prompt to retry
break;
case PurchaseErrorStatus.ProductAlreadyPurchasedError:
// Already purchased - restore instead
break;
default:
// Log and show generic error
break;
}
}
This project is licensed under the MIT License - see the file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0-android35.0 net9.0-android35.0 is compatible. net9.0-ios18.0 net9.0-ios18.0 is compatible. net10.0-android net10.0-android was computed. net10.0-ios net10.0-ios was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.2 | 197 | 1/1/2026 |
Initial release