You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
12 KiB
279 lines
12 KiB
using System; |
|
#if UNITY_IOS || UNITY_ANDROID |
|
//using UnityEngine.Advertisements; // only compile Ads code on supported platforms |
|
#endif |
|
|
|
using UnityEngine; |
|
using UnityEngine.Purchasing; |
|
// Placing the Purchaser class in the CompleteProject namespace allows it to interact with ScoreManager, |
|
// one of the existing Survival Shooter scripts. |
|
// Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing. |
|
public class Purchaser : MonoBehaviour, IStoreListener |
|
{ |
|
private static IStoreController m_StoreController; // The Unity Purchasing system. |
|
private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems. |
|
private int m_additionalCoins = 0; |
|
|
|
void Start() |
|
{ |
|
//if (m_StoreController == null) |
|
//InitializePurchasing(); |
|
} |
|
|
|
public void InitializePurchasing() |
|
{ |
|
// If we have already connected to Purchasing ... |
|
if (IsInitialized()) |
|
{ |
|
// ... we are done here. |
|
return; |
|
} |
|
|
|
Debug.Log( "IAP version: " + StandardPurchasingModule.k_PackageVersion ); |
|
|
|
// 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. |
|
foreach (string key in GlobalsVar.gStoreOffersInfo.Keys) |
|
{ |
|
ProductType type = ProductType.Consumable; |
|
builder.AddProduct(key, type); |
|
} |
|
|
|
// 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); |
|
} |
|
|
|
private void TargetAndroidStore(AndroidStore amazonAppStore) |
|
{ |
|
throw new NotImplementedException(); |
|
} |
|
|
|
private bool IsInitialized() |
|
{ |
|
// Only say we are initialized if both the Purchasing references are set. |
|
return m_StoreController != null && m_StoreExtensionProvider != null; |
|
} |
|
|
|
|
|
public void BuyConsumable( string productName) |
|
{ |
|
GlobalsVar.gBoard.StartNoInternetDialogIfNeed(); |
|
BuyProductID(productName); |
|
} |
|
|
|
void BuyProductID(string productId) |
|
{ |
|
// If Purchasing has been initialized ... |
|
if (IsInitialized()) |
|
{ |
|
DevToDevRealization.CustomEventWithParams( "start_real_purchase", "item", productId ); |
|
// ... 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) |
|
{ |
|
GlobalsVar.gBoard.StartDialog("WaitDialog"); |
|
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<IAppleExtensions>(); |
|
// Begin the asynchronous process of restoring purchases. Expect a confirmation response in |
|
// the Action<bool> 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"); |
|
|
|
GlobalsVar.gRealPurchasesWasInitialized = true; |
|
|
|
// Overall Purchasing system, configured with products for this application. |
|
m_StoreController = controller; |
|
// Store specific subsystem, for accessing device-specific store features. |
|
m_StoreExtensionProvider = extensions; |
|
|
|
foreach (var product in controller.products.all) |
|
{ |
|
string realPurchaseSKU = product.definition.id; |
|
|
|
StoreOffersInfo realPurchase = CommonFunctions.GetRealPurchaseBySKU(realPurchaseSKU); |
|
if (realPurchase != null) |
|
{ |
|
realPurchase.m_price = product.metadata.localizedPriceString; |
|
realPurchase.m_isoCurrencyCode = product.metadata.isoCurrencyCode; |
|
realPurchase.m_isoPrice = product.metadata.localizedPrice; |
|
} |
|
else |
|
CommonFunctions.myassert( false ); |
|
//Debug.Log(product.definition.id); |
|
//Debug.Log(product.metadata.localizedTitle); |
|
//Debug.Log(product.metadata.localizedDescription); |
|
//Debug.Log(product.metadata.localizedPriceString); |
|
} |
|
|
|
/*GameObject dialog = Globals.gGameApp.GetDialog( DialogTypes.STORE_DIALOG ); |
|
if ( dialog != null ) |
|
{ |
|
StoreDialog storeDialog = dialog.GetComponent; |
|
if (storeDialog != null) |
|
storeDialog.SetCostTextOnButtons(); |
|
else |
|
CommonFunctions.myassert(false); |
|
}*/ |
|
} |
|
|
|
|
|
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 void ValidatePurchaseAndSendFBEvent(PurchaseEventArgs args) |
|
{ |
|
#if UNITY_IOS || UNITY_ANDROID |
|
/*if (Globals.gAmazonBuild) |
|
return; |
|
|
|
bool validPurchase = true; |
|
var validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier); |
|
|
|
try |
|
{ |
|
// On Google Play, result will have a single product Id. |
|
// On Apple stores receipts contain multiple products. |
|
var result = validator.Validate(args.purchasedProduct.receipt); |
|
Debug.Log("Receipt is valid. Contents:"); |
|
// For informational purposes, we list the receipt(s) |
|
//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; |
|
} |
|
|
|
if (validPurchase) |
|
{ |
|
float localizedPrice = (float)(args.purchasedProduct.metadata.localizedPrice); |
|
string isoCode = args.purchasedProduct.metadata.isoCurrencyCode; |
|
FB.LogPurchase(localizedPrice, isoCode); |
|
Debug.Log(string.Format("FB.LogPurchase '{0}' '{1}'", localizedPrice, isoCode)); |
|
DevToDevRealization.CustomEvent("valid_receipt"); |
|
} |
|
else |
|
{ |
|
Debug.Log(string.Format("Invalid purchase")); |
|
DevToDevRealization.CustomEvent( "invalid_receipt"); |
|
}*/ |
|
#endif |
|
} |
|
|
|
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) |
|
{ |
|
GlobalsVar.gBoard.CloseWaitDlg(); |
|
// A consumable product has been purchased by this user. |
|
//if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal)) |
|
{ |
|
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id)); |
|
string purchaseSku = args.purchasedProduct.definition.storeSpecificId; |
|
CommonFunctions.WasRealPurchase(purchaseSku, args.purchasedProduct.transactionID); |
|
|
|
float localizedPrice = (float)(args.purchasedProduct.metadata.localizedPrice); |
|
string isoCode = args.purchasedProduct.metadata.isoCurrencyCode; |
|
string purchaseSkuForDevToDev = purchaseSku;; |
|
DevToDevRealization.RealPayment(localizedPrice, purchaseSkuForDevToDev, isoCode, args.purchasedProduct.transactionID); |
|
|
|
ValidatePurchaseAndSendFBEvent(args); |
|
// The consumable item has been successfully purchased, add 100 coins to the player's in-game score. |
|
} |
|
// Or ... a non-consumable product has been purchased by this user. |
|
//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. |
|
return PurchaseProcessingResult.Complete; |
|
} |
|
|
|
|
|
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) |
|
{ |
|
GlobalsVar.gBoard.CloseWaitDlg(); |
|
// 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)); |
|
} |
|
} |