質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

UnityIAPのAndroid実機検証でダイアログは出るがエラーが発生してしまう

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,596

S4ch1mos

score 10

前提・実現したいこと

Unity IAPを用いてアプリに課金システムの実装を行っています。
現状、Androidで課金検証を行うにあたりエラーが発生しました。

発生している問題・エラーメッセージ

実機で購入ダイアログを表示するとき、エラーが発生しました、と表示され購入できない。

IAPButton.OnPurchaseFailed(Product …, PurchaseFailureReason Unknown)


ダイアログ:指定したアイテムは購入できません

該当のソースコード

namespace UnityEngine.Purchasing
{
    public class CodelessIAPStoreListener : IStoreListener
    {
        private static CodelessIAPStoreListener instance;
        private List<IAPButton> activeButtons = new List<IAPButton>();
        private List<IAPListener> activeListeners = new List<IAPListener> ();
        private static bool unityPurchasingInitialized;

        protected IStoreController controller;
        protected IExtensionProvider extensions;
        protected ProductCatalog catalog;

        private static void InitializePurchasing()
        {
            StandardPurchasingModule module = StandardPurchasingModule.Instance();

            module.useFakeStoreUIMode = FakeStoreUIMode.StandardUser;

            ConfigurationBuilder builder = ConfigurationBuilder.Instance(module);

       IAPConfigurationHelper.PopulateConfigurationBuilder(ref builder, instance.catalog);

            UnityPurchasing.Initialize(instance, builder);

            unityPurchasingInitialized = true;
        }

        private CodelessIAPStoreListener()
        {
            catalog = ProductCatalog.LoadDefaultCatalog();
        }

        public static CodelessIAPStoreListener Instance
        {
            get
            {
                if (instance == null)
                {
                    CreateCodelessIAPStoreListenerInstance();
                }
                return instance;
            }
        }

        private static void CreateCodelessIAPStoreListenerInstance()
        {
            instance = new CodelessIAPStoreListener();
            if (!unityPurchasingInitialized)
            {
                Debug.Log("Initializing UnityPurchasing via Codeless IAP");
                InitializePurchasing();
            }
        }

     public void InitiatePurchase(string productID)
        {
            if (controller == null)
            {
                Debug.LogError("Purchase failed because Purchasing was not initialized correctly");

                foreach (var button in activeButtons)
                {
                    if (button.productId == productID)
                    {
                        button.OnPurchaseFailed(null, Purchasing.PurchaseFailureReason.PurchasingUnavailable);
                    }
                }
                return;
            }

            controller.InitiatePurchase(productID);
        }

        public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
        {
            initializationComplete = true;
            this.controller = controller;
            this.extensions = extensions;

            foreach (var button in activeButtons)
            {
                button.UpdateText();
            }
            Debug.Log("Initialized");
        }

        public void OnInitializeFailed(InitializationFailureReason error)
        {
            Debug.LogError(string.Format("Purchasing failed to initialize. Reason: {0}", error.ToString()));
        }

        public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
        {
            // if any receiver consumed this purchase we return the status
            bool consumePurchase = false;
            bool resultProcessed = false;

            foreach (IAPButton button in activeButtons)
            {
                if (button.productId == e.purchasedProduct.definition.id)
                {
                    result = button.ProcessPurchase(e);

                    if (result == PurchaseProcessingResult.Complete) {

                        consumePurchase = true;
                    }
                    resultProcessed = true;
                }
            }

            foreach (IAPListener listener in activeListeners)
            {
                result = listener.ProcessPurchase(e);

                if (result == PurchaseProcessingResult.Complete) {

                    consumePurchase = true;
                }
                resultProcessed = true;
            }

            // we expect at least one receiver to get this message
            if (!resultProcessed) {

                Debug.LogError("Purchase not correctly processed for product \"" +
                                 e.purchasedProduct.definition.id +
                                 "\". Add an active IAPButton to process this purchase, or add an IAPListener to receive any unhandled purchase events.");
            }
            return (consumePurchase) ? PurchaseProcessingResult.Complete : PurchaseProcessingResult.Pending;
        }

        public void OnPurchaseFailed(Product product, PurchaseFailureReason reason)
        {
            bool resultProcessed = false;

            foreach (IAPButton button in activeButtons)
            {
                if (button.productId == product.definition.id)
                {
                    button.OnPurchaseFailed(product, reason);

                    resultProcessed = true;
                }
            }

            foreach (IAPListener listener in activeListeners)
            {
                listener.OnPurchaseFailed(product, reason);

                resultProcessed = true;
            }

            // we expect at least one receiver to get this message
            if (!resultProcessed) {

                Debug.LogError("Failed purchase not correctly handled for product \"" + product.definition.id +
                                  "\". Add an active IAPButton to handle this failure, or add an IAPListener to receive any unhandled purchase failures.");
            }
            return;
        }
    }
}
#endif
namespace UnityEngine.Purchasing
{
    [RequireComponent(typeof(Button))]
    [AddComponentMenu("Unity IAP/IAP Button")]
    [HelpURL("https://docs.unity3d.com/Manual/UnityIAP.html")]
    public class IAPButton : MonoBehaviour
    {
        [HideInInspector]
        public string productId;

        [Tooltip("The type of this button, can be either a purchase or a restore button")]
        public ButtonType buttonType = ButtonType.Purchase;

        [Tooltip("Consume the product immediately after a successful purchase")]
        public bool consumePurchase = true;

        [Tooltip("Event fired after a successful purchase of this product")]
        public OnPurchaseCompletedEvent onPurchaseComplete;

        [Tooltip("Event fired after a failed purchase of this product")]
        public OnPurchaseFailedEvent onPurchaseFailed;

        [Tooltip("[Optional] Displays the localized title from the app store")]
        public Text titleText;

        [Tooltip("[Optional] Displays the localized description from the app store")]
        public Text descriptionText;

        [Tooltip("[Optional] Displays the localized price from the app store")]
        public Text priceText;

        void Start()
        {
            Button button = GetComponent<Button>();

            if (buttonType == ButtonType.Purchase)
            {
                if (button)
                {
                    button.onClick.AddListener(PurchaseProduct);
                }

                if (string.IsNullOrEmpty(productId))
                {
                    Debug.LogError("IAPButton productId is empty");
                }

                if (!CodelessIAPStoreListener.Instance.HasProductInCatalog(productId))
                {
                    Debug.LogWarning("The product catalog has no product with the ID \"" + productId + "\"");
                }
            }
            else if (buttonType == ButtonType.Restore)
            {
                if (button)
                {
                    button.onClick.AddListener(Restore);
                }
            }
        }

        void OnEnable()
        {
            if (buttonType == ButtonType.Purchase)
            {
                CodelessIAPStoreListener.Instance.AddButton(this);
                if (CodelessIAPStoreListener.initializationComplete) {
                    UpdateText();
                }
            }
        }

        void PurchaseProduct()
        {
            if (buttonType == ButtonType.Purchase)
            {
                Debug.Log("IAPButton.PurchaseProduct() with product ID: " + productId);

                CodelessIAPStoreListener.Instance.InitiatePurchase(productId);
            }
        }
        public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
        {
            Debug.Log(string.Format("IAPButton.ProcessPurchase(PurchaseEventArgs {0} - {1})", e,
                e.purchasedProduct.definition.id));

            onPurchaseComplete.Invoke(e.purchasedProduct);

            return (consumePurchase) ? PurchaseProcessingResult.Complete : PurchaseProcessingResult.Pending;
        }

        public void OnPurchaseFailed(Product product, PurchaseFailureReason reason)
        {
            Debug.Log(string.Format("IAPButton.OnPurchaseFailed(Product {0}, PurchaseFailureReason {1})", product,
                reason));

            onPurchaseFailed.Invoke(product, reason);
        }
    }
}
#endif

試したこと

実機にデバッカーを組み込み、エラーの絞り込みをしました。
CodelessIApListenerのInitiatePurchaseが呼ばれることは確認できましたが、その後Unityの内部処理があり、レスポンスとしてCodelessIApListenerのOnPurchaseFailedが呼ばれてしますようで難航しています。
FailedのReasonもUnknownと的確な原因がわからないレスポンスです。
どなたか原因を教えてほしいです。

補足情報(FW/ツールのバージョンなど)

Unity 2.16f
情報漏洩を防ぐためいくつか・・・で置き換えさせていただきました。コードに影響はないと思います。
一万時に抑えるためにコード削りました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • S4ch1mos

    2019/04/10 15:44

    回答が遅れてしまい申し訳ございません。
    今の状況としては、課金アイテムの価格や名前すら取得できていません。
    アイテムの購入UIをタップ→OS依存のダイアログが出る→ダイアログには「指定したアイテムは購入できません」の文字
    といった感じです。

    追記
    Storeに商品が登録できていると思ったのは、以前チェックしたときはOS依存のダイアログにクレジット支払いか、コンビニ支払いかのような選択肢が出るところまでは確認できていたからです。

    キャンセル

  • キャンセル

  • S4ch1mos

    2019/04/12 16:08

    はい,登録を確認しています.(><)

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る