I have few questions about using SDKBOX IAP to work with subs type item on iOS.
I tired to parse the receiptCipheredPayload by PKCS7 or ANS1 string, both cannot get the correct decoded receipt, am I doing something wrong?
I was decoding the receipt to get the subs expiring date, is there a simply way to do the subs iap restore?
When first init of SDKBOX IAP, it will automatically call onRestored callback couple times with same transaction id, but when I manually call sdkbox::IAP::restore() it has no IAP record (new sandbox account), is this normal?
I found out after set sdkbox::IAP::enableUserSideVerification(true).
Then purchase whatever IAP item, relaunch the app will happens the above onSuccess problem.
I understand the sandbox duration time is much shorter than actual, but it is not related to this problem, if I turn off sdkbox::IAP::enableUserSideVerification(false) or just comment it to use default settings, it will be fine, it won’t call onSuccess after onInitialized with same testing procedures.
Also, is it correct to call multiple times onSuccess of the same transaction id? I use native code to check the AppStore receipt, it is not the correct transaction id at all.
have you remove other sample iap config added by sdkbox?
between, which sdkbox iap version you using?
i remember last time sdkbox iap will auto restore iap even for non-consumable after app start / restart / purchased iap.
i’m not sure since which version the issue gone, but it not happen on version v2.4.1.1 and v2.4.3.3
I’m using sdkbox 2.4.3.3, I have a temporary fix by my own implementation using native code which avoiding to use sdkbox::IAP::restore(), now everything work perfectly.
I just changed the flow of purchase, onSuccess only process consumable items, non consumable item will call my restorePurchase implementation.
if (product.type == sdkbox::IAP_Type::CONSUMABLE) {
if (product.name == IAP_POTION_HP) {
// add item hp
_consumableIap += 1;
DataManager::getInstance()->saveData(KEY_IAP_POTION_HP, _consumableIap);
_consumableIapLabel->setString(StringUtils::format("Consumable IAP\n%d", _consumableIap));
}
} else {
// Non consumable item use restore.
Game::getInstance()->restoreProduct();
}
The restore function will proceed the receipt verification and then call my onRestored implementation.
if let expireDate = iapItem.subscriptionExpirationDate {
// The IAP item is subscription.
let currentDate = Date()
if currentDate < expireDate {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy'-'MM'-'dd HH':'mm':'ss"
formatter.timeZone = TimeZone.current
let dateString = formatter.string(from: expireDate)
PurchaseValidatorWrapper.sharedInstance().onRestored(iapItem.productIdentifier, expireDate: dateString)
}
} else {
// The IAP item is non consumable.
PurchaseValidatorWrapper.sharedInstance().onRestored(iapItem.productIdentifier, expireDate: "")
}
At the end, due to the recent purchase will show in the receipt no matter what iap type, so the onRestore callback need to check the restored item type, skip it if it is consumable.