DigitalGoods
Read an app store's catalogue and the user's entitlements from inside an installed PWA - the store's own titles and prices, the purchases it has on file, and consuming one that has been used up.
@inject Bit.Butil.DigitalGoods digitalGoodsMDN reference
https://play.google.com/billing) and the item id in its Data; the
purchase then shows up in ListPurchases.
getDigitalGoodsService() only connects inside an app installed from the store it is
asking, so Connect returns false in a browser tab. And every entitlement decision
belongs on your server, verified against the store's API with a PurchaseToken: a
client saying it paid is a claim, not a receipt.
IsSupported says the function exists; Connect says there is a store behind it. An uninstalled app has the first and not the second, which is why the store UI should be gated on Connect.
@inject Bit.Butil.DigitalGoods digitalGoods
var supported = await digitalGoods.IsSupported();
var connected = await digitalGoods.Connect(); // defaults to Google Play billingThe store's own title, description and price for each item id, in the user's currency. Render these rather than a copy from your database - the price here is the number the user will actually be charged.
var items = await digitalGoods.GetDetails(["coins_100", "pro_monthly"]);
foreach (var item in items)
{
var price = $"{item.Price?.Value} {item.Price?.Currency}";
}ListPurchases is what is active now - unconsumed one-offs and live subscriptions - and what a client restores entitlements from after a reinstall. ListPurchaseHistory is the most recent purchase per item, consumed and expired ones included.
var active = await digitalGoods.ListPurchases();
var history = await digitalGoods.ListPurchaseHistory();
// Send purchase.PurchaseToken to the server; let the server ask the store.Marks a purchase as used up so the item can be bought again - the coin pack the user spent. Consume only after your server has recorded what the purchase bought: consuming first and crediting second loses the purchase entirely if anything in between fails.
var consumed = await digitalGoods.Consume(purchase.PurchaseToken);API reference
const string GooglePlayBilling = "https://play.google.com/billing"ValueTask<bool> IsSupported()ValueTask<bool> Connect(string serviceProvider = GooglePlayBilling)ValueTask<DigitalGoodsItem[]> GetDetails(string[] itemIds, string serviceProvider = GooglePlayBilling)ValueTask<DigitalGoodsPurchase[]> ListPurchases(string serviceProvider = GooglePlayBilling)ValueTask<DigitalGoodsPurchase[]> ListPurchaseHistory(string serviceProvider = GooglePlayBilling)ValueTask<bool> Consume(string purchaseToken, string serviceProvider = GooglePlayBilling)string ItemId, string Title, string? Description, PaymentCurrencyAmount? Price, string? Type, string[] IconUrls, string? SubscriptionPeriod, string? FreeTrialPeriod, PaymentCurrencyAmount? IntroductoryPrice, string? IntroductoryPricePeriod, int? IntroductoryPriceCyclesstring ItemId, string PurchaseToken