【问题标题】:In-App purchase trouble on Windows 10 UWPWindows 10 UWP 上的应用内购买问题
【发布时间】:2016-03-27 21:52:06
【问题描述】:

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

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 相关:link

建议?

【问题讨论】:

  • 我有一个消耗品显示为 IAPs-premium 并且标签是高级的,我使用的密钥也是高级的。所以可能使用点和其他符号在某个地方有错误,谁知道
  • @JuanPabloGarciaCoello 如果我能在将应用程序提交到商店之前进行可靠的测试...我相信商店会更改包以包含应用内购买信息
  • 在我的情况下,在 IAP 项目认证后的几天内显示了“选择另一个项目”消息。但后来,错误信息消失了。
  • (await CurrentApp.LoadListingInformationAsync()).ProductListings 中有什么?
  • @gregkalapos 我不知道这是否应该发生,但每次我尝试为商店生成应用程序包时,它都会让我在“选择应用程序名称”对话框中选择我的应用程序并显示“Windows 应用商店中的包标识”为无。可能是店里有问题? -- 当我打开仪表板上的“App Identity”链接时,它会正确显示“Package/Identity/Name”项

标签: c# in-app-purchase windows-10 win-universal-app uwp


【解决方案1】:

在与 Microsoft 支持人员交谈 2 个月后,他们终于解决了一些问题,我的 IAP 开始工作了。

我相信修复是全球性的,但如果您的 IAP 仍然无法正常工作,请联系他们重新发布。

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

我们已在此应用中重新发布您的 IAP。这应该 过程完成后立即纠正这种情况。你可能想要 在接下来的几个小时内定期检查,看看你是否能够 确认修复对您有效。让我知道你看到了什么。

【讨论】:

  • 最后 :) 问题不在于代码 :P
  • 是的,这是 MS 的问题,新应用仍然有空的 ProductLicenses 集合,但 ProductListing 包含产品,并且新应用在 WinPhone 商店应用中查看时没有图标和屏幕截图。
【解决方案2】:

请检查 IAP 的 productId。我猜你在代码中提到的那个和商店里的不一样。

如果相同,我建议使用返回 IAP 列表的方法 LoadListingInformationAsync,然后从该列表中选择所需的 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 项目,所有这些项目都标记为已发布从几天前开始。然而我收到一个空对象
  • 您是在新仪表板中创建 IAP 还是使用在旧仪表板中创建的 IAP。如果它是旧仪表板,则更新 IAP 并将其设置为可用于所有可用市场。查看 MSDN ...似乎很多人都遇到了这个问题。 original MSDN post
  • 我在新仪表板上创建
  • :(请在解决此问题后发布答案:(
  • 我还是有同样的问题。不知何故,我的应用程序没有在商店搜索中列出...我相信 Windows 商店中存在错误...
【解决方案3】:

我认为这里的问题是您需要区分测试和生产。除非您在商店中发布,否则您无法使用生产模式。见CurrentAppCurrentAppSimulator

来自CurrentAppSimiulator 页面:

备注

在应用程序在 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 是这里的关键。如果它适用于模拟器,它应该适用于您的生产项目。您只需要为所有各种条件准备好所有其他部分。在调试器中进行一些测试是最容易的。

【讨论】:

  • 事情是这样的。我不能在生产中使用CurrentApp。很难相信即使我的应用程序已经发布,我也只能使用 CurrentAppSimulator。甚至我在商店中发布的那个与 CurrentApp 的行为方式相同
【解决方案4】:

我尝试就此问题与 Microsoft 联系,他们要求我将 IAP 设为不可用,然后再使其可用。 我必须说它没有解决我的问题,但如果您想尝试一下,请按照以下步骤操作:

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

之后,他们告诉我尝试让所有国家/地区都无法使用整个应用并发布它。然后做相反的事情。也没有成功...

【讨论】:

    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      我的新 UWP 应用“Midi Player”也有类似问题。 IAP 可在认证和发布后立即在 WP 8.1 上购买,但在 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(所有时间)后发布了应用程序并等待了两周...... :(
      • 对此很抱歉;您是否尝试联系商店的客户支持? MS 商店有点问题,我仍然有几个未解决的问题(并且没有希望解决,因为支持非常不专业)
      • 是的,那里的支持非常不专业......我根据我的经验发布了answer here
      猜你喜欢
      • 2016-06-21
      • 1970-01-01
      • 2016-03-09
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多