- Home /
Guideline 2.1 - Performance - App Completeness
We found that your in-app purchase products still exhibited one or more bugs when reviewed on iPad running iOS 14.3 on Wi-Fi.
Specifically, your App displayed an error alert when we tapped to buy In-app purchase.
IAP is working on my device, I tried to solve the problem in many ways but they still rejecting the build with this message.
I'm validating the receipt in the backend Any help?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Nrjwolf.Tools;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Security;
using UnityEngine.UI;
using SimpleJSON;
using Duck.Http;
using Duck.Http.Service;
public class IAPManager : MonoBehaviour, IStoreListener
{
private const string API_URL = "api";
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
//Step 1 create your products
private string vipForever = "vipforever";
public string vipForeverPrice = "0";
public Text upgradeText;
public GameObject initPanel;
private bool showRestore = false;
private string restoreMessage = "";
//************************** Adjust these methods **************************************
private void HandleSuccess(HttpResponse response)
{
JSONNode receiptData = JSON.Parse(response.Text);
if (receiptData["code"] == 200)
{
foreach (JSONNode iap in receiptData["in_app"].Children)
{
if (iap == vipForever)
{
PlayerPrefs.SetInt("vip_purchase", 1);
}
}
}
}
void checkRecipt(string receipt)
{
JSONObject reciptDic = new JSONObject();
reciptDic.Add("receipt", receipt);
string bodyJsonString = reciptDic.ToString();
Http.PostJson(API_URL + "checkReceipt", bodyJsonString).OnSuccess(HandleSuccess)
.OnError(response => Debug.Log(response.StatusCode))
.Send();
}
public void InitializePurchasing()
{
if (IsInitialized()) { return; }
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
//Step 2 choose if your product is a consumable or non consumable
builder.AddProduct(vipForever, ProductType.NonConsumable);
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
//Step 3 Create methods
public void getVipForever()
{
BuyProductID(vipForever);
}
public void purchasePack(string packName)
{
BuyProductID(packName);
}
//Step 4 modify purchasing
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
// Unity IAP's validation logic is only included on these platforms.
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
//Get a reference to IAppleConfiguration during IAP initialization.
var appleConfig = builder.Configure<IAppleConfiguration>();
try
{
var receiptData = Convert.FromBase64String(appleConfig.appReceipt);
AppleReceipt receipt = new AppleValidator(AppleTangle.Data()).Validate(receiptData);
foreach (AppleInAppPurchaseReceipt productReceipt in receipt.inAppPurchaseReceipts)
{
if (productReceipt.productID == vipForever)
{
PlayerPrefs.SetInt("vip_purchase", 1);
Scenes.Load("HomeScreen");
}
}
}
catch (FormatException e)
{
}
return PurchaseProcessingResult.Complete;
}
//**************************** Dont worry about these methods ***********************************
void Start()
{
// If we haven't set up the Unity Purchasing reference
if (m_StoreController == null)
{
// Begin to configure our connection to Purchasing
InitializePurchasing();
}
}
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
{
showRestore = true;
restoreMessage = "Cannot purchase this item, Please check your internet connection or your account";
Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
}
}
else
{
showRestore = true;
restoreMessage = "Cannot initialize Billing settings! Please check your internet connection or your account";
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) =>
{
if (!result)
{
showRestore = true;
restoreMessage = "You don't have any purchases!";
//IOSNativeAlert.ShowAlertMessage("Restore Purchases", );
}
else
{
showRestore = true;
restoreMessage = "Your purchases had been restored. You can restart the game.";
//IOSNativeAlert.ShowAlertMessage("Restore Purchases", "Your purchases had been restored. You can restart the game.");
}
});
}
else
{
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
private void OnGUI()
{
if (showRestore)
{
#if UNITY_IOS
IOSNativeAlert.ShowAlertMessage("Patterns Puzzles", restoreMessage);
showRestore = false;
#endif
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
initPanel.SetActive(false);
m_StoreController = controller;
m_StoreExtensionProvider = extensions;
vipForeverPrice = controller.products.WithID(vipForever).metadata.localizedPrice.ToString() + " " + controller.products.WithID(vipForever).metadata.isoCurrencyCode;
upgradeText.text = "Upgrade For " + vipForeverPrice;
extensions.GetExtension<IAppleExtensions>().RefreshAppReceipt(receipt =>
{
// This handler is invoked if the request is successful.
// Receipt will be the latest app receipt.
checkRecipt(receipt);
},
() =>
{
// This handler will be invoked if the request fails,
// such as if the network is unavailable or the user
// enters the wrong password.
showRestore = true;
restoreMessage = "Cannot initialize Billing settings! Please check your internet connection or your account";
});
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
//showRestore = true;
//restoreMessage = "Cannot initialize Billing settings! Please check your internet connection or your account";
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
}
Comment