检查自动续订订阅是否仍然有效
Check if an Auto-Renewable Subscription is still valid
我想在打开应用程序时检查自动续订订阅状态。
这是为了确保用户仍订阅该服务。我该如何实现?
有什么想法吗?谢谢
P.S.: 我正在使用 SwiftyStoreKit
这里有几种进行收据验证以检查用户是否被授予订阅的方法。这里有两种正确的方法:
- 在本地进行收据验证 here。
远程执行收据验证 here。提到不应在应用程序内将收据发送到 App Store。简短摘要:
- 您的应用将收据发送到您的后端。
- 您的后端将收据发送到 Apple 后端进行验证。
- 您的后端从苹果获得响应。
- 您的后端将结果发送回您的应用程序是收据有效还是无效。
在这两种方式中,您都将获得应用内购买列表。它还将包含过期的订阅。您需要浏览所有订阅并检查到期日期。如果它仍然有效,您必须授予用户订阅。
据我了解,您正在使用 SwiftyStoreKit,这是 local receipt validation 的开放任务。
您可以使用此功能查看。它适用于 swift4
func receiptValidation() {
let SUBSCRIPTION_SECRET = "yourpasswordift"
let receiptPath = Bundle.main.appStoreReceiptURL?.path
if FileManager.default.fileExists(atPath: receiptPath!){
var receiptData:NSData?
do{
receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped)
}
catch{
print("ERROR: " + error.localizedDescription)
}
//let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
let base64encodedReceipt = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions.endLineWithCarriageReturn)
print(base64encodedReceipt!)
let requestDictionary = ["receipt-data":base64encodedReceipt!,"password":SUBSCRIPTION_SECRET]
guard JSONSerialization.isValidJSONObject(requestDictionary) else { print("requestDictionary is not valid JSON"); return }
do {
let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt" // this works but as noted above it's best to use your own trusted server
guard let validationURL = URL(string: validationURLString) else { print("the validation url could not be created, unlikely error"); return }
let session = URLSession(configuration: URLSessionConfiguration.default)
var request = URLRequest(url: validationURL)
request.httpMethod = "POST"
request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.uploadTask(with: request, from: requestData) { (data, response, error) in
if let data = data , error == nil {
do {
let appReceiptJSON = try JSONSerialization.jsonObject(with: data)
print("success. here is the json representation of the app receipt: \(appReceiptJSON)")
// if you are using your server this will be a json representation of whatever your server provided
} catch let error as NSError {
print("json serialization failed with error: \(error)")
}
} else {
print("the upload task returned an error: \(error)")
}
}
task.resume()
} catch let error as NSError {
print("json serialization failed with error: \(error)")
}
}
}
我想为那些仍然偶然发现这个问题的人提供一个使用 RevenueCat SDK 的替代解决方案。
AppDelegate.swift
使用您的 api 密钥和可选的用户标识符配置 RevenueCat Purchases SDK。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Purchases.configure(withAPIKey: "<...>", appUserID: "<...>")
...
return true
}
订阅状态函数
下面的函数检查 PurchaserInfo
以查看用户是否仍有活动的 "entitlement"(或者您可以直接检查活动的产品 ID)。
func subscriptionStatus(completion: @escaping (Bool)-> Void) {
Purchases.shared.purchaserInfo { (info, error) in
// Check if the purchaserInfo contains the pro feature ID you configured
completion(info?.activeEntitlements.contains("pro_feature_ID") ?? false)
// Alternatively, you can directly check if there is a specific product ID
// that is active.
// completion(info?.activeSubscriptions.contains("product_ID") ?? false)
}
}
正在获取订阅状态
您可以根据需要随时调用上述函数,因为结果由 Purchases SDK 缓存,在大多数情况下它将 return 同步并且不需要网络请求。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
subscriptionStatus { (subscribed) in
if subscribed {
// Show that great pro content
}
}
}
如果您使用的是 SwiftyStoreKit,则 RevenueCat 语法非常相似,并且有一个 migration guide 可用于帮助切换。
另一种使用 Qonversion SDK 处理 auto-renewable iOS 订阅的解决方案。
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Qonversion.launch(withKey: "yourProjectKey")
return true
}
获取订阅状态
Link App Store 订阅 Qonversion 产品,link 产品获得许可。
然后你只需要在你的应用程序开始时触发 checkPermissions
方法来检查用户的订阅是否仍然有效。此方法将检查用户收据并将 return 当前权限。然后对于still-active订阅,你可以得到订阅者有turned-offauto-renewal,是否处于grace period(计费重试状态)等
的详细信息
Qonversion.checkPermissions { (permissions, error) in
if let error = error {
// handle error
return
}
if let premium = permissions["premium"], premium.isActive {
switch premium.renewState {
case .willRenew, .nonRenewable:
// .willRenew is the state of an auto-renewable subscription
// .nonRenewable is the state of consumable/non-consumable IAPs that could unlock lifetime access
break
case .billingIssue:
// Grace period: permission is active, but there was some billing issue.
// Prompt the user to update the payment method.
break
case .cancelled:
// The user has turned off auto-renewal for the subscription, but the subscription has not expired yet.
// Prompt the user to resubscribe with a special offer.
break
default: break
}
}
}
您可以查看我们演示 auto-renewable 订阅实施的示例应用 here。
我想在打开应用程序时检查自动续订订阅状态。
这是为了确保用户仍订阅该服务。我该如何实现?
有什么想法吗?谢谢
P.S.: 我正在使用 SwiftyStoreKit
这里有几种进行收据验证以检查用户是否被授予订阅的方法。这里有两种正确的方法:
- 在本地进行收据验证 here。
远程执行收据验证 here。提到不应在应用程序内将收据发送到 App Store。简短摘要:
- 您的应用将收据发送到您的后端。
- 您的后端将收据发送到 Apple 后端进行验证。
- 您的后端从苹果获得响应。
- 您的后端将结果发送回您的应用程序是收据有效还是无效。
在这两种方式中,您都将获得应用内购买列表。它还将包含过期的订阅。您需要浏览所有订阅并检查到期日期。如果它仍然有效,您必须授予用户订阅。
据我了解,您正在使用 SwiftyStoreKit,这是 local receipt validation 的开放任务。
您可以使用此功能查看。它适用于 swift4
func receiptValidation() {
let SUBSCRIPTION_SECRET = "yourpasswordift"
let receiptPath = Bundle.main.appStoreReceiptURL?.path
if FileManager.default.fileExists(atPath: receiptPath!){
var receiptData:NSData?
do{
receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped)
}
catch{
print("ERROR: " + error.localizedDescription)
}
//let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
let base64encodedReceipt = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions.endLineWithCarriageReturn)
print(base64encodedReceipt!)
let requestDictionary = ["receipt-data":base64encodedReceipt!,"password":SUBSCRIPTION_SECRET]
guard JSONSerialization.isValidJSONObject(requestDictionary) else { print("requestDictionary is not valid JSON"); return }
do {
let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt" // this works but as noted above it's best to use your own trusted server
guard let validationURL = URL(string: validationURLString) else { print("the validation url could not be created, unlikely error"); return }
let session = URLSession(configuration: URLSessionConfiguration.default)
var request = URLRequest(url: validationURL)
request.httpMethod = "POST"
request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.uploadTask(with: request, from: requestData) { (data, response, error) in
if let data = data , error == nil {
do {
let appReceiptJSON = try JSONSerialization.jsonObject(with: data)
print("success. here is the json representation of the app receipt: \(appReceiptJSON)")
// if you are using your server this will be a json representation of whatever your server provided
} catch let error as NSError {
print("json serialization failed with error: \(error)")
}
} else {
print("the upload task returned an error: \(error)")
}
}
task.resume()
} catch let error as NSError {
print("json serialization failed with error: \(error)")
}
}
}
我想为那些仍然偶然发现这个问题的人提供一个使用 RevenueCat SDK 的替代解决方案。
AppDelegate.swift
使用您的 api 密钥和可选的用户标识符配置 RevenueCat Purchases SDK。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Purchases.configure(withAPIKey: "<...>", appUserID: "<...>")
...
return true
}
订阅状态函数
下面的函数检查 PurchaserInfo
以查看用户是否仍有活动的 "entitlement"(或者您可以直接检查活动的产品 ID)。
func subscriptionStatus(completion: @escaping (Bool)-> Void) {
Purchases.shared.purchaserInfo { (info, error) in
// Check if the purchaserInfo contains the pro feature ID you configured
completion(info?.activeEntitlements.contains("pro_feature_ID") ?? false)
// Alternatively, you can directly check if there is a specific product ID
// that is active.
// completion(info?.activeSubscriptions.contains("product_ID") ?? false)
}
}
正在获取订阅状态
您可以根据需要随时调用上述函数,因为结果由 Purchases SDK 缓存,在大多数情况下它将 return 同步并且不需要网络请求。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
subscriptionStatus { (subscribed) in
if subscribed {
// Show that great pro content
}
}
}
如果您使用的是 SwiftyStoreKit,则 RevenueCat 语法非常相似,并且有一个 migration guide 可用于帮助切换。
另一种使用 Qonversion SDK 处理 auto-renewable iOS 订阅的解决方案。
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Qonversion.launch(withKey: "yourProjectKey")
return true
}
获取订阅状态
Link App Store 订阅 Qonversion 产品,link 产品获得许可。
然后你只需要在你的应用程序开始时触发 checkPermissions
方法来检查用户的订阅是否仍然有效。此方法将检查用户收据并将 return 当前权限。然后对于still-active订阅,你可以得到订阅者有turned-offauto-renewal,是否处于grace period(计费重试状态)等
Qonversion.checkPermissions { (permissions, error) in
if let error = error {
// handle error
return
}
if let premium = permissions["premium"], premium.isActive {
switch premium.renewState {
case .willRenew, .nonRenewable:
// .willRenew is the state of an auto-renewable subscription
// .nonRenewable is the state of consumable/non-consumable IAPs that could unlock lifetime access
break
case .billingIssue:
// Grace period: permission is active, but there was some billing issue.
// Prompt the user to update the payment method.
break
case .cancelled:
// The user has turned off auto-renewal for the subscription, but the subscription has not expired yet.
// Prompt the user to resubscribe with a special offer.
break
default: break
}
}
}
您可以查看我们演示 auto-renewable 订阅实施的示例应用 here。