 @available(watchOSApplicationExtension 6.2, *)
 fileprivate var refreshSession: RefreshSession?
 
+@available(iOS 12.0, *)
+public class SKSubscriptionGroup
+{
+	let identifier: GroupIdentifier
+	var products: [SKProduct] = []
+	
+	init(with identifier: GroupIdentifier)
+	{
+		self.identifier = identifier
+		self.products = []
+	}
+	
+	init(with products: [SKProduct])
+	{
+		self.identifier = products.first?.subscriptionGroupIdentifier ?? ""
+		self.products = products
+	}
+	
+	func insert(product: SKProduct)
+	{
+		if identifier != product.subscriptionGroupIdentifier
+		{
+			fatalError("`Product.subscriptionGroupIdentifier` must be equal to current identifier")
+		}
+		
+		var products = Set(self.products)
+		products.insert(product)
+		
+		self.products = Array(products)
+	}
+	
+	func contains(_ productIdentifier: String) -> Bool
+	{
+		return products.contains(where: { $0.productIdentifier == productIdentifier })
+	}
+}
+
+public typealias GroupIdentifier = String
+
+@available(iOS 12.0, *)
+extension SKProductsResponse
+{
+	/// Build a dictionary that contains the subscription groups
+	///
+	/// The dictionary contains `SKSubscriptionGroup` objects where the key is a group identifier `GroupIdentifier`
+	///
+	/// - Returns  `[GroupIdentifier: SKSubscriptionGroup]`. Empty if no subscription groups found
+	var subscriptionGroups: [GroupIdentifier: SKSubscriptionGroup]
+	{
+		var groups: [GroupIdentifier: SKSubscriptionGroup] = [:]
+		
+		for p in products
+		{
+			guard let gid = p.subscriptionGroupIdentifier else
+			{
+				continue
+			}
+			
+			guard let group = groups[gid] else
+			{
+				let g = SKSubscriptionGroup(with: gid)
+				g.insert(product: p)
+				
+				groups[gid] = g
+				
+				continue
+			}
+			
+			group.insert(product: p)
+		}
+		
+		return groups
+	}
+}
+
 public extension InAppReceipt
 {
-    /**
-    *  Refresh local in-app receipt
-    *  - Parameter completion: handler for result
-    */
+    
+	///  Refresh local in-app receipt
+	///
+    ///  - Parameter completion: handler for result
     @available(watchOSApplicationExtension 6.2, *)
     static func refresh(completion: @escaping IAPRefreshRequestResult)
     {

    {
        refreshSession = nil
    }
}

public typealias IAPRefreshRequestResult = ((Error?) -> ())


#endif

public typealias SubscriptionGroup = Array<String>

extension InAppReceipt
{
	/// Check whether user is eligible for introductory offer for any products within the same subscription group
	///
	/// - Returns `false` if user isn't eligible for introductory offer, otherwise `true`
	func isEligibleForIntroductoryOffer(for group: SubscriptionGroup) -> Bool
	{
		let purchases = purchases.filter { $0.subscriptionTrialPeriod || $0.subscriptionIntroductoryPricePeriod }
			.filter { group.contains($0.productIdentifier) }
		
		return purchases.isEmpty
	}
	
	/// Check whether user is eligible for introductory offer for a specific product
	///
	/// - Returns `false` if user isn't eligible for introductory offer, otherwise `true`
	func isEligibleForIntroductoryOffer(for productIdentifier: String) -> Bool
