Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
nik3212 committed Jan 17, 2024
1 parent aad205c commit af6a427
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 16 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ Flare is a framework written in Swift that makes it easy for you to work with in
## Features
- [x] Support Consumable & Non-Consumable Purchases
- [x] Support Subscription Purchase
- [x] Refresh Receipt
- [x] Complete Unit Test Coverage
- [x] Support Promotional & Introductory Offers
- [x] iOS, tvOS, watchOS, macOS, and visionOS compatible
- [x] Complete Unit Test & Integration Coverage

## Documentation
Check out [flare documentation](https://space-code.github.io/flare/documentation/flare/).
Expand Down
14 changes: 7 additions & 7 deletions Sources/Flare/Flare.docc/Articles/perform-purchase.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The transactions array will only be synchronized with the server while the queue

```swift
// Adds transaction observer to the payment queue and handles payment transactions.
Flare.default.addTransactionObserver { result in
Flare.shared.addTransactionObserver { result in
switch result {
case let .success(transaction):
debugPrint("A transaction was received: \(transaction)")
Expand All @@ -22,7 +22,7 @@ Flare.default.addTransactionObserver { result in

```swift
// Removes transaction observer from the payment queue.
Flare.default.removeTransactionObserver()
Flare.shared.removeTransactionObserver()
```

## Getting Products
Expand All @@ -32,7 +32,7 @@ The fetch method sends a request to the App Store, which retrieves the products
> important: Before attempting to add a payment always check if the user can actually make payments. The Flare does it under the hood, if a user cannot make payments, you will get an ``IAPError`` with the value ``IAPError/paymentNotAllowed``.
```swift
Flare.default.fetch(productIDs: ["product_id"]) { result in
Flare.shared.fetch(productIDs: ["product_id"]) { result in
switch result {
case let .success(products):
debugPrint("Fetched products: \(products)")
Expand All @@ -46,7 +46,7 @@ Additionally, there are versions of both fetch that provide an `async` method, a

```swift
do {
let products = try await Flare.default.fetch(productIDs: Set(arrayLiteral: ["product_id"]))
let products = try await Flare.shared.fetch(productIDs: Set(arrayLiteral: ["product_id"]))
} catch {
debugPrint("An error occurred while fetching products: \(error.localizedDescription)")
}
Expand All @@ -64,7 +64,7 @@ Flare provides a few methods to perform a purchase:
The method accepts a product parameter which represents a product:

```swift
Flare.default.purchase(product: product) { result in
Flare.shared.purchase(product: product) { result in
switch result {
case let .success(transaction):
debugPrint("A transaction was received: \(transaction)")
Expand All @@ -77,7 +77,7 @@ Flare.default.purchase(product: product) { result in
If your app has a deployment target higher than iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, you can pass a set of [`options`](https://developer.apple.com/documentation/storekit/product/purchaseoption) along with a purchase request.

```swift
let transaction = try await Flare.default.purchase(product: product, options: [.appAccountToken(UUID())])
let transaction = try await Flare.shared.purchase(product: product, options: [.appAccountToken(UUID())])
```

## Finishing Transaction
Expand All @@ -87,7 +87,7 @@ Finishing a transaction tells StoreKit that your app completed its workflow to m
To finish the transaction, call the ``IFlare/finish(transaction:completion:)`` method.

```swift
Flare.default.finish(transaction: transaction, completion: nil)
Flare.shared.finish(transaction: transaction, completion: nil)
```

> important: Don’t call the ``IFlare/finish(transaction:completion:)`` method before the transaction is actually complete and attempt to use some other mechanism in your app to track the transaction as unfinished. StoreKit doesn’t function that way, and doing that prevents your app from downloading Apple-hosted content and can lead to other issues.
Expand Down
86 changes: 86 additions & 0 deletions Sources/Flare/Flare.docc/Articles/promotional-offers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Promotional Offers

Learn how to use promotional offers.

## Overview

[Promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_promotional_offers_in_your_app) can be effective in winning back lapsed subscribers or retaining current subscribers. You can provide lapsed or current subscribers a limited-time offer of a discounted or free period of service for auto-renewable subscriptions on macOS, iOS, and tvOS.

[Introductory offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_introductory_offers_in_your_app#2940726) can offer a discounted introductory price, including a free trial, to eligible users. You can make introductory offers to customers who haven’t previously received an introductory offer for the given product, or for any products in the same subscription group.

> note: To implement the offers, first complete the setup on App Store Connect, including generating a private key. See [Setting up promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/setting_up_promotional_offers) for more details.
## Introductory Offers

> important: Do not show a subscription offer to users if they are not eligible for it. It’s very important to check this beforehand.
First, check if the user is eligible for an introductory offer.

> tip For this purpose can be used ``IFlare/checkEligibility(productIDs:)`` method. This method requires iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0. Otherwise, see [Determine Eligibility](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_introductory_offers_in_your_app#2940726).
```swift
func isEligibleForIntroductoryOffer(productID: String) async -> Bool {
let dict = await Flare.shared.checkEligibility(productIDs: [productID])
return dict[productID] == .eligible
}
```

Second, proceed with the purchase as usual. See [Perform Purchase](<doc:perform-purchase>)

## Promotional Offers

First, you need to fetch the signature from your server. See [Generation a signature for promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/generating_a_signature_for_promotional_offers) for more information.

Second, configure ``IFlare`` with a ``Configuration``.

```swift
Flare.configure(configuration: Configuration(applicationUsername: "username"))
```

Third, request a signature from your server and prepare the discount offer.

```swift
func prepareOffer(username: String, productID: String, offerID: String, completion: @escaping (PromotionalOffer.SignedData) -> Void) {
YourServer.fetchOfferDetails(
username: username,
productIdentifier: productID,
offerIdentifier: offerID,
completion: { (nonce: UUID, timestamp: NSNumber, keyIdentifier: String, signature: String) in
let signedData = PromotionalOffer.SignedData(
identifier: offerID,
keyIdentifier: keyIdentifier,
nonce: nonce,
signature: signature,
timestamp: timestamp
)

completion(signedData)
}
}
```

Fourth, complete the purchase with the promotional offer.

```swift
func purchase(product: StoreProduct, discount: StoreProductDiscount, signedData: SignedData) {
let promotionalOffer = PromotionalOffer(discount: discount, signedData: signedData)

Flare.default.purchase(product: product, promotionalOffer: promotionalOffer) { result in
switch result {
case let .success(transaction):
break
case let .failure(error):
break
}
}

// Or using async/await
let transaction = Flare.shared.purchase(product: product, promotionalOffer: promotionalOffer)
}
```

Fifth, complete the transaction.

```swift
Flare.default.finish(transaction: transaction)
```
2 changes: 1 addition & 1 deletion Sources/Flare/Flare.docc/Articles/refund-purchase.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Starting with iOS 15, Flare now includes support for refunding purchases as part
Flare suggest to use ``IFlare/beginRefundRequest(productID:)`` for refunding purchase.

```swift
let status = try await Flare.default.beginRefundRequest(productID: "product_id")
let status = try await Flare.shared.beginRefundRequest(productID: "product_id")
```

> important: If an issue occurs during the refund process, this method throws an ``IAPError/refund(error:)`` error.
Expand Down
4 changes: 2 additions & 2 deletions Sources/Flare/Flare.docc/Articles/restore-purchase.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Use this API to request a new app receipt from the App Store if the receipt is i
> important: The receipt refresh request displays a system prompt that asks users to authenticate with their App Store credentials. For a better user experience, initiate the request after an explicit user action, like tapping or clicking a button.
```swift
Flare.default.receipt { result in
Flare.shared.receipt { result in
switch result {
case let .success(receipt):
// Handle a receipt
Expand All @@ -32,5 +32,5 @@ Flare.default.receipt { result in
There is an ``IFlare/receipt()`` method for obtaining a receipt using async/await.

```swift
let receipt = try await Flare.default.receipt()
let receipt = try await Flare.shared.receipt()
```
9 changes: 5 additions & 4 deletions Sources/Flare/Flare.docc/Flare.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ Flare provides a clear and convenient API for making in-app purchases.
import Flare

/// Fetch a product with the given id
guard let product = try await Flare.default.products(productIDs: ["product_identifier"]) else { return }
guard let product = try await Flare.shared.products(productIDs: ["product_identifier"]) else { return }
/// Purchase a product
let transaction = try await Flare.default.purchase(product: product)
let transaction = try await Flare.shared.purchase(product: product)
/// Finish a transaction
Flare.default.finish(transaction: transaction, completion: nil)
Flare.shared.finish(transaction: transaction, completion: nil)
```

Flare supports both StoreKit and StoreKit2; it decides which one to use under the hood based on the operating system version. Flare provides two ways to work with in-app purchases (IAP): it supports the traditional closure-based syntax and the modern async/await approach.
Expand All @@ -23,7 +23,7 @@ Flare supports both StoreKit and StoreKit2; it decides which one to use under th
import Flare

/// Fetch a product with the given id
Flare.default.products(productIDs: ["product_identifier"]) { result in
Flare.shared.products(productIDs: ["product_identifier"]) { result in
switch result {
case let .success(products):
// Purchase a product
Expand Down Expand Up @@ -64,3 +64,4 @@ flare is available under the MIT license. See the LICENSE file for more info.
- <doc:perform-purchase>
- <doc:restore-purchase>
- <doc:refund-purchase>
- <doc:promotional-offers>

0 comments on commit af6a427

Please sign in to comment.