我使用了Unity“购买者脚本”(在Unity的IAP示例中)测试IAP,但它们在测试期间不会在手机上初始化,即使它们确实初始化并传入编辑器。我知道Unity编辑器总是通过IAP,因此这意味着我没有在Apple方面做任何步骤。iTunes Connect声明IAP必须与应用程序更新一起提交,所以我不知道如何在iTunes Connect上单独创建IAP进行测试。有人可以帮助我了解我从这里去能够初始化和使用IAP?所有的帮助是非常感谢。
注意:这是一个不包含IAP的应用程序的更新。此外,我已经确保我的产品ID与我的脚本中的ID相匹配。
总结:
- IAP在Unity编辑器中工作,而不是iPhone
1.我在itunes connect上创建了IAP,它有一个与我的脚本匹配的产品ID,这是Unity提供的“买方脚本”(如下图所示:https://unity3d.com/learn/tutorials/topics/analytics/integrating-unity-iap-your-game)
1.购买初始化时出错,正在失败。
采购商代码:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
// Placing the Purchaser class in the CompleteProject namespace allows it to interact with ScoreManager, one of the existing Survival Shooter scripts.
//namespace CompleteProject
//{
// Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing.
public class Purchaser : MonoBehaviour, IStoreListener
{
private static IStoreController m_StoreController; // Reference to the Purchasing system.
private static IExtensionProvider m_StoreExtensionProvider; // Reference to store-specific Purchasing subsystems.
// Product identifiers for all products capable of being purchased: "convenience" general identifiers for use with Purchasing, and their store-specific identifier counterparts
// for use with and outside of Unity Purchasing. Define store-specific identifiers also on each platform's publisher dashboard (iTunes Connect, Google Play Developer Console, etc.)
private static string kProductIDConsumable = "RyanCbuy100G";
private static string kProductIDConsumable2 = "RyanCbuy200G"; // General handle for the consumable product.
private static string kProductIDConsumable3 = "RyanCbuy300G";
private static string kProductIDConsumable4 = "RyanCbuy400G";
private static string kProductNameAppleConsumable = "RyanCbuy100G"; // Apple App Store identifier for the consumable product.
private static string kProductNameAppleConsumable2 = "RyanCbuy200G"; // Apple App Store identifier for the consumable product.
private static string kProductNameAppleConsumable3 = "RyanCbuy300G";
private static string kProductNameAppleConsumable4 = "RyanCbuy400G";
void Start()
{
// If we haven't set up the Unity Purchasing reference
if (m_StoreController == null)
{
// Begin to configure our connection to Purchasing
InitializePurchasing();
}
}
public void InitializePurchasing()
{
// If we have already connected to Purchasing ...
if (IsInitialized())
{
// ... we are done here.
return;
}
// Create a builder, first passing in a suite of Unity provided stores.
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
// Add a product to sell / restore by way of its identifier, associating the general identifier with its store-specific identifiers.
builder.AddProduct(kProductIDConsumable, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable, AppleAppStore.Name },});// Continue adding the non-consumable product.
builder.AddProduct(kProductIDConsumable2, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable2, AppleAppStore.Name },});// Continue adding the non-consumable product.
builder.AddProduct(kProductIDConsumable3, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable3, AppleAppStore.Name },});// Continue adding the non-consumable product.
builder.AddProduct(kProductIDConsumable4, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable4, AppleAppStore.Name },});// Continue adding the non-consumable product.
// Kick off the remainder of the set-up with an asynchrounous call, passing the configuration and this class' instance. Expect a response either in OnInitialized or OnInitializeFailed.
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
// Only say we are initialized if both the Purchasing references are set.
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyConsumable()
{
// Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable);
}
public void BuyConsumable2()
{
// Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable2);
}
public void BuyConsumable3()
{
// Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable3);
}
public void BuyConsumable4()
{
// Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable4);
}
void BuyProductID(string productId)
{
// If the stores throw an unexpected exception, use try..catch to protect my logic here.
try
{
// If Purchasing has been initialized ...
if (IsInitialized())
{
// ... look up the Product reference with the general product identifier and the Purchasing system's products collection.
Product product = m_StoreController.products.WithID(productId);
// If the look up found a product for this device's store and that product is ready to be sold ...
if (product != null && product.availableToPurchase)
{
Debug.Log (string.Format("Purchasing product asychronously: '{0}'", product.definition.id));// ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
m_StoreController.InitiatePurchase(product);
}
// Otherwise ...
else
{
// ... report the product look-up failure situation
Debug.Log ("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
// Otherwise ...
else
{
// ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or retrying initiailization.
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
// Complete the unexpected exception handling ...
catch (Exception e)
{
// ... by reporting any unexpected exception for later diagnosis.
Debug.Log ("BuyProductID: FAIL. Exception during purchase. " + e);
}
}
// Restore purchases previously made by this customer. Some platforms automatically restore purchases. Apple currently requires explicit purchase restoration for IAP.
public void RestorePurchases()
{
// If Purchasing has not yet been set up ...
if (!IsInitialized())
{
// ... report the situation and stop restoring. Consider either waiting longer, or retrying initialization.
Debug.Log("RestorePurchases FAIL. Not initialized.");
return;
}
// If we are running on an Apple device ...
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.OSXPlayer)
{
// ... begin restoring purchases
Debug.Log("RestorePurchases started ...");
// Fetch the Apple store-specific subsystem.
var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
// Begin the asynchronous process of restoring purchases. Expect a confirmation response in the Action<bool> below, and ProcessPurchase if there are previously purchased products to restore.
apple.RestoreTransactions((result) => {
// The first phase of restoration. If no more responses are received on ProcessPurchase then no purchases are available to be restored.
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
});
}
// Otherwise ...
else
{
// We are not running on an Apple device. No work is necessary to restore purchases.
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
//
// --- IStoreListener
//
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
// Purchasing has succeeded initializing. Collect our Purchasing references.
Debug.Log("OnInitialized: PASS");
// Overall Purchasing system, configured with products for this application.
m_StoreController = controller;
// Store specific subsystem, for accessing device-specific store features.
m_StoreExtensionProvider = extensions;
}
public void OnInitializeFailed(InitializationFailureReason error)
{
// Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
// A consumable product has been purchased by this user.
if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));//If the consumable item has been successfully purchased, add 100 coins to the player's in-game score.
inpMoveH i = new inpMoveH();
i.addGold (50);
//UpdateGoldScript updater = new UpdateGoldScript ();
//updater.updateGold ();
}
// Or ... a non-consumable product has been purchased by this user.
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable2, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
inpMoveH i = new inpMoveH();
i.addGold (100);
}// Or ... a subscription product has been purchased by this user.
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable3, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
inpMoveH i = new inpMoveH();
i.addGold (250);
}
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable4, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
inpMoveH i = new inpMoveH();
i.addGold (1000);
}
// Or ... an unknown product has been purchased by this user. Fill in additional products here.
else
{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));}// Return a flag indicating wither this product has completely been received, or if the application needs to be reminded of this purchase at next app launch. Is useful when saving purchased products to the cloud, and when that save is delayed.
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
// A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing this reason with the user.
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}",product.definition.storeSpecificId, failureReason));}
}
XCODE错误:
m_StoreController IS NULL.
Purchaser:IsInitialized()
Purchaser:InitializePurchasing()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
m_StoreControllerProvider IS NULL.
Purchaser:IsInitialized()
Purchaser:InitializePurchasing()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
ReturningFalse
Purchaser:IsInitialized()
Purchaser:InitializePurchasing()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
2016-06-12 11:56:32.106 RC1[254:9485] UnityIAP:Requesting 4 products
2016-06-12 11:56:32.118 RC1[254:9485] UnityIAP:Requesting product data...
2016-06-12 11:56:32.866 RC1[254:9485] UnityIAP:Received 0 products
2016-06-12 11:56:32.870 RC1[254:9485] UnityIAP:No App Receipt found
Unavailable product RCbuy100Gold -RCbuy100Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
Unavailable product RCbuy250Gold -RCbuy250Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
Unavailable product RCbuy650Gold -RCbuy650Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
Unavailable product RCbuy1000Gold -RCbuy1000Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
OnInitializeFailed InitializationFailureReason:NoProductsAvailable
Purchaser:OnInitializeFailed(InitializationFailureReason)
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/ UnityEngineDebugBindings.gen.cpp Line: 37)
2016-06-12 11:56:32.887 RC1[254:9485] UnityIAP:addTransactionObserver
m_StoreController IS NULL.
Purchaser:IsInitialized()
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
m_StoreControllerProvider IS NULL.
Purchaser:IsInitialized()
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEve ntData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/ UnityEngineDebugBindings.gen.cpp Line: 37)
ReturningFalse
Purchaser:IsInitialized()
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[]) UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/ UnityEngineDebugBindings.gen.cpp Line: 37)
BuyProductID FAIL. Not initialized.
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()
7条答案
按热度按时间wh6knrhe1#
我收到“收到0产品”,直到我填写了联系信息,银行信息和税务信息。我是如此疯狂,我不能让它工作超过2个月。
ruarlubt2#
我认为你已经解决了这个问题。如果没有,我将在Apple开发者页面上分享一些我是如何做到的截图:
1-上传应用到testflight(使用XCode或应用加载器将应用上传到控制台)-此步骤已经完成。
2-去功能x1c 0d1x和添加尽可能多的项目,你想要的.我相信你有项目在这里与“提交修订”状态.正如你所看到的,我已经批准并在我的团结项目工作.
3-IAP项目应该在24小时后激活以进行测试(对于您的试飞批准的用户)。要添加用户,您必须转到Apple Developer Console并在其中编辑配置文件的角色。
4-如果你做了这一切(我相信你做了);唯一剩下的就是XCode端了。不过,我建议你在场景中添加IAP脚本作为空对象,以确保它被初始化,并给予它足够的时间来正确设置所有内容。
5-XCODE:要添加IAP功能,您需要在配置文件中设置适当的权限,并添加功能
。
6 -团队配置的进一步帮助:提供了一些有用的帮助。Apple IAP Documentation-〉Xcode将更新您的证书,如果您检查IAP功能。
无论如何,我有同样的问题,你有,我的谷歌IAP是工作,但我的iOS版本是失败的购买过程.我的最后建议是审查所有的代码/设置/证书,并等待24小时,以确保苹果应用到您的应用程序的更改.
请告诉我们。
谢谢。
iqjalb3h3#
因此,在您的代码中,有一个对
Start()
的调用,它调用InitializePurchasing()
,然后设置ConfigurationBuilder
并最终调用:我认为你在构建器中设置了一些你不需要的东西,特别是GooglePlay产品ID。例如,从你的
InitializePurchasing()
方法:我会首先调用
AddProduct
,只提供一个商店(iOS应用商店)的详细信息。*(我还会删除所有不需要的代码,以及额外的消耗品,因为它只会让你的代码塞满你不需要的东西,让你更难弄清楚发生了什么)_。例如,从Unity 3d pages之一:
在该示例代码中,已经在
Start()
方法中创建、添加和初始化了ConfigurationBuilder
...甚至在执行此操作之前,您应该能够找到调用的结果:
UnityPurchasing.Initialize(this, builder);
...我会这么做是因为你的失败是
因此,我们知道在
void BuyProductID(string productId)
中对if (IsInitialized())
的调用返回false,导致:下面是
IsInitialized()
方法:所以,
m_StoreController
或m_StoreExtensionProvider
中的一个是null...现在让我们看看两个IStoreListener
回调:检查您的调试日志(或者在每个方法中放置一个断点)...在前面调用
UnityPurchasing.Initialize(this, builder);
之后-您得到了什么?OnInitialized
?你需要知道你是否获得了
OnInitialized
的成功,从而初始化m_StoreController
和m_StoreController
。更新1
不确定你是否查阅过Unity文档中的这些页面;第一部分介绍了iTunes Connect和Xcode项目的IAP设置,第二部分提供了其他信息:
efzxgjgh4#
我假设您在Itune connect上创建了一个IAP产品,并且产品ID在代码和itune connect之间匹配,并且bundle ID是正确的:
可能您还没有选择项目中的团队设置,您还需要创建一个沙盒测试账号,并在测试设备上注销真实的应用商店账号,才能对IAP进行全面测试
5cnsuln75#
由于这是我第一次在应用程序购买设置中使用ios,阻止我的项目是填写税务和银行信息。一旦完成,我就可以用沙盒帐户进行测试。
nwsw7zdq6#
我有同样的问题.之后,我尝试应用它在“itunes连接”的合同为
paid applications
(联系信息,税务信息,银行信息)尝试这个直接链接https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/da/jumpTo?page=contractsi5desfxk7#
如果IAP Unity中的设置正确,则在编辑器上购买成功。然后您所要做的就是检查此部分,协议中的银行信息,税收和“付费应用程序”部分已启用。如下图