// 支付成功处理函数; public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) { Debug.Log("Purchase OK: " + e.purchasedProduct.definition.id); #if RECEIPT_VALIDATION // Local validation is available for GooglePlay, Apple, and UnityChannel stores if (m_IsGooglePlayStoreSelected || //(m_IsUnityChannelSelected && m_FetchReceiptPayloadOnPurchase) || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.tvOS) { try { var result = validator.Validate(e.purchasedProduct.receipt); Debug.Log("Receipt is valid. Contents:"); foreach (IPurchaseReceipt productReceipt in result) { Debug.Log("UNITY IAP productID : " + productReceipt.productID); Debug.Log("UNITY IAP purchaseDate : " + productReceipt.purchaseDate); Debug.Log("UNITY IAP transactionID : " + productReceipt.transactionID); GooglePlayReceipt google = productReceipt as GooglePlayReceipt; if (null != google) { Debug.Log(google.purchaseState); Debug.Log(google.purchaseToken); } UnityChannelReceipt unityChannel = productReceipt as UnityChannelReceipt; if (null != unityChannel) { Debug.Log(unityChannel.productID); Debug.Log(unityChannel.purchaseDate); Debug.Log(unityChannel.transactionID); } AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt; if (null != apple) { Debug.Log("UNITY IAP originalTransactionIdentifier : " + apple.originalTransactionIdentifier); Debug.Log("UNITY IAP subscriptionExpirationDate : " + apple.subscriptionExpirationDate); Debug.Log("UNITY IAP cancellationDate : " + apple.cancellationDate); Debug.Log("UNITY IAP quantity : " + apple.quantity); } // For improved security, consider comparing the signed // IPurchaseReceipt.productId, IPurchaseReceipt.transactionID, and other data // embedded in the signed receipt objects to the data which the game is using // to make this purchase. } } catch (IAPSecurityException ex) { Debug.Log("Invalid receipt, not unlocking content. " + ex); return(PurchaseProcessingResult.Complete); } } #endif if (null != m_Usr_ReqVerifyTransaction) { m_Usr_ReqVerifyTransaction.SafeInvoke(e.purchasedProduct.definition.id, e.purchasedProduct.receipt); } else { return(PurchaseProcessingResult.Complete); } // 我们自己后台完毕的话,通过代码设置成功(如果是不需要后台设置直接设置完毕,不要设置Pending); return(PurchaseProcessingResult.Pending); }
/// <summary> /// This will be called when a purchase completes. /// </summary> public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) { Debug.Log("Purchase OK: " + e.purchasedProduct.definition.id); Debug.Log("Receipt: " + e.purchasedProduct.receipt); m_LastTransationID = e.purchasedProduct.transactionID; m_LastReceipt = e.purchasedProduct.receipt; m_PurchaseInProgress = false; // Decode the UnityChannelPurchaseReceipt, extracting the gameOrderId if (m_IsUnityChannelSelected) { var unifiedReceipt = JsonUtility.FromJson <UnifiedReceipt>(e.purchasedProduct.receipt); if (unifiedReceipt != null && !string.IsNullOrEmpty(unifiedReceipt.Payload)) { var purchaseReceipt = JsonUtility.FromJson <UnityChannelPurchaseReceipt>(unifiedReceipt.Payload); Debug.LogFormat("UnityChannel receipt: storeSpecificId = {0}, transactionId = {1}, orderQueryToken = {2}", purchaseReceipt.storeSpecificId, purchaseReceipt.transactionId, purchaseReceipt.orderQueryToken); } } #if RECEIPT_VALIDATION // Local validation is available for GooglePlay, Apple, and UnityChannel stores if (m_IsGooglePlayStoreSelected || (m_IsUnityChannelSelected && m_FetchReceiptPayloadOnPurchase) || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.tvOS) { try { 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) { Debug.Log(google.purchaseState); Debug.Log(google.purchaseToken); } UnityChannelReceipt unityChannel = productReceipt as UnityChannelReceipt; if (null != unityChannel) { Debug.Log(unityChannel.productID); Debug.Log(unityChannel.purchaseDate); Debug.Log(unityChannel.transactionID); } AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt; if (null != apple) { Debug.Log(apple.originalTransactionIdentifier); Debug.Log(apple.subscriptionExpirationDate); Debug.Log(apple.cancellationDate); Debug.Log(apple.quantity); } // For improved security, consider comparing the signed // IPurchaseReceipt.productId, IPurchaseReceipt.transactionID, and other data // embedded in the signed receipt objects to the data which the game is using // to make this purchase. } } catch (IAPSecurityException ex) { Debug.Log("Invalid receipt, not unlocking content. " + ex); return(PurchaseProcessingResult.Complete); } } #endif // Unlock content from purchases here. #if USE_PAYOUTS if (e.purchasedProduct.definition.payouts != null) { Debug.Log("Purchase complete, paying out based on defined payouts"); foreach (var payout in e.purchasedProduct.definition.payouts) { Debug.Log(string.Format("Granting {0} {1} {2} {3}", payout.quantity, payout.typeString, payout.subtype, payout.data)); } } #endif // Indicate if we have handled this purchase. // PurchaseProcessingResult.Complete: ProcessPurchase will not be called // with this product again, until next purchase. // PurchaseProcessingResult.Pending: ProcessPurchase will be called // again with this product at next app launch. Later, call // m_Controller.ConfirmPendingPurchase(Product) to complete handling // this purchase. Use to transactionally save purchases to a cloud // game service. #if DELAY_CONFIRMATION StartCoroutine(ConfirmPendingPurchaseAfterDelay(e.purchasedProduct)); return(PurchaseProcessingResult.Pending); #else UpdateHistoryUI(); return(PurchaseProcessingResult.Complete); #endif }
/// <summary> /// This will be called when a purchase completes. /// </summary> public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) { Debug.Log("Purchase OK: " + e.purchasedProduct.definition.id); Debug.Log("Receipt: " + e.purchasedProduct.receipt); m_LastTransationID = e.purchasedProduct.transactionID; m_LastReceipt = e.purchasedProduct.receipt; m_PurchaseInProgress = false; // Decode the UnityChannelPurchaseReceipt, extracting the gameOrderId if (m_IsUnityChannelSelected) { var unifiedReceipt = JsonUtility.FromJson <UnifiedReceipt>(e.purchasedProduct.receipt); if (unifiedReceipt != null && !string.IsNullOrEmpty(unifiedReceipt.Payload)) { var purchaseReceipt = JsonUtility.FromJson <UnityChannelPurchaseReceipt>(unifiedReceipt.Payload); Debug.LogFormat("UnityChannel receipt: storeSpecificId = {0}, transactionId = {1}, orderQueryToken = {2}", purchaseReceipt.storeSpecificId, purchaseReceipt.transactionId, purchaseReceipt.orderQueryToken); } } #if RECEIPT_VALIDATION // Local validation is available for GooglePlay, Apple, and UnityChannel stores if (m_IsGooglePlayStoreSelected || (m_IsUnityChannelSelected && m_FetchReceiptPayloadOnPurchase) || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.tvOS) { try { 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) { Debug.Log(google.purchaseState); Debug.Log(google.purchaseToken); } UnityChannelReceipt unityChannel = productReceipt as UnityChannelReceipt; if (null != unityChannel) { Debug.Log(unityChannel.productID); Debug.Log(unityChannel.purchaseDate); Debug.Log(unityChannel.transactionID); } AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt; if (null != apple) { Debug.Log(apple.originalTransactionIdentifier); Debug.Log(apple.subscriptionExpirationDate); Debug.Log(apple.cancellationDate); Debug.Log(apple.quantity); } // For improved security, consider comparing the signed // IPurchaseReceipt.productId, IPurchaseReceipt.transactionID, and other data // embedded in the signed receipt objects to the data which the game is using // to make this purchase. } } catch (IAPSecurityException ex) { Debug.Log("Invalid receipt, not unlocking content. " + ex); return(PurchaseProcessingResult.Complete); } } #endif // Verify remotely // If this game has a Game Server and is capable of Server-to-Server communication, consider // server-based verification, instead of client-based verification, to avoid "man in the middle" // security attacks. bool needRemoteValidation = m_IsCloudMoolahStoreSelected; if (needRemoteValidation) { // CloudMoolah purchase completion / finishing currently requires using the API // extension IMoolahExtension.RequestPayout to finish a transaction. if (m_IsCloudMoolahStoreSelected) { // Finish transaction with CloudMoolah server m_MoolahExtensions.RequestPayOut(e.purchasedProduct.transactionID, (string transactionID, RequestPayOutState state, string message) => { if (state == RequestPayOutState.RequestPayOutSucceed) { // Finally, finish transaction with Unity IAP's local // transaction log, recording the transaction id there m_Controller.ConfirmPendingPurchase(e.purchasedProduct); // Unlock content here from purchases when using CloudMoolah. } else { Debug.Log("RequestPayOut: failed. transactionID: " + transactionID + ", state: " + state + ", message: " + message); // Finishing failed. Retry later. } }); } return(PurchaseProcessingResult.Pending); } // Unlock content from purchases here. #if USE_PAYOUTS if (e.purchasedProduct.definition.payouts != null) { Debug.Log("Purchase complete, paying out based on defined payouts"); foreach (var payout in e.purchasedProduct.definition.payouts) { Debug.Log(string.Format("Granting {0} {1} {2} {3}", payout.quantity, payout.typeString, payout.subtype, payout.data)); } } #endif // Indicate if we have handled this purchase. // PurchaseProcessingResult.Complete: ProcessPurchase will not be called // with this product again, until next purchase. // PurchaseProcessingResult.Pending: ProcessPurchase will be called // again with this product at next app launch. Later, call // m_Controller.ConfirmPendingPurchase(Product) to complete handling // this purchase. Use to transactionally save purchases to a cloud // game service. #if DELAY_CONFIRMATION StartCoroutine(ConfirmPendingPurchaseAfterDelay(e.purchasedProduct)); return(PurchaseProcessingResult.Pending); #else UpdateHistoryUI(); return(PurchaseProcessingResult.Complete); #endif }