SwiftyStoreKit
SwiftyStoreKit copied to clipboard
InAppReceiptRefreshRequest's refreshReceiptRequest not call requestDidFinish or didFailWithError
Platform
- [x ] iOS
- [ ] macOS
- [ ] tvOS
In app purchase type
- [x ] Consumable
- [ ] Non-consumable
- [ x] Auto-Renewable Subscription
- [ ] Non-Renewing Subscription
Environment
- [ x] Sandbox
- [ x] Production
Version
0.10.7
Related issues
Report
Issue summary
- when do a purchase. I use SwiftyStoreKit.verifyReceipt to check whether have unfinished purchase. 2.if no unfinished purchase. I use SwiftyStoreKit.purchaseProduct to buy it.
- It's all ok for the first time. But when I do a purchase twice.SwiftyStoreKit.verifyReceipt's callback does not invoke.
- I try to debug the reason. I found InAppReceiptRefreshRequest's refreshReceiptRequest not call requestDidFinish or didFailWithError, but self.refreshReceiptRequest.start() invoked.
- when I run the app again. It still not work. I have to delete the app. Login out the Apple Account. then I can run the code right at one time. here is the sample code
var serviceType = AppleReceiptValidator.VerifyReceiptURLType.production;
#if DEBUG
serviceType = AppleReceiptValidator.VerifyReceiptURLType.sandbox;
#endif
let appleValidator = AppleReceiptValidator.init(service: serviceType);
// 没有执行的话,这个回调是不会执行的
// https://stackoverflow.com/questions/30114489/skreceiptrefreshrequest-not-working-the-second-time-it-is-called-after-a-cancel
SwiftyStoreKit.verifyReceipt(using: appleValidator, password: IN_APP_PURCHASE_PASSWORD, forceRefresh: true) { (result:VerifyReceiptResult) in
switch result {
case .success(let receiptInfo):
print(receiptInfo);
if let status = receiptInfo["status"] as? Int {
if status == 0 {
if let latest_receipt = receiptInfo["latest_receipt"] as? String {
// have receipt do other things
} else {
SwiftyStoreKit.purchaseProduct(productID, quantity: 1, atomically: isAutoRenew) { result in
switch result {
case .success(let purchase):
print(purchase)
case .error(let error):
print(error);
}
}
}
} else {
print(" (CODE:\(status)")
}
} else {
print(" (CODE:NO_STATUS)")
}
case .error(let error):
print(error);
}
};
What did you expect to happen
- code run well.
What happened instead
- code only can run one time.
I’m wondering if this is a result of the deinit
:
deinit {
refreshReceiptRequest.delegate = nil
}
So, if InAppReceiptRefreshRequest
is deallocated, the delegate is set to nil
even if the request is still in progress, and thus neither of the delegate methods will be called. (The delegate
is weak
, so I don’t know why you need to manually set it to nil
, anyway. But whether deinit
sets it to nil
or whether the weak
property takes care of it, that’s not really relevant, as the issue is the same, namely that the delegate
can be set to nil
before the request is done.)
So, I wonder if there’s a path of execution where the last reference to the InAppReceiptRefreshRequest
is getting released before the request finishes.
FWIW, https://stackoverflow.com/q/55294986/1271826 is reporting a similar problem, where the completion handlers are not always getting called, and I suspect it’s a related problem.
I am having the same problem here and NO, problem is not solved by disabling the deinit part.