// Verify that at least one receipt has the right product id
ifletfirstItem=receiptItems.first{
return.purchased(item:firstItem)
}
return.notPurchased
}
/**
* Verify the validity of a set of subscriptions in a receipt.
*
* This method extracts all transactions matching the given productIds and sorts them by date in descending order. It then compares the first transaction expiry date against the receipt date, to determine its validity.
* - Note: You can use this method to check the validity of (mutually exclusive) subscriptions in a subscription group.
* - Remark: The type parameter determines how the expiration dates are calculated for all subscriptions. Make sure all productIds match the specified subscription type to avoid incorrect results.
* - Parameter type: .autoRenewable or .nonRenewing.
* - Parameter productIds: The product ids of the subscriptions to verify.
* - Parameter receipt: The receipt to use for looking up the subscriptions
* - Parameter validUntil: Date to check against the expiry date of the subscriptions. This is only used if a date is not found in the receipt.
* - return: Either .notPurchased or .purchased / .expired with the expiry date found in the receipt.
*/
classfuncverifySubscriptions(
ofTypetype:SubscriptionType,
productIds:Set<String>,
inReceiptreceipt:ReceiptInfo,
validUntildate:Date=Date()
)->VerifySubscriptionResult{
// The values of the latest_receipt and latest_receipt_info keys are useful when checking whether an auto-renewable subscription is currently active. By providing any transaction receipt for the subscription and checking these values, you can get information about the currently-active subscription period. If the receipt being validated is for the latest renewal, the value for latest_receipt is the same as receipt-data (in the request) and the value for latest_receipt_info is the same as receipt.
* Having one payment queue observer for each request causes extra processing
* Failed transactions only ever belong to queued payment requests.
* restoreCompletedTransactionsFailedWithError is always called when a restore purchases request fails.
* paymentQueueRestoreCompletedTransactionsFinished is always called following 0 or more update transactions when a restore purchases request succeeds.
* A complete transactions handler is require to catch any transactions that are updated when the app is not running.
* Registering a complete transactions handler when the app launches ensures that any pending transactions can be cleared.
* If a complete transactions handler is missing, pending transactions can be mis-attributed to any new incoming payments or restore purchases.
*
* The order in which transaction updates are processed is:
* 1. payments (transactionState: .purchased and .failed for matching product identifiers)
* 2. restore purchases (transactionState: .restored, or restoreCompletedTransactionsFailedWithError, or paymentQueueRestoreCompletedTransactionsFinished)
/// The formatted, localized period / date for the product discount.
/// - note: The subscription period for the discount is independent of the product's regular subscription period, and does not have to match in units or duration.
/// The product identifier of the item that was purchased. This value corresponds to the `productIdentifier` property of the `SKPayment` object stored in the transaction’s payment property.
publicvarproductId:String
/// The number of items purchased. This value corresponds to the `quantity` property of the `SKPayment` object stored in the transaction’s payment property.
publicvarquantity:Int
/// The transaction identifier of the item that was purchased. This value corresponds to the transaction’s `transactionIdentifier` property.
publicvartransactionId:String
/// For a transaction that restores a previous transaction, the transaction identifier of the original transaction.
///
/// Otherwise, identical to the transaction identifier. This value corresponds to the original transaction’s `transactionIdentifier` property. All receipts in a chain of renewals for an auto-renewable subscription have the same value for this field.
publicvaroriginalTransactionId:String
/// The date and time that the item was purchased. This value corresponds to the transaction’s `transactionDate` property.
publicvarpurchaseDate:Date
/// For a transaction that restores a previous transaction, the date of the original transaction. This value corresponds to the original transaction’s `transactionDate` property. In an auto-renewable subscription receipt, this indicates the beginning of the subscription period, even if the subscription has been renewed.
publicvaroriginalPurchaseDate:Date
/// The primary key for identifying subscription purchases.
publicvarwebOrderLineItemId:String?
/// The expiration date for the subscription, expressed as the number of milliseconds since January 1, 1970, 00:00:00 GMT. This key is **only** present for **auto-renewable** subscription receipts.
publicvarsubscriptionExpirationDate:Date?
/// For a transaction that was canceled by Apple customer support, the time and date of the cancellation.
///
/// Treat a canceled receipt the same as if no purchase had ever been made.
publicvarcancellationDate:Date?
/// Indicates whether or not the subscription item is currently within a given trial period.
publicvarisTrialPeriod:Bool
/// Indicates whether or not the subscription item is currently within an intro offer period.
/// The App Store could not read the JSON object you provided.
casejsonNotReadable=21000
/// The data in the receipt-data property was malformed or missing.
casemalformedOrMissingData=21002
/// The receipt could not be authenticated.
casereceiptCouldNotBeAuthenticated=21003
/// The shared secret you provided does not match the shared secret on file for your account.
casesecretNotMatching=21004
/// The receipt server is not currently available.
casereceiptServerUnavailable=21005
/// This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.
casesubscriptionExpired=21006
/// This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.
casetestReceipt=21007
/// This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.
caseproductionEnvironment=21008
varisValid:Bool{returnself==.valid}
}
// Receipt field as defined in : https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
publicenumReceiptInfoField:String{
/// Bundle Identifier. This corresponds to the value of CFBundleIdentifier in the Info.plist file.
casebundle_id
/// The app’s version number.This corresponds to the value of CFBundleVersion (in iOS) or CFBundleShortVersionString (in OS X) in the Info.plist.
caseapplication_version
/// The version of the app that was originally purchased. This corresponds to the value of CFBundleVersion (in iOS) or CFBundleShortVersionString (in OS X) in the Info.plist file when the purchase was originally made.
caseoriginal_application_version
/// The date when the app receipt was created.
casecreation_date
/// The date that the app receipt expires. This key is present only for apps purchased through the Volume Purchase Program.
caseexpiration_date
/// The receipt for an in-app purchase.
casein_app
publicenumInApp:String{
/// The number of items purchased. This value corresponds to the quantity property of the SKPayment object stored in the transaction’s payment property.
casequantity
/// The product identifier of the item that was purchased. This value corresponds to the productIdentifier property of the SKPayment object stored in the transaction’s payment property.
caseproduct_id
/// The transaction identifier of the item that was purchased. This value corresponds to the transaction’s transactionIdentifier property.
casetransaction_id
/// For a transaction that restores a previous transaction, the transaction identifier of the original transaction. Otherwise, identical to the transaction identifier. This value corresponds to the original transaction’s transactionIdentifier property. All receipts in a chain of renewals for an auto-renewable subscription have the same value for this field.
caseoriginal_transaction_id
/// The date and time that the item was purchased. This value corresponds to the transaction’s transactionDate property.
casepurchase_date
/// For a transaction that restores a previous transaction, the date of the original transaction. This value corresponds to the original transaction’s transactionDate property. In an auto-renewable subscription receipt, this indicates the beginning of the subscription period, even if the subscription has been renewed.
caseoriginal_purchase_date
/// The expiration date for the subscription, expressed as the number of milliseconds since January 1, 1970, 00:00:00 GMT. This key is only present for auto-renewable subscription receipts.
caseexpires_date
/// For a transaction that was canceled by Apple customer support, the time and date of the cancellation. Treat a canceled receipt the same as if no purchase had ever been made.
casecancellation_date
#if os(iOS) || os(tvOS)
/// A string that the App Store uses to uniquely identify the application that created the transaction. If your server supports multiple applications, you can use this value to differentiate between them. Apps are assigned an identifier only in the production environment, so this key is not present for receipts created in the test environment. This field is not present for Mac apps. See also Bundle Identifier.
caseapp_item_id
#endif
/// An arbitrary number that uniquely identifies a revision of your application. This key is not present for receipts created in the test environment.
caseversion_external_identifier
/// The primary key for identifying subscription purchases.
caseweb_order_line_item_id
}
}
#if os(OSX)
publicenumReceiptExitCode:Int32{
/// If validation fails in OS X, call exit with a status of 173. This exit status notifies the system that your application has determined that its receipt is invalid. At this point, the system attempts to obtain a valid receipt and may prompt for the user’s iTunes credentials
* Verify the validity of a subscription (auto-renewable, free or non-renewing) in a receipt.
*
* This method extracts all transactions matching the given productId and sorts them by date in descending order. It then compares the first transaction expiry date against the receipt date to determine its validity.
* - Parameter type: `.autoRenewable` or `.nonRenewing`.
* - Parameter productId: The product id of the subscription to verify.
* - Parameter receipt: The receipt to use for looking up the subscription.
* - Parameter validUntil: Date to check against the expiry date of the subscription. This is only used if a date is not found in the receipt.
* - returns: Either `.notPurchased` or `.purchased` / `.expired` with the expiry date found in the receipt.
* Verify the validity of a set of subscriptions in a receipt.
*
* This method extracts all transactions matching the given productIds and sorts them by date in descending order. It then compares the first transaction expiry date against the receipt date, to determine its validity.
* - Note: You can use this method to check the validity of (mutually exclusive) subscriptions in a subscription group.
* - Remark: The type parameter determines how the expiration dates are calculated for all subscriptions. Make sure all productIds match the specified subscription type to avoid incorrect results.
* - Parameter type: `.autoRenewable` or `.nonRenewing`.
* - Parameter productIds: The product IDs of the subscriptions to verify.
* - Parameter receipt: The receipt to use for looking up the subscriptions
* - Parameter validUntil: Date to check against the expiry date of the subscriptions. This is only used if a date is not found in the receipt.
* - returns: Either `.notPurchased` or `.purchased` / `.expired` with the expiry date found in the receipt.