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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

0回答

4404閲覧

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

S4ch1mos

総合スコア10

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/04/08 10:34

編集2022/01/12 10:55

前提・実現したいこと

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

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

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

IAPButton.OnPurchaseFailed(Product …, PurchaseFailureReason Unknown)

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

該当のソースコード

C#

1namespace UnityEngine.Purchasing 2{ 3 public class CodelessIAPStoreListener : IStoreListener 4 { 5 private static CodelessIAPStoreListener instance; 6 private List<IAPButton> activeButtons = new List<IAPButton>(); 7 private List<IAPListener> activeListeners = new List<IAPListener> (); 8 private static bool unityPurchasingInitialized; 9 10 protected IStoreController controller; 11 protected IExtensionProvider extensions; 12 protected ProductCatalog catalog; 13 14 private static void InitializePurchasing() 15 { 16 StandardPurchasingModule module = StandardPurchasingModule.Instance(); 17 18 module.useFakeStoreUIMode = FakeStoreUIMode.StandardUser; 19 20 ConfigurationBuilder builder = ConfigurationBuilder.Instance(module); 21 22       IAPConfigurationHelper.PopulateConfigurationBuilder(ref builder, instance.catalog); 23 24 UnityPurchasing.Initialize(instance, builder); 25 26 unityPurchasingInitialized = true; 27 } 28 29 private CodelessIAPStoreListener() 30 { 31 catalog = ProductCatalog.LoadDefaultCatalog(); 32 } 33 34 public static CodelessIAPStoreListener Instance 35 { 36 get 37 { 38 if (instance == null) 39 { 40 CreateCodelessIAPStoreListenerInstance(); 41 } 42 return instance; 43 } 44 } 45 46 private static void CreateCodelessIAPStoreListenerInstance() 47 { 48 instance = new CodelessIAPStoreListener(); 49 if (!unityPurchasingInitialized) 50 { 51 Debug.Log("Initializing UnityPurchasing via Codeless IAP"); 52 InitializePurchasing(); 53 } 54 } 55 56     public void InitiatePurchase(string productID) 57 { 58 if (controller == null) 59 { 60 Debug.LogError("Purchase failed because Purchasing was not initialized correctly"); 61 62 foreach (var button in activeButtons) 63 { 64 if (button.productId == productID) 65 { 66 button.OnPurchaseFailed(null, Purchasing.PurchaseFailureReason.PurchasingUnavailable); 67 } 68 } 69 return; 70 } 71 72 controller.InitiatePurchase(productID); 73 } 74 75 public void OnInitialized(IStoreController controller, IExtensionProvider extensions) 76 { 77 initializationComplete = true; 78 this.controller = controller; 79 this.extensions = extensions; 80 81 foreach (var button in activeButtons) 82 { 83 button.UpdateText(); 84 } 85 Debug.Log("Initialized"); 86 } 87 88 public void OnInitializeFailed(InitializationFailureReason error) 89 { 90 Debug.LogError(string.Format("Purchasing failed to initialize. Reason: {0}", error.ToString())); 91 } 92 93 public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) 94 { 95 // if any receiver consumed this purchase we return the status 96 bool consumePurchase = false; 97 bool resultProcessed = false; 98 99 foreach (IAPButton button in activeButtons) 100 { 101 if (button.productId == e.purchasedProduct.definition.id) 102 { 103 result = button.ProcessPurchase(e); 104 105 if (result == PurchaseProcessingResult.Complete) { 106 107 consumePurchase = true; 108 } 109 resultProcessed = true; 110 } 111 } 112 113 foreach (IAPListener listener in activeListeners) 114 { 115 result = listener.ProcessPurchase(e); 116 117 if (result == PurchaseProcessingResult.Complete) { 118 119 consumePurchase = true; 120 } 121 resultProcessed = true; 122 } 123 124 // we expect at least one receiver to get this message 125 if (!resultProcessed) { 126 127 Debug.LogError("Purchase not correctly processed for product \"" + 128 e.purchasedProduct.definition.id + 129 "\". Add an active IAPButton to process this purchase, or add an IAPListener to receive any unhandled purchase events."); 130 } 131 return (consumePurchase) ? PurchaseProcessingResult.Complete : PurchaseProcessingResult.Pending; 132 } 133 134 public void OnPurchaseFailed(Product product, PurchaseFailureReason reason) 135 { 136 bool resultProcessed = false; 137 138 foreach (IAPButton button in activeButtons) 139 { 140 if (button.productId == product.definition.id) 141 { 142 button.OnPurchaseFailed(product, reason); 143 144 resultProcessed = true; 145 } 146 } 147 148 foreach (IAPListener listener in activeListeners) 149 { 150 listener.OnPurchaseFailed(product, reason); 151 152 resultProcessed = true; 153 } 154 155 // we expect at least one receiver to get this message 156 if (!resultProcessed) { 157 158 Debug.LogError("Failed purchase not correctly handled for product \"" + product.definition.id + 159 "\". Add an active IAPButton to handle this failure, or add an IAPListener to receive any unhandled purchase failures."); 160 } 161 return; 162 } 163 } 164} 165#endif

C#

1 2namespace UnityEngine.Purchasing 3{ 4 [RequireComponent(typeof(Button))] 5 [AddComponentMenu("Unity IAP/IAP Button")] 6 [HelpURL("https://docs.unity3d.com/Manual/UnityIAP.html")] 7 public class IAPButton : MonoBehaviour 8 { 9 [HideInInspector] 10 public string productId; 11 12 [Tooltip("The type of this button, can be either a purchase or a restore button")] 13 public ButtonType buttonType = ButtonType.Purchase; 14 15 [Tooltip("Consume the product immediately after a successful purchase")] 16 public bool consumePurchase = true; 17 18 [Tooltip("Event fired after a successful purchase of this product")] 19 public OnPurchaseCompletedEvent onPurchaseComplete; 20 21 [Tooltip("Event fired after a failed purchase of this product")] 22 public OnPurchaseFailedEvent onPurchaseFailed; 23 24 [Tooltip("[Optional] Displays the localized title from the app store")] 25 public Text titleText; 26 27 [Tooltip("[Optional] Displays the localized description from the app store")] 28 public Text descriptionText; 29 30 [Tooltip("[Optional] Displays the localized price from the app store")] 31 public Text priceText; 32 33 void Start() 34 { 35 Button button = GetComponent<Button>(); 36 37 if (buttonType == ButtonType.Purchase) 38 { 39 if (button) 40 { 41 button.onClick.AddListener(PurchaseProduct); 42 } 43 44 if (string.IsNullOrEmpty(productId)) 45 { 46 Debug.LogError("IAPButton productId is empty"); 47 } 48 49 if (!CodelessIAPStoreListener.Instance.HasProductInCatalog(productId)) 50 { 51 Debug.LogWarning("The product catalog has no product with the ID \"" + productId + "\""); 52 } 53 } 54 else if (buttonType == ButtonType.Restore) 55 { 56 if (button) 57 { 58 button.onClick.AddListener(Restore); 59 } 60 } 61 } 62 63 void OnEnable() 64 { 65 if (buttonType == ButtonType.Purchase) 66 { 67 CodelessIAPStoreListener.Instance.AddButton(this); 68 if (CodelessIAPStoreListener.initializationComplete) { 69 UpdateText(); 70 } 71 } 72 } 73 74 void PurchaseProduct() 75 { 76 if (buttonType == ButtonType.Purchase) 77 { 78 Debug.Log("IAPButton.PurchaseProduct() with product ID: " + productId); 79 80 CodelessIAPStoreListener.Instance.InitiatePurchase(productId); 81 } 82 } 83 public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) 84 { 85 Debug.Log(string.Format("IAPButton.ProcessPurchase(PurchaseEventArgs {0} - {1})", e, 86 e.purchasedProduct.definition.id)); 87 88 onPurchaseComplete.Invoke(e.purchasedProduct); 89 90 return (consumePurchase) ? PurchaseProcessingResult.Complete : PurchaseProcessingResult.Pending; 91 } 92 93 public void OnPurchaseFailed(Product product, PurchaseFailureReason reason) 94 { 95 Debug.Log(string.Format("IAPButton.OnPurchaseFailed(Product {0}, PurchaseFailureReason {1})", product, 96 reason)); 97 98 onPurchaseFailed.Invoke(product, reason); 99 } 100 } 101} 102#endif

試したこと

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

IShix

2019/04/08 13:33

Google Playですでにリリースしているアプリですか?
S4ch1mos

2019/04/09 01:02

β版を公開しているはずです。 Storeに商品の登録まではできていると思います。
IShix

2019/04/09 11:02

ダイアログのメッセージ「指定したアイテムは購入できません 」はAndroidからのメッセージってことですよね?今は下記の感じですか? ・課金アイテムの価格や名前は正常に取得できている ・課金アイテムの購入ボタンを押すと、「指定したアイテムは購入できません 」とエラーが出る
S4ch1mos

2019/04/10 06:44

回答が遅れてしまい申し訳ございません。 今の状況としては、課金アイテムの価格や名前すら取得できていません。 アイテムの購入UIをタップ→OS依存のダイアログが出る→ダイアログには「指定したアイテムは購入できません」の文字 といった感じです。 追記 Storeに商品が登録できていると思ったのは、以前チェックしたときはOS依存のダイアログにクレジット支払いか、コンビニ支払いかのような選択肢が出るところまでは確認できていたからです。
S4ch1mos

2019/04/12 07:08

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問