2022年11月13日日曜日

サブスクリプション βテスター募集

 サブスクリプションのβテスターを募集します。募集完了しました

テスターの条件は、

■マイクロソフトアカウントがあること

■マイクロソフトアカウントにクレジットカードが登録されていること

■サブスクリプションのテストにご参加頂き2ヶ月分(サブスクリプション2ヶ月分@480x2)をご負担頂けること

です。


<お礼>

テスト後(2ヶ月)にサブスクリプションをキャンセルして頂きます。

代わりに、買い切りライセンス(永続ライセンス@50000相当)をプレゼントします。

参加頂ける方はサポートまでご連絡ください。(定員となり次第、締め切りします。)

下記は、サブスクリプション購入の様子です。実際に以下のような感じで操作しサブスクリプションを購入して頂きます。

現在は、公開されていませんが、βテスターには、URLをご案内します。

入手をクリックします。ダウンロードが始まります。2-3分かかるようです。



開くをクリックします。
サブスクリプションの説明が表示されます。この表示はマイクロソフトアカウントに
接続されていれば、一回だけ表示され、以降は表示されないようです。(ダイアログを出力しているのはスケジュールナースですが..)
とりあえず、いいえをクリックします。

購入しなかったので、次の表示となります。終了します。


再度、起動します。今度は「はい」をクリックします。
サブスクリプションは、1ヶ月毎と1年毎があります。「はい」で一ヶ月を選択します。
ここからは、スケジュールナースではなくストアAPIが出力しているダイアログになります。マイクロソフトアカウント名を入力します。
アカウントのパスワードを入力します。
次へをクリックします。
私の場合、Amazonでプレペイド@1500を購入しており、それを使いたかったのですが、下の表示では、切れた場合の処置が必須となっており、結局クレジットカードが必要となるようです。

申し込むをクリックします。
申し込むをクリックします。
成功すると「ご購入ありがとうございます。」が表示されます。これは、スケジュールナースがストアAPIの結果より出力しています。
いったん終了し再起動します。
通常は、ここより起動します。
以上が、サブスクリプション購入に関する手続きです。
購入すると、マイクロソフトよりアカウントメールアドレスに以下のようなメールが届きます。
****
サブスクリプション毎月 の無料試用版へようこそ

サブスクリプション毎月 をお試しいただき、ありがとうございます。ご利用に感謝いたします。
サブスクリプション毎月 の試用版は Sunday, November 13, 2022 から開始し、8 日間無料です。
Sunday, November 20, 2022 以降、1 月 ごとに Microsoft account balance 宛で JPY 480.00 税金を含む を 課金されます。
この価格に変更がある場合は、事前にお知らせいたします。
....
****

<課金される前に無効にする処理>
試行期間だけで、止める場合の処理です。

マイクロソフトアカウント上で、
「定期請求を無効にする」をクリックします。

確認のダイアログが出現します。
選択すると、次のようなダイアログとなります。
定期請求オフ後、試行期間が残っていれば、操作は、試用期間一杯まで可能です。
試用期間が過ぎた後起動すると、サブスクリプション購入を促すダイアログが出現します。


いいえ、の場合次のダイアログが出て終了となってしまいます。






以下は、上のサブスクリプションに関わるスケジュールナースのC#コードです。
	{
            //GetContext();
            Debug.Print("Hello");
           context = StoreContext.GetDefault();
            IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)context;
            initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
            //context.OfflineLicensesChanged += context_OfflineLicensesChanged;
            //Task task=SetupSubscriptionInfoAsync();//タスク引き取り待ちで抜ける
            //AsyncMethod();
            CheckLicenseState();
            //SetupSubscriptionInfoAsync();
            //if (!has_license)
            //{
            //    this.Close();
            //}
}
      private StoreContext context = null;
        private StoreProduct subscriptionStoreProductMonth;
        private StoreProduct subscriptionStoreProductYear;
        private StoreAppLicense license;
#if STORE
        private bool has_license = false;//NOV032022
#endif
        private async Task PurchaseNonSubscLicense()
        {
            // Get app store product details
            StoreProductResult productResult = await context.GetStoreProductForCurrentAppAsync();
            if (productResult.ExtendedError != null)
            {
                // The user may be offline or there might be some other server failure
                //Debug.Print($"ExtendedError: {productResult.ExtendedError.Message}", NotifyType.ErrorMessage);
                return;
            }

            //rootPage.NotifyUser("Buying the full license...", NotifyType.StatusMessage);
            //StoreAppLicense license = await storeContext.GetAppLicenseAsync();
            //if (license.IsTrial)
            {
                StorePurchaseResult result = await productResult.Product.RequestPurchaseAsync();
                if (result.ExtendedError != null)
                {
                    //rootPage.NotifyUser($"Purchase failed: ExtendedError: {result.ExtendedError.Message}", NotifyType.ErrorMessage);
                    return;
                }

                switch (result.Status)
                {
                    case StorePurchaseStatus.AlreadyPurchased:
                        has_license = true;
                        Debug.Print("StorePurchaseStatus.AlreadyPurchased\n");
                        //rootPage.NotifyUser($"You already bought this app and have a fully-licensed version.", NotifyType.ErrorMessage);
                        break;

                    case StorePurchaseStatus.Succeeded:
                        Debug.Print("StorePurchaseStatus.Succeeded\n");
                        has_license = true;
                        // License will refresh automatically using the StoreContext.OfflineLicensesChanged event
                        break;

                    case StorePurchaseStatus.NotPurchased:
                        Debug.Print("StorePurchaseStatus.NotPurchased\n");
                        //rootPage.NotifyUser("Product was not purchased, it may have been canceled.", NotifyType.ErrorMessage);
                        break;

                    case StorePurchaseStatus.NetworkError:
                        Debug.Print("StorePurchaseStatus.NetworkError\n");
                        //rootPage.NotifyUser("Product was not purchased due to a Network Error.", NotifyType.ErrorMessage);
                        break;

                    case StorePurchaseStatus.ServerError:
                        Debug.Print("StorePurchaseStatus.ServerError\n");
                        //rootPage.NotifyUser("Product was not purchased due to a Server Error.", NotifyType.ErrorMessage);
                        break;

                    default:
                        Debug.Print("StorePurchaseStatus.default\n");
                        //rootPage.NotifyUser("Product was not purchased due to an Unknown Error.", NotifyType.ErrorMessage);
                        break;
                }
            }
            
        }
    



    private async Task PromptUserToPurchaseAsync(StoreProduct product)
        {
            // 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.
            Debug.Print("RequestPurchaseAsync");
            StorePurchaseResult result = await product.RequestPurchaseAsync();

            // Capture the error message for the operation, if any.
            string extendedError = string.Empty;
            if (result.ExtendedError != null)
            {
                extendedError = result.ExtendedError.Message;
            }
            string stm = extendedError+" ";
            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. 
                    has_license = true;
                    stm += rm.GetString("thank_you");

                    break;

                case StorePurchaseStatus.NotPurchased:
                    if (!has_license)
                    {
                        stm += rm.GetString("see_you_again");
                    }
                    has_license = false;
                    
                    System.Diagnostics.Debug.WriteLine("The purchase did not complete. " +
                        "The customer may have cancelled the purchase. ExtendedError: " + extendedError);
                    break;

                case StorePurchaseStatus.ServerError:
                case StorePurchaseStatus.NetworkError:
                    if (!has_license)
                    {
                        has_license = false;
                    }
                    stm += rm.GetString("server_error");
                    System.Diagnostics.Debug.WriteLine("The purchase was unsuccessful due to a server or network error. " +
                        "ExtendedError: " + extendedError);
                    break;

                case StorePurchaseStatus.AlreadyPurchased:
                    has_license = true;
                    stm += rm.GetString("already_puchased");
                    System.Diagnostics.Debug.WriteLine("The customer already owns this subscription." +
                            "ExtendedError: " + extendedError);
                    break;
            }
            MessageBox.Show(stm);

        }
        public string get_date_info(StoreDurationUnit u, uint billingPeriod)
        {
            string s = "";
            s += billingPeriod.ToString();
            switch (u)
            {
                case (StoreDurationUnit.Minute): s += rm.GetString("Minute");break;
                case (StoreDurationUnit.Hour): s += rm.GetString("Hour");break;
                case (StoreDurationUnit.Day): s += rm.GetString("Day");break;
                case (StoreDurationUnit.Week): s += rm.GetString("Weeks");break;
                case (StoreDurationUnit.Month): s += rm.GetString("Month");break;
                case (StoreDurationUnit.Year): s += rm.GetString("Year");break;
                
            }
            return s;
        }
        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 null;
            }
            string stm = "";
            foreach (KeyValuePair item in queryResult.Products)
            {
                // Access the Store product info for the add-on.
               
                
                StoreProduct product = item.Value;
                //subscriptionStoreProduct = product;//productを保存する。

                string store_id = product.StoreId;
                string store_title = product.Title;
                string store_price = product.Price.FormattedPrice;

                stm += store_id +" ";
                stm += store_title + " ";
                stm += store_price + " ";
                // 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;
                        if (billingPeriodUnit == StoreDurationUnit.Year)
                        {
                            subscriptionStoreProductYear = product;

                        }else if (billingPeriodUnit == StoreDurationUnit.Month)
                        {
                            subscriptionStoreProductMonth = product;
                        }else
                        {
                            Debug.Assert(false);
                        }
                        uint billingPeriod = sku.SubscriptionInfo.BillingPeriod;
                        stm += rm.GetString("subscription") + " ";
                        stm +=get_date_info(billingPeriodUnit,billingPeriod );
                    }
                    if (sku.IsTrial)
                    {
                        stm += rm.GetString("trial");
                        
                    }
                }
                stm += "\n";
            }
            Debug.Print(stm);
            //MessageBox.Show(stm);
            return queryResult;
        }
        private async Task CheckLicenseState()
        {
            //GetContext();
            Debug.Print("CheckLicenseState\n");
            StoreProductQueryResult sresult = await GetSubscriptionsInfo();
            if (subscriptionStoreProductYear==null && subscriptionStoreProductMonth==null)//sresult == null)//NonSubscription
            {
                Debug.Print("NonSubscription\n");
                StoreAppLicense appLicense = await context.GetAppLicenseAsync();
                if (appLicense != null)
                {
                    if (!appLicense.IsActive)
                    {
                        Debug.Print("!appLicense.IsActive\n");
                        await PurchaseNonSubscLicense();
                    }
                    else
                    {
                        Debug.Print("appLicense.IsActive\n");
                        has_license = true;
                    }
                }else
                {
                    Debug.Print("no license is active.\n");
                    
                }
            }else
            {
                Debug.Print("CheckSubscriptionAddonStatusesAsync\n");
                await CheckSubscriptionAddonStatusesAsync();
                if (!has_license)
                {
                    Debug.Print("purchase_subscription\n");
                    await purchase_subscription();
                }

            }
            if (!has_license)
            {
                MessageBox.Show(rm.GetString("no_license_detected"));
                this.Close();
            }
        }


        private async Task purchase_subscription()
        {

            //Dialog サブスクリプションを購入しますか
            //Yes/No
            //Dialog サブスクリプションは1か月と1年があります。1か月を購入しますか?
            //Yes/No/Cancel
            //   
            DialogResult result = MessageBox.Show(rm.GetString("purchase_subscription_q"), rm.GetString("purchase_subscription"),  MessageBoxButtons.YesNo);
            Debug.Print(rm.GetString("purchase_subscription_q"));


            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                

                DialogResult result2 = MessageBox.Show(rm.GetString("purchase_subscription_which"), rm.GetString("purchase_subscription"), MessageBoxButtons.YesNoCancel);
                Debug.Print(rm.GetString("purchase_subscription_which"));
                if (result2 == System.Windows.Forms.DialogResult.Yes)
                {//一か月購入
                    Debug.Print("一か月購入");
                    await PromptUserToPurchaseAsync(subscriptionStoreProductMonth);
                }
                else if (result2 == System.Windows.Forms.DialogResult.No)
                {//一年購入
                    Debug.Print("一年購入");
                    await PromptUserToPurchaseAsync(subscriptionStoreProductYear);


                }
            }
        }
        public enum LicenseStatus
        {
            Unknown = 0,
            Trial,
            Full
        }
        public async Task CheckSubscriptionAddonStatusesAsync()
        {
            //_context ??= StoreContext.GetDefault();
            //GetContext();

            StoreProductQueryResult queryResult = await context.GetUserCollectionAsync(new[] { "Durable" });
            if (queryResult.ExtendedError != null)
            {
                MessageBox.Show(rm.GetString("trial_requires_subscription"));
                return;//ADDON はあって登録subscriptionはない
            }
            //    throw queryResult.ExtendedError;

            foreach (KeyValuePair pair in queryResult.Products)
            {
                StoreSku sku = pair.Value.Skus.FirstOrDefault();
                
                StoreCollectionData data = sku?.CollectionData;
                if (data != null)
                {
                    has_license = true;
                    
                    LicenseStatus status = data.IsTrial ? LicenseStatus.Trial : LicenseStatus.Full;
                    DateTimeOffset startDate = data.StartDate;
                    bool isAutoRenewal = IsAutoRenewal(data.ExtendedJsonData);

                    Debug.WriteLine($"Store ID ------- {pair.Key}");
                    Debug.WriteLine($"License status - {status}");
                    Debug.WriteLine($"Start date ----- {startDate:yyyy/MM/dd}");
                    Debug.WriteLine($"Auto renewal --- {isAutoRenewal}");
                }
            }
        }

        private  bool IsAutoRenewal(string json)
        {
            if (string.IsNullOrEmpty(json))
                return false;

            // For this JSON value, see:
            // https://docs.microsoft.com/en-us/windows/uwp/monetize/data-schemas-for-store-products
            var pattern = new Regex(@"""autoRenew"":(?true|false)", RegexOptions.IgnoreCase);
            var match = pattern.Match(json);
            return match.Success
                && bool.TryParse(match.Groups["value"].Value, out bool value)
                && value;
        }

0 件のコメント:

コメントを投稿