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

14

我正在尝试在我的应用程序中启用一个应用内购买项目(已经在Windows 10商店上),但是每当我尝试购买此项目时,我总是收到相同的错误消息:

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

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

代码非常简单,就是文档建议的内容:

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;
}

更多信息:

  • 按照文档的要求,我在构建包之前创建并提交了应用内物品
  • 该物品的名称在商店和应用中是相同的(代码中的itemName
  • 我在提交到商店之前尝试过这种方法
  • 我在提交到商店之后尝试过这种方法(我的应用目前无法正常运行!--无法购买该项目)

我怀疑问题可能与以下相关:

  • 应用程序显示名称(在Package.appxmanifest上)与商店上的应用程序名称不同(我想要的名称不可用,所以我将其设置为更长的名称,但安装后应用将显示原始名称)。这个较短的名称是错误消息中的名称...

我已将“显示名称”更改为应用程序的完整名称,但出现了相同的错误。我不知道将其发送到商店是否会更改此情况(我不想部署另一个带有漏洞的版本来测试这个理论)

额外信息: 我在网上找到的关于这个问题的唯一资源都是无用的,并且与Windows 8有关:链接

有什么建议吗?


1
我有一个可消耗的物品,显示为IAPs-premium,标签为premium,我使用的密钥也是premium。因此,在某个地方可能存在使用点和其他符号的错误,谁知道呢。 - Juan Pablo Garcia Coello
1
@JuanPabloGarciaCoello 如果我能在提交应用程序到商店之前可靠地测试它就好了... 我相信商店会更改包以包含应用内购买信息。 - JBernardo
@gregkalapos 它返回一个空的IReadOnlyDictionary。这个应该在 Visual Studio 上应用程序上工作吗(我的意思是,不是在应用商店上)? - JBernardo
这是一个非常好的问题,我还没有找到关于这个问题的文档。但我可以告诉你的是,我有一个在商店中使用IAP的应用程序(一切正常),当我从VS中使用它(例如在开发下一个功能时等),我可以看到所有我的IAP在列表中,同时我正在使用VS进行调试。 - gregkalapos
1
@gregkalapos 我不知道这是否应该发生,但每次我尝试为商店生成应用程序包时,它都会让我在“选择应用程序名称”对话框中选择我的应用程序,并显示“Windows Store中的包标识”为None。这可能是商店的问题吗?--当我在我的仪表板上打开“应用程序标识”链接时,它正确显示了“包/标识/名称”项。 - JBernardo
显示剩余3条评论
6个回答

5
经过两个月与 Microsoft 技术支持的沟通,他们终于在他们的系统上修复了一些问题,我的应用内购买功能开始正常工作了。
我相信这次修复是全局性的,但如果您的应用内购买仍然无法正常工作,请与 Microsoft 联系以重新发布它。
以下是他们发给我的电子邮件摘录:
“我们已经为您的应用内购买商品发布了重新发布。一旦该过程完成,情况就会得到纠正。您可能想在接下来的几个小时内定期检查以确认修复是否有效。请告诉我您看到了什么。”

终于 :) 问题不是代码的问题 :P - Razor
是的,这是一个微软的问题,新应用程序仍然具有空的ProductLicenses集合,但ProductListing包含产品,在WinPhone商店应用程序中查看时,新应用程序没有图标和截图。 - f14shm4n

4
请检查IAP的productId。我猜您在代码中提到的productId与商店中的不同。
如果是相同的,我建议使用方法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 
        }

问题是,就像我在上面的评论中写的那样,我的“ProductListings”始终是一个空的“IReadOnlyDictionary”... 我的仪表板上有3个IAP项目,它们都标记为发布了几天。然而,我收到了一个空对象。 - JBernardo
你在新的仪表板中创建了IAP吗?还是使用旧的仪表板中创建的?如果是旧的仪表板,请更新IAP并将其设置为所有可用市场。查看MSDN...似乎许多人都遇到了这个问题。原始MSDN帖子 - Razor
我创建了新的仪表板。 - JBernardo
请在修复后发布答案 :( - Razor
我仍然遇到同样的问题。不知何故,我的应用程序没有出现在商店搜索列表中... 我相信Windows商店上有一个错误... - JBernardo
请重新提交您的应用程序,然后再尝试。 - Razor

1
我认为这里的问题在于你需要区分测试和生产环境。除非你已经发布到商店,否则不能使用生产模式。请参阅 CurrentAppCurrentAppSimulator
CurrentAppSimulator 页面上可以看到:
备注
在应用程序被列在 Windows 商店之前,CurrentApp 对象将无法在应用程序中工作。在开发应用程序时,请使用 CurrentAppSimulator 测试您的应用程序许可证和应用内产品。在测试应用程序之后,并在提交到 Windows 商店之前,您必须将 CurrentAppSimulator 的实例替换为 CurrentApp。如果应用程序使用 CurrentAppSimulator,则应用程序将无法通过认证。
以下是我在我的应用程序中使用的 #define 解决此问题的方法,我根据测试/生产更改它,并使用一个代理类在 CurrentApp 和 CurrentAppSimulator 之间切换,以使我的其他代码更容易阅读。
App.xaml.cs, App()
            //
            // 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

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);
    }
}

在我的应用程序中的使用...
    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 是关键。如果它在模拟器上运行正常,那么它应该可以与您的生产项目一起使用。您只需为各种条件准备好所有其他组件即可。一些测试最容易在调试器中进行。


1
问题是,我不能在生产环境中使用“CurrentApp”。很难相信即使我的应用程序已经发布,我仍然只能使用“CurrentAppSimulator”。即使我在商店发布的应用程序也以同样的方式使用“CurrentApp”。 - JBernardo

1

我曾尝试联系微软解决这个问题,他们建议我将IAP设置为不可用,然后再重新设置为可用。 但我必须说这并没有解决我的问题,但如果您想尝试,请按照以下步骤操作:

  1. 创建IAP的更新
  2. 在“分发和可见性”下,将IAP设置为不可购买
  3. 提交更新
  4. 等待更新发布
  5. 创建IAP的新更新
  6. 将“分发和可见性”设置回“可购买”
  7. 提交更新
  8. 更新发布后,重新测试IAP

之后,他们告诉我尝试将整个应用程序对所有国家都设置为不可用,然后再发布。然而也没有成功...


0

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


0

我在我的新UWP应用程序“Midi Player”中遇到了类似的问题。在WP 8.1认证和发布后,IAP可以购买,但在W10M(Windows 10 Mobile)平台上显示相同的错误(我相信所有Windows 10 UWP应用程序都有相同的商店)。

我已经向Microsoft提出了问题,但他们无法帮助我。幸运的是,这个问题现在已经解决了 :) 我所做的:

  • 发布初始应用程序修订版
  • 创建IAP
  • 测试IAP(在WP8.1上工作,在W10M上不工作)
  • 我发现我的Package.appxmanifest文件在发布后略有改变(那个字符串mp:PhoneIdentity PhoneProductId="7f32ab79-xxx-xxx-aff3-ce228745b36f" PhonePublisherId="00000000-0000-0000-0000-000000000000"
  • 我更改了版本(次要编号),并提交了具有更改的Package.appxmanifest的新版本
  • 今天,我在W10M Lumia 950上检查了IAP,它可以工作。

所以,我的结论:

  • 创建IAP后,您需要重新发布应用程序。
  • 您应该稍等一会儿。

我在创建IAP(所有时间)后发布了应用程序,并等待了两个星期... :( - JBernardo
抱歉,你尝试联系商店的客户支持了吗?微软商店有点不稳定,我还有几个未解决的问题(而且没有希望解决,因为支持非常不专业)。 - SeNS
是的,支持那里非常不专业... 我在这里发布了一个答案,分享我的经验。 - JBernardo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接