I have an urgent production issues, where all users have access to PRO features since migrated to RevenueCat due to the following,
- I have an issue where customerInfo.entitlements.active.isEmpty is always returns a value when user is not subscribed.
- The customerInfo.activeSubscriptions always returns the product identifier for users who have subscribed but cancelled their subscription.
I have added
print("ENTITLEMENTS \(customerInfo.entitlements)")
print("ACTIVE SUBS \(customerInfo.activeSubscriptions)")
This returns
ENTITLEMENTS <RCEntitlementInfos: self.all=[pro:],
self.active=[:],self.verification=VerificationResult.notRequested>
ACTIVE SUBS [“com.appname.com.promonthly", “com.appname.com.proyearly”]
I have also tried removing cached info with Purchases.shared.invalidateCustomerInfoCache()
Also when opening Debug > StoreKit, not transactions are show.
func verifyIAPReceipt() {
Purchases.shared.invalidateCustomerInfoCache()
Purchases.shared.getCustomerInfo { (customerInfo, error) in
if error == nil {
if let customerInfo = customerInfo {
if customerInfo.entitlements.active.isEmpty {
print("ENTITLEMENTS IS EMPTY") <-- This is not executed
self.unsubscribe()
} else {
print("ENTITLEMENTS IS NOT EMPTY") <-- Executed
print("ENTITLEMENTS \(customerInfo.entitlements)")
print("ACTIVE SUBS \(customerInfo.activeSubscriptions)")
if customerInfo.activeSubscriptions.isEmpty == false {
print("Active Subscriptions is NOT empty") <-- Executed
for s in customerInfo.activeSubscriptions {
if s == "com.app.come.promonthly" || s == "com.app.com.proyearly" {
subscribe() <-- Executed Unlocks features
}
}
} else if customerInfo.activeSubscriptions.isEmpty == true {
print("Active Subscriptions are empty")
self.unsubscribe()
} else {
print("Active Subscription and profile is subscribed")
}
}
}
} else {
print("ERROR GETTING CUSTOMER INFO TO VERIFY RECEIPTS")
}
}
}
When using `fetchPolicy: .fetchCurrent` it is returning active subscriptions
Purchases.shared.getCustomerInfo(fetchPolicy: .fetchCurrent, completion: { (customerInfo, error) in
if error != nil {
print("FETCH POLICY ERROR:\(error)")
}
if customerInfo != nil {
print("FETCH POLICY ACTIVE SUBSCRIPTIONS:\(customerInfo!.activeSubscriptions)")
print("FETCH POLICY ACTIVE ENTITLEMENTS:\(customerInfo!.entitlements)")
print("FETCH POLICY ACTIVE ALL PURCHASED PRODUCT ID'S:\(customerInfo!.allPurchasedProductIdentifiers)")
}
})
Output
> FETCH POLICY ACTIVE SUBSCRIPTIONS:["com.appname.com.promonthly"]
> FETCH POLICY ACTIVE ENTITLEMENTS:<RCEntitlementInfos: self.all=[:],
> self.active=[:],self.verification=VerificationResult.notRequested>
> FETCH POLICY ACTIVE ALL PURCHASED PRODUCT
> ID'S:["com.appname.com.promonthly"]
This is the subscribe code
func subscribe() {
print("Subscribe")
//Revenue Cat
if let packages = offering?.availablePackages {
for p in packages {
if p.storeProduct.productIdentifier == selectedproductbundle {
Purchases.shared.purchase(package: p) { (transaction, customerInfo, error, userCancelled) in
print("PURCHASE")
if userCancelled {
print("User cancelled purchase")
return
}
if let err = error {
if let error = error as? RevenueCat.ErrorCode {
print(error.errorCode)
print("ERROR: \(error.errorUserInfo)")
switch error {
case .purchaseNotAllowedError:
errorDescription = "Purchases not allowed on this device."
showError.toggle()
case .purchaseInvalidError:
errorDescription = "Purchase invalid, check payment source."
default: break
}
}
} else if customerInfo?.activeSubscriptions.isEmpty == false {
print("Unlocked Pro 🎉")
// Update profile
print("Customer INFO: \(customerInfo!)")
print("Entitlements: \(customerInfo!.entitlements.all)")
if customerInfo != nil {
for s in customerInfo!.activeSubscriptions {
if s == "com.appname.com.promonthly" || s == "com.appname.com.proyearly" {
subscribeToPro()
}
}
}
} else {
print("PURCHASE WITH: \(String(describing: transaction?.productIdentifier)) && \(String(describing: customerInfo?.activeSubscriptions.count))")
}
}
}
}
}
}
I have tested via simulator and on device.
Code Samples: