Read features from app store receipt
- Use Kvitto to parse App Store receipt - Infer feature/provider eligibility from features - Assume full version in beta - Read receipt even if no products were purchased
This commit is contained in:
parent
e62aae16fc
commit
026a94065c
|
@ -26,14 +26,33 @@
|
|||
import Foundation
|
||||
import StoreKit
|
||||
import Convenience
|
||||
import SwiftyBeaver
|
||||
import Kvitto
|
||||
import PassepartoutCore
|
||||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class ProductManager: NSObject {
|
||||
private static let lastFullVersionNumber = "1.8.1"
|
||||
|
||||
private static let lastFullVersionBuild = "2016"
|
||||
|
||||
struct ProductManager {
|
||||
static let shared = ProductManager()
|
||||
|
||||
private let inApp: InApp<Product>
|
||||
|
||||
private init() {
|
||||
private var purchasedAppVersion: String?
|
||||
|
||||
private var purchasedFeatures: Set<Product>
|
||||
|
||||
private override init() {
|
||||
inApp = InApp()
|
||||
purchasedAppVersion = nil
|
||||
purchasedFeatures = []
|
||||
|
||||
super.init()
|
||||
|
||||
reloadReceipt()
|
||||
}
|
||||
|
||||
func listProducts(completionHandler: (([SKProduct]) -> Void)?) {
|
||||
|
@ -47,6 +66,75 @@ struct ProductManager {
|
|||
}
|
||||
|
||||
func purchase(_ product: SKProduct, completionHandler: @escaping (InAppPurchaseResult, Error?) -> Void) {
|
||||
inApp.purchase(product: product, completionHandler: completionHandler)
|
||||
inApp.purchase(product: product) {
|
||||
if $0 == .success {
|
||||
self.reloadReceipt()
|
||||
}
|
||||
completionHandler($0, $1)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: In-app eligibility
|
||||
|
||||
private func reloadReceipt() {
|
||||
guard let url = Bundle.main.appStoreReceiptURL else {
|
||||
log.warning("No App Store receipt found!")
|
||||
return
|
||||
}
|
||||
guard let receipt = Receipt(contentsOfURL: url) else {
|
||||
log.error("Could not parse App Store receipt!")
|
||||
return
|
||||
}
|
||||
|
||||
purchasedAppVersion = receipt.originalAppVersion
|
||||
purchasedFeatures.removeAll()
|
||||
|
||||
if let version = purchasedAppVersion {
|
||||
log.debug("Original purchased version: \(version)")
|
||||
|
||||
// treat former purchases as full versions
|
||||
if version <= ProductManager.lastFullVersionNumber {
|
||||
purchasedFeatures.insert(.fullVersion)
|
||||
}
|
||||
}
|
||||
if let iapReceipts = receipt.inAppPurchaseReceipts {
|
||||
log.debug("In-app receipts:")
|
||||
iapReceipts.forEach {
|
||||
guard let pid = $0.productIdentifier, let date = $0.originalPurchaseDate else {
|
||||
return
|
||||
}
|
||||
log.debug("\t\(pid) [\(date)]")
|
||||
}
|
||||
for r in iapReceipts {
|
||||
guard let pid = r.productIdentifier, let product = Product(rawValue: pid) else {
|
||||
continue
|
||||
}
|
||||
purchasedFeatures.insert(product)
|
||||
}
|
||||
}
|
||||
log.info("Purchased features: \(purchasedFeatures)")
|
||||
}
|
||||
|
||||
func isFullVersion() -> Bool {
|
||||
guard !AppConstants.Flags.isBeta else {
|
||||
return true
|
||||
}
|
||||
return purchasedFeatures.contains(.fullVersion)
|
||||
}
|
||||
|
||||
func isEligible(forFeature feature: Product) -> Bool {
|
||||
guard !isFullVersion() else {
|
||||
return true
|
||||
}
|
||||
return purchasedFeatures.contains(feature)
|
||||
}
|
||||
|
||||
func isEligible(forProvider name: Infrastructure.Name) -> Bool {
|
||||
guard !isFullVersion() else {
|
||||
return true
|
||||
}
|
||||
return purchasedFeatures.contains {
|
||||
return $0.rawValue.hasSuffix("providers.\(name.rawValue)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1
Podfile
1
Podfile
|
@ -21,6 +21,7 @@ end
|
|||
|
||||
target 'PassepartoutCore-iOS' do
|
||||
shared_pods
|
||||
pod 'Kvitto'
|
||||
end
|
||||
|
||||
target 'Passepartout-iOS' do
|
||||
|
|
17
Podfile.lock
17
Podfile.lock
|
@ -10,6 +10,14 @@ PODS:
|
|||
- Convenience/Persistence (0.0.1)
|
||||
- Convenience/Reviewer (0.0.1)
|
||||
- Convenience/Tables (0.0.1)
|
||||
- DTFoundation/Core (1.7.14)
|
||||
- DTFoundation/DTASN1 (1.7.14):
|
||||
- DTFoundation/Core
|
||||
- Kvitto (1.0.3):
|
||||
- DTFoundation/DTASN1 (~> 1.7.13)
|
||||
- Kvitto/Core (= 1.0.3)
|
||||
- Kvitto/Core (1.0.3):
|
||||
- DTFoundation/DTASN1 (~> 1.7.13)
|
||||
- MBProgressHUD (1.1.0)
|
||||
- OpenSSL-Apple (1.1.0l.4)
|
||||
- SSZipArchive (2.2.2)
|
||||
|
@ -35,6 +43,7 @@ DEPENDENCIES:
|
|||
- Convenience/Persistence (from `https://github.com/keeshux/convenience`, commit `b990a8c`)
|
||||
- Convenience/Reviewer (from `https://github.com/keeshux/convenience`, commit `b990a8c`)
|
||||
- Convenience/Tables (from `https://github.com/keeshux/convenience`, commit `b990a8c`)
|
||||
- Kvitto
|
||||
- MBProgressHUD
|
||||
- SSZipArchive
|
||||
- TunnelKit/Extra/LZO (from `https://github.com/passepartoutvpn/tunnelkit`, commit `4d930d3`)
|
||||
|
@ -42,6 +51,8 @@ DEPENDENCIES:
|
|||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- DTFoundation
|
||||
- Kvitto
|
||||
- MBProgressHUD
|
||||
- OpenSSL-Apple
|
||||
- SSZipArchive
|
||||
|
@ -64,13 +75,15 @@ CHECKOUT OPTIONS:
|
|||
:git: https://github.com/passepartoutvpn/tunnelkit
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Convenience: c2bc96be4ca77c7018f85b2c63b95c2a44c05c5a
|
||||
Convenience: c4240c936b2119752ffa0841d40a4bc6a0ba8a5d
|
||||
DTFoundation: 25aa19bb7c6e225b1dfae195604fb8cf1da0ab4c
|
||||
Kvitto: d451f893f84ad669850b7cb7d3f8781363e14232
|
||||
MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
|
||||
OpenSSL-Apple: f3d1668588ea8f06b076dcfa6177cd90452e3800
|
||||
SSZipArchive: fa16b8cc4cdeceb698e5e5d9f67e9558532fbf23
|
||||
SwiftyBeaver: aaf2ebd7dac2e952991f46a82ed24ad642867ae2
|
||||
TunnelKit: 0743f0306be0869d51118ac33e274e7507a93537
|
||||
|
||||
PODFILE CHECKSUM: f45a3fd3744e646a5513e3e25d447d1550c9fefa
|
||||
PODFILE CHECKSUM: d1e12ff38bc1839dddbbbcaa5e436ea0fad60f70
|
||||
|
||||
COCOAPODS: 1.8.4
|
||||
|
|
Loading…
Reference in New Issue