Skip to content

Instantly share code, notes, and snippets.

@AddyDaDaddy
Last active March 30, 2017 08:58
Show Gist options
  • Save AddyDaDaddy/0b88a72d414f334388d7f101b8780f29 to your computer and use it in GitHub Desktop.
Save AddyDaDaddy/0b88a72d414f334388d7f101b8780f29 to your computer and use it in GitHub Desktop.
Implement Receipt Validation
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Analytics;
namespace CompleteProject
{
// Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing.
public class Purchaser : MonoBehaviour, IStoreListener
{
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
public static string kProductIDNonConsumable = "MYIDFORPURCHASE";
void Start()
{
// If we haven't set up the Unity Purchasing reference
if (m_StoreController == null)
{
InitializePurchasing();
}
}
public void InitializePurchasing()
{
// If we have already connected to Purchasing ...
if (IsInitialized())
{
// ... we are done here.
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
// Continue adding the non-consumable product.
builder.AddProduct(kProductIDNonConsumable, ProductType.NonConsumable);
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
// Only say we are initialized if both the Purchasing references are set.
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyNonConsumable()
{
BuyProductID(kProductIDNonConsumable);
}
void BuyProductID(string productId)
{
// If Purchasing has been initialized ...
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
{
// ... report the product look-up failure situation
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 Purchasing has not yet been set up ...
if (!IsInitialized())
{
Debug.Log("RestorePurchases FAIL. Not initialized.");
return;
}
// If we are running on an Apple device ...
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);
}
}
//
// --- IStoreListener
//
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)
{
//a non-consumable product has been purchased by this user.
if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumable, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
// TODO: The non-consumable item has been successfully purchased, grant this item to the player.
if (DataObject.instance == null)
{
DataObject.instance = new DataObject();
DataObject.instance.Load();
}
DataObject.instance.adsRemoved = true;
Debug.Log("Ads Removed");
EndlessButton.SetActive (true); // This is set to false on first start, and true after pruchase.
DataObject.instance.Save();
}
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));
if (DataObject.instance == null)
{
DataObject.instance = new DataObject();
DataObject.instance.Load();
}
DataObject.instance.adsRemoved = false;
Debug.Log("Purchase Failed, Text is Remove Ads & Endless");
EndlessButton.SetActive (false); // This is set to false if purchase fails
DataObject.instance.Save();
}
}
}
@AddyDaDaddy
Copy link
Author

`using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Analytics;

namespace CompleteProject
{
// Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing.
public class Purchaser : MonoBehaviour, IStoreListener
{

    private static IStoreController m_StoreController;
    private static IExtensionProvider m_StoreExtensionProvider;

    public static string kProductIDNonConsumable = "MYIDFORPURCHASE";

    void Start()
    {

#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
// Get a reference to IAppleConfiguration during IAP initialization.
var appleConfig = builder.Configure();
var receiptData = System.Convert.FromBase64String(appleConfig.appReceipt);
AppleReceipt receipt = new AppleValidator(AppleTangle.Data()).Validate(receiptData);

Debug.Log(receipt.bundleID);
Debug.Log(receipt.receiptCreationDate);
foreach (AppleInAppPurchaseReceipt productReceipt in receipt.inAppPurchaseReceipts) {
Debug.Log(productReceipt.transactionIdentifier);
Debug.Log(productReceipt.productIdentifier);
}
#endif

       // If we haven't set up the Unity Purchasing reference
        if (m_StoreController == null)
        {
            InitializePurchasing();
        }
    }

    public void InitializePurchasing()
    {
        // If we have already connected to Purchasing ...
        if (IsInitialized())
        {
            // ... we are done here.
            return;
        }

        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

        // Continue adding the non-consumable product.
        builder.AddProduct(kProductIDNonConsumable, ProductType.NonConsumable);

        UnityPurchasing.Initialize(this, builder);
    }


    private bool IsInitialized()
    {
        // Only say we are initialized if both the Purchasing references are set.
        return m_StoreController != null && m_StoreExtensionProvider != null;
    }


    public void BuyNonConsumable()
    {
        BuyProductID(kProductIDNonConsumable);
    }



    void BuyProductID(string productId)
    {
        // If Purchasing has been initialized ...
        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
            {
                // ... report the product look-up failure situation  
                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 Purchasing has not yet been set up ...
        if (!IsInitialized())
        {
            Debug.Log("RestorePurchases FAIL. Not initialized.");
            return;
        }

        // If we are running on an Apple device ... 
        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);
        }
    }


    //  
    // --- IStoreListener
    //

    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)
    {

        //a non-consumable product has been purchased by this user.
        if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumable, StringComparison.Ordinal))
        {
            Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
            // TODO: The non-consumable item has been successfully purchased, grant this item to the player.
            if (DataObject.instance == null)
            {
                DataObject.instance = new DataObject();
                DataObject.instance.Load();
            }
            DataObject.instance.adsRemoved = true;
            Debug.Log("Ads Removed");
            DataObject.instance.Save();

        }
        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));

        if (DataObject.instance == null)
        {
            DataObject.instance = new DataObject();
            DataObject.instance.Load();
        }
        DataObject.instance.adsRemoved = false;
        Debug.Log("Purchase Failed, Text is Remove Ads & Endless");
        DataObject.instance.Save();
    }

    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
    {
        bool validPurchase = true; // Presume valid for platforms with no R.V.

        // Unity IAP's validation logic is only included on these platforms.

#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
// Prepare the validator with the secrets we prepared in the Editor
// obfuscation window.
var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
AppleTangle.Data(), Application.bundleIdentifier);

try {
    // On Google Play, result has a single product ID.
    // On Apple stores, receipts contain multiple products.
    var result = validator.Validate(e.purchasedProduct.receipt);
    // For informational purposes, we list the receipt(s)
    Debug.Log("Receipt is valid. Contents:");
    foreach (IPurchaseReceipt productReceipt in result) {
        Debug.Log(productReceipt.productID);
        Debug.Log(productReceipt.purchaseDate);
        Debug.Log(productReceipt.transactionID);
    }
} catch (IAPSecurityException) {
    Debug.Log("Invalid receipt, not unlocking content");
    validPurchase = false;
}

#endif

        if (validPurchase)
        {
            if (DataObject.instance == null)
            {
                DataObject.instance = new DataObject();
                DataObject.instance.Load();
            }
            DataObject.instance.adsRemoved = true;
            Debug.Log("Ads Removed");
            DataObject.instance.Save();
        }

        return PurchaseProcessingResult.Complete;
    }

    var result = validator.Validate(e.purchasedProduct.receipt);
    Debug.Log("Receipt is valid. Contents:");

foreach (IPurchaseReceipt productReceipt in result) {
Debug.Log(productReceipt.productID);
Debug.Log(productReceipt.purchaseDate);
Debug.Log(productReceipt.transactionID);

GooglePlayReceipt google = productReceipt as GooglePlayReceipt;
if (null != google) {
    // This is Google's Order ID.
    // Note that it is null when testing in the sandbox
    // because Google's sandbox does not provide Order IDs.
    Debug.Log(google.transactionID);
    Debug.Log(google.purchaseState);
    Debug.Log(google.purchaseToken);
}

AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt;
if (null != apple) {
    Debug.Log(apple.originalTransactionIdentifier);
    Debug.Log(apple.subscriptionExpirationDate);
    Debug.Log(apple.cancellationDate);
    Debug.Log(apple.quantity);
}

}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment