我们正在使用自动续订订阅的应用程序。我们只有一个选项 - 每月自动续订订阅,一周免费试用。我们还使用“订阅状态URL”来接收订阅通知。
应用程序本身类似于“待办事项列表”应用程序,可以在多个用户之间共享任务。因此,我们将数据保存在服务器上。
每次用户加载应用程序或创建任务时,数据都来自服务器,其中包含current_subscription_status参数,例如我们只需根据服务器上的当前日期检查收货到期日期,即可在服务器上进行订阅状态验证。
目前我们只有iOS版本,但也适用于Android版本。并且用户应该能够在具有不同苹果ID的不同设备上唱歌他/她的帐户。
我们遇到的问题是,我们没有收到实际购买(订阅)通知。例如。当用户点击“开始免费试用1周”按钮并订阅时,我们会收到通知(输入INITIAL_BUY)。在这一周的试用期过后,我们应该再次收到类似“RENEWAL”的通知,但我们什么都没收到。
我们联系了Apple开发者支持,但没有得到真正的帮助。他们只是发送Apple文档的链接。我们在哪里找到了以下注释(here is the link):
“要在处理活动时获取最新信息,您的应用应通过App Store验证最新收据。”
因此,基于此,我对可能的用例场景有疑问:
用户在iOS设备上订阅每月自动续订订阅,例如他/她希望被指控他/她的苹果iTunes帐户。但是,在最初购买后他/她关闭(杀死)应用程序,甚至不再在iOS设备上打开它。用户将应用下载到Android设备并仅在Android上使用该应用。因此,App Store应该每个月向该用户收费并向服务器发送订阅状态通知,即使用户再也没有在他的iOS设备上打开该应用程序。因此,iOS应用程序永远不会发生“...最新收据验证...”。如何实施?
技术细节:
我们使用SwiftyStoreKit。这些是应用内购买实施的两个部分:
在AppDelegate中我们有:
// Auto-renewal complete transactions
SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
for purchase in purchases {
if purchase.transaction.transactionState == .purchased || purchase.transaction.transactionState == .restored {
if purchase.needsFinishTransaction {
// Deliver content from server, then:
SwiftyStoreKit.finishTransaction(purchase.transaction)
}
}
}
}
当用户点击“开始免费试用按钮”时,会调用订阅功能:
func subscribe(completion: @escaping (_ response:Bool, _ message: String?) -> Void) {
SwiftyStoreKit.purchaseProduct(self.productId, atomically: true) { result in
if case .success(let purchase) = result {
if purchase.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(purchase.transaction)
}
let appleValidator = AppleReceiptValidator(service: self.env, sharedSecret: self.sharedSecret)
SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
if case .success(let receipt) = result {
let purchaseResult = SwiftyStoreKit.verifySubscription(
type: .autoRenewable,
productId: self.productId,
inReceipt: receipt)
switch purchaseResult {
case .purchased(let expiryDate, let receiptItems):
if let receiptItem = receiptItems.first {
// Send receipt to the server functionality
.............................
}
completion(true, nil)
case .expired(let expiryDate, let receiptItems):
completion(false, "Receipt has been expired")
case .notPurchased:
completion(false, "Purchase has not been processed")
}
} else {
// receipt verification error
completion(false, "ERROR OCCURED")
}
}
} else {
// purchase error
completion(false, "Canceled")
}
}}