I love UWP Platform

Gianfranco Percopo 16 Reputation points
2019-11-30T10:57:35.243+00:00

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 :(((((((((((((((((((((((((((((((

Universal Windows Platform (UWP)
{count} vote

2 answers

Sort by: Most helpful
  1. Alberto T. Gomez 1 Reputation point
    2019-12-01T16:05:40.187+00:00

    Internet connection


  2. Gianfranco Percopo 16 Reputation points
    2019-12-02T13:49:42.747+00:00

    Finally passed certification. I love uwp platform :) Finally.... I'm happy