void OnReceiptVerificationComplete() { Debug.Log("OnReceiptVerificationComplete"); KongregateAPI kongregate = KongregateAPI.GetAPI(); // we keep a list of transactions here so that we don't run into race conditions Dictionary <string, object> stillInVerification = new Dictionary <string, object> (); foreach (var transactionId in mTransactionsInVerification.Keys) { string status = kongregate.Mtx.ReceiptVerificationStatus(transactionId); if (status != KongregateAPI.RECEIPT_VERIFICATION_STATUS_PROCESSING) { Debug.Log("Verification for " + transactionId + " is " + status); #if UNITY_IPHONE if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_VALID) { StoreKitTransaction transaction = (StoreKitTransaction)mTransactionsInVerification[transactionId]; KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_SUCCESS, transactionId, getPurchaseFields()); // Below is an alternative iOS FinishPurchase() call. This version may be used if your plugin // does not make the transaction Id available or finishes the transaction before passing control // back to Unity. FinishPurchase() is preferred because purchase details may be pulled directly from // the transaction. // KongregateAPI.GetAPI().Analytics.FinishPurchaseWithProductId(KongregateAPI.PURCHASE_SUCCESS, // transaction.productIdentifier, transaction.base64EncodedTransactionReceipt, getPurchaseFields()); } else if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_INVALID) { KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_RECEIPT_FAIL, transactionId, getPurchaseFields()); } // call to finish the transaction regardless of it we are valid or not StoreKitBinding.finishPendingTransaction(transactionId); #elif UNITY_ANDROID GooglePurchase transaction = (GooglePurchase)mTransactionsInVerification [transactionId]; if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_VALID) { KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_SUCCESS, transaction.originalJson, getPurchaseFields(), transaction.signature); } else if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_INVALID) { KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_RECEIPT_FAIL, transaction.originalJson, getPurchaseFields()); } // call to finish transaction regardless of it we are valid or not GoogleIAB.consumeProduct(transaction.productId); #endif mPurchaseReady = true; } else { Debug.Log("Still waiting on verification for " + transactionId); stillInVerification [transactionId] = mTransactionsInVerification [transactionId]; } } mTransactionsInVerification = stillInVerification; }
void callback_Compelete_puchaseIOS() { // loading UI true Loadmanager.instance.LoadingUI(true); //소모 처 리를 한다 StoreKitBinding.finishPendingTransaction(transactionProduct.transactionIdentifier); }
IEnumerator WaitForRequest(WWW www, StoreKitTransaction transaction) { yield return(www); // check for errors if (www.error == null) { Debug.Log("WWW Ok!: " + www.data); if (www.text == "0") { GameObject mallTableObj = GameObject.Find("MallDragPanel"); mallTableObj.SendMessage("addDiamond", transaction.productIdentifier); // foreach (DiamondProductData diamondProduct in ItemModel.Instance.diamondProducts) // { // if(diamondProduct.productID == transaction.productIdentifier) // { // UserManagerCloud.Instance.CurrentUser.UserGoldCoins += diamondProduct.diamondNum; // // Update user.data // UserCloud.Serialize(UserManagerCloud.FILE_NAME_LOCAL); // Debug.Log("Purchase has success,"+ diamondProduct.diamondNum +" diamonds added!"); // } // } } } else { GameObject mallTableObj = GameObject.Find("MallDragPanel"); mallTableObj.SendMessage("addDiamond", transaction.productIdentifier); // Debug.Log("WWW Error: "+ www.error); // int times = PlayerPrefs.GetInt(transaction.transactionIdentifier, 0); // Debug.Log("restore transaction times:" + times); // if(times > tryTimes) // { // PlayerPrefs.DeleteKey(transaction.transactionIdentifier); // StoreKitBinding.finishPendingTransaction(transaction.transactionIdentifier); // } // else // { // times += 1; // PlayerPrefs.SetInt(transaction.transactionIdentifier, times); // productPurchaseFailed("Server Verify Failed!!"); // } // PlayerPrefs.Save(); } StoreKitBinding.finishPendingTransaction(transaction.transactionIdentifier); }
//상품리스트 성공적으로 들어올떄 콜백함수 void productListReceivedEvent(List <StoreKitProduct> productList) { UserEditor.Getsingleton.EditLog("productListReceivedEvent. total products received: " + productList.Count); // print the products to the console //foreach (StoreKitProduct product in productList) // UserEditor.Getsingleton.EditLog(product.ToString() + "\n"); //Loadmanager.instance.LoadingUI(false); //상품정보(가격, 화폐단위) 받아오기 for (int i = 0; i < productList.Count; i++) { Dic_StorkitProductInfo [productList [i].productIdentifier] = productList[i]; //Debug.Log (productList [i].productIdentifier + " / " + productList [i].price + " / " + productList [i].currencyCode + " / " + productList [i].formattedPrice + // " / " + productList [i].currencySymbol); } // 구입 했던 거래 정보 List <StoreKitTransaction> _storeKitTrns = StoreKitBinding.getAllSavedTransactions(); UserEditor.Getsingleton.EditLog("getAllSavedTransactions count : " + _storeKitTrns.Count); // for(int i = 0 ; i < _storeKitTrns.Count ; i++) // { // UserEditor.Getsingleton.EditLog ("getAllSavedTransactions _ Transaction state : " + _storeKitTrns[i].ToString()); // // } // 구매 후 소모 처리 되지 않은 상 품들 List <StoreKitTransaction> _storekitAllCurrent = StoreKitBinding.getAllCurrentTransactions(); UserEditor.Getsingleton.EditLog("getAllCurrentTransactions count : " + _storekitAllCurrent.Count); for (int i = 0; i < _storekitAllCurrent.Count; i++) { isForceConsume = true; UserEditor.Getsingleton.EditLog("getAllCurrentTransactions _ Transaction state : " + _storekitAllCurrent[i].ToString()); if (_storekitAllCurrent [i].transactionState == StoreKitTransactionState.Purchased) //거래 대기열에 있음, 사용자에게 청구 됨. 클라이언트는 트랜잭션을 완료해야함. { // 다시 소모 처리 시된 상품 저장 => 만약 소모처리중 프로토콜 에러 발 생시 강제 소모 하려고 storekitTracs.Add(_storekitAllCurrent [i]); //거래 상품중에 소모를 하지않은 상품들 소모해준다 productPurchaseAwaitingConfirmationEvent(_storekitAllCurrent [i]); //StoreKitBinding.finishPendingTransaction (_storekitAllCurrent [i].transactionIdentifier); } else if (_storekitAllCurrent [i].transactionState == StoreKitTransactionState.Failed) // 거래 실패된 상품 거래 는 그냥 소모 처리 한다 { UserEditor.Getsingleton.EditLog("강제소모 함 : " + _storekitAllCurrent [i].productIdentifier + " / " + _storekitAllCurrent [i].transactionState); StoreKitBinding.finishPendingTransaction(_storekitAllCurrent [i].transactionIdentifier); } } if (_storekitAllCurrent.Count > 0) { isForceConsume = false; } IsGetQueryInventory = true; }
// Demonstarte how to handle Kongregate Events void HandleKongregateEvent(string eventName) { Debug.Log("HandleKongregateEvent: " + eventName); KongregateAPI kongregate = KongregateAPI.GetAPI(); switch (eventName) { case KongregateAPI.KONGREGATE_EVENT_READY: // Kongregate API is ready to go // You may now access the current Kongregate User, submit stats, etc. // You may also check to see if the game auth token is available. If this is the first time // the user lauched your game, they may not have an AuthToken yet. A // KONGEGATE_EVENT_GAME_AUTH_CHANGED will follow (if they have an internet connection). You only // need the Game Auth Token, if you plan to perform server-side verification. Debug.Log("Kongregate API is ready"); Debug.Log("Kongregate Auto props as JSON: " + kongregate.Analytics.GetAutoPropertiesJSON()); UpdateNotificationCount(); // If you're implementing guild chat, you can update your character token at this time // if it is available: // kongregate.Services.SetCharacterToken("server-generated-token"); DemoRequestUserItems(); DemoUpdateGameUserData(); Debug.Log("app opened using deep link: " + kongregate.Mobile.GetOpenURL()); break; case KongregateAPI.KONGREGATE_EVENT_USER_CHANGED: // this could be one of: // 1) user was a guest and then logged in/registered // 2) user was logged in and then logged out and is now guest // 3) user was logged in and then logged out and is now a different user // Note that the user id will come back for Guests as well. To check for a // guest, use the IsGuest() method. // if you are also concerned about the Auth Token, you should instead listen // for KONGREGATE_EVENT_USER_AUTH_CHANGED as it is a superset of this event mUserId = kongregate.Services.GetUserId(); mUsername = kongregate.Services.GetUsername(); mGuest = kongregate.Services.IsGuest(); mHasKongPlus = kongregate.Services.HasKongPlus(); Debug.Log("user " + mUserId + " " + (mGuest ? "is" : "is not") + " a guest"); DemoRequestUserItems(); break; case KongregateAPI.KONGREGATE_EVENT_GAME_AUTH_CHANGED: // User's game auth token has changed, either by way of login, logout, or if their password changes. // This event will always follow KONGREGATE_EVENT_USER_CHANGED (if they have intenet access). // Note that Guests will also have an Auth Token and will cause this to event to fire as well. // Guest token is the same for all Guests. you can check if the user is a Guest using the // isGuest() method. Their is no need to perform server-side verification for the Guests token. // If you want to listen for a single event that covers all the scenarios of a user change or // an auth token change, this is the event to listen for mUserId = kongregate.Services.GetUserId(); mAuthToken = kongregate.Services.GetGameAuthToken(); mGuest = kongregate.Services.IsGuest(); Debug.Log("user " + mUserId + " " + (mGuest ? "is" : "is not") + " a guest"); Debug.Log("game auth has changed to:" + mAuthToken); break; case KongregateAPI.KONGREGATE_EVENT_OPEN_DEEP_LINK: Debug.Log("app opened using deep link: " + kongregate.Mobile.GetOpenURL()); break; case KongregateAPI.KONGREGATE_EVENT_OPENING: // Kongregate Window is opening Debug.Log("Kongregate Window is opening - pausing logic and sound"); mKongregateWindowOpen = true; #if UNITY_IPHONE // Android closes the panel when the app goes to the background, so iOS only. Time.timeScale = 0; AudioListener.pause = true; #endif break; case KongregateAPI.KONGREGATE_EVENT_CLOSED: // Kongregate Window is clsoed Debug.Log("Kongregate Window is closed - resuming logic and sound"); mKongregateWindowOpen = false; #if UNITY_IPHONE // Android closes the panel when the app goes to the background, so iOS only. Time.timeScale = 1; AudioListener.pause = false; #endif break; case KongregateAPI.KONGREGATE_EVENT_USER_INVENTORY: // User inventory is now available, we can call hasItem to check for promotional items mInventory = true; DemoGetUserItems(); break; case KongregateAPI.KONGREGATE_EVENT_SERVICE_UNAVAILABLE: // A request to Kongregate failed. This will typically occur when the user does not // have a network connection or Kongregate is experiencing a scheduled downtime. Requests // will be stored locally until the service becomes available again. Game clients // should only need to handle this event if they require server side auth, // do not have a game auth token yet, and wish to message to the user that they are unable // to validate them. Debug.Log("Kongregate Service Unavailable"); break; case KongregateAPI.KONGREGATE_EVENT_RECEIPT_VERIFICATION_COMPLETE: // A purchase receipt has been verified, we can now check the result for our transaction Debug.Log("A receipt has finished verification"); // we keep a list of transactions here so that we don't run into race conditions Dictionary <string, object> stillInVerification = new Dictionary <string, object>(); foreach (var transactionId in mTransactionsInVerification.Keys) { string status = kongregate.Mtx.ReceiptVerificationStatus(transactionId); if (status != KongregateAPI.RECEIPT_VERIFICATION_STATUS_PROCESSING) { Debug.Log("Verification for " + transactionId + " is " + status); #if UNITY_IPHONE && PRIME31_STOREKIT if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_VALID) { StoreKitTransaction transaction = (StoreKitTransaction)mTransactionsInVerification[transactionId]; KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_SUCCESS, transactionId, getPurchaseFields()); // Below is an alternative iOS FinishPurchase() call. This version may be used if your plugin // does not make the transaction Id available or finishes the transaction before passing control // back to Unity. FinishPurchase() is preferred because purchase details may be pulled directly from // the transaction. // KongregateAPI.GetAPI().Analytics.FinishPurchaseWithProductId(KongregateAPI.PURCHASE_SUCCESS, // transaction.productIdentifier, transaction.base64EncodedTransactionReceipt, getPurchaseFields()); } else if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_INVALID) { KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_RECEIPT_FAIL, transactionId, getPurchaseFields()); } // call to finish the transaction regardless of it we are valid or not StoreKitBinding.finishPendingTransaction(transactionId); #elif UNITY_ANDROID && PRIME31_STOREKIT GooglePurchase transaction = (GooglePurchase)mTransactionsInVerification[transactionId]; if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_VALID) { KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_SUCCESS, transaction.originalJson, getPurchaseFields(), transaction.signature); } else if (status == KongregateAPI.RECEIPT_VERIFICATION_STATUS_INVALID) { KongregateAPI.GetAPI().Analytics.FinishPurchase(KongregateAPI.PURCHASE_RECEIPT_FAIL, transaction.originalJson, getPurchaseFields()); } // call to finish transaction regardless of it we are valid or not GoogleIAB.consumeProduct(transaction.productId); #endif mPurchaseReady = true; } else { Debug.Log("Still waiting on verification for " + transactionId); stillInVerification[transactionId] = mTransactionsInVerification[transactionId]; } } mTransactionsInVerification = stillInVerification; break; case KongregateAPI.KONGREGATE_EVENT_SWRVE_RESOURCES_UPDATES: DemoSwrveResources(); break; case KongregateAPI.KONGREGATE_EVENT_NOTIFICATION_COUNT_UPDATED: Debug.Log("notification count updated: " + kongregate.Services.GetNotificationCount()); UpdateNotificationCount(); break; } // the following should be called to let the API know processing is complete // this is particularly important for when pausing the game via iOS (default) kongregate.MessageReceived(eventName); }