Hey Sami,
I’m sorry to say that it looks like your images didn’t come through! You say that your subscriptions aren’t currently working on your iOS app - are you getting any errors when testing?
Hello Kaitlin,
I've attached the images again, I hope I attached them correctly now. The screenshots show the rejection reason from Apple. After a successful purchase on the iPad, the user can't skip the paywall.
In addition, below is my implementation of the purchasing process using RevenueCat, would you please take a look at it, I don't know if I am doing it right.
import Foundation
import RevenueCat
import SwiftUI
class PurchaseManager: ObservableObject {
static let shared = PurchaseManager()
/* Set from the didSet method of customerInfo above, based on the entitlement set in Constants.swift */
@Published var offerrings: Offerings? = nil
@Published var subscriptionActive: Bool = false
@Published var showModal: Bool = true
init() {
refreshSubscription()
Task {
let offerrings = try await Purchases.shared.offerings()
await MainActor.run {
self.offerrings = offerrings
}
}
}
func restore() {
Purchases.shared.restorePurchases { customerInfo, error in
if error != nil {
return
}
self.processInfo(info: customerInfo)
}
}
public func refreshSubscription() {
Purchases.shared.getCustomerInfo { (info, _) in
self.processInfo(info: info)
}
}
func purchase(package: Package) {
Purchases.shared.purchase(package: package) { (transaction, customerInfo, error, userCancelled) in
if error != nil || userCancelled {
return
}
self.processInfo(info: customerInfo)
}
}
private func processInfo(info: CustomerInfo?) {
if info?.entitlements[Constant.entitlementId]?.isActive == true {
self.subscriptionActive = true
self.showModal = false
}
else {
self.subscriptionActive = false
self.showModal = true
}
}
}
And at the paywall, I call “purchase” function when user tries to Subscribe. The following is implementation of the subscription button:
struct iOSSubscriptionButton: View {
@Binding var showModal: Bool
@EnvironmentObject var purchaseManager: PurchaseManager
var annualSub : Package? {
purchaseManager.offerrings?.current?.availablePackages.first(where: { package in
package.storeProduct.productIdentifier == Constant.productId
})
}
var body: some View {
if purchaseManager.subscriptionActive {
Text(NSLocalizedString("SUBSCRIBED", comment: "Subscribed"))
.foregroundColor(.green)
} else {
Button(action: {
guard let annualSub = annualSub else {return}
purchaseManager.purchase(package: annualSub)
}, label: {
if let price = annualSub?.localizedPriceString {
VStack {
Text(NSLocalizedString("TRY", comment: "Try"))
}
}
else {
ProgressView()
}
})
.disabled(annualSub == nil)
}
}
}
Is my code correct?
Should I do something after the purchase done successfully?
If yes, how should I do that using a completion handler or something similar?
Your User View Model looks good and I was able to get an app up and working using your code. Regarding the paywall, it’s tough to give coding advice just by looking at a chunk that also ties to other parts of your app - my recommendation is to take a look at our Swift UI sample app and how the Paywall is implemented there:
https://github.com/RevenueCat/purchases-ios/blob/main/Examples/MagicWeatherSwiftUI/Shared/Sources/Views/PaywallView.swift