mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-16 21:02:04 +00:00
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 Foundation
|
||||||
import StoreKit
|
import StoreKit
|
||||||
import Convenience
|
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()
|
static let shared = ProductManager()
|
||||||
|
|
||||||
private let inApp: InApp<Product>
|
private let inApp: InApp<Product>
|
||||||
|
|
||||||
private init() {
|
private var purchasedAppVersion: String?
|
||||||
|
|
||||||
|
private var purchasedFeatures: Set<Product>
|
||||||
|
|
||||||
|
private override init() {
|
||||||
inApp = InApp()
|
inApp = InApp()
|
||||||
|
purchasedAppVersion = nil
|
||||||
|
purchasedFeatures = []
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
reloadReceipt()
|
||||||
}
|
}
|
||||||
|
|
||||||
func listProducts(completionHandler: (([SKProduct]) -> Void)?) {
|
func listProducts(completionHandler: (([SKProduct]) -> Void)?) {
|
||||||
@ -47,6 +66,75 @@ struct ProductManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func purchase(_ product: SKProduct, completionHandler: @escaping (InAppPurchaseResult, Error?) -> Void) {
|
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
|
target 'PassepartoutCore-iOS' do
|
||||||
shared_pods
|
shared_pods
|
||||||
|
pod 'Kvitto'
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'Passepartout-iOS' do
|
target 'Passepartout-iOS' do
|
||||||
|
17
Podfile.lock
17
Podfile.lock
@ -10,6 +10,14 @@ PODS:
|
|||||||
- Convenience/Persistence (0.0.1)
|
- Convenience/Persistence (0.0.1)
|
||||||
- Convenience/Reviewer (0.0.1)
|
- Convenience/Reviewer (0.0.1)
|
||||||
- Convenience/Tables (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)
|
- MBProgressHUD (1.1.0)
|
||||||
- OpenSSL-Apple (1.1.0l.4)
|
- OpenSSL-Apple (1.1.0l.4)
|
||||||
- SSZipArchive (2.2.2)
|
- SSZipArchive (2.2.2)
|
||||||
@ -35,6 +43,7 @@ DEPENDENCIES:
|
|||||||
- Convenience/Persistence (from `https://github.com/keeshux/convenience`, commit `b990a8c`)
|
- Convenience/Persistence (from `https://github.com/keeshux/convenience`, commit `b990a8c`)
|
||||||
- Convenience/Reviewer (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`)
|
- Convenience/Tables (from `https://github.com/keeshux/convenience`, commit `b990a8c`)
|
||||||
|
- Kvitto
|
||||||
- MBProgressHUD
|
- MBProgressHUD
|
||||||
- SSZipArchive
|
- SSZipArchive
|
||||||
- TunnelKit/Extra/LZO (from `https://github.com/passepartoutvpn/tunnelkit`, commit `4d930d3`)
|
- TunnelKit/Extra/LZO (from `https://github.com/passepartoutvpn/tunnelkit`, commit `4d930d3`)
|
||||||
@ -42,6 +51,8 @@ DEPENDENCIES:
|
|||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
https://github.com/cocoapods/specs.git:
|
https://github.com/cocoapods/specs.git:
|
||||||
|
- DTFoundation
|
||||||
|
- Kvitto
|
||||||
- MBProgressHUD
|
- MBProgressHUD
|
||||||
- OpenSSL-Apple
|
- OpenSSL-Apple
|
||||||
- SSZipArchive
|
- SSZipArchive
|
||||||
@ -64,13 +75,15 @@ CHECKOUT OPTIONS:
|
|||||||
:git: https://github.com/passepartoutvpn/tunnelkit
|
:git: https://github.com/passepartoutvpn/tunnelkit
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Convenience: c2bc96be4ca77c7018f85b2c63b95c2a44c05c5a
|
Convenience: c4240c936b2119752ffa0841d40a4bc6a0ba8a5d
|
||||||
|
DTFoundation: 25aa19bb7c6e225b1dfae195604fb8cf1da0ab4c
|
||||||
|
Kvitto: d451f893f84ad669850b7cb7d3f8781363e14232
|
||||||
MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
|
MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
|
||||||
OpenSSL-Apple: f3d1668588ea8f06b076dcfa6177cd90452e3800
|
OpenSSL-Apple: f3d1668588ea8f06b076dcfa6177cd90452e3800
|
||||||
SSZipArchive: fa16b8cc4cdeceb698e5e5d9f67e9558532fbf23
|
SSZipArchive: fa16b8cc4cdeceb698e5e5d9f67e9558532fbf23
|
||||||
SwiftyBeaver: aaf2ebd7dac2e952991f46a82ed24ad642867ae2
|
SwiftyBeaver: aaf2ebd7dac2e952991f46a82ed24ad642867ae2
|
||||||
TunnelKit: 0743f0306be0869d51118ac33e274e7507a93537
|
TunnelKit: 0743f0306be0869d51118ac33e274e7507a93537
|
||||||
|
|
||||||
PODFILE CHECKSUM: f45a3fd3744e646a5513e3e25d447d1550c9fefa
|
PODFILE CHECKSUM: d1e12ff38bc1839dddbbbcaa5e436ea0fad60f70
|
||||||
|
|
||||||
COCOAPODS: 1.8.4
|
COCOAPODS: 1.8.4
|
||||||
|
Loading…
Reference in New Issue
Block a user