[英]How to Implement In-App Purchases in Windows 10 Apps?
我想將應用內購買集成到我的Windows通用應用中。 在編碼之前,我要做以下事情。
在Windows Dev Center上制作應用
在IAP部分中添加具有詳細信息的產品,然后提交到商店,如您在Image中所見
CurrentApp
而不是CurrentAppSimulator
,但是它例外。 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.xml
的IsTrial
設置為true,在這種模式下,應用內購買似乎無效。 當我將其更改為false時,它開始為我工作。
因此,首先我們要在開發過程中(通過使用CurrentAppSimulator
類)討論對應用內購買的模擬。 在這種情況下,您需要一個WindowsStoreProxy.xml
文件。 在這里描述
現在,您顯示的窗口由CurrentAppSimulator.RequestProductPurchaseAsync
行打開。 它基本上控制着Windows Runtime本機方法的返回值(這對我來說很奇怪……我認為這不是Microsoft故意的……應該在此做其他事情),但是如果讓它返回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\\<username>\\AppData\\Local\\Packages\\<app package folder>\\LocalState\\Microsoft\\Windows Store\\ApiData\\WindowsStoreProxy.xml
不起作用,但是單個更改已解決問題:我更改了這部分
<LicenseInformation> <App> <IsActive>true</IsActive> <IsTrial>true</IsTrial> </App> </LicenseInformation>
對此:
<LicenseInformation> <App> <IsActive>true</IsActive> <IsTrial>false</IsTrial> </App> </LicenseInformation>
(因此IsTrial
設置為false ...)
現在,在這一點上,我還想提一下,這有點奇怪,因為在默認的WindowsStoreProxy.xml
中,沒有為我的應用內購買定義任何產品。 因此,對於我的“ RemoveAds”,正確的WindowsStoreProxy.xml
如下所示:
<?xml version="1.0" encoding="utf-16" ?> <CurrentApp> <ListingInformation> <App> <AppId>00000000-0000-0000-0000-000000000000</AppId> <LinkUri>http://apps.microsoft.com/webpdp/app/00000000-0000-0000-0000-000000000000</LinkUri> <CurrentMarket>en-US</CurrentMarket> <AgeRating>3</AgeRating> <MarketData xml:lang="en-US"> <Name>AppName</Name> <Description>AppDescription</Description> <Price>1.00</Price> <CurrencySymbol>$</CurrencySymbol> <CurrencyCode>USD</CurrencyCode> </MarketData> </App> <Product ProductId="RemoveAds" LicenseDuration="1" ProductType="Durable"> <MarketData xml:lang="en-US"> <Name>RemoveAds</Name> <Price>1.00</Price> <CurrencySymbol>$</CurrencySymbol> <CurrencyCode>USD</CurrencyCode> </MarketData> </Product> </ListingInformation> <LicenseInformation> <App> <IsActive>true</IsActive> <IsTrial>false</IsTrial> </App> <Product ProductId="1"> <IsActive>true</IsActive> </Product> </LicenseInformation> <ConsumableInformation> <Product ProductId="RemoveAds" TransactionId="10000000-0000-0000-0000-000000000000" Status="Active" /> </ConsumableInformation> </CurrentApp>
我想指出的另一件事是,帶有兩個參數的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<StorageFile> GetWindowsStoreProxyXmlAsync(string productKey, bool isActive = false, bool isTrial = false)
{
StorageFile xmlFile = null;
var currentApp = LoadCurrentApp(productKey, isActive, isTrial);
var xml = StorageHelper.SerializeToXML<CurrentApp>(currentApp);
if (!string.IsNullOrEmpty(xml))
{
xmlFile = await StorageHelper.LocalFolder.CreateFileAsync("MarketData.xml", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(xmlFile, xml);
}
return xmlFile;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.