如何使Unity IAP与Google Play IAB一起使用?

如何解决如何使Unity IAP与Google Play IAB一起使用?

我已经完成了Unity IAP教程中的所有步骤。

Unity IAP Setup

但是我的游戏仍在Google Play控制台中进行审查。我知道我不需要等待内部测试的审查。但是我可以从互联网上获得的所有信息都告诉我,至少,我需要将我的应用置于Alpha状态。如果我错了,请告诉我。

Alpha Test

我的代码是这样的:

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using Veewo.Systems.Base;

// Placing the Purchaser class in the CompleteProject namespace allows it to interact with ScoreManager,// one of the existing Survival Shooter scripts.
namespace Veewo.Systems
{
    // Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing.
    public class IAPSystem : SystemBase,IStoreListener
    {
        private static IStoreController m_StoreController;          // The Unity Purchasing system.
        private static IExtensionProvider m_StoreExtensionProvider; // The 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.)

        // General product identifiers for the consumable,non-consumable,and subscription products.
        // Use these handles in the code to reference which product to purchase. Also use these values 
        // when defining the Product Identifiers on the store. Except,for illustration purposes,the 
        // kProductIDSubscription - it has custom Apple and Google identifiers. We declare their store-
        // specific mapping to Unity Purchasing's AddProduct,below.
        public static string kProductIDConsumable =    "veewo.pi.diamond600";   
        public static string kProductIDNonConsumable = "veewo.pi.limited.goldheropiece";
        public static string kProductIDSubscription =  "subscription"; 

        // Apple App Store-specific product identifier for the subscription product.
        private static string kProductNameAppleSubscription =  "com.unity3d.subscription.new";

        // Google Play Store-specific product identifier subscription product.
        private static string kProductNameGooglePlaySubscription =  "com.unity3d.subscription.original";

        protected override void OnInitialize()
        {
            base.OnInitialize();
            // 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() 
        {
            Debug.Log("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.
            ConfigurationBuilder builder;
//            if (Application.platform == RuntimePlatform.Android
//                && StandardPurchasingModule.Instance().appStore == AppStore.GooglePlay)
//            {
//                builder = ConfigurationBuilder.Instance(
//                    Google.Play.Billing.GooglePlayStoreModule.Instance());
//            }
//            else
//            {
                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);
            // Continue adding the non-consumable product.
            builder.AddProduct(kProductIDNonConsumable,ProductType.NonConsumable);
            // And finish adding the subscription product. Notice this uses store-specific IDs,illustrating
            // if the Product ID was configured differently between Apple and Google stores. Also note that
            // one uses the general kProductIDSubscription handle inside the game - the store-specific IDs 
            // must only be referenced here. 
//            builder.AddProduct(kProductIDSubscription,ProductType.Subscription,new IDs(){
//                { kProductNameAppleSubscription,AppleAppStore.Name },//                { kProductNameGooglePlaySubscription,GooglePlay.Name },//            });

            // 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);
            Debug.Log("UnityPurchasing.Initialize");
        }


        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 BuyNonConsumable()
        {
            // Buy the non-consumable product using its general identifier. Expect a response either 
            // through ProcessPurchase or OnPurchaseFailed asynchronously.
            BuyProductID(kProductIDNonConsumable);
        }


        public void BuySubscription()
        {
            // Buy the subscription product using its the general identifier. Expect a response either 
            // through ProcessPurchase or OnPurchaseFailed asynchronously.
            // Notice how we use the general product identifier in spite of this ID being mapped to
            // custom store-specific identifiers above.
            BuyProductID(kProductIDSubscription);
        }


        void BuyProductID(string productId)
        {
            // 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.");
            }
        }


        // Restore purchases previously made by this customer. Some platforms automatically restore purchases,like Google. 
        // Apple currently requires explicit purchase restoration for IAP,conditionally displaying a password prompt.
        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));
                // The consumable item has been successfully purchased,add 100 coins to the player's in-game score.
                //TODO:
            }
            // Or ... a non-consumable product has been purchased by this user.
            else if (String.Equals(args.purchasedProduct.definition.id,kProductIDNonConsumable,args.purchasedProduct.definition.id));
                // TODO: The non-consumable item has been successfully purchased,grant this item to the player.
            }
            // Or ... a subscription product has been purchased by this user.
            else if (String.Equals(args.purchasedProduct.definition.id,kProductIDSubscription,args.purchasedProduct.definition.id));
                // TODO: The subscription item has been successfully purchased,grant this to the player.
            }
            // 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 whether this product has completely been received,or if the application needs 
            // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still 
            // 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 to guide their troubleshooting actions.
            Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}',PurchaseFailureReason: {1}",product.definition.storeSpecificId,failureReason));
        }

        public IEnumerable<Product> GetAllProducts()
        {
            if (!IsInitialized()) yield break;

            foreach (var product in m_StoreController.products.set)
            {
                yield return product;
            }
        }
    }
}

我非常确定产品密钥正确。

Product keys

但是我仍然无法完成这项工作。我在BlueStack4和Android9移动版上进行了测试,但都失败了。无法通过调用UnityPurchasing.Initialize完成OnInitialized

bluestack中的日志为:

10-29 09:51:17.193  5183  5203 I Unity   : UnityIAP Version: 2.1.1
10-29 09:51:17.219  5183  5203 I UnityIAP: Starting in-app billing setup.
10-29 09:51:17.221  5183  5183 I UnityIAP: Billing service connected.
10-29 09:51:17.222  5183  5203 I Unity   : UnityPurchasing.Initialize
10-29 09:51:17.224  5183  5238 I UnityIAP: Billing Service Manager invoking callback 1 of 1
10-29 09:51:17.224  5183  5238 I UnityIAP: Checking for in-app billing 3 support.
10-29 09:51:17.224  4671  4683 W Finsky  : [291] iec.a(16): com.veewo.alienland: No account found.
10-29 09:51:17.226  5183  5238 D UnityIAP: onIabSetupFinished: 3
10-29 09:51:17.226  5183  5238 I UnityIAP: Failed to setup IAB. Notifying Unity...
10-29 09:51:17.276  5183  5203 I Unity   : OnInitializeFailed InitializationFailureReason:PurchasingUnavailable
10-29 09:51:17.276  5183  5203 I Unity   : UnityEngine.Logger:Log(LogType,Object)
10-29 09:51:17.276  5183  5203 I Unity   : Veewo.Systems.IAPSystem:OnInitializeFailed(InitializationFailureReason)
10-29 09:51:17.276  5183  5203 I Unity   : UnityEngine.Purchasing.Extension.UnityUtil:Update()
10-29 09:51:17.276  5183  5203 I Unity   :
10-29 09:51:17.276  5183  5203 I Unity   : (Filename: ./Runtime/Export/Debug.bindings.h Line: 45)
10-29 09:51:17.276  5183  5203 I Unity   :
10-29 09:51:30.322  1962  3360 I NetworkScheduler.Stats: Task com.google.android.gms/com.google.android.gms.auth.account.be.legacy.AuthCronService started execution. cause:4 exec_start_elapsed_seconds: 1056 [CONTEXT service_id=218 ]
10-29 09:51:32.652  4671  4707 E Finsky  : [314] log.b(1): Error while refreshing device settings: network time: 32342,HTTP status code: na,exception com.android.volley.TimeoutError. Retrying.
10-29 09:51:32.652  4671  4707 E Finsky  : network time: 32342,exception com.android.volley.TimeoutError
10-29 09:51:32.652  4671  4707 E Finsky  :      at vqf.hq(PG)
10-29 09:51:32.652  4671  4707 E Finsky  :      at czn.r(PG:2)
10-29 09:51:32.652  4671  4707 E Finsky  :      at exo.r(PG:3)
10-29 09:51:32.652  4671  4707 E Finsky  :      at czg.run(PG:3)
10-29 09:51:32.652  4671  4707 E Finsky  :      at android.os.Handler.handleCallback(Handler.java:751)
10-29 09:51:32.652  4671  4707 E Finsky  :      at android.os.Handler.dispatchMessage(Handler.java:95)
10-29 09:51:32.652  4671  4707 E Finsky  :      at android.os.Looper.loop(Looper.java:154)
10-29 09:51:32.652  4671  4707 E Finsky  :      at android.app.ActivityThread.main(ActivityThread.java:6138)
10-29 09:51:32.652  4671  4707 E Finsky  :      at java.lang.reflect.Method.invoke(Native Method)
10-29 09:51:32.652  4671  4707 E Finsky  :      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
10-29 09:51:32.652  4671  4707 E Finsky  :      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
10-29 09:51:32.653  4671  4704 E Finsky  : [311] lon.b(-1): Error getting device settings.
10-29 09:51:32.653  4671  4704 E Finsky  : network time: 32342,exception com.android.volley.TimeoutError
10-29 09:51:32.653  4671  4704 E Finsky  :      at vqf.hq(PG)
10-29 09:51:32.653  4671  4704 E Finsky  :      at czn.r(PG:2)
10-29 09:51:32.653  4671  4704 E Finsky  :      at exo.r(PG:3)
10-29 09:51:32.653  4671  4704 E Finsky  :      at czg.run(PG:3)
10-29 09:51:32.653  4671  4704 E Finsky  :      at android.os.Handler.handleCallback(Handler.java:751)
10-29 09:51:32.653  4671  4704 E Finsky  :      at android.os.Handler.dispatchMessage(Handler.java:95)
10-29 09:51:32.653  4671  4704 E Finsky  :      at android.os.Looper.loop(Looper.java:154)
10-29 09:51:32.653  4671  4704 E Finsky  :      at android.app.ActivityThread.main(ActivityThread.java:6138)
10-29 09:51:32.653  4671  4704 E Finsky  :      at java.lang.reflect.Method.invoke(Native Method)
10-29 09:51:32.653  4671  4704 E Finsky  :      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
10-29 09:51:32.653  4671  4704 E Finsky  :      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
10-29 09:51:32.653  4671  4707 I Finsky  : [314] abij.n(4): SCH: jobFinished: 31-305419896. TimeElapsed: 32344ms.
10-29 09:51:32.653  4671  4671 I Finsky  : [1] abgy.c(7): SCH: Job 31-305419896 finished. Rescheduling.
10-29 09:51:32.653  4671  4671 I Finsky  : [1] abgx.handleMessage(60): SCH: RunningQueue size: 0,PendingQueue size: 0
10-29 09:51:32.654  4671  4671 I Finsky  : [1] abgx.handleMessage(26): SCH: Executor finished
10-29 09:51:32.658  4671  4671 I Finsky  : [1] abjk.b(5): SCH: Jobs in database: 1-1337 24-77777777 26-1414141414 31-305419896
10-29 09:51:32.659  4671  4671 I Finsky  : [1] abhw.d(37): SCH: ConstraintMapping: 24-77777777,-> L: 0ms,D: 24834708ms,C: false,I: true,N: 0
10-29 09:51:32.660  4671  4671 I Finsky  : [1] abhw.d(37): SCH: ConstraintMapping: 1-1337,31-305419896,-> L: 127994ms,D: 32437706ms,I: false,N: 1
10-29 09:51:32.660  4671  4671 I Finsky  : [1] abhw.d(37): SCH: ConstraintMapping: 26-1414141414,-> L: 29458222ms,D: 30358222ms,N: 0
10-29 09:51:32.662  4671  4671 I Finsky  : [1] abhw.f(7): SCH: Cancelling existing jobscheduler jobs: 9000 9005
10-29 09:51:32.662  4671  4671 I Finsky  : [1] abhw.e(23): SCH: Scheduling job Id: 9001,L: 0,D: 24834708,N: 0
10-29 09:51:32.663  4671  4671 I Finsky  : [1] abhw.e(23): SCH: Scheduling job Id: 9002,L: 127994,D: 32437706,N: 1
10-29 09:51:32.664  4671  4671 I Finsky  : [1] abhw.e(23): SCH: Scheduling job Id: 9003,L: 29458222,D: 30358222,N: 0

已经4天了,我无法完成这项工作。我所有的猜测是:

  1. 网络问题,我在中国,虽然我使用的是VPN,但无法连接到Google Service,但它不稳定。
  2. 我没有正确设置Unity IAP
  3. 我需要等待Google Play控制台审核完成,然后等待其状态发布。
  4. 我没有在手机中使用正确的Google帐户登录信息。我将同一个帐户用于Google Play帐户,并且已经将其添加到测试帐户列表中,是否应该使用新帐户?

我现在很困惑,不知道下一步该怎么做。请帮助我。

解决方法

似乎您的代码是正确的。但是您的应用程序需要已经发布。如果正在审核中,它将无法正常工作。等待填充已批准。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res