bizz84 / SwiftyStoreKit

Lightweight In App Purchases Swift framework for iOS 8.0+, tvOS 9.0+ and macOS 10.10+ ⛺
MIT License
6.5k stars 793 forks source link

VerifySubscriptions Not Working in Production #353

Open Jerland2 opened 6 years ago

Jerland2 commented 6 years ago

Platform

In app purchase type

Environment

Version

0.10.4

Related issues

N/A

Report

Issue summary

Production users are complaining that my IAP view keeps popping up after their subscription is supposed to renew. This is an issue with "verifySubscriptions" method. Even if the user presses the "Restore" button their auto renewing IAP does not restore properly.

It is worth mentioning that in sandbox it seems to work perfectly.
Steps: DL App -> Purchase Subscription -> Delete App -> DL App -> Press Restore Button.

This is the specific method used

let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
    switch result {
    case .success(let receipt):
        let productIds = Set([ "com.musevisions.SwiftyStoreKit.Weekly",
                               "com.musevisions.SwiftyStoreKit.Monthly",
                               "com.musevisions.SwiftyStoreKit.Yearly" ])
        let purchaseResult = SwiftyStoreKit.verifySubscriptions(productIds: productIds, inReceipt: receipt)
        switch purchaseResult {
        case .purchased(let expiryDate, let items):
            print("\(productIds) are valid until \(expiryDate)\n\(items)\n")
            // Set Userdefault bool here
           // Set expiryDate (date that we will rerun this method in app delegate) using
        case .expired(let expiryDate, let items):
            print("\(productIds) are expired since \(expiryDate)\n\(items)\n")
        case .notPurchased:
            print("The user has never purchased \(productIds)")
        }
    case .error(let error):
        print("Receipt verification failed: \(error)")
    }
}

What did you expect to happen

User opens app after a time period where their Subscription renews and they are free to use the app.

What happened instead

User opens the app and is prompted by IAP screen. Our app checks in app delegate if the current date is > subscription expiry date, if it is then we use the new "verifySubscriptions" block to either reinstate a UserDefault or to block access using user defaults.

352 # Edit:

I think. I have pinpointed the problem, but I am a little lost as to the exact solution, perhaps someone here can help.

I believe the Complete Transaction block as described: I don't ever unlock my content as a result. HOW WOULD I UNLOCK CONTENT? So my usual way is a Bool "isPremium", but I also have an expirationDate, but this block does not have an expiration date parameter. How have people gone about using this block in context with an auto-renew subscription?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // see notes below for the meaning of Atomic / Non-Atomic
    SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
        for purchase in purchases {
            switch purchase.transaction.transactionState {
            case .purchased, .restored:
                if purchase.needsFinishTransaction {
                    // Deliver content from server, then:
                    SwiftyStoreKit.finishTransaction(purchase.transaction)
                }
                // Unlock content
            case .failed, .purchasing, .deferred:
                break // do nothing
            }
        }
    }
    return true
}

Edit2: Do I just verify the subscription group in the line "// Unlock content"? As described in original post?

dsb92 commented 6 years ago

I'm having this problem too with clients complaining about having to buy a subscription again when just purchased. I am verifing subscriptions with above method. Please fix this bug ASAP!