Easy Purchase Reciept Validator
Easy Purchase Reciept Validator 是一个极简、完全使用 Swift 编写的库,旨在本地解释和验证苹果 In-App Purchase 收款单。
功能
- 访问每个 In-App 收款单属性的详细信息
- 验证 In-App Purchase 收款单(包括签名、包版本和标识符、哈希)
- iOS 11+ 已准备好:提供对从 App Store 开始的应用内购买的支持(兼容 iOS 11 及以上)。
- 用户友好的 API:享受易于理解的基于块的模式 API。
要求
如果您的最低 iOS 版本设置为 11.0,则所有功能都应可用。因此,仅针对 iOS 设备的要求
- iOS 11.0
安装
您可以在项目中安装 Easy Purchase Receipt Validator,有多种选择,其中推荐使用 Swift Package Manager、CocoaPods 和 Carthage 集成。
无论您选择哪种方法,都确保将项目导入到您打算使用的任何地方
import Easy_Purchase_Receipt_Validator
Swift 包管理器
Swift 包管理器(SPM)是一个用于自动化 Swift 代码分布的工具,无缝集成到 Xcode 和 Swift 编译器中。它是 Easy Purchase Reciept Validator 推荐的安装方法。使用 SPM,Easy Purchase Reciept Validator 的更新将立即应用到您的项目中。SPM 也直接集成到 Xcode 中。
如果您使用的是 Xcode 11 或更新版本,请按照以下步骤将 Easy_Purchase_Receipt_Validator 添加为依赖项
- 点击 文件。
- 选择 Swift 包。
- 选择 添加包依赖...。
- 指定 Easy_Purchase_Receipt_Validator 的 git URL。
https://github.com/BJIT-RnD/Easy-Purchase-Receipt-Validator.git
CocoaPods
Easy Purchase Reciept Validator 可以作为 CocoaPod 安装,并以 Swift 框架的形式构建。
要安装,请在 Podfile 中包含以下内容。
use_frameworks!
pod ‘Easy_Purchase_Receipt_Validator'
使用指南
通过收据初始化
我们的库将确保您的收据按照规则解码,并将解码后的数据返回给使用我们库的开发者。
要开始验证过程,请按照以下步骤操作
- 从您应用的bundle的appStoreReceiptURL加载收据。
if let receiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: receiptURL.path) {
let receiptData = try? Data(contentsOf: receiptURL, options: .alwaysMapped)
do {
// Continue with the validation process
} catch {
// Handle errors during the loading of receipt data
}
}
- 为了继续验证过程并捕获错误
do {
let appleContainer = try AppleContainer(data: receiptData!)
let receiptData = try appleContainer.AppleReceipt()
} catch {
// Handle errors during the parsing of receipt data
// e.g., print("Error occurred during parsing receipt data")
}
确保将以下代码段集成到您的应用程序中以有效地加载和验证In-App Purchase收据。根据您应用程序的需求调整错误处理机制。
收据验证
在成功从上述部分获取receiptData之后,您可以检查数据的有效性
do {
let receiptValidityCheck = try receiptData.isValidReceipt()
} catch ReceiptError.verificationFailed {
// Do something if verification is failed
}
注意:苹果强烈建议在您应用启动时立即进行收据验证。为了提高安全性,请在您的应用活动时定期重新检查验证。另外,在iOS上的验证失败的情况下,建议首先尝试刷新收据。
访问已验证收据的多种信息
确保您拥有已验证的收据后,您可以根据需要访问收据中的各种信息。
- 访问Bundle标识符
let bundleIdentifier = receiptData.bundleIdentifier
- 访问原始App版本
let originalAppVersion = receiptData.originalAppVersion
- 访问Bundle版本
let bundleVersion = receiptData.bundleVersion
- 访问购买列表
guard let purchase = receiptData.purchases else { return }
- 访问不透明值
let opaqueValue = receiptData.opaqueValue
- 访问Bundle标识符数据
let bundleIdentifierData = receiptData.bundleIdentifierData
- 访问收据哈希值
let receiptHash = receiptData.receiptHash
- 访问收据创建日期
let receiptCreationDate = receiptData.creationDate
- 访问收据过期日期
let receiptExpirationDate = receiptData.expirationDate
- 以字符串形式访问收据创建日期
let creationDateString = receiptData.creationDateString
- 以字符串形式访问收据过期日期
let expirationDateString = receiptData.expirationDateString
一些有用方法
本部分解释如何调用我们的库的不同方法,这些方法将根据您的需求执行特定任务。
/// Returns the original transaction identifier for the first purchase of a specific product identifier.
///
/// - Parameter productIdentifier: The product identifier.
/// - Returns: The original transaction identifier, or `nil` if no purchases exist.
public func originalTransactionIdentifier(ofProductIdentifier productIdentifier: String) -> String?
// MARK: Contains Purchase
/// Checks if there is a purchase for a specific product identifier.
///
/// - Parameter productIdentifier: The product identifier.
/// - Returns: `true` if the product has been purchased, `false` otherwise.
public func containsPurchase(ofProductIdentifier productIdentifier: String) -> Bool
// MARK: Purchase Expired Date
/// Returns the expiration date of the first purchase for a specific product identifier.
///
/// - Parameter productIdentifier: The product identifier.
/// - Returns: The expiration date, or `nil` if no purchases exist or the expiration date is `nil`.
public func getPurchaseExpiredDatebyProductId(ofProductIdentifier productIdentifier: String) throws -> Date?
// MARK: Purchases
/// Returns an array of purchases for a specific product identifier.
///
/// - Parameters:
/// - productIdentifier: The product identifier.
/// - sort: An optional sorting block for the purchases.
/// - Returns: An array of purchases, sorted if a sorting block is provided.
public func allPurchasesByProductId(ofProductIdentifier productIdentifier: String,
sortedBy sort: ((PurchaseData, PurchaseData) -> Bool)? = nil) -> [PurchaseData]
// MARK: Currently Active Auto-Renewable Subscription Purchases Within a Specific Date
/// Returns the currently active auto-renewable subscription purchase for a specific product identifier and date.
///
/// - Parameters:
/// - productIdentifier: The product identifier.
/// - date: The date for which the subscription's status is checked.
/// - Returns: The active auto-renewable subscription purchase, or `nil` if none is found.
///
public func isActiveAutoRenewableByDate(ofProductIdentifier productIdentifier: String, forDate date: Date) throws -> PurchaseData?
// MARK: Currently Active Auto-Renewable Subscription Purchases
/// Returns the currently active auto-renewable subscription purchase for a specific product identifier.
///
/// - Parameters:
/// - productIdentifier: The product identifier.
/// - Returns: The active auto-renewable subscription purchase by checking current date using Date(), or `nil` if none is found.
///
public func isCurrentlyActiveAutoRenewable(ofProductIdentifier productIdentifier: String) throws -> PurchaseData?
// MARK: All Auto-renewable products receipt containing
/// Returns all the auto-renewable subscription purchase ever done by the user.
///
/// - Returns: The list of all the auto-renewable subscription purchase ever done by the user.
///
public var allAutoRenewables: [PurchaseData]
// MARK: All Active Auto-renewable products receipt containing
/// Returns all the active auto-renewable subscription purchases.
///
/// - Returns: The list of all the active auto-renewable subscription purchase ever done by the user.
///
// MARK: - Non-Renewable Product Validation
/// Determines the validity of a non-renewable product based on a specified number of days.
///
/// - Parameters:
/// - productIdentifier: The identifier of the non-renewable product.
/// - day: The number of days the product is considered valid.
/// - currentDate: The current date for comparison.
/// - Returns: `true` if the product is valid, `false` otherwise.
/// - Throws: An error if there are issues with product purchase or date calculations.
public func isNonRenewableActive(productIdentifier: String, validForDay day: Int, currentDate: Date) throws -> Bool
/// Determines the validity of a non-renewable product based on a specified number of months.
///
/// - Parameters:
/// - productIdentifier: The identifier of the non-renewable product.
/// - month: The number of months the product is considered valid.
/// - currentDate: The current date for comparison.
/// - Returns: `true` if the product is valid, `false` otherwise.
/// - Throws: An error if there are issues with product purchase or date calculations.
public func isNonRenewableActive(productIdentifier: String, validForMonth month: Int, currentDate: Date) throws -> Bool
/// Determines the validity of a non-renewable product based on a specified number of years.
///
/// - Parameters:
/// - productIdentifier: The identifier of the non-renewable product.
/// - year: The number of years the product is considered valid.
/// - currentDate: The current date for comparison.
/// - Returns: `true` if the product is valid, `false` otherwise.
/// - Throws: An error if there are issues with product purchase or date calculations.
public func isNonRenewableActive(productIdentifier: String, validForYear year: Int, currentDate: Date) throws -> Bool
/// Private method for checking the validity of a non-renewable product.
///
/// - Parameters:
/// - productIdentifier: The identifier of the non-renewable product.
/// - activeDays: The total number of days the product is considered valid.
/// - currentDate: The current date for comparison.
/// - Returns: `true` if the product is valid, `false` otherwise.
/// - Throws: An error if there are issues with product purchase or date calculations.
private func checkNonRenewableValidity(productIdentifier: String, activeDays: Int, currentDate: Date) throws -> Bool
注意。
Easy Purchase Receipt Validator不会在本地层面保留应用内购买数据。管理 storage 数据的责任落在使用此库的客户或开发者身上。他们有灵活性选择他们偏好的存储解决方案,这可能是包括 NSUserDefaults、CoreData 或 Keychain 等选项。换句话说,此库不处理应用内购买信息的本地存储;这项任务留给客户自行决定,让他们能够选择最适合他们需求的方案。