Skip to content

Releases: bizz84/SwiftyStoreKit

Verify Subscription improvements + added quantity and originalTransaction to Payment

11 May 10:54
Compare
Choose a tag to compare

NOTE This release introduces some API breaking changes (see #202). Change-set:

#198: Subscription verification unit tests

#199 (fixes #192, #190 and #65): Add ReceiptItem to VerifyPurchaseResult, VerifySubscriptionResult

This change introduces a new strong-typed ReceiptItem struct:

public struct ReceiptItem {
    // 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.
    public let productId: String
    // The number of items purchased. This value corresponds to the quantity property of the SKPayment object stored in the transaction’s payment property.
    public let quantity: Int
    // The transaction identifier of the item that was purchased. This value corresponds to the transaction’s transactionIdentifier property.
    public let transactionId: 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.
    public let originalTransactionId: String
    // The date and time that the item was purchased. This value corresponds to the transaction’s transactionDate property.
    public let purchaseDate: 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.
    public let originalPurchaseDate: Date
    // The primary key for identifying subscription purchases.
    public let webOrderLineItemId: 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.
    public let subscriptionExpirationDate: 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.
    public let cancellationDate: Date?

    public let isTrialPeriod: Bool
}

This is parsed from the receipt and returned as part of the verifySubscription and verifyPurchase methods:

// Result for Consumable and NonConsumable
public enum VerifyPurchaseResult {
    case purchased(item: ReceiptItem)
    case notPurchased
}

// Verify subscription result
public enum VerifySubscriptionResult {
    case purchased(expiryDate: Date, items: [ReceiptItem])
    case expired(expiryDate: Date, items: [ReceiptItem])
    case notPurchased
}

Note that when one or more subscriptions are found for a given product id, they are returned as a ReceiptItem array ordered by expiryDate, with the first one being the newest.

This is useful to get all the valid date ranges for a given subscription.

#202 (fix for #200): It's now possible to specify the quantity when making a purchase. Quantity is also accessible in the callback.

This is an API breaking change. Product has been renamed to Purchase:

public struct Purchase {
    public let productId: String
    public let quantity: Int
    public let transaction: PaymentTransaction
    public let needsFinishTransaction: Bool
}

PurchaseResult

public enum PurchaseResult {
    //case success(product: Product) // old
    case success(purchase: Purchase) // new
    case error(error: SKError)
}

RestoreResults

public struct RestoreResults {
    //public let restoredProducts: [Product] // old
    //public let restoreFailedProducts: [(SKError, String?)] // old
    public let restoredPurchases: [Purchase] // new
    public let restoreFailedPurchases: [(SKError, String?)] // new
}

#203 (fix for #193): Add originalTransaction from SKPaymentTransaction.original to Payment type

Improved Documentation

24 Apr 18:05
Compare
Choose a tag to compare

This release only improves documentation for the project, specifically covering these areas:

It also removes a console log that was being printed when detecting a transaction in .purchasing state (see #179)

Xcode 8.3 support

17 Apr 07:41
Compare
Choose a tag to compare

This is a minor release to update the project to Xcode 8.3 and SwiftLint 0.71. A tvOS demo app target is also added.

  • #173: Update project to Xcode 8.3, iOS 10.3
  • #172: Fix warning from Xcode 8.3
  • #170: Updated syntax to new rules in SwiftLint 0.17
  • #167: Add tvOS demo app

Treat cancelled subscriptions as if the product was never purchased

16 Mar 22:09
Compare
Choose a tag to compare

Add SubscriptionType to differentiate between auto-renewable and non-renewing subscriptions

09 Mar 16:40
Compare
Choose a tag to compare

This is a bug-fix release to address #161.

API Changes

Auto-Renewable

The verifySubscription() method API has changed:

let purchaseResult = SwiftyStoreKit.verifySubscription(
            type: .autoRenewable,
            productId: "com.musevisions.SwiftyStoreKit.Subscription",
            inReceipt: receipt)

Non-Renewing

let purchaseResult = SwiftyStoreKit.verifySubscription(
            type: .nonRenewing(validDuration: 3600 * 24 * 30),
            productId: "com.musevisions.SwiftyStoreKit.Subscription",
            inReceipt: receipt)

See the README file for more details.

Changes

For auto-renewable, receipt["latest_receipt_info"] is used.
For non-renewing, receipt["receipt"]?["in_app"] is used.

This fixes a bug where receipt verification fails for non-renewing subscriptions (which were previously using "latest_receipt_info".

Minor fixes for completeTransactions()

26 Feb 09:02
Compare
Choose a tag to compare
  • Don't call completeTransactions callback if there aren't any transactions to process (#150)
  • Additional logging to clarify intended usage of completeTransactions() (#151)

Added SwiftLint, minor tweaks

23 Feb 07:53
Compare
Choose a tag to compare

This is a minor release with no change in functionality:

  • Added SwiftLint #141
  • Fixed leaks #120
  • Improved payment queue logging - related to #142

Simplified error checking API

20 Feb 22:01
Compare
Choose a tag to compare

This release makes it easy to check if the user has canceled a purchase.

This is an API breaking change as the PurchaseError type has been removed in favour of SKError. Clients can now make purchases and check errors like this:

SwiftyStoreKit.purchaseProduct("com.musevisions.SwiftyStoreKit.Purchase1", atomically: true) { result in
    switch result {
    case .success(let product):
        print("Purchase Success: \(product.productId)")
    case .error(let error):
        switch error.code {
        case .unknown: print("Unknown error. Please contact support")
        case .clientInvalid: print("Not allowed to make the payment")
        case .paymentCancelled: break
        case .paymentInvalid: print("The purchase identifier was invalid")
        case .paymentNotAllowed: print("The device is not allowed to make the payment")
        case .storeProductNotAvailable: print("The product is not available in the current storefront")
        case .cloudServicePermissionDenied: print("Access to cloud service information is not allowed")
        case .cloudServiceNetworkConnectionFailed: print("Could not connect to the network")
        }
    }
}

This is in line with: https://developer.apple.com/reference/storekit/skerror.code

Related PR: #138

Use receipt["latest_receipt_info"] when verifying subscriptions

05 Feb 08:36
Compare
Choose a tag to compare
  • See related PR: #134
  • Should fix this: #129

Reference page:

https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html

Quoting:

latest_receipt_info: Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions. The JSON representation of the receipt for the most recent renewal.

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.

Major update to purchase flows

29 Jan 22:04
Compare
Choose a tag to compare

In short:

  • This is a non-API breaking change
  • Payments, Restore Purchases, Complete Transactions are now all performed on the same
    SKPaymentQueue observer.

This may resolve number of issues:

#130
#124
#120
#117
#110
#98
#80
#57

Extensive testing is recommended.

Full details on this PR: #131