We are getting excessive ANR reports in Google Play and it is putting our game above the ANR "Bad behavior" threshold.
Below is what most of the logs look like:
#00 pc 00000000000e1aaf /data/app/com.doubletapsoftware.basketballbattle-UpZm6V6zLj2a-Tg-QXAtkg==/lib/arm/libunity.so (???)
#00 pc 000000000000045d /data/app/com.doubletapsoftware.basketballbattle-UpZm6V6zLj2a-Tg-QXAtkg==/oat/arm/base.odex (Java_com_unity3d_player_ReflectionHelper_nativeProxyInvoke__JLjava_lang_String_2_3Ljava_lang_Object_2+156)
at com.unity3d.player.ReflectionHelper.nativeProxyInvoke (Native method)
at com.unity3d.player.ReflectionHelper.a (unavailable)
at com.unity3d.player.ReflectionHelper$1.invoke (unavailable)
at java.lang.reflect.Proxy.invoke (Proxy.java:913)
at com.android.billingclient.api.BillingClientStateListener.onBillingSetupFinished
at com.android.billingclient.api.zzae.run
at android.os.Handler.handleCallback (Handler.java:790)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:164)
at android.app.ActivityThread.main (ActivityThread.java:7000)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1408)
We have tried upgrading from In App Purchasing 2.2.2 to 3.1.0 but the problem remains.
Does anyone know how to fix this issue?
↧
Google Play ANR com.android.billingclient.api.BillingClientStateListener.onBillingSetupFinished
↧
Unity Codeless IAP behaving strange in iOS TestFlight
I am working on a Mobile project that uses Unity 2017.4.40 and where I have integrated the Codeless AI.
Lately, there have been unusual behaviours during the tests in the iOS Testflight a few days ago. When a tester tries to purchase a previously purchased non-consumable item, the transaction is automatically confirmed with no dialogue screen asking for a password, and when he tries to Restore a purchase the OnPurchaseComplete() method is not called. This behaviour seems to happen with the iPhones 11 and 12, but we don't know if it is a problem with the TestFlight or the Codeless IAP or if it's a normal response.
↧
↧
IAP: Unusually large number of "Unavailable product" and "Purchasing failed to initialize."
Hello,
I am tracing a rather hard to solve bug with Unity IAP. We are getting a very high number of those errors (approximately 400 per product per day while DAU is around 2000). Our configuration seems to be in order, and noone on my team is able to even reproduce the bug. It simply works on all the test/our devices and the configuration is fine. All the payments go through and there seem to be no issue.
I have gathered that it is not about internet connection, because bug reports on bugsnag show the devices are connected to wifi etc. It does not seem to prefer any particular country either, the distribution seems to follow our general user base ratios. Same with android version - seems to happening on all. There is nothing in particular that it seems to be correlating with except for "freeMemory" and "totalMemory" both of which seem to be around 0.5gb or less in most reports, but I'm not sure if this could be related?
Here is the error we get on GameAnalytics and Bugsnag:
Unavailable product 2000magic-2000magic UnityEngine.Purchasing.Extension.UnityUtil:Update()we get the same for each product available, just different name , and also plenty of this:
UnityLogErrorUnityEngine.Purchasing.Extension.UnityUtil:Update():0 Purchasing failed to initialize. Reason: NoProductsAvailableAs you can see it's not much to follow up on. I am completely lost here, but it does seem to correlate with drop in our payments, so we're really worried here. The version of unity In App Purchasing is 3.0.2. It seems to have started happening loong time ago, but spiked around two months ago when we updated unity to 2020.3 (not sure if this could be related). Looking for any kind of help here, perhaps there is a way to make unity dump more information on what exactly went wrong? The only similar cases I have found on google were all misconfigurations, but our config seems fine. And there doesn't seem to be much options to set in IAP plugin either. How could we approach this?
↧
Unity IAP not working for android need google public key
I have to include in app purchases in my game so i used the codeless Iap and so i need the google public key to work but it is redirecting me to google play console and asking to pay but i dont want to publish the game on play store instead on a website so do i need to buy the play console developer account for it work?
![alt text][1]![alt text][2]
[1]: /storage/temp/181830-playconsole.png
[2]: /storage/temp/181829-iap.png
↧
Unity IAP not working for android need google public key
I have to include in app purchases in my game so i used the codeless Iap and so i need the google public key to work but it is redirecting me to google play console and asking to pay but i dont want to publish the game on play store instead on a website so do i need to buy the play console developer account for it work?
![alt text][1]![alt text][2]
[1]: /storage/temp/181830-playconsole.png
[2]: /storage/temp/181829-iap.png
↧
↧
Purchase not being acknowledged on google store
I have an option to remove ads in my game, it is a one time purchase and when using the google test purchase I will get an email about 5 minutes after the purchase stating that the test purchase was cancelled because it was not acknowledged. I have done some research but not had any luck on how to fix this. Below is a screenshot of my IAP button. I have ensured I am updated to the latest package. I have the consume purchase box checked. Any idea as to what may be causing this?
![alt text][1]
[1]: /storage/temp/182699-screenshot-3.png
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
public class RemoveAds : MonoBehaviour
{
public GameObject button;
public GameObject button2;
IStoreController controller;
public void Start()
{
if (PlayerPrefs.HasKey("ads"))
{
button.SetActive(false);
button2.SetActive(false);
}
}
public void RemoveAdverts()
{
if (PlayerPrefs.HasKey("ads") == false)
{
PlayerPrefs.SetInt("ads", 0);
button.SetActive(false);
button2.SetActive(false);
}
}
public void Restore()
{
if (controller.products.WithID("cowabductor.removeads").hasReceipt)
{
PlayerPrefs.SetInt("ads", 0);
button.SetActive(false);
button2.SetActive(false);
}
}
}
↧
Google Play IAP - "The item you requested is not available for purchase."
Hi,
Im currently trying to implement a simple ingame purchase for Google Play (codeless IAP), but I cant seem to get it to work. Testing it in the editor with the FakeStore works fine, but when I upload to google play and try to purchase on my phone, I get the message: "The item you requested is not available for purchase.", it can be seen [here (in german)](https://i.imgur.com/LBAGR83.jpg). I downloaded the app via internal app-sharing and was logged into a test account on my phone (in play store).
Im using IAP Version 3.2.2., [targeting google play](https://i.imgur.com/JmejtzP.png), have a signed app (but not published for everyone), product ids are the same as in google play and default currency is HUF (hungarian), but shouldnt be a problem, right? Im not sure if I missed something.
Any help would be appreciated, as Ive been sitting on this for about a week now. Ive also checked related posts about this problem, but have found no solution as of yet.
↧
Is IAP necessary for main app pricing?
I am checking out the official documentation for IAP and I'm not understanding if this only applies to in-app purchases or if it includes the price of the app itself (https://docs.unity3d.com/Packages/com.unity.purchasing@3.2/manual/UnityIAPSettingUp.html).
All I would like to do is use a script to check if the app was purchased on the Google Play Store. It is unclear if IAP is required for this. I have already completed the step of defining the pricing in the Google Play Console according to (https://support.google.com/googleplay/android-developer/answer/6334373).
How would I go about checking to see if the user purchased it in code? Are there additional options for getting the listed store price?
↧
How to i save purchuased items with user-registration ?
----------
After update my game had rejected by ios. I have no non-consumable items in game but when you purchased with intermediary money its not running out. Off course if you delete app all your datas will delete. Google services doing this automatically, on ios platforms how to i do this ?
----------
Guideline 3.1.1 - Business - Payments - In-App Purchase
----------------------------------------
----------
Your app uses intermediary currency to purchase items that function as non-consumable products but does not include a restore mechanism.
Users restore transactions to maintain access to content that they've already purchased.
----------
Next Steps
To resolve this issue, please modify your app to include an optional user-registration feature that allows users to restore their purchases to all of their iOS devices.
We recommend indicating that account registration is necessary to restore previously purchased in-app purchase products and providing a way for users to register later if they wish to access this content in the future.
Please see attached screenshot for details.
----------
Bug Fix Submissions
If this is a bug fix submission and you'd like to have it approved at this time, reply to this message in Resolution Center to let us know. You do not need to resubmit your app for us to proceed.
Alternatively, if you'd like to resolve these issues now, please feel free to resubmit. Let us know if you have any questions about the issues we found in our review.
You may appeal your app rejection if you believe this decision was made incorrectly. We also invite you to provide feedback on our review guidelines."
----------
![alt text][1]
[1]: /storage/temp/183823-attachmentscreenshot-0721-102618-min.png
↧
↧
I'm looking for UDP store name list
UDP publish apk to markets:
Samsung Galaxy Store
HUAWEI AppGallery
ONE store
etc...
for each store StoreService.StoreName returns specific value
on Samsung market StoreService.StoreName = "SamsungGalaxyStore"
I need full StoreName list for each UDP markets
↧
Migrating IAP according to documentation gives console error.
**Background**
I am trying to upgrade an old project to use the new IAM, moving from Addon to using the Package manager version 3.x. I am using Unity 2019.4.19f1 and on a MacBook Pro.
Following these instructions (https://docs.unity3d.com/2019.4/Documentation/Manual/com.unity.purchasing.html)
**Problem**
I got to step 3 but after deleting the whole folder with the subfolders, Assets/Plugins/UnityPurchasing/*
I had to go back and restore a specific file since the editor was complaining about it:
It feels like there is some reset that needs to be done, or some refresh / regeneration of folders?
I did also use the Windows -> Unity IAP -> Delete for/Prepare for upgrade to 3 option.
**The Error from Console is pasted below for reference**
DirectoryNotFoundException: Could not find a part of the path “/PATH_TO_PROJECT/Assets/Plugins/UnityPurchasing/Editor/IAPUpdaterPreferences.json". System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) (at <9577ac7a62ef43179789031239ba8798>:0) System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options, System.String msgPath, System.Boolean bFromProxy, System.Boolean useLongPath, System.Boolean checkHost) (at <9577ac7a62ef43179789031239ba8798>:0) (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions,string,bool,bool,bool) System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks, System.Int32 bufferSize, System.Boolean checkHost) (at <9577ac7a62ef43179789031239ba8798>:0) System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks, System.Int32 bufferSize) (at <9577ac7a62ef43179789031239ba8798>:0) System.IO.StreamReader..ctor (System.String path, System.Boolean detectEncodingFromByteOrderMarks) (at <9577ac7a62ef43179789031239ba8798>:0) System.IO.StreamReader..ctor (System.String path) (at <9577ac7a62ef43179789031239ba8798>:0) (wrapper remoting-invoke-with-check) System.IO.StreamReader..ctor(string) System.IO.File.ReadAllText (System.String path) (at <9577ac7a62ef43179789031239ba8798>:0) UnityEditor.Purchasing.UnityIAPUpdater.LoadPreferences (System.Boolean& autoCheck, System.String& skipVersion) (at <2d7779cb8f3840989e79e2ad6995b2c7>:0) UnityEditor.Purchasing.UpdaterWindow:Init()
↧
IAP subscription not working on mobile devices
Hi,
So I Integrated Unity In-app purchases for my project I am working on and actually it works great, except for the subscription part.
It works great in the editor as it fetches the price from the store and also allows me to purchase the subscription and shows me the dialog box for this. But, when I make a build, upload it to the dev console for internal testing, and try the app, just the subscription part does not work. It does not fetch the price from the store and when I try to buy something, nothing happens. Except that the entire IAP system works fine. All the consumable and non-consumable items fetch the price from the store and show me the default google purchase UI when I try to buy. I don't know why the subscription doesn't work? Also, it just shows me the price as 0.
This is my IAPPurchaser Script
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Security;
public class Purchaser : MonoBehaviour, 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 kProductIDConsumable100Tokens = "consumable100_tokens";
public static string kProductIDConsumable500Tokens = "consumable500_tokens";
public static string kProductIDConsumable1000Tokens = "consumable1000_tokens";
public static string kProductIDNonConsumableNoAds = "nonconsumable_noads";
public static string kProductIDNonConsumableFullAccess = "nonconsumable_fullaccess";
public static string kProductIDSubscription = "weekly_subscription_1";
// Apple App Store-specific product identifier for the subscription product.
private static string kProductNameAppleSubscription = "com.unity3d.subscription.weekly_subscription_1";
// Google Play Store-specific product identifier subscription product.
private static string kProductNameGooglePlaySubscription = "com.unity3d.subscription.weekly_subscription_1";
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(kProductIDConsumable100Tokens, ProductType.Consumable);
builder.AddProduct(kProductIDConsumable500Tokens, ProductType.Consumable);
builder.AddProduct(kProductIDConsumable1000Tokens, ProductType.Consumable);
// Continue adding the non-consumable product.
builder.AddProduct(kProductIDNonConsumableNoAds, ProductType.NonConsumable);
builder.AddProduct(kProductIDNonConsumableFullAccess, 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);
}
public bool IsInitialized()
{
// Only say we are initialized if both the Purchasing references are set.
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void Buy100Tokens()
{
// Buy the consumable product using its general identifier. Expect a response either
// through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable100Tokens);
}
public void Buy500Tokens()
{
// Buy the consumable product using its general identifier. Expect a response either
// through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable500Tokens);
}
public void Buy1000Tokens()
{
// Buy the consumable product using its general identifier. Expect a response either
// through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDConsumable1000Tokens);
}
public void BuyNoAds()
{
// Buy the non-consumable product using its general identifier. Expect a response either
// through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDNonConsumableNoAds);
}
public void BuyFullAccess()
{
// Buy the non-consumable product using its general identifier. Expect a response either
// through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDNonConsumableFullAccess);
}
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();
// Begin the asynchronous process of restoring purchases. Expect a confirmation response in
// the Action 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");
MenuUIHandler.instance.UpdateStorePricing();
// 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, kProductIDConsumable100Tokens, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// The consumable item has been successfully purchased, add 100 Tokens to the player's in-game score.
GameDataStore.tokens += 100;
MenuUIHandler.instance.UpdateTokenUI();
}
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable500Tokens, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// The consumable item has been successfully purchased, add 500 Tokens to the player's in-game score.
GameDataStore.tokens += 500;
MenuUIHandler.instance.UpdateTokenUI();
}
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable1000Tokens, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// The consumable item has been successfully purchased, add 1000 Tokens to the player's in-game score.
GameDataStore.tokens += 1000;
MenuUIHandler.instance.UpdateTokenUI();
}
// Or ... a non-consumable product has been purchased by this user.
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumableNoAds, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
FindObjectOfType().removedAds_enabled = true;
FindObjectOfType().SaveSettings();
FindObjectOfType().RemoveAdSection.SetActive(false);
FindObjectOfType().RemoveAdSection_2.SetActive(false);
FindObjectOfType().StoreRemoveAds.SetActive(false);
// TODO: The non-consumable item has been successfully purchased, grant this item to the player.
}
// Or ... a non-consumable product has been purchased by this user.
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumableFullAccess, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
FindObjectOfType().full_access_purchased = true;
FindObjectOfType().SaveSettings();
FindObjectOfType().RemoveAdSection.SetActive(false);
FindObjectOfType().RemoveAdSection_2.SetActive(false);
FindObjectOfType().StoreBuySubsButton.SetActive(false);
FindObjectOfType().StoreRemoveAds.SetActive(false);
MenuUIHandler.instance.hardModeBeforeLevelUnlocked.gameObject.SetActive(false);
MenuUIHandler.instance.hardModeAfterLevelUnlocked.gameObject.SetActive(true);
GameDataStore.hardModeAvailable = true;
LoadingSceneLoader.instance.LoadMenu();
// 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, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
FindObjectOfType().subscription_purchased = true;
FindObjectOfType().SaveSettings();
FindObjectOfType().RemoveAdSection.SetActive(false);
FindObjectOfType().RemoveAdSection_2.SetActive(false);
FindObjectOfType().StoreBuySubsButton.SetActive(false);
FindObjectOfType().StoreRemoveAds.SetActive(false);
MenuUIHandler.instance.hardModeBeforeLevelUnlocked.gameObject.SetActive(false);
MenuUIHandler.instance.hardModeAfterLevelUnlocked.gameObject.SetActive(true);
DailyRewardManager.instance.InitializeRewardManager();
GameDataStore.hardModeAvailable = true;
LoadingSceneLoader.instance.LoadMenu();
// 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.
SaveSystem.Save();
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 string GetProductPriceFromStore(string id)
{
if (IsInitialized())
return m_StoreController.products.WithID(id).metadata.isoCurrencyCode + " " + m_StoreController.products.WithID(id).metadata.localizedPrice;
else
{
return "UnDefined";
}
}
}
↧
Android IAP Cannot confirm purchase due to missing transaction id
I am implementing server-side IAP verification and having an issue when it comes time to call ConfirmPendingPurchase, which returns the following error in the logs...
`Unable to confirm purchase; Product has missing or empty transactionID`
Here is a step-by-step sequence of events:
1. Initiate purchase
2. (user completes purchase with store UI, payment, etc)
3. `ProcessPurchase(PurchaseEventArgs e)` is called, details of transaction are sent to server I return `PurchaseProcessingResult.Pending`
4. Server verification is successful
5. Call `ConfirmPendingPurchase(product)` after looking up product by id
6. Error and purchase it ultimately cancelled due to not being acknowledged
Logging reveals to transactionID is present and valid in all steps except #5 onward. Something is clearing the transactionID between the time Pending is returned and message is sent to server and when product is looked up for confirmation.
Any ideas welcome and appreciated!
Unity 2020.2.1f1
Unity IAP 2.2.1
↧
↧
Why is my UDP sandbox login still popping up?
I am using IAP with UDP. My initial UDP login that I put in my opening script (suggested to be put in GameManager script),
StoreService.Initialize(listener);
I commented out. But when I go to my IAP screen, the login pops up.
There must be some Store Service Initializer not in my scripts.
I had two people play my game downloaded from the google play store and both had this pop up on them.
How do I get the login to not pop up?
↧
Last unity iap version bug !
**unity IAP for UWP build "Initialized" but return google play error on windows 10 platform when try buying .**
![alt text][1]
**I use the Last "Sample IAP Project" and Last unityIap this is my code:**
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.UI;
using UnityEngine.Purchasing.Security;
public class MyIAPManager : MonoBehaviour, IStoreListener
{
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider; subsystems.
private IAppleExtensions m_AppleExtensions;
private IGooglePlayStoreExtensions m_GoogleExtensions;
private IMicrosoftExtensions m_MicrosoftExtensions;
public static string RemoveAds = "RemoveAds";
public static string GOLD_50 = "gold50";
public static string NONCONSUMABLE1 = "nonconsume1";
public static string WEEKLYSUB = "weeklysub";
public Text myText;
void Awake()
{
}
void Start()
{
// If we haven't set up the Unity Purchasing reference
if (m_StoreController == null)
{
// Begin to configure our connection to Purchasing, can use button click instead
//InitializePurchasing();
}
}
public void MyInitialize()
{
InitializePurchasing();
}
public void InitializePurchasing()
{
if (IsInitialized())
{
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.Configure().useMockBillingSystem = true;
builder.AddProduct(RemoveAds, ProductType.Consumable);
MyDebug("Starting Initialized...");
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuySubscription()
{
BuyProductID(WEEKLYSUB);
}
public void BuyGold50()
{
BuyProductID(RemoveAds);
}
public void BuyNonConsumable()
{
BuyProductID(NONCONSUMABLE1);
}
public void RestorePurchases()
{
m_StoreExtensionProvider.GetExtension().RestoreTransactions(result => {
if (result)
{
MyDebug("Restore purchases succeeded.");
}
else
{
MyDebug("Restore purchases failed.");
}
});
}
void BuyProductID(string productId)
{
if (IsInitialized())
{
UnityEngine.Purchasing.Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
MyDebug(string.Format("Purchasing product:" + product.definition.id.ToString()));
m_StoreController.InitiatePurchase(product);
}
else
{
MyDebug("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
MyDebug("BuyProductID FAIL. Not initialized.");
}
}
public void ListProducts()
{
foreach (UnityEngine.Purchasing.Product item in m_StoreController.products.all)
{
if (item.receipt != null)
{
MyDebug("Receipt found for Product = " + item.definition.id.ToString());
}
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
MyDebug("OnInitialized: PASS");
m_StoreController = controller;
m_StoreExtensionProvider = extensions;
m_AppleExtensions = extensions.GetExtension();
m_GoogleExtensions = extensions.GetExtension();
m_MicrosoftExtensions = extensions.GetExtension();
m_GoogleExtensions?.SetDeferredPurchaseListener(OnPurchaseDeferred);
Dictionary dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
foreach (UnityEngine.Purchasing.Product item in controller.products.all)
{
if (item.receipt != null)
{
string intro_json = (dict == null || !dict.ContainsKey(item.definition.storeSpecificId)) ? null : dict[item.definition.storeSpecificId];
if (item.definition.type == ProductType.Subscription)
{
SubscriptionManager p = new SubscriptionManager(item, intro_json);
SubscriptionInfo info = p.getSubscriptionInfo();
MyDebug("SubInfo: " + info.getProductId().ToString());
MyDebug("isSubscribed: " + info.isSubscribed().ToString());
MyDebug("isFreeTrial: " + info.isFreeTrial().ToString());
}
}
}
}
public void OnPurchaseDeferred(Product product)
{
MyDebug("Deferred product " + product.definition.id.ToString());
}
public void OnInitializeFailed(InitializationFailureReason error)
{
// Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
MyDebug("OnInitializeFailed InitializationFailureReason:" + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
try
{
Debug.Log("Application.identifier="+ Application.identifier);
var validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier);
var result = validator.Validate(args.purchasedProduct.receipt);
MyDebug("Validate = " + result.ToString());
foreach (IPurchaseReceipt productReceipt in result)
{
MyDebug("Valid receipt for " + productReceipt.productID.ToString());
}
}
catch (Exception e)
{
MyDebug("Error is " + e.Message.ToString());
}
MyDebug(string.Format("ProcessPurchase: " + args.purchasedProduct.definition.id));
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(UnityEngine.Purchasing.Product product, PurchaseFailureReason failureReason)
{
MyDebug(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
private void MyDebug(string debug)
{
Debug.Log(debug);
myText.text += "\r\n" + debug;
}
}
please help thnx.
[1]: /storage/temp/185451-sd.png
↧
Getting a lot of payment declined after updating APP (using Unity IAP)
Hi,
I seem to have an unusual number of "payment declined" errors in my Google Play Developer Console after uploading a new version of my app to the Playstore.
These are from people that appear to be able to make purchases successfully in the old version, yet fail to since the update:
![alt text][1]
I notice in the case of this particular individual, they have not updated the app, meaning, that the version number which they are running is not the same as the live version on the store. I note that such discrepancies cause payment issues in a test environment so wondered if this could be somehow related. The solution might be to force everyone to update to the latest version, yet I know of many apps that don't do this. We had the same issue with our last app update with regular purchasers getting repeat declines and only since using Unity IAP. Our previous prime31 solution seemed to transition better between updates.
I'm sorry I can't be more precise describing this only we don't get a whole lot of purchases. If this sounds like it could be symptomatic of anything in particular that we could focus on I'd appreciate any help or ideas.
[1]: /storage/temp/186948-122.png
↧
Unity IAP .isSubscribed() is always true?
Unity IAP, latest Unity, latest IAP... it seems `.isSubscribed()` is always true? How does one find out whether a user has actually subscribed to an IAP product?
```
for(int i = 0; i < subscription_product_id.Length; i++){
SubscriptionInfo si = new SubscriptionInfo(subscription_product_id[i]);
print(si.isSubscribed() + " " + si.isCancelled());
}
```
↧
↧
Does an app have to be published for IAP to work?
I have been testing my app in Internal Testing on the Google Play Developer Console and I have not published it yet, I set up my merchant account and assigned licensed testers. However, when I try to purchase something on the test build of the app, it says "The item you requested is not available for purchase". Keep in mind that this is my first time using IAP so I really don't know what I'm doing.
↧
Unity IAP Google Play acknowledge the purchase
Hi, recently when I integrated IAP into my game and when I put it on Google Play store Google asked to acknowledge the purchase or the order will be refunded. But I found no instructions for acknowledge the purchase for C# code in Unity. Can someone help me. Thanks very much. (I'm on Unity IAP 4.1.0).
https://developer.android.com/google/play/billing/integrate#acknowledge
↧
StoreController.products not returning subscriptions from Google Play.
I set up subscriptions in Google Play but they're not showing up in my game. Anyone faced this? Thanks.
↧