How to implement google play billing in MAUI .NET 8

Ryan Ruffing 0 Reputation points
2024-05-17T16:02:36.84+00:00

I'm trying to implement the google play billing library in my .net maui application (8.0). I tried following instructions on this thread. https://learn.microsoft.com/en-us/answers/questions/1347017/im-curious-about-the-google-play-store-payment-fea
Apparently all you have to do now is initialize a billing client and it will unlock the subscriptions in the google play console, but that has not worked so far for me.
Am I doing something wrong?

using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using Android.BillingClient.Api;

public class SubscriptionManager
{
    private BillingClient billingClient;
    private Context context;
    private Action<bool> subscriptionCallback;

    public SubscriptionManager(Context context)
    {
        this.context = context;
        InitializeBillingClient();
    }

    private void InitializeBillingClient()
    {
        billingClient = BillingClient.NewBuilder(context)
            .EnablePendingPurchases()
            .SetListener(new PurchasesUpdateListener(this))
            .Build();

        billingClient.StartConnection(new SubscriptionConnectionListener(this));
    }

    private class SubscriptionConnectionListener : Java.Lang.Object, IBillingClientStateListener
    {
        private readonly SubscriptionManager subscriptionManager;

        public SubscriptionConnectionListener(SubscriptionManager subscriptionManager)
        {
            this.subscriptionManager = subscriptionManager;
        }

        public void OnBillingServiceDisconnected()
        {
            // Try to restart the connection on the next request to BillingClient
            subscriptionManager.InitializeBillingClient();
        }

        public void OnBillingSetupFinished(BillingResult billingResult)
        {
            if (billingResult.ResponseCode == BillingResponseCode.Ok)
            {
                // BillingClient is ready
            }
            else
            {
                // Handle setup failure
                // Example: Log error or show a message to the user
            }
        }
    }

    public void InitiateSubscriptionPurchase(string skuId, Action<bool> callback)
    {
        subscriptionCallback = callback;
        SkuDetailsParams.Builder paramsBuilder = SkuDetailsParams.NewBuilder();
        paramsBuilder.SetType(BillingClient.SkuType.Subs);

        List<string> skuList = new List<string> { skuId };
        paramsBuilder.SetSkusList(skuList);

        SkuDetailsParams skuDetailsParams = paramsBuilder.Build();

        billingClient.QuerySkuDetailsAsync(skuDetailsParams);
    }

    private void LaunchSubscriptionBillingFlow(SkuDetails skuDetails)
    {
        BillingFlowParams billingFlowParams = BillingFlowParams.NewBuilder()
            .SetSkuDetails(skuDetails)
            .Build();
        BillingResult result = billingClient.LaunchBillingFlow((Activity)context, billingFlowParams);
        if (result.ResponseCode != BillingResponseCode.Ok)
        {
         
            subscriptionCallback?.Invoke(false);
        }
    }

    private class SkuDetailsResponseListener : Java.Lang.Object, ISkuDetailsResponseListener
    {
        private readonly SubscriptionManager subscriptionManager;

        public SkuDetailsResponseListener(SubscriptionManager subscriptionManager)
        {
            this.subscriptionManager = subscriptionManager;
        }

        public void OnSkuDetailsResponse(BillingResult billingResult, IList<SkuDetails> skuDetailsList)
        {
            if (billingResult.ResponseCode == BillingResponseCode.Ok && skuDetailsList != null && skuDetailsList.Count > 0)
            {
                SkuDetails skuDetails = skuDetailsList.FirstOrDefault(); 
                subscriptionManager.LaunchSubscriptionBillingFlow(skuDetails);
            }
            else
            {
               
                subscriptionManager.subscriptionCallback?.Invoke(false);
            }
        }
    }

    internal class PurchasesUpdateListener : Java.Lang.Object, IPurchasesUpdatedListener
    {
        private readonly SubscriptionManager subscriptionManager;

        public PurchasesUpdateListener(SubscriptionManager subscriptionManager)
        {
            this.subscriptionManager = subscriptionManager;
        }

        public void OnPurchasesUpdated(BillingResult billingResult, IList<Purchase> purchases)
        {
            if (billingResult.ResponseCode == BillingResponseCode.Ok && purchases != null)
            {
                foreach (var purchase in purchases)
                {
                    // Handle each purchase
                    if (purchase.PurchaseState == PurchaseState.Purchased)
                    {
                        // Purchase was successful
                        subscriptionManager.subscriptionCallback?.Invoke(true);
                    }
                    else if (purchase.PurchaseState == PurchaseState.Pending)
                    {
                        // Purchase is pending, handle accordingly
                        // Example: Show a message to the user
                    }
                    else
                    {
                        // Purchase failed or was canceled
                        subscriptionManager.subscriptionCallback?.Invoke(false);
                    }
                }
            }
            else
            {
                // Handle purchase update failure
                subscriptionManager.subscriptionCallback?.Invoke(false);
            }
        }
    }
}
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,058 questions
{count} votes