首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用SwiftyStoreKit自动续费

使用SwiftyStoreKit自动续费
EN

Stack Overflow用户
提问于 2021-07-01 14:47:45
回答 1查看 338关注 0票数 2

SwiftyStoreKit对我来说是一个非常困难的产品,因为几乎一个星期以来,我在StackOverflow,YouTube和谷歌上到处搜索答案。我找不到任何答案,因为我正在研究Auto-Renewable,我试图找出用户是否取消订阅或过期,应用程序将要求重新订阅。在测试期间,购买效果很好,但我需要弄清楚应用程序是如何知道订阅是否过期的。每次我尝试验证我的验证收据时,都会返回以下错误消息。我做错什么了?

代码语言:javascript
复制
Receipt verification failed: receiptInvalid(receipt: ["status": 21002], status: SwiftyStoreKit.ReceiptStatus.malformedOrMissingData)

下面是我的顶级代码:

代码语言:javascript
复制
import SwiftyStoreKit

var sharedSecret = " * My shared Secret * "
let appleValidator = AppleReceiptValidator(service: .sandbox, sharedSecret: sharedSecret)

enum RegisteredPurchase: String {
    case autoRenewable = " * My Auto-Renewable Bundle ID * "
}

我在购买时使用按钮的代码

代码语言:javascript
复制
@objc func startSub() {
   StoreManager.shared.purchase(purchase: RegisteredPurchase.autoRenewable)
}

AppDelegate.swift

代码语言:javascript
复制
SwiftyStoreKit.completeTransactions(atomically: true) { purchaseStatus in
   for products in purchaseStatus {
      switch products.transaction.transactionState {
      case .purchased,.restored:
         if products.needsFinishTransaction {
            SwiftyStoreKit.finishTransaction(products.transaction)
         }
      default: break
      }
   }
}

SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
   switch result {
   case .success(let receipt):
      let productID = Set([RegisteredPurchase.autoRenewable.rawValue])
      let purchaseResult = SwiftyStoreKit.verifySubscriptions(productIds: productID, inReceipt: receipt)
      switch purchaseResult {
      case .purchased(let expiryDate, let items):
         print("\(productID) are valid until \(expiryDate), \(items).")
      case .expired(let expiryDate, let items):
         print("\(productID) are expired since \(expiryDate), \(items).")
      case .notPurchased:
         print("The product has never purchased...")
      }
   case .error(let error):
      print("Receipt verification failed: \(error)")
   }
}

StoreKitManager.swift

代码语言:javascript
复制
class StoreManager: NSObject {
   @objc static let shared = StoreManager()

   func getInfo(purchase: RegisteredPurchase) {
      SwiftyStoreKit.retrieveProductsInfo([purchase.rawValue], completion: { result in
         if result.error == nil {
            for x in result.retrievedProducts {
               print("Get Information: \(x.localizedTitle)")
            }
         } else {
             print("Error getting information")
         }
      })
   }

   func purchase(purchase: RegisteredPurchase) {
      SwiftyStoreKit.purchaseProduct(purchase.rawValue, completion: { result in
          if case .success(let product) = result {
              if product.needsFinishTransaction {
                  SwiftyStoreKit.finishTransaction(product.transaction)
              }
              print("Purchasing: \(result)")
              self.purchaseResult(result: result)
          }
      })
   }

    
   func verifyReceipt() {
       SwiftyStoreKit.verifyReceipt(using: appleValidator, completion: { result in
           self.verifyReceipt(result: result)
           if case .error(let error) = result {
               if case .noReceiptData = error {
                   self.refreshReceipt()
               }
           }
       })
   }
    
   func verifyPurchase(product: RegisteredPurchase) {
       SwiftyStoreKit.verifyReceipt(using: appleValidator, completion: { result in
           switch result {
           case .success(let receipt):
               let productID = RegisteredPurchase.autoRenewable
               if product == .autoRenewable {
                   let purchseResult = SwiftyStoreKit.verifySubscription(ofType: .autoRenewable, productId: productID.rawValue, inReceipt: receipt, validUntil: Date())
                   print("Verify Purchase Result: \(purchseResult)")
               }
           case .error(let error):
               print("Error verify purchase: \(error)")
               if case .noReceiptData = error {
                   self.refreshReceipt()
               }
           }
       })
   }
   
   func refreshReceipt() {
       SwiftyStoreKit.fetchReceipt(forceRefresh: true, completion: { result in
           print("Start refreshing the receipt...")
       })
   }
   
   func purchaseResult(result: PurchaseResult) {
       switch result {
       case .success(let product):
           print("Purchase Successful: \(product.productId)")
       case .error(let error):
           print("Purchase Failed: \(error)")
       }
   }
   
   func restoreResult(result: RestoreResults) {
       if result.restoreFailedPurchases.count > 0 {
           print("Restore failed by unknown error")
       } else if result.restoredPurchases.count > 0 {
           print("Restore Successful")
       } else {
           print("Nothing to Restore.")
       }
   }
   
   func verifyReceipt(result: VerifyReceiptResult) {
       switch result {
       case .success(let receipt): return print("Verify Receipt: \(receipt)")
       case .error(let error):
           switch error {
           case .noRemoteData: return print("No receipt founded. Try again")
           default: return print("Error Verify Receipt: \(error)")
           }
       }
   }
   
   func verifySubscription(result: VerifySubscriptionResult) {
       switch result {
       case .purchased(let expiryDate):
           print("Product is purchased, valid until \(expiryDate)")
       case .notPurchased:
           print("Product has never purchased.")
       case .expired(let expiredDate):
           print("The product is expired since \(expiredDate)!")
       }
   }
   
   func verifyPurchase(result: VerifyPurchaseResult) {
       switch result {
       case .purchased: print("Product is purchased, will not expired.")
       case .notPurchased: print("Product is not purchased, has never been purchased.")
       }
   }
   
   func refreshReceipt(result: FetchReceiptResult) {
      switch result {
      case .success(let receiptData): print("Receipt Refreshed, \(receiptData)")
      case .error(let receiptData): print("Receipt not Refresh, \(receiptData)")
      }
   }
}
EN

回答 1

Stack Overflow用户

发布于 2021-09-10 09:15:53

我刚接触StoreKit,但这是我的2分钱。该错误消息表明您的服务器可能无法接收有效数据。

以下是苹果公司的说法。

不要从你的应用调用应用商店服务器verifyReceipt终结点。你不能直接在用户的设备和App Store之间建立可信连接,因为你不能控制连接的任何一端,这使得它很容易受到中间机攻击。

Validating Receipts with the App Store

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68205503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档