Swift IAP 订阅处理所有交易
Swift IAP subscription processing all transactions
我对 swift 中的 IAP 订阅处理有疑问。
我在我的应用程序中使用 IAP 订阅,逻辑完美无缺,我没有任何问题。我想检查处理来自 paymentQueue 的交易。我注意到它正在循环 paymentQueue 中的所有交易,我必须验证所有交易的收据。这是否有必要循环检查所有交易,或者我应该只关注最后一笔交易。最后一笔交易会是最近的一笔交易吗?以下是部分代码的代码片段。
在输出控制台中,我得到以下几行(最后三行循环 140 次):
总交易数 - 140
开始刷新收据...
内部解析收据....
已购买交易
问题:是否需要处理所有的交易(本例中为140)这个140是针对同一个产品的。我可以通过任何方式避免这种循环,从而改进处理。
提前致谢。
extension IAPManager: SKPaymentTransactionObserver {
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print(" Total Transaction Count - \(queue.transactions.count)")
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased:
notifyIsPurchased(transaction: transaction)
SKPaymentQueue.default().finishTransaction(transaction)
print ("Transaction Purchased")
break
case .failed:
SKPaymentQueue.default().finishTransaction(transaction)
self.failureBlock?(transaction.error)
cleanUp()
break
case .restored:
notifyIsPurchased(transaction: transaction)
SKPaymentQueue.default().finishTransaction(transaction)
print("restored")
break
case .deferred:
print("defered")
break
case .purchasing:
print("purchasing")
break
default:
break
}
}
}
private func notifyIsPurchased(transaction: SKPaymentTransaction) {
refreshSubscriptionsStatus(callback: {
self.successBlock?()
self.cleanUp()
}) { (error) in
// couldn't verify receipt
self.failureBlock?(error)
self.cleanUp()
}
}
func refreshSubscriptionsStatus(callback : @escaping SuccessBlock, failure : @escaping FailureBlock) {
print("Start refreshing reciept...")
self.refreshSubscriptionSuccessBlock = callback
self.refreshSubscriptionFailureBlock = failure
guard let receiptUrl = Bundle.main.appStoreReceiptURL else {
print("No reciept")
refreshReceipt()
return
}
let urlString = "https://sandbox.itunes.apple.com/verifyReceipt"
//let urlString = "https://buy.itunes.apple.com/verifyReceipt"
let receiptData = try? Data(contentsOf: receiptUrl).base64EncodedString()
let requestData = ["receipt-data" : receiptData ?? "", "password" : self.sharedSecret, "exclude-old-transactions" : true] as [String : Any]
var request = URLRequest(url: URL(string: urlString)!)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
let httpBody = try? JSONSerialization.data(withJSONObject: requestData, options: [])
request.httpBody = httpBody
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
if data != nil {
if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments){
//print (json)
self.parseReceipt(json as! Dictionary<String, Any>)
return
}
} else {
print("error validating receipt: \(error?.localizedDescription ?? "")")
}
self.refreshSubscriptionFailureBlock?(error)
self.cleanUpRefeshReceiptBlocks()
}
}.resume()
}
private func parseReceipt(_ json : Dictionary<String, Any>) {
print("Inside Parsing Reciept....")
guard let receipts_array = json["latest_receipt_info"] as? [Dictionary<String, Any>] else {
self.refreshSubscriptionFailureBlock?(nil)
self.cleanUpRefeshReceiptBlocks()
return
}
process the receipt array and check if it is expired or valid...
}
无法 100% 保证您 [SKPaymentTransaction]
中的最后一笔交易是您最近的一笔交易,根据 Apple documentation 的记载 transactions
属性 是:
An array of the transactions that were updated.
那里没有明确说明 transactions
已正确排序,尽管数组通常用于顺序很重要的元素。但是您可以通过访问 transactionDate
属性。这是一个例子:
func paymentQueue(_ queue: SKPaymentQueue,
updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
let ascendingTransactions = transactions.filter({[=10=].transactionDate != nil})
.sorted(by: {.transactionDate! > [=10=].transactionDate!})
let latestTransaction = ascendingTransactions.last
}
}
我对 swift 中的 IAP 订阅处理有疑问。 我在我的应用程序中使用 IAP 订阅,逻辑完美无缺,我没有任何问题。我想检查处理来自 paymentQueue 的交易。我注意到它正在循环 paymentQueue 中的所有交易,我必须验证所有交易的收据。这是否有必要循环检查所有交易,或者我应该只关注最后一笔交易。最后一笔交易会是最近的一笔交易吗?以下是部分代码的代码片段。
在输出控制台中,我得到以下几行(最后三行循环 140 次): 总交易数 - 140
开始刷新收据...
内部解析收据....
已购买交易
问题:是否需要处理所有的交易(本例中为140)这个140是针对同一个产品的。我可以通过任何方式避免这种循环,从而改进处理。
提前致谢。
extension IAPManager: SKPaymentTransactionObserver {
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print(" Total Transaction Count - \(queue.transactions.count)")
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased:
notifyIsPurchased(transaction: transaction)
SKPaymentQueue.default().finishTransaction(transaction)
print ("Transaction Purchased")
break
case .failed:
SKPaymentQueue.default().finishTransaction(transaction)
self.failureBlock?(transaction.error)
cleanUp()
break
case .restored:
notifyIsPurchased(transaction: transaction)
SKPaymentQueue.default().finishTransaction(transaction)
print("restored")
break
case .deferred:
print("defered")
break
case .purchasing:
print("purchasing")
break
default:
break
}
}
}
private func notifyIsPurchased(transaction: SKPaymentTransaction) {
refreshSubscriptionsStatus(callback: {
self.successBlock?()
self.cleanUp()
}) { (error) in
// couldn't verify receipt
self.failureBlock?(error)
self.cleanUp()
}
}
func refreshSubscriptionsStatus(callback : @escaping SuccessBlock, failure : @escaping FailureBlock) {
print("Start refreshing reciept...")
self.refreshSubscriptionSuccessBlock = callback
self.refreshSubscriptionFailureBlock = failure
guard let receiptUrl = Bundle.main.appStoreReceiptURL else {
print("No reciept")
refreshReceipt()
return
}
let urlString = "https://sandbox.itunes.apple.com/verifyReceipt"
//let urlString = "https://buy.itunes.apple.com/verifyReceipt"
let receiptData = try? Data(contentsOf: receiptUrl).base64EncodedString()
let requestData = ["receipt-data" : receiptData ?? "", "password" : self.sharedSecret, "exclude-old-transactions" : true] as [String : Any]
var request = URLRequest(url: URL(string: urlString)!)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
let httpBody = try? JSONSerialization.data(withJSONObject: requestData, options: [])
request.httpBody = httpBody
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
if data != nil {
if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments){
//print (json)
self.parseReceipt(json as! Dictionary<String, Any>)
return
}
} else {
print("error validating receipt: \(error?.localizedDescription ?? "")")
}
self.refreshSubscriptionFailureBlock?(error)
self.cleanUpRefeshReceiptBlocks()
}
}.resume()
}
private func parseReceipt(_ json : Dictionary<String, Any>) {
print("Inside Parsing Reciept....")
guard let receipts_array = json["latest_receipt_info"] as? [Dictionary<String, Any>] else {
self.refreshSubscriptionFailureBlock?(nil)
self.cleanUpRefeshReceiptBlocks()
return
}
process the receipt array and check if it is expired or valid...
}
无法 100% 保证您 [SKPaymentTransaction]
中的最后一笔交易是您最近的一笔交易,根据 Apple documentation 的记载 transactions
属性 是:
An array of the transactions that were updated.
那里没有明确说明 transactions
已正确排序,尽管数组通常用于顺序很重要的元素。但是您可以通过访问 transactionDate
属性。这是一个例子:
func paymentQueue(_ queue: SKPaymentQueue,
updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
let ascendingTransactions = transactions.filter({[=10=].transactionDate != nil})
.sorted(by: {.transactionDate! > [=10=].transactionDate!})
let latestTransaction = ascendingTransactions.last
}
}