I have in-app purchase in my app. My purchase is activated after button click. But if I open app first time and click on button I have this result: No products found with identifier
from this function:
func purchaseProduct(identifier:String) {
guard let product = self.product(identifier: identifier) else {
print("No products found with identifier: (identifier)")
// fire purchase status: failed notification
delegate?.purchaseStatusDidUpdate(PurchaseStatus.init(state: .failed, error: PurchaseError.productNotFound, transaction: nil, message:"An error occured"))
return
}
//.etc
}
But if I press the button again, everything works fine. Also if I close app, open again and press the button mu purchase works fine. Why this happens only in first time app launch? And how to fix it?
I use this code for in-app purchases https://stackoverflow.com/a/51688015
Update
There is the following class and I think the point is in it:
class MyAppProductStore: Store {
static let shared = MyAppProductStore()
// purchase processor
var itunes: iTunesStore = iTunesStore()
init() {
// register for purchase status update callbacks
itunes.delegate = self
validateProducts(MyProductIds.allIdentifiers())
}
/// This function is called during the purchase/restore purchase process with each status change in the flow. If the status is complete then access to the product should be granted at this point.
///
/// - Parameter status: The current status of the transaction.
internal func processPurchaseStatus(_ status: PurchaseStatus) {
switch status.state {
case .initiated:
// TODO: show alert that purchase is in progress...
break
case .complete:
if let productID = status.transaction?.payment.productIdentifier {
// Store product id in UserDefaults or some other method of tracking purchases
UserDefaults.standard.set(true , forKey: productID)
UserDefaults.standard.synchronize()
}
case .cancelled:
break
case .failed:
// TODO: notify user with alert...
break
}
}
}
extension MyAppProductStore: iTunesPurchaseStatusReceiver, iTunesProductStatusReceiver {
func purchaseStatusDidUpdate(_ status: PurchaseStatus) {
// process based on received status
processPurchaseStatus(status)
}
func restoreStatusDidUpdate(_ status: PurchaseStatus) {
// pass this into the same flow as purchasing for unlocking products
processPurchaseStatus(status)
}
func didValidateProducts(_ products: [SKProduct]) {
print("Product identifier validation complete with products: (products)")
// TODO: if you have a local representation of your products you could
// sync them up with the itc version here
}
func didReceiveInvalidProductIdentifiers(_ identifiers: [String]) {
// TODO: filter out invalid products? maybe... by default isActive is false
}
}
if I click on button after calling it, everything will work fine.
To call it I use the following line var store = MyAppProductStore()
in AppDelegate
it is look like this:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var store = MyAppProductStore()
.etc
Is this the fastest way to call the class?
question from:
https://stackoverflow.com/questions/65845488/in-app-purchases-fail-only-in-first-time-app-launch 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…