
- Is GrantCredits called after the user’s credit card is charged? Or, is there a different way to verify the purchase?
- Once I verify a successful purchase, do I store that info locally on the device?

Yes, GrantCredits will be called after a successful purchase. You can also handle purchases by implementing the IStoreListener interface.
If the product type is Non-Consumable or Subscription, you can check and process the product after the next initialization.
If the product type is Consumable, you need to save the purchase. You can choose to save your purchases to the cloud or locally. Please be aware that saving purchases locally risk data loss or tampering.
Thanks for the info. That is very helpful.
If a user purchases a Non-Consumable or Subscription, the GrantCredits method will be called every time the user starts the app? Is this dependent on an internet connection?
So, the GrantCredits method would be a good place to call something like HidePaymentButton? Or, if I want to hide the payment button, is it better to use something like IStoreController.products.WithID(productId).hasReceip?
Because of the limited functionality of Codeless IAP, I suggest you use Code IAP instead of Codeless IAP.
*If a user purchases a Non-Consumable or Subscription, the GrantCredits method will be called every time the user starts the app?
No, the GrantCredits method only processes purchases that have not been completed at the next initialization.
If you want to check Non-Consumable or Subscription purchases, you can check after IAP initialization.
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
this.controller = controller;
this.extensions = extensions;
CheckPurchasedProducts();
}
private void CheckPurchasedProducts()
{
foreach (Product product in controller.products.all)
{
if (product.hasReceipt == true)
{
if (product.definition.type == ProductType.NonConsumable)
{
ProcessNonConsumableProduct(product);
}
else if (product.definition.type == ProductType.Subscription)
{
ProcessSubscriptionProduct(product);
}
}
}
}
*Is this dependent on an internet connection?
Yes
*So, the GrantCredits method would be a good place to call something like HidePaymentButton? Or, if I want to hide the payment button, is it better to use something like IStoreController.products.WithID(productId).hasReceip?
You can use the GrantCredits method hide button after purchase and use the IStoreController.products.WithID(productId).hasReceip hide button on the next launch.
how can I make a IAP Subscription code in unity 2019.1.9 for google play ,
means when he buy 5000 score subscription so add 5000 score to UIManager but it expired so back scores ? I do not using subscription so far ,I want if subscriptions was for 2 months call it after first month and add 5000 score for second month too, and when it was expired so it be 0 score
help me please
Is this code correct?
```csharp
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using CodeStage.AntiCheat.ObscuredTypes;
public class ShopManager2 : MonoBehaviour,IStoreListener
{ public static ShopManager2 Instance{ set; get;}
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
public static string kProductIDConsumable = "consumable";
public static string kProductIDNonConsumable = "nonconsumable";
public static string kProductIDSubscription = "subscription";
private static string kProductNameAppleSubscription="com.unity3d.subscription.new";
private static string kProductNameGooglePlaySubscription ="com.company.s.subscription.zshahin";
void Start()
{
if (m_StoreController == null)
{
InitializePurchasing();
}
}
public void InitializePurchasing()
{
if (IsInitialized())
{
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct(kProductIDConsumable, ProductType.Consumable);
builder.AddProduct(kProductIDNonConsumable, ProductType.NonConsumable);
builder.AddProduct(kProductIDSubscription, ProductType.Subscription, new IDs(){
{ kProductNameAppleSubscription, AppleAppStore.Name },
{ kProductNameGooglePlaySubscription, GooglePlay.Name },
});
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyConsumable()
{
BuyProductID(kProductIDConsumable);
}
public void BuyNonConsumable()
{
BuyProductID(kProductIDNonConsumable);
}
public void BuySubscription()
{
BuyProductID(kProductIDSubscription);
}
void BuyProductID(string productId)
{
if (IsInitialized())
{
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
m_StoreController.InitiatePurchase(product);
}
else
{
Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
public void RestorePurchases()
{
if (!IsInitialized())
{
Debug.Log("RestorePurchases FAIL. Not initialized.");
return;
}
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.OSXPlayer)
{
Debug.Log("RestorePurchases started ...");
var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
apple.RestoreTransactions((result) => {
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
});
}
else
{
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
Debug.Log("OnInitialized: PASS");
m_StoreController = controller;
m_StoreExtensionProvider = extensions;
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{ //This can be called anytime after initialization
//And it should probably be limited to Google Play and not just Android
#if UNITY_ANDROID
foreach (Product p in m_StoreController.products.all) {
GooglePurchaseData data = new GooglePurchaseData(p.receipt);
if (p.hasReceipt) {
Debug.Log(data.json.autoRenewing);
Debug.Log(data.json.orderId);
Debug.Log(data.json.packageName);
Debug.Log(data.json.productId);
Debug.Log(data.json.purchaseTime);
Debug.Log(data.json.purchaseState);
Debug.Log(data.json.purchaseToken);
}
}
#endif
if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, kProductIDSubscription, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else
{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
}
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason);
{
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
}
You can check if the user has purchased a subscription, if it is then add 5000 score, otherwise do not add.
/// <summary>
/// This will be called when Unity IAP has finished initialising.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
m_Controller = controller;
m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
foreach (var item in controller.products.all)
{
if (item.availableToPurchase)
{
// this is the usage of SubscriptionManager class
if (item.receipt != null)
{
if (item.definition.type == ProductType.Subscription)
{
string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
try
{
SubscriptionManager p = new SubscriptionManager(item, intro_json);
SubscriptionInfo info = p.getSubscriptionInfo();
{
if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add 5000 score, otherwise do not add
{
Add5000Scrore();
}
}
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
else
{
Debug.Log("the product is not a subscription product");
}
}
else
{
Debug.Log("the product should have a valid receipt");
}
}
}
}
ok I wrote a new script , is this correct?
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;
using UnityEngine.Purchasing;
public class ShopManager2 : MonoBehaviour, IStoreListener
{ public static ShopManager2 Instance{ set; get;}
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
public static string em_1000s = "com.company.ss.1000s";
public static string em_2000s = "com.company.ss.2000s";
public static string PRODUCT_Removeadss = "com.company.ss.xxx";
public static string ProductIDConsumable = "consumable";
public static string ProductIDNonConsumable = "nonconsumable";
public static string ProductIDSubscription = "subscription";
private void Awake(){
Instance = this;
}
void Start()
{
if (m_StoreController == null)
{
InitializePurchasing();
}
}
public void InitializePurchasing()
{
if (IsInitialized())
{
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct(ProductIDConsumable, ProductType.Consumable);
builder.AddProduct(em_1000s, ProductType.Consumable);
builder.AddProduct(em_2000s, ProductType.Consumable);
builder.AddProduct(PRODUCT_Removeadss, ProductType.Consumable);
builder.AddProduct(ProductIDNonConsumable, ProductType.NonConsumable);
builder.AddProduct(ProductIDSubscription, ProductType.Subscription);
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyConsumable()
{
BuyProductID(ProductIDConsumable);
}
public void BuyNonConsumable()
{
BuyProductID(ProductIDNonConsumable);
}
public void BuySubscription()
{
BuyProductID(ProductIDSubscription);
}
public void em_1000ss()
{
BuyProductID(em_1000s);
}
public void em_2000ss()
{
BuyProductID(em_2000s);
}
public void removeadsss()
{
BuyProductID(PRODUCT_Removeadss);
}
void BuyProductID(string productId)
{
if (IsInitialized())
{ //This can be called anytime after initialization
//And it should probably be limited to Google Play and not just Android
#if UNITY_ANDROID
foreach (Product p in m_StoreController.products.all) {
GooglePurchaseData data = new GooglePurchaseData(p.receipt);
if (p.hasReceipt) {
Debug.Log(data.json.autoRenewing);
Debug.Log(data.json.orderId);
Debug.Log(data.json.packageName);
Debug.Log(data.json.productId);
Debug.Log(data.json.purchaseTime);
Debug.Log(data.json.purchaseState);
Debug.Log(data.json.purchaseToken);
}
}
#endif
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
m_StoreController.InitiatePurchase(product);
}
else
{
Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
public void RestorePurchases()
{
if (!IsInitialized())
{
Debug.Log("RestorePurchases FAIL. Not initialized.");
return;
}
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.OSXPlayer)
{
Debug.Log("RestorePurchases started ...");
var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
apple.RestoreTransactions((result) => {
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
});
}
else
{
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
m_Controller = controller;
m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
foreach (var item in controller.products.all)
{
if (item.availableToPurchase)
{
if (item.receipt != null)
{
if (item.definition.type == ProductType.Subscription)
{
string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
try
{
SubscriptionManager p = new SubscriptionManager(item, intro_json);
SubscriptionInfo info = p.getSubscriptionInfo();
{
if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add 5000 score, otherwise do not add
{
Add5000Scrore();
}
}
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
else
{
Debug.Log("the product is not a subscription product");
}
}
else
{
Debug.Log("the product should have a valid receipt");
}
}
}
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
if (String.Equals(args.purchasedProduct.definition.id, ProductIDConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, ProductIDNonConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, ProductIDSubscription, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
if (String.Equals(args.purchasedProduct.definition.id,emtiaz_1000s, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,emtiaz_2000s, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,PRODUCT_Removeadss, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
{
addscore=5000 ;
}
else
{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
}
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
public void Add5000Scrore(){
add=5000;
}
}
2- and is this script must be in my script ( at above ) or I can remove it?:
//This can be called anytime after initialization
//And it should probably be limited to Google Play and not just Android
#if UNITY_ANDROID
foreach (Product p in m_StoreController.products.all) {
GooglePurchaseData data = new GooglePurchaseData(p.receipt);
if (p.hasReceipt) {
Debug.Log(data.json.autoRenewing);
Debug.Log(data.json.orderId);
Debug.Log(data.json.packageName);
Debug.Log(data.json.productId);
Debug.Log(data.json.purchaseTime);
Debug.Log(data.json.purchaseState);
Debug.Log(data.json.purchaseToken);
}
}
#endif
answer to 2 questions
You use the GooglePurchaseData in the wrong place. This is used to verify the receipt, you should use it in ProcessPurchase. [Closed] How do I track auto-renewing subscriptions?
And, you can use another way to verify the receipt: Unity - Manual: Receipt validation
void BuyProductID(string productId)
{
if (IsInitialized())
{ //This can be called anytime after initialization
//And it should probably be limited to Google Play and not just Android
#if UNITY_ANDROID
foreach (Product p in m_StoreController.products.all) {
GooglePurchaseData data = new GooglePurchaseData(p.receipt);
if (p.hasReceipt) {
Debug.Log(data.json.autoRenewing);
Debug.Log(data.json.orderId);
Debug.Log(data.json.packageName);
Debug.Log(data.json.productId);
Debug.Log(data.json.purchaseTime);
Debug.Log(data.json.purchaseState);
Debug.Log(data.json.purchaseToken);
}
}
#endif
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
m_StoreController.InitiatePurchase(product);
}
else
{
Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
Excuseme SamOYUnity3D,please write full script for me (5000 score and remove ads for weekly subscription in googleplay and amazon(if it is enabled on amazon ) ),because I am confusing,if it is 2 code Separately so please both of them thanks
We would not be able to write your code, you would want to hire someone. I already provided the code in the Sample project. Please get the Sample project working first. If you don’t get the basics working, then any customization won’t work either.
thanks for answer, ok , please help
SamOYUnity3D
, JeffDUnity3D, I am confusing ,I changed it so
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;
using UnityEngine.Purchasing;
public class ShopManager2 : MonoBehaviour, IStoreListener
{ public static ShopManager2 Instance{ set; get;}
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
public static string em_1000s = "com.company.ss.1000s";
public static string em_2000s = "com.company.ss.2000s";
public static string PRODUCT_Removeadss = "com.company.ss.xxx";
public static string ProductIDConsumable = "consumable";
public static string ProductIDNonConsumable = "nonconsumable";
public static string ProductIDSubscription = "subscription";
private void Awake(){
Instance = this;
}
void Start()
{
if (m_StoreController == null)
{
InitializePurchasing();
}
}
public void InitializePurchasing()
{
if (IsInitialized())
{
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct(ProductIDConsumable, ProductType.Consumable);
builder.AddProduct(em_1000s, ProductType.Consumable);
builder.AddProduct(em_2000s, ProductType.Consumable);
builder.AddProduct(PRODUCT_Removeadss, ProductType.Consumable);
builder.AddProduct(ProductIDNonConsumable, ProductType.NonConsumable);
builder.AddProduct(ProductIDSubscription, ProductType.Subscription);
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyConsumable()
{
BuyProductID(ProductIDConsumable);
}
public void BuyNonConsumable()
{
BuyProductID(ProductIDNonConsumable);
}
public void BuySubscription()
{
BuyProductID(ProductIDSubscription);
}
public void em_1000ss()
{
BuyProductID(em_1000s);
}
public void em_2000ss()
{
BuyProductID(em_2000s);
}
public void removeadsss()
{
BuyProductID(PRODUCT_Removeadss);
}
void BuyProductID(string productId)
{
if (IsInitialized())
{ //This can be called anytime after initialization
//And it should probably be limited to Google Play and not just Android
#if UNITY_ANDROID
foreach (Product p in m_StoreController.products.all) {
GooglePurchaseData data = new GooglePurchaseData(p.receipt);
if (p.hasReceipt) {
Debug.Log(data.json.autoRenewing);
Debug.Log(data.json.orderId);
Debug.Log(data.json.packageName);
Debug.Log(data.json.productId);
Debug.Log(data.json.purchaseTime);
Debug.Log(data.json.purchaseState);
Debug.Log(data.json.purchaseToken);
}
}
#endif
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
m_StoreController.InitiatePurchase(product);
}
else
{
Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
public void RestorePurchases()
{
if (!IsInitialized())
{
Debug.Log("RestorePurchases FAIL. Not initialized.");
return;
}
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.OSXPlayer)
{
Debug.Log("RestorePurchases started ...");
var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
apple.RestoreTransactions((result) => {
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
});
}
else
{
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
m_Controller = controller;
m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
foreach (var item in controller.products.all)
{
if (item.availableToPurchase)
{
if (item.receipt != null)
{
if (item.definition.type == ProductType.Subscription)
{
string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
try
{
SubscriptionManager p = new SubscriptionManager(item, intro_json);
SubscriptionInfo info = p.getSubscriptionInfo();
{
if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add 5000 score, otherwise do not add
{
Add5000Scrore();
}
}
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
else
{
Debug.Log("the product is not a subscription product");
}
}
else
{
Debug.Log("the product should have a valid receipt");
}
}
}
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
if (String.Equals(args.purchasedProduct.definition.id, ProductIDConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, ProductIDNonConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, ProductIDSubscription, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
if (String.Equals(args.purchasedProduct.definition.id,em_1000s, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,em_2000s, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,PRODUCT_Removeadss, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
{
addscore=5000 ;
}
else
{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
}
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
public void Add5000Scrore(){
add=5000;
}
}
I wrote it so is it correct, thanks
thanks
2- I thought this was a private conversation
Can I make this conversation private?
thanks
@shahin2019 I would not expect this code to compile. You have not defined addscore or add, for example. And you are not incrementing the value by 5000, you are directly assigning a value (to two separate variables), contrary to the instructions I sent you via DM. Is there a reason you are not following my suggestions? And again, you are awarding points in a subscription model? As mentioned before, this is an incorrect use of a subscription product. What if I use the 5000 points on the first day, do I wait until next week for my subscription to renew? Instead, you want to use a Consumable. If you want to turn off ads with a subscription, you would set a boolean, like showAds = false; Please get the Sample IAP project working first with a single Consumable product, THEN add your customizations. This is common programming practice, get the basics working first!
OK , I use it for remove ads (bool)
thanks for answer, ok , please help
SamOYUnity3D
, JeffDUnity3D, I am confusing ,I changed it again so
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;
using UnityEngine.Purchasing;
public class ShopManager2 : MonoBehaviour, IStoreListener
{ public static ShopManager2 Instance{ set; get;}
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
public static string em_1000s = "com.company.ss.1000s";
public static string em_2000s = "com.company.ss.2000s";
public static string PRODUCT_Removeadss = "com.company.ss.xxx";
public static string ProductIDConsumable = "consumable";
public static string ProductIDNonConsumable = "nonconsumable";
public static string ProductIDSubscription = "subscription";
private void Awake(){
Instance = this;
}
void Start()
{
if (m_StoreController == null)
{
InitializePurchasing();
}
}
public void InitializePurchasing()
{
if (IsInitialized())
{
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct(ProductIDConsumable, ProductType.Consumable);
builder.AddProduct(em_1000s, ProductType.Consumable);
builder.AddProduct(em_2000s, ProductType.Consumable);
builder.AddProduct(PRODUCT_Removeadss, ProductType.Subscription);
builder.AddProduct(ProductIDNonConsumable, ProductType.NonConsumable);
builder.AddProduct(ProductIDSubscription, ProductType.Subscription);
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyConsumable()
{
BuyProductID(ProductIDConsumable);
}
public void BuyNonConsumable()
{
BuyProductID(ProductIDNonConsumable);
}
public void BuySubscription()
{
BuyProductID(ProductIDSubscription);
}
public void em_1000ss()
{
BuyProductID(em_1000s);
}
public void em_2000ss()
{
BuyProductID(em_2000s);
}
public void removeadsss()
{
BuyProductID(PRODUCT_Removeadss);
}
void BuyProductID(string productId)
{
if (IsInitialized())
{ //This can be called anytime after initialization
//And it should probably be limited to Google Play and not just Android
#if UNITY_ANDROID
foreach (Product p in m_StoreController.products.all) {
GooglePurchaseData data = new GooglePurchaseData(p.receipt);
if (p.hasReceipt) {
Debug.Log(data.json.autoRenewing);
Debug.Log(data.json.orderId);
Debug.Log(data.json.packageName);
Debug.Log(data.json.productId);
Debug.Log(data.json.purchaseTime);
Debug.Log(data.json.purchaseState);
Debug.Log(data.json.purchaseToken);
}
}
#endif
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
m_StoreController.InitiatePurchase(product);
}
else
{
Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
public void RestorePurchases()
{
if (!IsInitialized())
{
Debug.Log("RestorePurchases FAIL. Not initialized.");
return;
}
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.OSXPlayer)
{
Debug.Log("RestorePurchases started ...");
var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
apple.RestoreTransactions((result) => {
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
});
}
else
{
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
m_Controller = controller;
m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
foreach (var item in controller.products.all)
{
if (item.availableToPurchase)
{
if (item.receipt != null)
{
if (item.definition.type == ProductType.Subscription)
{
string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
try
{
SubscriptionManager p = new SubscriptionManager(item, intro_json);
SubscriptionInfo info = p.getSubscriptionInfo();
{
if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add showAds , otherwise do not add
{
Ads ();
}
}
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
else
{
Debug.Log("the product is not a subscription product");
}
}
else
{
Debug.Log("the product should have a valid receipt");
}
}
}
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
if (String.Equals(args.purchasedProduct.definition.id, ProductIDConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, ProductIDNonConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
else if (String.Equals(args.purchasedProduct.definition.id, ProductIDSubscription, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
}
if (String.Equals(args.purchasedProduct.definition.id,em_1000s, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,em_2000s, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,PRODUCT_Removeadss, StringComparison.Ordinal))
{
}
else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
{
if(ui.showads==false){ui.showads=true;//ui is a other script}
}
else
{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
}
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
public void ads(){
ui.showAds = true;//ui is a other script
}
}
I wrote it so is it correct, thanks
1- should I use “subscription” here:
"
else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
{
if(showads==false){showads=true;}
}
"
or here: "
if (info.getProductId() == “YourProductID”)//If the user purchases a subscription, add showAds , otherwise do not add
{
Ads ();
"
Where is the right place for this instruction?
thanks
2- I thought this was a private conversation
Can I make this conversation private?
thanks
@shahin2019 Please DO NOT continue to send private emails when you been directly asked not to. If you continue to do so, you will get blocked here on the forum. If you are not able or willing to follow out suggestions, we would not be able to assist. In your logic you just showed, you set showAds = true just after they purchased a subscription to not show ads. This is incorrect logic. You also have a series of If/Else statements with no code associated with the logic. In summary, get the Sample IAP project working FIRST, without ANY changes (except the product names), THEN add your customization. You want to award your products in ProcessPurchase, this is the event that is triggered when a user makes a purchase, please confirm in your testing with the Sample IAP project, coded without any changes. Publish on Google Play first, it’s easiest. And also you’ll want to learn how to capture device logs, they will be invaluable for troubleshooting later on, once you get it working. These links may help How To - Capturing Device Logs on Android and Unity - Manual: Configuring for Google Play Store