如何在Windows 10应用程序中实施应用程序内购买?

我想在我的Windows通用应用程序中集成应用程序内购买。 我在编码之前做了以下事情。

  • 在Windows开发人员中心制作应用程序

  • 在IAP部分添加包含详细信息的产品,并提交到商店,如图所示

  • 之后,我在我的应用程序中使用以下代码获取应用程序内购买产品列表和购买产品按钮。 我在我的代码中也使用了CurrentApp而不是CurrentAppSimulator ,但它是exception的。
 private async void RenderStoreItems() { picItems.Clear(); try { //StoreManager mySM = new StoreManager(); ListingInformation li = await CurrentAppSimulator.LoadListingInformationAsync(); System.Diagnostics.Debug.WriteLine(li); foreach (string key in li.ProductListings.Keys) { ProductListing pListing = li.ProductListings[key]; System.Diagnostics.Debug.WriteLine(key); string status = CurrentAppSimulator.LicenseInformation.ProductLicenses[key].IsActive ? "Purchased" : pListing.FormattedPrice; string imageLink = string.Empty; picItems.Add( new ProductItem { imgLink = key.Equals("BaazarMagzine101") ? "block-ads.png" : "block-ads.png", Name = pListing.Name, Status = status, key = key, BuyNowButtonVisible = CurrentAppSimulator.LicenseInformation.ProductLicenses[key].IsActive ? false : true } ); } pics.ItemsSource = picItems; } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.ToString()); } } private async void ButtonBuyNow_Clicked(object sender, RoutedEventArgs e) { Button btn = sender as Button; string key = btn.Tag.ToString(); if (!CurrentAppSimulator.LicenseInformation.ProductLicenses[key].IsActive) { ListingInformation li = await CurrentAppSimulator.LoadListingInformationAsync(); string pID = li.ProductListings[key].ProductId; string receipt = await CurrentAppSimulator.RequestProductPurchaseAsync(pID, true); System.Diagnostics.Debug.WriteLine(receipt); // RenderStoreItems(); } } 

我还将我的应用程序与Store关联,我的应用程序包与MS Dev Center App中的相同,如图所示

当我运行我的应用程序并点击“购买”按钮时,我得到了这个对话框,你可以在Image中看到,之后我没有从商店获得收据数据。

如果我做错了,请给我正确的指导,以实现应用内购买并测试我的笔记本电脑设备中的应用内购买。

我也有这个问题,问题出在WindowsStoreProxy.xml文件中。

简而言之

默认情况下,在WindowsStoreProxy.xmlIsTrial设置为true,在该模式下,应用内购买似乎不起作用。 当我把它改成假时,它开始为我工作。

解决方案多一点

  • 首先,我们在这里谈论在开发时间内模拟应用程序内购买(通过使用CurrentAppSimulator类)。 在这种情况下,您需要一个WindowsStoreProxy.xml文件。 它在这里描述

  • 现在,您显示的窗口由CurrentAppSimulator.RequestProductPurchaseAsync行打开。 它基本上控制了Windows运行时本机方法的返回值(这对我来说很奇怪……我认为这不是微软的故意……应该在那里做其他事情),但如果你让它返回S_OK ,那么基本上就是这样的情况。用户为应用内购买付费。

    购买模拟窗口的屏幕截图

  • 当它返回任何内容时, WindowsStoreProxy.xml某些内容很可能是错误的。 我建议你创建自己的WindowsStoreProxy.xml并使用CurrentAppSimulator.ReloadSimulatorAsync方法读取它,如下所示:

     var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@"Testing\WindowsStoreProxy.xml"); await CurrentAppSimulator.ReloadSimulatorAsync(file); 
  • 对我来说,使用C:\Users\\AppData\Local\Packages\\LocalState\Microsoft\Windows Store\ApiData\WindowsStoreProxy.xml不起作用,但单个更改已经解决问题:我改变了这一部分

       true true   

    对此:

       true false   

    (所以IsTrial被设置为假……)

  • 现在在这一点上我还想提一下,这有点奇怪,因为在默认的WindowsStoreProxy.xml中没有为我的应用程序内购买定义产品。 因此,对于我的“RemoveAds”,正确的WindowsStoreProxy.xml将是这样的:

         00000000-0000-0000-0000-000000000000 http://apps.microsoft.com/webpdp/app/00000000-0000-0000-0000-000000000000 en-US 3  AppName AppDescription 1.00 $ USD     RemoveAds 1.00 $ USD      true false   true       
  • 我想指出的另一件事是具有两个参数的CurrentAppSimulator.RequestProductPurchaseAsync已过时。 保留true参数,然后获取PurchaseResults实例作为结果,其中包含ReceiptXML属性中的收据。

WindowsStoreProxy.xml到c#代码并序列化为xml文件

 public static CurrentApp LoadCurrentApp(string productKey = "Premium", bool isActive = false, bool isTrial = false) { CurrentApp currentApp = new CurrentApp(); currentApp.ListingInformation = new ListingInformation() { App = new App() { AgeRating = "3", AppId = BasicAppInfo.AppId, CurrentMarket = "en-us", LinkUri = "", MarketData = new MarketData() { Name = "In-app purchases", Description = "AppDescription", Price = "5.99", CurrencySymbol = "$", CurrencyCode = "USD", } }, Product = new Product() { ProductId = productKey, MarketData = new MarketData() { Lang = "en-us", Name = productKey, Description = "AppDescription", Price = "5.99", CurrencySymbol = "$", CurrencyCode = "USD", } } }; currentApp.LicenseInformation = new LicenseInformation() { App = new App() { IsActive = isActive.ToString(), IsTrial = isTrial.ToString(), }, Product = new Product() { ProductId = productKey, IsActive = isActive.ToString(), } }; return currentApp; } 

基础xml模型

 [XmlRoot(ElementName = "MarketData")] public class MarketData { [XmlElement(ElementName = "Name")] public string Name { get; set; } [XmlElement(ElementName = "Description")] public string Description { get; set; } [XmlElement(ElementName = "Price")] public string Price { get; set; } [XmlElement(ElementName = "CurrencySymbol")] public string CurrencySymbol { get; set; } [XmlElement(ElementName = "CurrencyCode")] public string CurrencyCode { get; set; } [XmlAttribute(AttributeName = "lang", Namespace = "http://www.w3.org/XML/1998/namespace")] public string Lang { get; set; } } [XmlRoot(ElementName = "App")] public class App { [XmlElement(ElementName = "AppId")] public string AppId { get; set; } [XmlElement(ElementName = "LinkUri")] public string LinkUri { get; set; } [XmlElement(ElementName = "CurrentMarket")] public string CurrentMarket { get; set; } [XmlElement(ElementName = "AgeRating")] public string AgeRating { get; set; } [XmlElement(ElementName = "MarketData")] public MarketData MarketData { get; set; } [XmlElement(ElementName = "IsActive")] public string IsActive { get; set; } [XmlElement(ElementName = "IsTrial")] public string IsTrial { get; set; } } [XmlRoot(ElementName = "Product")] public class Product { [XmlElement(ElementName = "MarketData")] public MarketData MarketData { get; set; } [XmlAttribute(AttributeName = "ProductId")] public string ProductId { get; set; } [XmlElement(ElementName = "IsActive")] public string IsActive { get; set; } } [XmlRoot(ElementName = "ListingInformation")] public class ListingInformation { [XmlElement(ElementName = "App")] public App App { get; set; } [XmlElement(ElementName = "Product")] public Product Product { get; set; } } [XmlRoot(ElementName = "LicenseInformation")] public class LicenseInformation { [XmlElement(ElementName = "App")] public App App { get; set; } [XmlElement(ElementName = "Product")] public Product Product { get; set; } } [XmlRoot(ElementName = "CurrentApp")] public class CurrentApp { [XmlElement(ElementName = "ListingInformation")] public ListingInformation ListingInformation { get; set; } [XmlElement(ElementName = "LicenseInformation")] public LicenseInformation LicenseInformation { get; set; } } 

获取XmlFile

 public async static Task GetWindowsStoreProxyXmlAsync(string productKey, bool isActive = false, bool isTrial = false) { StorageFile xmlFile = null; var currentApp = LoadCurrentApp(productKey, isActive, isTrial); var xml = StorageHelper.SerializeToXML(currentApp); if (!string.IsNullOrEmpty(xml)) { xmlFile = await StorageHelper.LocalFolder.CreateFileAsync("MarketData.xml", CreationCollisionOption.ReplaceExisting); await FileIO.WriteTextAsync(xmlFile, xml); } return xmlFile; }