Internet connection
I love UWP Platform
Hi, this is original message from App Certification Kit
- Name: …….
- App ID: 9N43VPZH82F7
- Publisher name: ……
- Test ID: fa473b92-6984-4e38-b8bf-ab3671f5804e
- Review completed: 11/29/2019 01:48PM
Hello,
Thank you for contacting us. The app offers the ability to purchase digital goods or services in-app and must use the Microsoft Store in-app purchase API. Apps may enable users to consume previously purchased digital content or services (subscriptions) but must not direct users to a purchase mechanism other than the Microsoft Store in-app purchase API.
For more information on the Microsoft Store in-app purchase API, please see:
Enable in-app purchases of apps and add-ons: https://learn.microsoft.com/en-us/windows/uwp/monetize/enable-in-app-purchases-of-apps-and-add-ons
Enable subscription add-ons for your app: https://learn.microsoft.com/en-us/windows/uwp/monetize/enable-subscription-add-ons-for-your-app
If you need assistance implementing this feature, please contact Developer Support via your Partner Dashboard or at this link: http://aka.ms/storesupport.
Please let us know if you need any additional assistance.
Thank you,
Alice
Microsoft Store Team
This is my page.
namespace MyApp
{
///
/// Pagina vuota che può essere usata autonomamente oppure per l'esplorazione all'interno di un frame.
///
public sealed partial class MainPage : Page
{
private StoreContext context = null;
private StoreProduct subscriptionStoreProduct;
// Assign this variable to the Store ID of your subscription add-on.
private string subscriptionStoreId = "hide for security reason";
public MainPage()
{
this.InitializeComponent();
}
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
await GetSubscriptionsInfo();
}
// This is the entry point method for the example.
public async Task SetupSubscriptionInfoAsync()
{
if (context == null)
{
context = StoreContext.GetDefault();
// If your app is a desktop app that uses the Desktop Bridge, you
// may need additional code to configure the StoreContext object.
// For more info, see https://aka.ms/storecontext-for-desktop.
}
bool userOwnsSubscription = await CheckIfUserHasSubscriptionAsync();
if (userOwnsSubscription)
{
// Unlock all the subscription add-on features here.
Frame.Navigate(typeof(Accedi));
return;
}
// Get the StoreProduct that represents the subscription add-on.
subscriptionStoreProduct = await GetSubscriptionProductAsync();
if (subscriptionStoreProduct == null)
{
return;
}
// Check if the first SKU is a trial and notify the customer that a trial is available.
// If a trial is available, the Skus array will always have 2 purchasable SKUs and the
// first one is the trial. Otherwise, this array will only have one SKU.
StoreSku sku = subscriptionStoreProduct.Skus[0];
if (sku.SubscriptionInfo.HasTrialPeriod)
{
// You can display the subscription trial info to the customer here. You can use
// sku.SubscriptionInfo.TrialPeriod and sku.SubscriptionInfo.TrialPeriodUnit
// to get the trial details.
}
else
{
// You can display the subscription purchase info to the customer here. You can use
// sku.SubscriptionInfo.BillingPeriod and sku.SubscriptionInfo.BillingPeriodUnit
// to provide the renewal details.
}
// Prompt the customer to purchase the subscription.
await PromptUserToPurchaseAsync();
}
private async Task CheckIfUserHasSubscriptionAsync()
{
StoreAppLicense appLicense = await context.GetAppLicenseAsync();
// Check if the customer has the rights to the subscription.
foreach (var addOnLicense in appLicense.AddOnLicenses)
{
StoreLicense license = addOnLicense.Value;
if (license.SkuStoreId.StartsWith(subscriptionStoreId))
{
if (license.IsActive)
{
// The expiration date is available in the license.ExpirationDate property.
return true;
}
}
}
// The customer does not have a license to the subscription.
return false;
}
private async Task GetSubscriptionProductAsync()
{
// Load the sellable add-ons for this app and check if the trial is still
// available for this customer. If they previously acquired a trial they won't
// be able to get a trial again, and the StoreProduct.Skus property will
// only contain one SKU.
StoreProductQueryResult result =
await context.GetAssociatedStoreProductsAsync(new string[] { "Durable" });
if (result.ExtendedError != null)
{
//System.Diagnostics.Debug.WriteLine("Something went wrong while getting the add-ons. " +
//"ExtendedError:" + result.ExtendedError);
var messageDialog = new MessageDialog("Qualcosa è andato storto durante il recupero dei componenti aggiuntivi. Errore: " + result.ExtendedError, "Avviso");
await messageDialog.ShowAsync();
return null;
}
// Look for the product that represents the subscription.
foreach (var item in result.Products)
{
StoreProduct product = item.Value;
if (product.StoreId == subscriptionStoreId)
{
return product;
}
}
//System.Diagnostics.Debug.WriteLine("The subscription was not found.");
var messageDialogNull = new MessageDialog("L'abbonamento non è stato trovato.", "Avviso");
await messageDialogNull.ShowAsync();
return null;
}
private async Task PromptUserToPurchaseAsync()
{
// Request a purchase of the subscription product. If a trial is available it will be offered
// to the customer. Otherwise, the non-trial SKU will be offered.
StorePurchaseResult result = await subscriptionStoreProduct.RequestPurchaseAsync();
// Capture the error message for the operation, if any.
string extendedError = string.Empty;
if (result.ExtendedError != null)
{
extendedError = result.ExtendedError.Message;
}
switch (result.Status)
{
case StorePurchaseStatus.Succeeded:
// Show a UI to acknowledge that the customer has purchased your subscription
// and unlock the features of the subscription.
Frame.Navigate(typeof(Accedi));
break;
case StorePurchaseStatus.NotPurchased:
//System.Diagnostics.Debug.WriteLine("The purchase did not complete. " +
//"The customer may have cancelled the purchase. ExtendedError: " + extendedError);
var messageDialog = new MessageDialog("L'acquisto non è stato completato o è stato annullato. Errore: " + result.ExtendedError, "Avviso");
await messageDialog.ShowAsync();
break;
case StorePurchaseStatus.ServerError:
case StorePurchaseStatus.NetworkError:
//System.Diagnostics.Debug.WriteLine("The purchase was unsuccessful due to a server or network error. " +
//"ExtendedError: " + extendedError);
var messageDialogServerNetworkError = new MessageDialog("L'acquisto non è andato a buon fine a causa di un errore del server o della rete. Errore: " + result.ExtendedError, "Avviso");
await messageDialogServerNetworkError.ShowAsync();
break;
case StorePurchaseStatus.AlreadyPurchased:
//System.Diagnostics.Debug.WriteLine("The customer already owns this subscription." +
//"ExtendedError: " + extendedError);
var messageDialogAlreadyPurchased = new MessageDialog("Il cliente possiede già questo abbonamento. Errore: " + result.ExtendedError, "Avviso");
await messageDialogAlreadyPurchased.ShowAsync();
break;
}
}
public async Task GetSubscriptionsInfo()
{
if (context == null)
{
context = StoreContext.GetDefault();
// If your app is a desktop app that uses the Desktop Bridge, you
// may need additional code to configure the StoreContext object.
// For more info, see https://aka.ms/storecontext-for-desktop.
}
// Subscription add-ons are Durable products.
string[] productKinds = { "Durable" };
List filterList = new List(productKinds);
StoreProductQueryResult queryResult =
await context.GetAssociatedStoreProductsAsync(productKinds);
if (queryResult.ExtendedError != null)
{
// The user may be offline or there might be some other server failure.
System.Diagnostics.Debug.WriteLine($"ExtendedError: {queryResult.ExtendedError.Message}");
return;
}
foreach (KeyValuePair item in queryResult.Products)
{
// Access the Store product info for the add-on.
StoreProduct product = item.Value;
// For each add-on, the subscription info is available in the SKU objects in the add-on.
foreach (StoreSku sku in product.Skus)
{
if (sku.IsSubscription)
{
// Use the sku.SubscriptionInfo property to get info about the subscription.
// For example, the following code gets the units and duration of the
// subscription billing period.
StoreDurationUnit billingPeriodUnit = sku.SubscriptionInfo.BillingPeriodUnit;
uint billingPeriod = sku.SubscriptionInfo.BillingPeriod;
tb_info.Text = "Tipologia: " + sku.Title.ToString() + Environment.NewLine;
tb_info.Text += "Descrizione: " + sku.Description.ToString() + Environment.NewLine;
tb_info.Text += "Periodo di fatturazione: " + sku.SubscriptionInfo.BillingPeriodUnit.ToString() + Environment.NewLine;
}
}
}
}
private async void btn_prosegui_Click(object sender, RoutedEventArgs e)
{
//CONTROLLO L'ABBONAMENTO
await SetupSubscriptionInfoAsync();
}
}
}
Nevertheless my app is not valid. In my opinion the Microosft certifiers drink during the certification process :))))
I'm really frustrated :(((((((((((((((((((((((((((((((
2 answers
Sort by: Most helpful
-
-
Gianfranco Percopo 16 Reputation points
2019-12-02T13:49:42.747+00:00 Finally passed certification. I love uwp platform :) Finally.... I'm happy