再來看看消耗性商品的頁面吧。
InAppPurchaseConsumables
變數:
首先看一下Log:
那GetFulfillmentResults是什麼呢?來看一下內容:
然後我們來看GrantFeatureLocally方法:
然後是方法IsLocallyFulfilled:
再來看FulfillProduct1:
然後是try&catch去處理,你按下購買按鈕後,可以選擇四種情況,除了S_OK之外,其他三種都會失敗,這會丟出catch的例外狀況訊息。然後他檢查purchaseResults.Status,這是App內購買的狀態,有四種,這邊幫大家介紹一下:
狀況一,成功購買的話,先增加金幣或道具,然後再模擬購買的動作。狀況二,未完成,那就看IsLocallyFulfilled檢查結果,若檢查結果是失敗,那就呼叫GrantFeatureLocally,然後把它完成。最後一個狀況,沒有購買;這你在模擬購買時按取消,就會被呼叫,它就是顯示一個訊息。catch的部分就是其他狀況。
InAppPurchaseConsumables
變數:
- rootPage:為了使用MainPage的方法所創建的變數,為MainPage型別
- numberOfConsumablesPurchased:消耗性商品購買次數,為int型別
- grantedConsumableTransactionIds:為一字典,key是string,value是Guid的List。
- InAppPurchaseConsumables:初始子
- OnNavigatedTo:設定numberOfConsumablesPurchased為0,並讀取xml檔案資料
- OnNavigatingFrom:單純叫用super class的OnNavigatingFrom
- LoadInAppPurchaseConsumablesProxyFileAsync:讀取消耗性商品的proxy file,並將購買訊息顯示於畫面上。
- BuyAndFulfillProduct1Button_Click:按鈕,處理按下購買商品1按鈕的事件。根據回傳的string處理不同的條件之結果,
- FulfillProduct1:模擬購買商品1的處理,
- Log:擴充NotifyUser顯示訊息的方法
- GetFulfillmentResults:配合Log,只是增加一句訊息內容
- GrantFeatureLocally:主要是要處理購買後增加實際內容物的部分,像是金幣或道具
- IsLocallyFulfilled
首先看一下Log:
private void Log(string message, NotifyType type)
{
string logMessage = message + "\n\n" + GetFulfillmentResults();
rootPage.NotifyUser(logMessage, type);
}
第一行是建立訊息,第二行是使用MainPage的方法NotifyUser來顯示訊息,訊息字串內容第一行是message,然後換行兩次,加上由GetFulfillmentResults提供的訊息。NotifyType型別的type變數,是指明訊息的種類,是狀態訊息還是錯誤訊息。注意到它只是在訊息字串裡面多加一個方法GetFulfillmentResults,其他基本上還是NotifyUser的形式,所以Log只是一個NotifyUser的擴充方法而已。接下來你只要把它看成是NotifyUser就很容易接受了。那GetFulfillmentResults是什麼呢?來看一下內容:
private string GetFulfillmentResults()
{
string message = "Product 1 has been fulfilled " + numberOfConsumablesPurchased + " time" + (numberOfConsumablesPurchased == 1 ? "" : "s") + ".";
return message;
}
這邊是處理Log方法所要顯示的訊息內容的第二行,簡單說,是要告訴使用者,交易了幾次,然後如果是超過一次的話,注意複數要加s(所以只是處理文法上的問題)。然後我們來看GrantFeatureLocally方法:
private void GrantFeatureLocally(string productId, Guid transactionId)
{
if (!grantedConsumableTransactionIds.ContainsKey(productId))
{
grantedConsumableTransactionIds.Add(productId, new List<Guid>());
}
grantedConsumableTransactionIds[productId].Add(transactionId);
// Grant the user their content. You will likely increase some kind of gold/coins/some other asset count.
numberOfConsumablesPurchased++;
}
首先他看變數grantedConsumableTransactionIds裡面有沒有Key為productId,如果沒有,就把這Key-Value值加進去,value的部分是新建立的List。然後再加入transactionId。再來的一步他註記說:產生使用者它們的內容物,比方說增加金幣之類的。這就看個人的要求了。最後是增加numberOfConsumablesPurchased的次數(會顯示在Log)。所以這個方法主要是要處理購買後增加實際內容物的部分。然後是方法IsLocallyFulfilled:
private Boolean IsLocallyFulfilled(string productId, Guid transactionId)
{
return grantedConsumableTransactionIds.ContainsKey(productId) && grantedConsumableTransactionIds[productId].Contains(transactionId);
}
判斷變數grantedConsumableTransactionIds是否含有Key值productId以及如果有此key的話,是否也有Value的值。單純作為if陳述的判斷而已。再來看FulfillProduct1:
private async void FulfillProduct1(string productId, Guid transactionId)
{
try
{
FulfillmentResult result = await CurrentAppSimulator.ReportConsumableFulfillmentAsync(productId, transactionId);
switch (result)
{
case FulfillmentResult.Succeeded:
Log("You bought and fulfilled product 1.", NotifyType.StatusMessage);
break;
case FulfillmentResult.NothingToFulfill:
Log("There is no purchased product 1 to fulfill.", NotifyType.StatusMessage);
break;
case FulfillmentResult.PurchasePending:
Log("You bought product 1. The purchase is pending so we cannot fulfill the product.", NotifyType.StatusMessage);
break;
case FulfillmentResult.PurchaseReverted:
Log("You bought product 1. But your purchase has been reverted.", NotifyType.StatusMessage);
// Since the user's purchase was revoked, they got their money back.
// You may want to revoke the user's access to the consumable content that was granted.
break;
case FulfillmentResult.ServerError:
Log("You bought product 1. There was an error when fulfilling.", NotifyType.StatusMessage);
break;
}
}
catch (Exception)
{
Log("You bought Product 1. There was an error when fulfilling.", NotifyType.ErrorMessage);
}
}
第一行是模擬告訴Win Store說使用者已購買、並且有權訪問該內容。他回傳一個FulfillmentResult型別的值,說明App內消耗品購買的狀況。該型別列舉了五種情形,可自行參考連結內容。單看上述程式碼,大概可以發現這五種情況的意思:- Succeeded 買成功了,商品也實現了
- NothingToFulfill 沒有買成,沒有已購買的商品1
- PurchasePending 買了,但購買程序還未被清除,還在處理/暫停中,所以還沒實現此商品
- PurchaseReverted 買了,但購買已被回復。使用者的錢已退回,你可以在這邊撤銷產生的金幣/道具
- ServerError 買了,但要實現商品時有錯誤。
private async void BuyAndFulfillProduct1Button_Click(object sender, RoutedEventArgs e)
{
Log("Buying Product 1...", NotifyType.StatusMessage);
try
{
PurchaseResults purchaseResults = await CurrentAppSimulator.RequestProductPurchaseAsync("product1");
switch (purchaseResults.Status)
{
case ProductPurchaseStatus.Succeeded:
GrantFeatureLocally("product1", purchaseResults.TransactionId);
FulfillProduct1("product1", purchaseResults.TransactionId);
break;
case ProductPurchaseStatus.NotFulfilled:
if (!IsLocallyFulfilled("product1", purchaseResults.TransactionId))
{
GrantFeatureLocally("product1", purchaseResults.TransactionId);
}
FulfillProduct1("product1", purchaseResults.TransactionId);
break;
case ProductPurchaseStatus.NotPurchased:
Log("Product 1 was not purchased.", NotifyType.StatusMessage);
break;
}
}
catch (Exception)
{
Log("Unable to buy Product 1.", NotifyType.ErrorMessage);
}
}
首先他有更新頁面上的訊息,這個頁面是把訊息更新放在Log這個方法裡面處理,因為訊息都需要處理GetFulfillmentResults方法,所以他另外放在Log裡面,這等一下一起講。然後是try&catch去處理,你按下購買按鈕後,可以選擇四種情況,除了S_OK之外,其他三種都會失敗,這會丟出catch的例外狀況訊息。然後他檢查purchaseResults.Status,這是App內購買的狀態,有四種,這邊幫大家介紹一下:
- Succeeded 購買成功,使用者也已收到通知
- AlreadyPurchased 使用者之前已經買過了,無法再次購買
- NotFulfilled 前一次此消耗品購買未完成,所以無法完成
- NotPurchased 使用者決定不買,或有其他原因導致交易沒有完成
狀況一,成功購買的話,先增加金幣或道具,然後再模擬購買的動作。狀況二,未完成,那就看IsLocallyFulfilled檢查結果,若檢查結果是失敗,那就呼叫GrantFeatureLocally,然後把它完成。最後一個狀況,沒有購買;這你在模擬購買時按取消,就會被呼叫,它就是顯示一個訊息。catch的部分就是其他狀況。
留言
張貼留言