Some of my users reported they can not completed the purchase .
According to the logs and screen captures . Their purchase progress's last status are "purchasing"
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
....
....
case .purchasing:
// 处理正在购买的情况
//print("购买中");
AppDelegate.log.debug("paymentQueue purchasing");
LoadingAlert.shared.setText(text: "购买中".localized())
....
After this ,It neither entered any error branch nor prompted the user to confirm the purchase or enter a password, but simply stopped here. There are no other purchase-related logs, and the program is still running normally.
At the same time, other users are able to complete their purchases without any issues. However, there have been 4-5 users recently who reported problems with purchasing. What could be the possible reasons?
In my local environment, I repeated the test many times, including using sandbox users from different regions and real Apple IDs, and everything worked fine.
//
// Payment.swift
// RadialMenu
//
// Created by pat on 2023/6/26.
//
import Foundation
import StoreKit
class Payment:NSObject,SKProductsRequestDelegate,SKPaymentTransactionObserver{
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
AppDelegate.log.debug("paymentQueue transaction product = \(transaction.payment.productIdentifier) state = \(transaction.transactionState)");
//let productID = transaction.payment.productIdentifier
switch transaction.transactionState {
case .purchased,.restored:
if(transaction.transactionState == .purchased){
AppDelegate.log.debug("paymentQueue purchased");
LoadingAlert.shared.setText(text: "已购买".localized())
}
if(transaction.transactionState == .restored){
LoadingAlert.shared.setText(text: "已恢复".localized())
AppDelegate.log.debug("paymentQueue restored");
}
//}
break;
case .failed:
AppDelegate.log.debug("paymentQueue failed ");
if let error = transaction.error as? NSError {
// 获取错误代码和描述
let errorCode = error.code
let errorDescription = error.localizedDescription
AppDelegate.log.debug("paymentQueue Transaction failed with error code: \(errorCode), description: \(errorDescription)")
}
queue.finishTransaction(transaction)
LoadingAlert.shared.hideModal();
// 处理购买失败的情况
// 提供错误信息给用户
//print("购买失败");
alertRetry();
break;
case .deferred:
AppDelegate.log.debug("paymentQueue deferred");
LoadingAlert.shared.setText(text: "购买延迟".localized())
// 处理交易延迟的情况(仅限家庭共享)
break;
case .purchasing:
// 处理正在购买的情况
//print("购买中");
AppDelegate.log.debug("paymentQueue purchasing");
LoadingAlert.shared.setText(text: "购买中".localized())
break;
@unknown default:
AppDelegate.log.debug("paymentQueue nknown default\(transaction.transactionState)");
break
}
}
}
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
I read the documentation and it told I had to prepare the product on App Store connect and once it is at the state "Ready to submit" I could access it on a phone where I am connected with an Icloud account in the developper list of the apple development account.
This is what I've done but when I try to fetch in my flutter code the product with the id I set in App Store connect it says "No product found"
Here is where I fetch the product:
Future purchaseProduct(String productId) async {
try {
Set<String> _pIds = {productId};
final ProductDetailsResponse response =
await _iap.queryProductDetails(_pIds);
if (response.productDetails.isEmpty) {
throw 'Product not found';
}
final ProductDetails productDetails = response.productDetails.first;
final PurchaseParam purchaseParam =
PurchaseParam(productDetails: productDetails);
_iap.buyConsumable(purchaseParam: purchaseParam);
} catch (e) {
Services.debugLog('Error purchasing product: $e');
throw e;
}
}
I checked the product ID and it does not seems to be the problem. Is there some other steps I need to do ?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
App Store Connect
In-App Purchase
Debugging
While reviewing the Apple Documentation, I came across a potential issue in one of the examples that I believe is worth addressing.
The example appears to compare strings instead of integers, which could lead to unexpected behavior in production environments. Specifically, in the line where originalMajorVersion (a string) is compared with newBusinessModelMajorVersion (also a string) using <:
if originalMajorVersion < newBusinessModelMajorVersion
This comparison performs a lexicographical check rather than evaluating the numerical values of the strings. As a result, strings like "10" would incorrectly be considered less than "2", which is not the desired behaviour when comparing version numbers.
I have reported this via the Feedback assistant (FB16432337) but at the time of posting this there has been no reply at all (23 days)
Supporting business model changes by using the app transaction
do {
// Get the appTransaction.
let shared = try await AppTransaction.shared
if case .verified(let appTransaction) = shared {
// Hard-code the major version number in which the app's business model changed.
let newBusinessModelMajorVersion = "2"
// Get the major version number of the version the customer originally purchased.
let versionComponents = appTransaction.originalAppVersion.split(separator: ".")
let originalMajorVersion = versionComponents[0]
if originalMajorVersion < newBusinessModelMajorVersion {
// This customer purchased the app before the business model changed.
// Deliver content that they're entitled to based on their app purchase.
}
else {
// This customer purchased the app after the business model changed.
}
}
}
catch {
// Handle errors.
}
Topic:
App & System Services
SubTopic:
StoreKit
We are running auto-renewing subscriptions with StoreKit2 and the “get all subscription statuses” API is behaving unexpectedly.
record the originalTransactionId from the iPhone to the server side when purchasing a subscription with Storekit2.
query the get all subscription statuses API from the server side with the originalTransactionId recorded.
get all subscription statuses returns a response, but there is no data in the response that matches the originalTransactionId.
I have an error on my system because I have built my system on the assumption that all subscriptions including originalTransactionId will be returned.
Please allow me to confirm the Server Notifications V2 specification.
I am aware that if withdrawal an Apple account that has a subscription, the subscription will eventually be cancelled.
Regarding Server Notifications V2 notifications with a notificationType of EXPIRED, am I correct in thinking that they will be sent when the subscription expires even if the Apple account is withdrawal?
Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You may be connecting to a server masquerading as a "auth-sandbox.itunes.apple.com", which threatens the security of your confidential information. "
For Apple subscription payments, my server does not receive notifications for production environment payments, but it can receive notifications for sandbox payments at the same notification address.
Signed renewal info from 'Get Subscription Statuses' or in server notifications never has the offerType or offerDiscountType even when the corresponding transaction does have those values set.
Our offer is a free trial.
Do these properties refer to something different in JWSRenewalInfoDecodedPayload than they do in transactions?
I'm trying to determine whether a subscription (identified by originalTransactionId) is currently in a free trial based on server notifications. The status doesn't tell us if the subscription is currently in free trial and the signedTransactionInfo may be for an older transaction.
Hi everyone,
I’m struggling to get StoreKit 2 to fetch products in my SwiftUI app while using a sandbox user. I think I’ve followed all necessary setup steps in Xcode, App Store Connect, and my physical test device, but Product.products(for:) always returns an empty array. I’d appreciate any insights!
What I’ve Done
Local App Setup (Xcode 16.2)
Created a blank SwiftUI Xcode project.
Enabled In-App Purchase capability under Signing & Capabilities.
Implemented minimal StoreKit 2 code to fetch available products (see below).
Using the correct bundle identifier, which matches App Store Connect.
App Store Connect Configuration
Registered the app with the same bundle identifier.
Created an Auto-Renewable Subscription with:
Product ID: v1 (matches my code).
All fields filled (pricing, localization, etc.).
Status: Ready for Review.
Linked the subscription to the latest app version in App Store Connect.
Sandbox User & Testing Setup
Created a sandbox tester account.
Logged in with the sandbox user under Settings → Developer → Sandbox Apple ID. This was on my physical device (iOS 18.2).
Installed and ran the app directly from Xcode (⌘+R).
Issue: StoreKit Returns No Products
Product.products(for:) does not return any products.
There are no errors thrown, just an empty array.
I confirmed that StoreKit Configuration is set to None in Xcode.
No StoreKit-related logs appear in the Console.
Code Snippets
//StoreKitManager.swift
import StoreKit
import SwiftUI
@MainActor
class StoreKitManager: ObservableObject {
@Published var products: [Product] = []
@Published var errorMessage: String?
func fetchProducts() async {
do {
let productIDs: Set<String> = ["v1"] // Matches App Store Connect
let fetchedProducts = try await Product.products(for: productIDs)
print(fetchedProducts) // Debug output
DispatchQueue.main.async {
self.products = fetchedProducts
}
} catch {
DispatchQueue.main.async {
self.errorMessage = "Failed to fetch products: \(error.localizedDescription)"
}
}
}
}
//ContentView.swift
import SwiftUI
struct ContentView: View {
@StateObject private var storeKitManager = StoreKitManager()
var body: some View {
VStack {
if let errorMessage = storeKitManager.errorMessage {
Text(errorMessage).foregroundColor(.red)
} else if storeKitManager.products.isEmpty {
Text("No products available")
} else {
List(storeKitManager.products, id: \.id) { product in
VStack(alignment: .leading) {
Text(product.displayName).font(.headline)
Text(product.description).font(.subheadline)
Text("\(product.price.formatted(.currency(code: product.priceFormatStyle.currencyCode ?? "USD")))")
.bold()
}
}
}
Button("Fetch Products") {
Task {
await storeKitManager.fetchProducts()
}
}
}
.padding()
.onAppear {
Task {
await storeKitManager.fetchProducts()
}
}
}
}
#Preview {
ContentView()
}
Additional Information
iOS Version: 18.2
Xcode Version: 16.2
macOS Version: 15.3.1
Device: Physical iPhone (not simulator)
TestFlight Build: Not used (app is run directly from Xcode)
StoreKit Configuration: Set to None
I'm receiving the following error when attempting to validate an in‑app purchase receipt:
Certificate verification failed at depth 0 : forge.pki.UnknownCertificateAuthority
Certificate chain validation failed: Certificate is not trusted.
This error occurs during the certificate chain validation process of the receipt's PKCS#7 container. My implementation uses node‑forge to decode the receipt, extract the embedded certificate chain, and verify that the chain properly links from the leaf certificate (which directly signed the receipt) through the intermediate certificate to the trusted Apple Inc. Root certificate.
What the Error Indicates:
"UnknownCertificateAuthority" at depth 0:
This suggests that the leaf certificate in the receipt is not being recognized as part of a valid chain because it cannot be linked back to a trusted root in my CA store.
"Certificate chain validation failed: Certificate is not trusted":
This means that the entire certificate chain does not chain up to a trusted certificate authority (in this case, the Apple Inc. Root certificate) as expected.
Steps Taken:
I verified that the receipt is a valid PKCS#7 container.
I extracted the certificate chain from the receipt. However, the receipt only provided the leaf certificate.
I manually added the intermediate certificate (AppleWWDRCAG5.pem) to complete the chain.
I loaded the official Apple Inc. Root certificate (AppleIncRootCertificate.pem) into my CA store.
Despite these steps, the validation still fails at depth 0, indicating that the leaf certificate is not recognized as being issued by a trusted authority.
Request for Assistance:
Could you please help clarify the following points:
Is the certificate chain for receipts (leaf → intermediate → Apple Inc. Root) as expected, or has there been any change in the chain that I should account for?
Is there a recommended or updated intermediate certificate I should be using for receipt validation?
Are there known issues or recent changes on Apple's side that might cause the leaf certificate to not be recognized as part of a valid chain?
Any guidance to resolve this certificate chain validation error would be greatly appreciated.
有人遇到这个问题吗,在支付的时候提示未知错误,具体的错误信息如下:
交易失败,outTradeNo:2025022631999900326, productId:com.f6car.p0001, error:Err-or -Domain=SKErrorDomain Code=0 "发生未知错误" UserInfo={NSLocalizedDescription=发生未知错误, NSUnderlyingError=0x302f50120 {Error Domain=ASDServerErrorDomain Code=3512 "无效的应用程序外部版本。" UserInfo={NSLocalizedFailureReason=无效的应用程序外部版本。}}}
寻求解决方案,感谢.
I ran into a problem. When using Storekit1 to purchase an SKU, the user payment was successful, but StoreKit1 did return paymentCancelled to my App. I would like to know under what circumstances this problem may occur? How do I fix it? Thank you
Hello,
Our server isn't receiving Apple App Store Server Notification for in-app purchases.
It works for Sandbox Server, even I sent a test notification which I received on the Production Server URL, but the real in-app payment notification isn't coming to the server.
I checked this already: https://developer.apple.com/documentation/appstoreservernotifications/enabling-app-store-server-notifications and everything here has been reviewed.
Transport Layer Security (TLS) version and others things mentioned have been checked, test notification was received. But the main in-app purchase notification for live transaction isn't coming. What's the issue precisely?
Topic:
App & System Services
SubTopic:
StoreKit
users download app with Streamlined Purchasing ,but the logic of checking subscription doesn't work. there the code:
func checkSubscriptionStatus() async {
for await entitlement in Transaction.currentEntitlements {
guard case .verified(let transaction) = entitlement else { continue }
if transaction.productID == monthlyProductID || transaction.productID == yearlyProductID {
if transaction.revocationDate == nil && !transaction.isUpgraded {
let activeSubscribed = transaction.expirationDate ?? .distantFuture > .now
if activeSubscribed {
hasActiveSubscription = activeSubscribed
// other operation
}
}
}
}
}
A customer of mine signed up for a free trial. I got a apple server notification with notification type DID_RENEW. What does that mean? Does that mean that they will be charged the subscription price now?
We use Transaction.currentEntitlements in StokeKit 2 to unlock functionality based on a Non-Consumable IAP but we have a case involving a refund that seems wrong and I am trying to understand the interation between transactionId, originalTransactionId & revocationReason.
The Context:
We have a universal App on macOS and iOS that offers a shared Non-Consumable IAP. For this example I have named it "app.lifetime"
On macOS we use StoreKit 2 and I am calling the Transaction.currentEntitlements and Transaction.all functions.
On iOS we are still using StoreKit 1.
This example customer:
Originally purchased "app.lifetime" on 2024-10-27
Was refunded by Apple for "app.lifetime" on 2024-10-29
Re-purchased "app.lifetime on 2025-02-24 (I have seen an email receipt of this transaction but it never shows up in Transaction data)
(all the above happened on the mac via StoreKit 2)
The Transactions (all lightly redacted for privacy):
on macOS the following is returned from Transaction.currentEntitlements...
{
"appTransactionId" : "...8123",
"bundleId" : "app",
"currency" : "USD",
"deviceVerification" : "...",
"deviceVerificationNonce" : "...",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1729997808000,
"originalTransactionId" : "...9955",
"price" : 1,
"productId" : "app.lifetime",
"purchaseDate" : 1729997808000,
"quantity" : 1,
"signedDate" : 1740416289102,
"storefront" : "USA",
"storefrontId" : "143441",
"transactionId" : "...7511",
"transactionReason" : "PURCHASE",
"type" : "Non-Consumable"
}
Note in the above example the originalTransactionId & transactionId are different. Transaction.all however returns both transactions:
[
{
"appTransactionId" : "...8123",
"bundleId" : "app",
"currency" : "USD",
"deviceVerification" : "...",
"deviceVerificationNonce" : "...",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1729997808000,
"originalTransactionId" : "...9955",
"price" : 1,
"productId" : "app.lifetime",
"purchaseDate" : 1729997808000,
"quantity" : 1,
"revocationDate" : 1730224102000,
"revocationReason" : 0,
"signedDate" : 1740415969925,
"storefront" : "USA",
"storefrontId" : "143441",
"transactionId" : "...9955",
"transactionReason" : "PURCHASE",
"type" : "Non-Consumable"
},
{
"appTransactionId" : "...8123",
"bundleId" : "app",
"currency" : "USD",
"deviceVerification" : "...",
"deviceVerificationNonce" : "...",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1729997808000,
"originalTransactionId" : "...9955",
"price" : 1,
"productId" : "app.lifetime",
"purchaseDate" : 1729997808000,
"quantity" : 1,
"signedDate" : 1740416289102,
"storefront" : "USA",
"storefrontId" : "143441",
"transactionId" : "...7511",
"transactionReason" : "PURCHASE",
"type" : "Non-Consumable"
}
]
Note here that the original transaction ("...9955") includes a revocationDate and revocationReason that match the expected refund but the secondary transaction that seems to match on all other details is missing the revocation info.
Looking at the iOS SK1 receipt data to compare, after a receipt refresh I see only a single transaction "...9955" which includes the cancellation info and transaction "...7511" is not present at all. The impact of this is that on iOS we are considering the purchase void but on macOS we are following currentEntitlements and consdering it still valid.
Calling the inApps/v1/history/... server API with the "...7511" transactionId that is shown in the currentEntitlements response returns the "...9955" transaction with the correct revocation status but "...7511" is no returned at all.
To Summarise:
currentEntitlements on macOS shows transaction "...7511" as active and with an originalTransactionId of "...9955"
all on macOS includes both "...7511" as active and "...9955" as revoked
iOS reciept data shows only "...9955" as revoked
Server API shows only "...9955" as revoked event when explicitly called with "...7511"
Neither of them show a more recent purchase the same customer made for the same IAP product.
My questions are:
Is this a StoreKit bug or am I mis-understanding something? If it's a bug how can I work around it to ensure revoked purchases aren't still appearing in currentEntitlements?
Under what conditions can StoreKit generate multiple transactionIds for the same underlying originalTransactionId? I had assumed (and the docs suggest) this only happens for subscriptions but here it is happening for a Non-Consumable IAP.
Why would transactionId "...7511" only be present on macOS/SK2 and not visible at all on iOS/SK1 or API?
I don't understand why the latest IAP from 2025-02-24 that the customer assures me they made (and has shown me the receipt for is not showing up in the Transactions history at all. Any ideas?
I have an App Clip that uses SKOverlay.AppClipConfiguration to install the full app. Before I added a Live Activity call (Activity.request), the user could see “Install,” then “Open.” Now, once “Get” is tapped, the Clip immediately closes—no “Open” button appears. If I remove the Live Activity code, it works again.
I’ve confirmed that parent/child entitlements match, and tested via TestFlight. Is there a known issue or recommended workaround for combining SKOverlay + Live Activities in an App Clip so it doesn’t dismiss prematurely? Any insights are appreciated!
Note live activity is for App Clip only.
User Initiated a Single Consumable Purchase but Was Charged Twice
A user initiated a single in-app purchase for a consumable item, but they were charged twice. Both transactions have the same purchase token.
Additional details: After the user successfully completed the in-app purchase, the completeTransactions callback was triggered again. This was called at app launch using SwiftyStoreKit.completeTransactions to finish any pending transactions.
Could this be causing the duplicate charge? Any insights would be appreciated.
Hi everyone,
I'm experiencing an issue with APNs server notifications where I receive a 404 error when trying to validate the signedPayload from Apple's notification. Below is a sanitized version of my code:
class ServerNotificationAppleController extends Controller
{
// URL for StoreKit keys (Sandbox environment)
private $storeKitKeysUrl = 'https://api.storekit-sandbox.itunes.apple.com/inApps/v1/keys';
public function handleNotification(Request $request)
{
\Log::info($request);
$signedPayload = $request->input('signedPayload');
if (!$signedPayload) {
return response()->json(['error' => 'signedPayload not provided'], 400);
}
// Step 1: Create your JWT token (token creation logic can be in a separate service)
$jwtToken = $this->generateAppleJWT();
// Step 2: Send a request to the StoreKit keys endpoint
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $jwtToken,
])->get($this->storeKitKeysUrl);
Log::info('Apple Keys Status:', ['status' => $response->status()]);
Log::info('Apple Keys Body:', ['body' => $response->body()]);
if ($response->status() !== 200) {
return response()->json(['error' => "Apple public keys couldn't be retrieved"], 401);
}
$keysData = $response->json();
// Step 3: Validate the signedPayload
$validatedPayload = $this->validateSignedPayload($signedPayload, $keysData);
if (!$validatedPayload) {
return response()->json(['error' => 'Invalid signedPayload'], 400);
}
// Process the validated data as needed
Log::info("Apple Purchase Data:", (array)$validatedPayload);
return response()->json(['message' => 'Notification processed successfully'], 200);
}
private function generateAppleJWT()
{
// API key details (replace placeholders with actual values)
$keyId = config('services.apple.key_id'); // e.g., <YOUR_KEY_ID>
$issuerId = config('services.apple.issuer_id'); // e.g., <YOUR_ISSUER_ID>
$privateKey = file_get_contents(storage_path(config('services.apple.private_key')));
// Set current UTC time and expiration time (20 minutes later)
$nowUtc = Carbon::now('UTC');
$expirationUtc = $nowUtc->copy()->addMinutes(20);
// Create the payload with UTC timestamps
$payload = [
'iss' => $issuerId,
'iat' => $nowUtc->timestamp,
'exp' => $expirationUtc->timestamp,
'aud' => 'appstoreconnect-v1',
'bid' => 'com.example.app', // Replace with your Bundle ID if necessary
];
// Generate the JWT token
return JWT::encode($payload, $privateKey, 'ES256', $keyId);
}
private function validateSignedPayload($signedPayload, $keysData)
{
try {
$jwkKeys = JWK::parseKeySet($keysData);
return JWT::decode($signedPayload, $jwkKeys, ['RS256']);
} catch (\Exception $e) {
Log::error("Apple Purchase Validation Error: " . $e->getMessage());
return null;
}
}
}
I’m particularly puzzled by the fact that I receive a 404 error when trying to retrieve the public keys from the StoreKit keys endpoint. Has anyone encountered this issue or can provide insight into what might be causing the error?
Any help or suggestions would be greatly appreciated. Thanks!
Hi,
I have developed an app which has two in-app purchase subscriptions. During the test, the app can successfully get the status of the subscriptions. After it's released, I downloaded it from app store and subscribed it with my apple account. I found that in most cases, the app can identify that I have subscribed it and I can use its all functions. But yesterday, when I launched it again, it showed the warning that I haven't subscribed it. I checked my subscription in my account and the subscription status hasn't been changed, that is, I have subscribed it. And after one hour, I launched it again. This time the app identified that I have subscribed it. Why? The following is the code about listening to the subscription status. Is there any wrong about it?
HomeView()
.onAppear(){
Task {
await getSubscriptionStatus()
}
}
func getSubscriptionStatus() async {
var storeProducts = [Product]()
do {
let productIds = ["6740017137","6740017138"]
storeProducts = try await Product.products(for: productIds)
} catch {
print("Failed product request: \(error)")
}
guard let subscription1 = storeProducts.first?.subscription else {
// Not a subscription
return
}
do {
let statuses = try await subscription1.status
for status in statuses {
let info = try checkVerified(status.renewalInfo)
switch status.state {
case .subscribed:
if info.willAutoRenew {
purchaseStatus1 = true
debugPrint("getSubscriptionStatus user subscription is active.")
} else {
purchaseStatus1 = false
debugPrint("getSubscriptionStatus user subscription is expiring.")
}
case .inBillingRetryPeriod:
debugPrint("getSubscriptionStatus user subscription is in billing retry period.")
purchaseStatus1 = false
case .inGracePeriod:
debugPrint("getSubscriptionStatus user subscription is in grace period.")
purchaseStatus1 = false
case .expired:
debugPrint("getSubscriptionStatus user subscription is expired.")
purchaseStatus1 = false
case .revoked:
debugPrint("getSubscriptionStatus user subscription was revoked.")
purchaseStatus1 = false
default:
fatalError("getSubscriptionStatus WARNING STATE NOT CONSIDERED.")
}
}
} catch {
// do nothing
}
guard let subscription2 = storeProducts.last?.subscription else {
// Not a subscription
return
}
do {
let statuses = try await subscription2.status
for status in statuses {
let info = try checkVerified(status.renewalInfo)
switch status.state {
case .subscribed:
if info.willAutoRenew {
purchaseStatus2 = true
debugPrint("getSubscriptionStatus user subscription is active.")
} else {
purchaseStatus2 = false
debugPrint("getSubscriptionStatus user subscription is expiring.")
}
case .inBillingRetryPeriod:
debugPrint("getSubscriptionStatus user subscription is in billing retry period.")
purchaseStatus2 = false
case .inGracePeriod:
debugPrint("getSubscriptionStatus user subscription is in grace period.")
purchaseStatus2 = false
case .expired:
debugPrint("getSubscriptionStatus user subscription is expired.")
purchaseStatus2 = false
case .revoked:
debugPrint("getSubscriptionStatus user subscription was revoked.")
purchaseStatus2 = false
default:
fatalError("getSubscriptionStatus WARNING STATE NOT CONSIDERED.")
}
}
} catch {
// do nothing
}
if purchaseStatus1 == true || purchaseStatus2 == true {
purchaseStatus = true
} else if purchaseStatus1 == false && purchaseStatus2 == false {
purchaseStatus = false
}
return
}
Topic:
App & System Services
SubTopic:
StoreKit