Plugin.InAppBilling
9.0.1-beta
See the version list below for details.
dotnet add package Plugin.InAppBilling --version 9.0.1-beta
NuGet\Install-Package Plugin.InAppBilling -Version 9.0.1-beta
<PackageReference Include="Plugin.InAppBilling" Version="9.0.1-beta" />
paket add Plugin.InAppBilling --version 9.0.1-beta
#r "nuget: Plugin.InAppBilling, 9.0.1-beta"
// Install Plugin.InAppBilling as a Cake Addin #addin nuget:?package=Plugin.InAppBilling&version=9.0.1-beta&prerelease // Install Plugin.InAppBilling as a Cake Tool #tool nuget:?package=Plugin.InAppBilling&version=9.0.1-beta&prerelease
In-App Billing Plugin for .NET MAUI and Windows
A simple In-App Purchase plugin for .NET MAUI and Windows to query item information, purchase items, restore items, and more.
Subscriptions are supported on iOS, Android, and Mac. Windows/UWP/WinUI 3 - does not support subscriptions at this time.
Important Version Information
- v8 now supports .NET 8+ .NET MAUI and Windows Apps.
- v7 now supports .NET 6+, .NET MAUI, UWP, and Xamarin/Xamarin.Forms projects
- v7 is built against Android Billing Library 6.0
- See migration guides below
Documentation
Get started by reading through the In-App Billing Plugin documentation.
NuGet
- NuGet: Plugin.InAppBilling
Platform Support
Platform | Version |
---|---|
iOS for .NET | 10+ |
macCatlyst for .NET | All |
tvOS for .NET | 10.13.2 |
Android for .NET | 21+ |
Windows App SDK (WinUI 3) | 10+ |
.NET MAUI | All |
Created By: @JamesMontemagno
- Twitter: @JamesMontemagno
- Blog: Montemagno.com
- Podcast: Merge Conflict
- Videos: James's YouTube Channel
Version 8 Major Updates
- Nice new re-write and re-implementation of APIs!
- Built against .NET 8
- Now using latest Android Billing v6.2.1
Version 7 Major Updates
- Android: You must compile and target against Android 12 or higher (or Android 13 if v7.1)
- Android: Now using Android Billing v6
- Android: Major changes to Android product details, subscriptions, and more
- Android: Please read through: https://developer.android.com/google/play/billing/migrate-gpblv6
- Android:
AcknowledgePurchaseAsync
is nowFinalizePurchaseAsync
- All: There are now "Extras" for all products that give you back tons of info for each platform
If you receive an error in Google Play you may need to add this to your AndroidManifest.xml inside the application node:
<meta-data
android:name="com.google.android.play.billingclient.version"
android:value="6.1.0" />
If you are building against .NET 8 for Android you will need to add the following packages when using v7:
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
<PackageReference Include="Xamarin.AndroidX.Activity" Version="1.9.0.3" />
<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.9.0.3" />
<PackageReference Include="Xamarin.AndroidX.Collection" Version="1.4.0.5" />
<PackageReference Include="Xamarin.AndroidX.Collection.Ktx" Version="1.4.0.4" />
<PackageReference Include="Xamarin.GooglePlayServices.Base" Version="118.4.0" />
</ItemGroup>
Pending Transactions:
- If the result of PurchaseAsync is PurchaseState.PaymentPending, store the order details locally and inform the user that they will have access to the product when the payment completes
- When the user starts the app (and/or visits a particular page), if the stored PurchaseState is PaymentPending, call GetPurchasesAsync and query the result for a purchase that matches the stored purchase.
- If the PurchaseState for this purchase is still PaymentPending, show the same no-access message
- If the PurchaseState is Purchased, call ConsumePurchaseAsync or AcknowledgePurchaseAsync, depending on the product type
To respond to pending transactions you can subscribe to a listener in your Android project startup:
// Connect to the service here
await CrossInAppBilling.Current.ConnectAsync();
// Check if there are pending orders, if so then subscribe
var purchases = await CrossInAppBilling.Current.GetPurchasesAsync(ItemType.InAppPurchase);
if (purchases?.Any(p => p.State == PurchaseState.PaymentPending) ?? false)
{
Plugin.InAppBilling.InAppBillingImplementation.OnAndroidPurchasesUpdated = (billingResult, purchases) =>
{
// decide what you are going to do here with purchases
// probably acknowledge
// probably disconnect
};
}
else
{
await CrossInAppBilling.Current.DisconnectAsync();
}
If you do connect the IsConnected
propety will be true
and when you make purchases or check purchases again you should check ahead of time and not re-connect or disconnect if there are pending purchases
I highly recommend reading the entire Google Play Billing System docs.
Consumable vs Non-consumables on Android
On Android if you purchase anything you must first Acknowledge a purchase else it will be refunded. See the android documentation.
https://developer.android.com/google/play/billing/integrate#process https://developer.android.com/google/play/billing/integrate#pending
For consumables, the consumeAsync() method fulfills the acknowledgement requirement and indicates that your app has granted entitlement to the user. This method also enables your app to make the one-time product available for purchase again.
So, if you have a consumable... ConsumePurchaseAsync
will also acknowledge it, if you have a non-consumable you will need to call AcknowledgePurchaseAsync
.
Version 4+ Linker Settings
For linking if you are setting Link All you may need to add:
Android:
Plugin.InAppBilling;Xamarin.Android.Google.BillingClient
Android Progaurd Rules
-keep class com.android.billingclient.api.** { *; }
-keep class com.android.vending.billing.** { *; }
iOS:
--linkskip=Plugin.InAppBilling
License
The MIT License (MIT), see LICENSE file.
Want To Support This Project?
All I have ever asked is to be active by submitting bugs, features, and sending those pull requests down! Want to go further? Make sure to subscribe to my weekly development podcast Merge Conflict, where I talk all about awesome Xamarin goodies and you can optionally support the show by becoming a supporter on Patreon.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0-android34.0 is compatible. net8.0-ios18.0 is compatible. net8.0-maccatalyst18.0 is compatible. net8.0-macos15.0 is compatible. net8.0-windows10.0.19041 is compatible. |
-
net8.0-android34.0
- Microsoft.Maui.Essentials (>= 8.0.82)
- Xamarin.Android.Google.BillingClient (>= 7.1.1)
- Xamarin.AndroidX.Activity (>= 1.9.2.1)
- Xamarin.AndroidX.Activity.Ktx (>= 1.9.2.1)
- Xamarin.AndroidX.Collection (>= 1.4.4)
- Xamarin.AndroidX.Collection.Ktx (>= 1.4.4)
- Xamarin.AndroidX.Lifecycle.LiveData (>= 2.8.6)
- Xamarin.AndroidX.Lifecycle.LiveData.Core (>= 2.8.6)
- Xamarin.AndroidX.Lifecycle.Runtime (>= 2.8.6)
- Xamarin.AndroidX.Lifecycle.ViewModel (>= 2.8.6)
- Xamarin.AndroidX.Lifecycle.ViewModelSavedState (>= 2.8.6)
-
net8.0-ios18.0
- No dependencies.
-
net8.0-maccatalyst18.0
- No dependencies.
-
net8.0-macos15.0
- No dependencies.
-
net8.0-windows10.0.19041
- No dependencies.
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Plugin.InAppBilling:
Package | Downloads |
---|---|
Zebble.Billing
Zebble IAP plugin for Xamarin. |
|
VerticesEngine.Android
The Android port of the Cross Platform Vertices Engine. |
|
VerticesEngine.iOS
The iOS port of the cross platform engine Vertices Engine |
|
ContactManager.Core
Package Description |
|
RedCorners.IAP
In App Purchase Plugins |
GitHub repositories (2)
Showing the top 2 popular GitHub repositories that depend on Plugin.InAppBilling:
Repository | Stars |
---|---|
jamesmontemagno/app-ac-islandtracker
Animal Crossing Island Tracking Mobile App
|
|
jamesmontemagno/MyStreamTimer
A cool app to count up or down that writes text to file for streamers
|
Version | Downloads | Last updated | |
---|---|---|---|
9.0.2-beta | 228 | 10/18/2024 | |
9.0.1-beta | 118 | 10/8/2024 | |
9.0.0-beta | 70 | 10/3/2024 | |
8.0.5 | 1,310 | 10/18/2024 | |
8.0.5-beta | 92 | 10/18/2024 | |
8.0.4 | 527 | 10/3/2024 | |
8.0.3-beta | 357 | 8/9/2024 | |
8.0.2-beta | 156 | 7/23/2024 | |
8.0.1-beta | 92 | 7/23/2024 | |
8.0.0-beta | 140 | 7/16/2024 | |
7.1.3 | 12,095 | 7/15/2024 | |
7.1.2 | 620 | 7/12/2024 | |
7.1.2-beta | 217 | 5/11/2024 | |
7.1.1-beta | 3,149 | 12/13/2023 | |
7.1.0 | 55,155 | 10/30/2023 | |
7.1.0-beta | 807 | 10/4/2023 | |
7.0.5 | 25,533 | 8/4/2023 | |
7.0.5-beta | 2,980 | 6/4/2023 | |
7.0.4-beta | 616 | 6/3/2023 | |
7.0.3-beta | 625 | 6/3/2023 | |
7.0.2-beta | 629 | 6/1/2023 | |
7.0.1-beta | 646 | 6/1/2023 | |
7.0.0-beta | 648 | 5/31/2023 | |
6.7.1-beta | 665 | 5/12/2023 | |
6.7.0 | 51,828 | 10/20/2022 | |
6.6.2-beta | 829 | 9/25/2022 | |
6.6.1 | 4,069 | 9/22/2022 | |
6.6.1-beta | 683 | 9/22/2022 | |
6.6.0-beta | 659 | 9/22/2022 | |
6.5.0-beta | 728 | 9/20/2022 | |
6.4.0-beta | 673 | 9/1/2022 | |
6.3.3-beta | 2,628 | 5/11/2022 | |
6.3.2-beta | 715 | 3/7/2022 | |
6.3.1-beta | 644 | 2/15/2022 | |
6.3.0-beta | 165 | 2/13/2022 | |
6.0.0-beta | 1,403 | 1/14/2022 | |
5.7.1-beta | 683 | 5/12/2023 | |
5.6.2-beta | 785 | 9/25/2022 | |
5.6.1 | 12,475 | 9/22/2022 | |
5.6.1-beta | 675 | 9/22/2022 | |
5.6.0-beta | 683 | 9/22/2022 | |
5.5.0-beta | 648 | 9/20/2022 | |
5.4.0-beta | 638 | 9/1/2022 | |
5.3.3-beta | 7,157 | 5/11/2022 | |
5.3.2-beta | 2,578 | 3/7/2022 | |
5.3.1-beta | 1,830 | 2/15/2022 | |
5.3.0-beta | 930 | 2/13/2022 | |
5.2.0-beta | 1,548 | 1/14/2022 | |
5.1.1-beta | 984 | 12/26/2021 | |
5.1.0-beta | 14,106 | 11/21/2021 | |
5.0.1-beta | 7,603 | 7/18/2021 | |
5.0.0-beta | 868 | 7/13/2021 | |
4.4.0-beta | 1,126 | 7/13/2021 | |
4.2.0-beta | 2,409 | 5/6/2021 | |
4.1.2-beta | 13,676 | 2/8/2021 | |
4.1.1-beta | 840 | 2/8/2021 | |
4.1.0-beta | 781 | 2/7/2021 | |
4.0.2 | 93,062 | 1/2/2021 | |
4.0.2-beta | 837 | 1/2/2021 | |
4.0.1-beta | 5,141 | 11/4/2020 | |
4.0.0-beta | 6,938 | 8/20/2020 | |
2.1.0.187-beta | 20,564 | 2/4/2019 | |
2.0.0.173-beta | 3,263 | 9/29/2018 | |
2.0.0 | 183,375 | 5/23/2018 | |
1.4.1.157-beta | 1,402 | 5/9/2018 | |
1.2.5.145-beta | 1,411 | 5/2/2018 | |
1.2.5.144-beta | 1,336 | 5/2/2018 | |
1.2.5 | 3,865 | 5/1/2018 | |
1.2.4.140-beta | 1,360 | 4/24/2018 | |
1.2.4.138-beta | 1,510 | 4/2/2018 | |
1.2.4.137-beta | 1,324 | 3/29/2018 | |
1.2.4.136-beta | 1,449 | 3/27/2018 | |
1.2.4.133-beta | 1,857 | 3/17/2018 | |
1.2.4.130-beta | 1,503 | 2/26/2018 | |
1.2.4.123-beta | 1,544 | 1/26/2018 | |
1.2.4.122-beta | 1,373 | 1/25/2018 | |
1.2.4.116-beta | 1,649 | 1/10/2018 | |
1.2.4.113-beta | 1,456 | 1/6/2018 | |
1.2.4.112-beta | 1,617 | 12/20/2017 | |
1.2.4.111-beta | 1,414 | 12/20/2017 | |
1.2.4 | 28,183 | 1/18/2018 | |
1.2.3.107 | 24,780 | 10/11/2017 | |
1.2.3.98-beta | 1,522 | 10/9/2017 | |
1.2.2 | 5,268 | 7/13/2017 | |
1.2.2-beta72 | 1,407 | 7/9/2017 | |
1.2.1 | 10,305 | 7/3/2017 | |
1.2.0.54-alpha | 1,439 | 7/1/2017 | |
1.2.0.51-alpha | 1,443 | 6/28/2017 | |
1.2.0.50-alpha | 3,586 | 6/21/2017 | |
1.2.0.49-alpha | 1,389 | 6/20/2017 | |
1.1.0.46-beta | 2,752 | 6/15/2017 | |
1.1.0.35-beta | 3,520 | 4/18/2017 | |
1.1.0.34-beta | 2,835 | 3/23/2017 | |
1.1.0.33-beta | 1,324 | 3/23/2017 | |
1.1.0.32-beta | 1,381 | 3/22/2017 | |
1.1.0.23-beta | 1,933 | 2/10/2017 | |
1.1.0.15-beta | 1,435 | 2/6/2017 | |
1.1.0.9-beta | 1,468 | 1/23/2017 | |
1.1.0.3-beta | 1,321 | 1/21/2017 | |
1.1.0.2-beta | 1,343 | 1/21/2017 | |
1.0.0.31-beta | 1,341 | 1/16/2017 | |
1.0.0.30-beta | 1,410 | 1/15/2017 | |
1.0.0.27-beta | 1,325 | 1/14/2017 |