在Windows 10 UWP上的应用内购买问题

时间:2021-02-24 07:25:42

I'm trying to enable an in-app purchase item on my app (already on Windows 10 store), but I always receive the same error message when trying to buy this item:

我正在尝试在我的应用上(已经在Windows 10 store上)启用内购项,但是当我试图购买这个项目时,我总是会收到相同的错误信息:

在Windows 10 UWP上的应用内购买问题

This in-App Purchase item is no longer available in MyAppName

应用程序内的购买项在appmyname中不再可用

The code is fairly simple and just what the docs recommend:

代码相当简单,正是文档所推荐的:

var itemName = "app.advanced_items.full";
if (CurrentApp.LicenseInformation.ProductLicenses[itemName].IsActive) {
    return true;
}
var results = await CurrentApp.RequestProductPurchaseAsync(itemName);

if (results.Status == ProductPurchaseStatus.Succeeded ||
    results.Status == ProductPurchaseStatus.AlreadyPurchased) {
    return true;
} else { 
    return false;
}

More information:

更多信息:

  • I created and submited the in-app item to the store before building the package as the documentation told me
  • 在构建包之前,我创建并将应用程序项下到商店中,文档告诉我。
  • The name of the item is the same both on the store and the app (itemName on code)
  • 商店和应用程序上的项目名称都是相同的(代码上的项目名称)
  • I tried this before submitting to the store
  • 我在提交商店之前试过了。
  • I tried this after submitting to the store (My app is currently broken there! -- unable to buy the item)
  • 我在提交给商店后尝试了这个(我的应用程序现在在那里坏了!)——无法购买物品)

I suspect the problem might be related with the following:

我怀疑这个问题可能与下列情况有关:

  • The app display name (on Package.appxmanifest) is not the same app name on the store (The name I wanted was not available so I made it longer, but the app once installed will display the original name). This shorter name is the one in the error message...
  • 应用程序显示名(在Package.appxmanifest上)在商店上不是相同的应用程序名(我想要的名字是不可用的,所以我把它加长了,但是一旦安装应用程序就会显示原来的名字)。这个简短的名字是错误消息中的名字……

I changed the "display name" to the full name of the app, but the error was the same. I don't know if sending it to the store might change this (I and don't want to deploy another buggy version just to test this theory)

我将“显示名”更改为应用程序的全名,但错误是相同的。我不知道发送到商店是否会改变这个(我不想部署另一个bug版本来测试这个理论)

Extra: The only resources I found online about this issue were useless and related to Windows 8: link

额外提示:我在网上找到的关于这个问题的唯一资源是无用的和与Windows 8: link相关的

Suggestions?

建议吗?

6 个解决方案

#1


5  

After 2 months talking to Microsoft support they finally fixed something on their side and my IAP started working.

两个月后,他们终于在微软的支持下解决了问题,我的IAP开始工作。

I believe the fix was global, but if your IAP still do not work, contact them to republish it.

我相信修复是全球性的,但是如果你的IAP仍然不工作,联系他们重新发布它。

Below is an excerpt from the email they sent me:

以下是他们发给我的邮件摘录:

We have issued a republish for your IAPs in this app. This should correct the situation as soon as the process completes. You may want to check periodically over the next few hours to see if you are able to confirm the fix worked for you. Let me know what you see.

我们已经在这款app中为您的IAPs发布了一份重新发布。这应该可以在流程完成后立即纠正情况。您可能希望在接下来的几个小时内定期检查,看看是否能够确认修复对您有效。让我知道你看到了什么。

#2


4  

Please check with the productId of the IAP. I guess the one you mention in your code is different from the one in the store.

请与IAP的生产厂家联系。我猜你在代码中提到的那个和商店里的那个不同。

If its the same, I recommend to use the method LoadListingInformationAsync which returns the list of IAP's and then select the required IAP from that list. If there's a name mismatch then you wont be able to retrieve that IAP. So we'll be able to find its because of the naming problem. I have also added a sample code for that. Give a try.

如果是相同的,我建议使用LoadListingInformationAsync方法,该方法返回IAP的列表,然后从该列表中选择所需的IAP。如果名称不匹配,那么您将无法检索该IAP。因为命名问题,我们可以找到它。我还添加了一个示例代码。给一试。

        try
        {
            var listing = await CurrentApp.LoadListingInformationAsync();
            var iap = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "removeads");
            receipt = await CurrentApp.RequestProductPurchaseAsync(iap.Value.ProductId, true);
            if (CurrentApp.LicenseInformation.ProductLicenses[iap.Value.ProductId].IsActive)
            {
                CurrentApp.ReportProductFulfillment(iap.Value.ProductId);
                //your code after purchase is successful
            }
        }
        catch (Exception ex)
        {
            //exception 
        }

#3


1  

I believe the problem here is that you need to differentiate between testing and production. You cannot use production mode unless you are published in the store. See CurrentApp and CurrentAppSimulator.

我认为这里的问题是您需要区分测试和生产。除非在商店中发布,否则不能使用生产模式。看到CurrentApp和CurrentAppSimulator。

From the CurrentAppSimiulator page:

从CurrentAppSimiulator页面:

Remarks

讲话

Until the app has been listed in the Windows Store, the CurrentApp object won't work in the app. Use the CurrentAppSimulator to test your app's licensing and in-app products while you develop your app. After you test your app, and before you submit it to the Windows Store, you must replace the instances of CurrentAppSimulator with CurrentApp. Your app will fail certification if it uses CurrentAppSimulator.

直到应用程序窗口中列出的商店,CurrentApp对象不会在应用工作。使用CurrentAppSimulator测试您的应用程序的许可和应用产品开发你的应用时。你测试你的应用程序之后,在您提交到Windows存储之前,你必须用CurrentApp替换CurrentAppSimulator的实例。如果您的应用程序使用CurrentAppSimulator,那么它将无法通过认证。

Here is how I solve this in my app with a #define which I change for testing/production, and a proxy class that switches between CurrentApp and CurrentAppSimulator to make my other code much easier on the eyes.

下面是我如何在我的应用程序中使用#define来解决这个问题,我将在测试/生产中修改它,并使用一个代理类来在CurrentApp和CurrentAppSimulator之间切换,使我的其他代码看起来更容易。

App.xaml.cs, App()

App.xaml。cs,应用()

            //
            // configure in-app purchasing
            //
#if false
#warning WARNING: You are using CurrentAppProxy in TEST MODE!
            CurrentAppProxy.SetTestMode(true); // true for test, false for production
#else
            CurrentAppProxy.SetTestMode(false); // true for test, false for production

CurrentAppProxy.cs

CurrentAppProxy.cs

public static class CurrentAppProxy
{
    static bool? testmode = null;
    public static async void SetTestMode(bool mode)
    {
        testmode = mode;
        if (mode)
        {
            var file = await Package.Current.InstalledLocation.GetFileAsync("WindowsStoreProxy.xml");
            if (file != null)
            {
                await CurrentAppSimulator.ReloadSimulatorAsync(file);
            }
        }
    }

    public static LicenseInformation LicenseInformation
    {
        get
        {
            if (testmode == null) throw new NotSupportedException();
            else if (testmode.Value) return CurrentAppSimulator.LicenseInformation;
            else return CurrentApp.LicenseInformation;
        }
    }

    public static IAsyncOperation<IReadOnlyList<UnfulfilledConsumable>> GetUnfulfilledConsumablesAsync()
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.GetUnfulfilledConsumablesAsync();
        else return CurrentApp.GetUnfulfilledConsumablesAsync();
    }

    public static IAsyncOperation<ListingInformation> LoadListingInformationAsync()
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.LoadListingInformationAsync();
        else return CurrentApp.LoadListingInformationAsync();
    }

    public static IAsyncOperation<FulfillmentResult> ReportConsumableFulfillmentAsync(string productId, Guid transactionId)
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.ReportConsumableFulfillmentAsync(productId, transactionId);
        else return CurrentApp.ReportConsumableFulfillmentAsync(productId, transactionId);
    }

    public static IAsyncOperation<PurchaseResults> RequestProductPurchaseAsync(string productId)
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.RequestProductPurchaseAsync(productId);
        else return CurrentApp.RequestProductPurchaseAsync(productId);
    }
}

Usage in my app...

使用在我的应用程序…

    private async Task RefreshInAppOffers()
    {
        // in-app offers
        List<KeyValuePair<string, ProductListing>> products = null;
        UnfulfilledConsumable unfulfilledConsumable = null;

        InAppOffers.Children.Clear();

        try
        {
            var listinginfo = await CurrentAppProxy.LoadListingInformationAsync();
            products = listinginfo.ProductListings.ToList();
            products.Sort((p1, p2) => p1.Value.FormattedPrice.CompareTo(p2.Value.FormattedPrice));

CurrentAppProxy is they key here. If it works with the simulator, it should work with your production items. You just need to have all the other pieces in place for all the various conditions. Some testing is easiest to do in the debugger.

CurrentAppProxy就是这里的键。如果它与模拟器一起工作,它应该与您的产品项一起工作。你只需要在所有不同的条件下准备好所有其他的部分。在调试器中进行一些测试是最容易的。

#4


1  

I tried contacting Microsoft about this issue and they asked me to make the IAP unavailable and then make it available again. I must say it did not solve my issue, but if you want to give it a try, follow these steps:

我试着联系微软公司,他们要求我让IAP不可用,然后让它再次出现。我必须说这并不能解决我的问题,但是如果你想尝试一下,请遵循以下步骤:

  1. Create an update for the IAP
  2. 为IAP创建一个更新
  3. Under Distribution and Visibility set the IAP to Not available for purchase
  4. 在分销和能见度下,IAP无法购买。
  5. Submit the update
  6. 提交的更新
  7. Wait for update to publish
  8. 等待更新发布。
  9. Create a new update for IAP
  10. 为IAP创建一个新的更新
  11. Set Distribution and Visibility back to Available for purchase
  12. 将分布和可见性设置为可购买
  13. Submit the update
  14. 提交的更新
  15. Once this update publishes, retest the IAP
  16. 一旦更新发布,重新测试IAP

After that, they told me to try making the whole app unavailable to all countries and publish it. Then do the opposite. No success either...

在那之后,他们让我尝试让所有国家都无法使用整个应用程序,并将其发布。然后做相反的事情。没有成功…

#5


0  

i've got the same problem. In my situation the solution is to add all language description in IAP and then it's works fine

我也有同样的问题。在我的情况下,解决方案是在IAP中添加所有的语言描述,然后它就可以正常工作了。

#6


0  

I had similar issue with my new UWP app, "Midi Player". IAP was available for purchase on WP 8.1 right after certification and publishing but shows same error on W10M (Windows 10 Mobile) platform (I believe, all Windows 10 UWP apps has the same store). I've opened issue with Microsoft but they can't help me. Fortunately, the issue now is gone :) What I did:

我的新UWP应用“Midi Player”也有类似的问题。IAP在认证和发布后立即可以在WP 8.1上购买,但在W10M (Windows 10 Mobile)平台上显示了同样的错误(我相信,所有Windows 10 UWP应用程序都有相同的存储)。我和微软有争执,但他们帮不了我。幸运的是,现在的问题已经消失了:我所做的:

  • published initial app revision
  • 发表初步应用修订
  • created IAP
  • 创建IAP
  • tested IAP (works on WP8.1, not working on W10M)
  • 测试IAP(在WP8.1上工作,不工作于W10M)
  • I found that my Package.appxmanifest file was changed slightly (that string mp:PhoneIdentity PhoneProductId="7f32ab79-xxx-xxx-aff3-ce228745b36f" PhonePublisherId="00000000-0000-0000-0000-000000000000") after publishing
  • 我发现我的包裹。appxmanifest文件在发布后略有变化(该字符串mp:PhoneIdentity PhoneProductId="7f32ab79-xxx-xxx-aff3-ce228745b36f" PhonePublisherId=" 000000000000000000000000- 000000000000")
  • I changed version (minor number) and submitted new release with changed Package.appxmanifest
  • 我更改了版本(次要编号),并提交了带有更改的Package.appxmanifest的新版本
  • today, I checked IAP on W10M Lumia 950 and it works.
  • 今天,我在W10M Lumia 950上检查了IAP,它是有效的。

So, my conclusion:

所以,我的结论是:

  • you need to re-publish app after creating IAP
  • 创建IAP后需要重新发布app
  • you should wait for a little
  • 你应该等一会儿

#1


5  

After 2 months talking to Microsoft support they finally fixed something on their side and my IAP started working.

两个月后,他们终于在微软的支持下解决了问题,我的IAP开始工作。

I believe the fix was global, but if your IAP still do not work, contact them to republish it.

我相信修复是全球性的,但是如果你的IAP仍然不工作,联系他们重新发布它。

Below is an excerpt from the email they sent me:

以下是他们发给我的邮件摘录:

We have issued a republish for your IAPs in this app. This should correct the situation as soon as the process completes. You may want to check periodically over the next few hours to see if you are able to confirm the fix worked for you. Let me know what you see.

我们已经在这款app中为您的IAPs发布了一份重新发布。这应该可以在流程完成后立即纠正情况。您可能希望在接下来的几个小时内定期检查,看看是否能够确认修复对您有效。让我知道你看到了什么。

#2


4  

Please check with the productId of the IAP. I guess the one you mention in your code is different from the one in the store.

请与IAP的生产厂家联系。我猜你在代码中提到的那个和商店里的那个不同。

If its the same, I recommend to use the method LoadListingInformationAsync which returns the list of IAP's and then select the required IAP from that list. If there's a name mismatch then you wont be able to retrieve that IAP. So we'll be able to find its because of the naming problem. I have also added a sample code for that. Give a try.

如果是相同的,我建议使用LoadListingInformationAsync方法,该方法返回IAP的列表,然后从该列表中选择所需的IAP。如果名称不匹配,那么您将无法检索该IAP。因为命名问题,我们可以找到它。我还添加了一个示例代码。给一试。

        try
        {
            var listing = await CurrentApp.LoadListingInformationAsync();
            var iap = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "removeads");
            receipt = await CurrentApp.RequestProductPurchaseAsync(iap.Value.ProductId, true);
            if (CurrentApp.LicenseInformation.ProductLicenses[iap.Value.ProductId].IsActive)
            {
                CurrentApp.ReportProductFulfillment(iap.Value.ProductId);
                //your code after purchase is successful
            }
        }
        catch (Exception ex)
        {
            //exception 
        }

#3


1  

I believe the problem here is that you need to differentiate between testing and production. You cannot use production mode unless you are published in the store. See CurrentApp and CurrentAppSimulator.

我认为这里的问题是您需要区分测试和生产。除非在商店中发布,否则不能使用生产模式。看到CurrentApp和CurrentAppSimulator。

From the CurrentAppSimiulator page:

从CurrentAppSimiulator页面:

Remarks

讲话

Until the app has been listed in the Windows Store, the CurrentApp object won't work in the app. Use the CurrentAppSimulator to test your app's licensing and in-app products while you develop your app. After you test your app, and before you submit it to the Windows Store, you must replace the instances of CurrentAppSimulator with CurrentApp. Your app will fail certification if it uses CurrentAppSimulator.

直到应用程序窗口中列出的商店,CurrentApp对象不会在应用工作。使用CurrentAppSimulator测试您的应用程序的许可和应用产品开发你的应用时。你测试你的应用程序之后,在您提交到Windows存储之前,你必须用CurrentApp替换CurrentAppSimulator的实例。如果您的应用程序使用CurrentAppSimulator,那么它将无法通过认证。

Here is how I solve this in my app with a #define which I change for testing/production, and a proxy class that switches between CurrentApp and CurrentAppSimulator to make my other code much easier on the eyes.

下面是我如何在我的应用程序中使用#define来解决这个问题,我将在测试/生产中修改它,并使用一个代理类来在CurrentApp和CurrentAppSimulator之间切换,使我的其他代码看起来更容易。

App.xaml.cs, App()

App.xaml。cs,应用()

            //
            // configure in-app purchasing
            //
#if false
#warning WARNING: You are using CurrentAppProxy in TEST MODE!
            CurrentAppProxy.SetTestMode(true); // true for test, false for production
#else
            CurrentAppProxy.SetTestMode(false); // true for test, false for production

CurrentAppProxy.cs

CurrentAppProxy.cs

public static class CurrentAppProxy
{
    static bool? testmode = null;
    public static async void SetTestMode(bool mode)
    {
        testmode = mode;
        if (mode)
        {
            var file = await Package.Current.InstalledLocation.GetFileAsync("WindowsStoreProxy.xml");
            if (file != null)
            {
                await CurrentAppSimulator.ReloadSimulatorAsync(file);
            }
        }
    }

    public static LicenseInformation LicenseInformation
    {
        get
        {
            if (testmode == null) throw new NotSupportedException();
            else if (testmode.Value) return CurrentAppSimulator.LicenseInformation;
            else return CurrentApp.LicenseInformation;
        }
    }

    public static IAsyncOperation<IReadOnlyList<UnfulfilledConsumable>> GetUnfulfilledConsumablesAsync()
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.GetUnfulfilledConsumablesAsync();
        else return CurrentApp.GetUnfulfilledConsumablesAsync();
    }

    public static IAsyncOperation<ListingInformation> LoadListingInformationAsync()
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.LoadListingInformationAsync();
        else return CurrentApp.LoadListingInformationAsync();
    }

    public static IAsyncOperation<FulfillmentResult> ReportConsumableFulfillmentAsync(string productId, Guid transactionId)
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.ReportConsumableFulfillmentAsync(productId, transactionId);
        else return CurrentApp.ReportConsumableFulfillmentAsync(productId, transactionId);
    }

    public static IAsyncOperation<PurchaseResults> RequestProductPurchaseAsync(string productId)
    {
        if (testmode == null) throw new NotSupportedException();
        else if (testmode.Value) return CurrentAppSimulator.RequestProductPurchaseAsync(productId);
        else return CurrentApp.RequestProductPurchaseAsync(productId);
    }
}

Usage in my app...

使用在我的应用程序…

    private async Task RefreshInAppOffers()
    {
        // in-app offers
        List<KeyValuePair<string, ProductListing>> products = null;
        UnfulfilledConsumable unfulfilledConsumable = null;

        InAppOffers.Children.Clear();

        try
        {
            var listinginfo = await CurrentAppProxy.LoadListingInformationAsync();
            products = listinginfo.ProductListings.ToList();
            products.Sort((p1, p2) => p1.Value.FormattedPrice.CompareTo(p2.Value.FormattedPrice));

CurrentAppProxy is they key here. If it works with the simulator, it should work with your production items. You just need to have all the other pieces in place for all the various conditions. Some testing is easiest to do in the debugger.

CurrentAppProxy就是这里的键。如果它与模拟器一起工作,它应该与您的产品项一起工作。你只需要在所有不同的条件下准备好所有其他的部分。在调试器中进行一些测试是最容易的。

#4


1  

I tried contacting Microsoft about this issue and they asked me to make the IAP unavailable and then make it available again. I must say it did not solve my issue, but if you want to give it a try, follow these steps:

我试着联系微软公司,他们要求我让IAP不可用,然后让它再次出现。我必须说这并不能解决我的问题,但是如果你想尝试一下,请遵循以下步骤:

  1. Create an update for the IAP
  2. 为IAP创建一个更新
  3. Under Distribution and Visibility set the IAP to Not available for purchase
  4. 在分销和能见度下,IAP无法购买。
  5. Submit the update
  6. 提交的更新
  7. Wait for update to publish
  8. 等待更新发布。
  9. Create a new update for IAP
  10. 为IAP创建一个新的更新
  11. Set Distribution and Visibility back to Available for purchase
  12. 将分布和可见性设置为可购买
  13. Submit the update
  14. 提交的更新
  15. Once this update publishes, retest the IAP
  16. 一旦更新发布,重新测试IAP

After that, they told me to try making the whole app unavailable to all countries and publish it. Then do the opposite. No success either...

在那之后,他们让我尝试让所有国家都无法使用整个应用程序,并将其发布。然后做相反的事情。没有成功…

#5


0  

i've got the same problem. In my situation the solution is to add all language description in IAP and then it's works fine

我也有同样的问题。在我的情况下,解决方案是在IAP中添加所有的语言描述,然后它就可以正常工作了。

#6


0  

I had similar issue with my new UWP app, "Midi Player". IAP was available for purchase on WP 8.1 right after certification and publishing but shows same error on W10M (Windows 10 Mobile) platform (I believe, all Windows 10 UWP apps has the same store). I've opened issue with Microsoft but they can't help me. Fortunately, the issue now is gone :) What I did:

我的新UWP应用“Midi Player”也有类似的问题。IAP在认证和发布后立即可以在WP 8.1上购买,但在W10M (Windows 10 Mobile)平台上显示了同样的错误(我相信,所有Windows 10 UWP应用程序都有相同的存储)。我和微软有争执,但他们帮不了我。幸运的是,现在的问题已经消失了:我所做的:

  • published initial app revision
  • 发表初步应用修订
  • created IAP
  • 创建IAP
  • tested IAP (works on WP8.1, not working on W10M)
  • 测试IAP(在WP8.1上工作,不工作于W10M)
  • I found that my Package.appxmanifest file was changed slightly (that string mp:PhoneIdentity PhoneProductId="7f32ab79-xxx-xxx-aff3-ce228745b36f" PhonePublisherId="00000000-0000-0000-0000-000000000000") after publishing
  • 我发现我的包裹。appxmanifest文件在发布后略有变化(该字符串mp:PhoneIdentity PhoneProductId="7f32ab79-xxx-xxx-aff3-ce228745b36f" PhonePublisherId=" 000000000000000000000000- 000000000000")
  • I changed version (minor number) and submitted new release with changed Package.appxmanifest
  • 我更改了版本(次要编号),并提交了带有更改的Package.appxmanifest的新版本
  • today, I checked IAP on W10M Lumia 950 and it works.
  • 今天,我在W10M Lumia 950上检查了IAP,它是有效的。

So, my conclusion:

所以,我的结论是:

  • you need to re-publish app after creating IAP
  • 创建IAP后需要重新发布app
  • you should wait for a little
  • 你应该等一会儿