Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ PODS:
- nanopb/encode (2.30908.0)
- OCMock (3.9.4)
- PromisesObjC (2.4.0)
- Qonversion (5.13.4):
- Qonversion/Main (= 5.13.4)
- Qonversion/Main (5.13.4)
- Qonversion (5.14.0):
- Qonversion/Main (= 5.14.0)
- Qonversion/Main (5.14.0)

DEPENDENCIES:
- Firebase/Auth (= 8.9.0)
Expand Down Expand Up @@ -109,8 +109,8 @@ SPEC CHECKSUMS:
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
Qonversion: 87bf82a98ce120fe6d90664c46b5b27a89efd65c
Qonversion: 7a392c3e17ac2442fcda5e8f6c57fd7c429f7cbb

PODFILE CHECKSUM: 44d29dbe325cd066d8cab5db21496f3b2a959485
PODFILE CHECKSUM: b64bc6917b5b209ae92a56b5699e8790ade97930

COCOAPODS: 1.16.2
12 changes: 12 additions & 0 deletions Qonversion.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
700636072C11CEF700BB9F9C /* QONFallbackObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 700636052C11CEF700BB9F9C /* QONFallbackObject.m */; };
700636142C12125900BB9F9C /* NSError+Sugare.h in Headers */ = {isa = PBXBuildFile; fileRef = 700636122C12125900BB9F9C /* NSError+Sugare.h */; };
700636152C12125900BB9F9C /* NSError+Sugare.m in Sources */ = {isa = PBXBuildFile; fileRef = 700636132C12125900BB9F9C /* NSError+Sugare.m */; };
700B9D4D2E742CBB0031B056 /* QONPurchaseResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 700B9D4C2E742CBB0031B056 /* QONPurchaseResult.m */; };
700B9D4E2E742CBB0031B056 /* QONPurchaseResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 700B9D4B2E742CBB0031B056 /* QONPurchaseResult.h */; };
700B9D502E742E5D0031B056 /* QONPurchaseResult+Protected.h in Headers */ = {isa = PBXBuildFile; fileRef = 700B9D4F2E742E5D0031B056 /* QONPurchaseResult+Protected.h */; };
700EC173291277130032E205 /* QONExperimentGroup+Protected.h in Headers */ = {isa = PBXBuildFile; fileRef = 700EC171291277130032E205 /* QONExperimentGroup+Protected.h */; };
701922732B10981200724926 /* QONSubscriptionPeriod.h in Headers */ = {isa = PBXBuildFile; fileRef = 701922712B10981200724926 /* QONSubscriptionPeriod.h */; settings = {ATTRIBUTES = (Public, ); }; };
701922742B10981200724926 /* QONSubscriptionPeriod.m in Sources */ = {isa = PBXBuildFile; fileRef = 701922722B10981200724926 /* QONSubscriptionPeriod.m */; };
Expand Down Expand Up @@ -408,6 +411,9 @@
700636052C11CEF700BB9F9C /* QONFallbackObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QONFallbackObject.m; sourceTree = "<group>"; };
700636122C12125900BB9F9C /* NSError+Sugare.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+Sugare.h"; sourceTree = "<group>"; };
700636132C12125900BB9F9C /* NSError+Sugare.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+Sugare.m"; sourceTree = "<group>"; };
700B9D4B2E742CBB0031B056 /* QONPurchaseResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QONPurchaseResult.h; sourceTree = "<group>"; };
700B9D4C2E742CBB0031B056 /* QONPurchaseResult.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QONPurchaseResult.m; sourceTree = "<group>"; };
700B9D4F2E742E5D0031B056 /* QONPurchaseResult+Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "QONPurchaseResult+Protected.h"; sourceTree = "<group>"; };
700EC171291277130032E205 /* QONExperimentGroup+Protected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "QONExperimentGroup+Protected.h"; sourceTree = "<group>"; };
701922712B10981200724926 /* QONSubscriptionPeriod.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QONSubscriptionPeriod.h; sourceTree = "<group>"; };
701922722B10981200724926 /* QONSubscriptionPeriod.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QONSubscriptionPeriod.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1125,6 +1131,8 @@
A1839793226FD80F320A246F /* QONUserProperty.h */,
A1839ACEB01696C50FEBB4F4 /* QONUserProperties.m */,
A1839DCD5FA33E85193A2684 /* QONUserProperties.h */,
700B9D4B2E742CBB0031B056 /* QONPurchaseResult.h */,
700B9D4C2E742CBB0031B056 /* QONPurchaseResult.m */,
70CB7CDB2C246DF200241FF1 /* QONPromotionalOffer.h */,
70CB7CDC2C246DF200241FF1 /* QONPromotionalOffer.m */,
);
Expand Down Expand Up @@ -1463,6 +1471,7 @@
8957323F26DD03A3009507A6 /* Protected */ = {
isa = PBXGroup;
children = (
700B9D4F2E742E5D0031B056 /* QONPurchaseResult+Protected.h */,
700EC171291277130032E205 /* QONExperimentGroup+Protected.h */,
7097C6BD2A38BFC800565DE4 /* QONRemoteConfig+Protected.h */,
6A121DAF2BB44D7B0073B330 /* QONRemoteConfigList+Protected.h */,
Expand Down Expand Up @@ -1726,6 +1735,7 @@
6A121DAE2BB446740073B330 /* QONRemoteConfigList.h in Headers */,
895732CA26DD03A3009507A6 /* QNUtils.h in Headers */,
8957328126DD03A3009507A6 /* QONEntitlement.h in Headers */,
700B9D4E2E742CBB0031B056 /* QONPurchaseResult.h in Headers */,
8957330526DD03A3009507A6 /* QNIdentityServiceInterface.h in Headers */,
895732FE26DD03A3009507A6 /* QNAPIClient.h in Headers */,
702BF8B629531A68000B6C3E /* QONScreenCustomizationDelegate.h in Headers */,
Expand Down Expand Up @@ -1753,6 +1763,7 @@
895732D026DD03A3009507A6 /* QNUserInfo.h in Headers */,
895732B126DD03A3009507A6 /* QONAutomationsFlowAssembly.h in Headers */,
700636142C12125900BB9F9C /* NSError+Sugare.h in Headers */,
700B9D502E742E5D0031B056 /* QONPurchaseResult+Protected.h in Headers */,
6A21BF532AB2059F005BDA7C /* QONRequest.h in Headers */,
8957329026DD03A3009507A6 /* QONEntitlementsUpdateListener.h in Headers */,
8957329326DD03A3009507A6 /* QONExperimentGroup.h in Headers */,
Expand Down Expand Up @@ -2238,6 +2249,7 @@
8957329526DD03A3009507A6 /* QONLaunchResult.m in Sources */,
70D05A9429C9FF3C00EA5DDF /* QONRemoteConfigService.m in Sources */,
895732B726DD03A3009507A6 /* QONAutomationsScreenProcessor.m in Sources */,
700B9D4D2E742CBB0031B056 /* QONPurchaseResult.m in Sources */,
895732BD26DD03A3009507A6 /* QNRequestSerializer.m in Sources */,
895732F526DD03A3009507A6 /* QNAttributionManager.m in Sources */,
895732EF26DD03A3009507A6 /* QNErrorsMapper.m in Sources */,
Expand Down
48 changes: 48 additions & 0 deletions Sources/Qonversion/Public/QONPurchaseResult.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// QONPurchaseResult.h
// Qonversion
//
// Created by Suren Sarkisyan on 18.12.2024.
// Copyright © 2024 Qonversion Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>

@class QONEntitlement;

NS_ASSUME_NONNULL_BEGIN

NS_SWIFT_NAME(Qonversion.PurchaseResult)
/**
* Result of a purchase operation containing entitlements, error, transaction and cancellation status.
*/
@interface QONPurchaseResult : NSObject

/**
* Dictionary of entitlements that were granted as a result of the purchase.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's incorrect, as we're returning the complete entitlements, not only the result of current purchase

* Key is entitlement identifier, value is QONEntitlement object.
*/
@property (nonatomic, copy, readonly, nullable) NSDictionary<NSString *, QONEntitlement *> *entitlements;

/**
* Error that occurred during the purchase process, if any.
*/
@property (nonatomic, strong, readonly, nullable) NSError *error;

/**
* StoreKit transaction associated with the purchase.
* Can be nil if the purchase failed before reaching StoreKit.
*/
@property (nonatomic, strong, readonly, nullable) SKPaymentTransaction *transaction;

/**
* Indicates whether the user canceled the purchase.
* This is different from a purchase failure - cancellation is user-initiated.
*/
@property (nonatomic, assign, readonly) BOOL isUserCanceled;


@end

NS_ASSUME_NONNULL_END
54 changes: 54 additions & 0 deletions Sources/Qonversion/Public/QONPurchaseResult.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// QONPurchaseResult.m
// Qonversion
//
// Created by Suren Sarkisyan on 18.12.2024.
// Copyright © 2024 Qonversion Inc. All rights reserved.
//

#import "QONPurchaseResult.h"
#import "QONPurchaseResult+Protected.h"
#import "QONEntitlement.h"

@implementation QONPurchaseResult

- (instancetype)initWithEntitlements:(nullable NSDictionary<NSString *, QONEntitlement *> *)entitlements
transaction:(nullable SKPaymentTransaction *)transaction {
return [self initWithEntitlements:entitlements
error:nil
transaction:transaction
isUserCanceled:NO];
}

- (instancetype)initWithError:(nullable NSError *)error
isUserCanceled:(BOOL)isUserCanceled {
return [self initWithEntitlements:nil
error:error
transaction:nil
isUserCanceled:isUserCanceled];
}

- (instancetype)initWithError:(nullable NSError *)error
transaction:(nullable SKPaymentTransaction *)transaction
isUserCanceled:(BOOL)isUserCanceled {
return [self initWithEntitlements:nil
error:error
transaction:transaction
isUserCanceled:isUserCanceled];
}

- (instancetype)initWithEntitlements:(nullable NSDictionary<NSString *, QONEntitlement *> *)entitlements
error:(nullable NSError *)error
transaction:(nullable SKPaymentTransaction *)transaction
isUserCanceled:(BOOL)isUserCanceled {
self = [super init];
if (self) {
_entitlements = entitlements;
_error = error;
_transaction = transaction;
_isUserCanceled = isUserCanceled;
}
return self;
}

@end
12 changes: 12 additions & 0 deletions Sources/Qonversion/Public/Qonversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#import "QONUserProperty.h"
#import "QONSubscriptionPeriod.h"
#import "QONPurchaseOptions.h"
#import "QONPurchaseResult.h"
#import "QONPromotionalOffer.h"

#if TARGET_OS_IOS
Expand Down Expand Up @@ -174,6 +175,17 @@ static NSString *const QonversionApiErrorDomain = @"com.qonversion.io.api";
*/
- (void)purchase:(NSString *)productID completion:(QONPurchaseCompletionHandler)completion;

// MARK: - New Purchase Method with PurchaseResult

/**
Make a purchase and validate that through server-to-server using Qonversion's Backend

@param product Product created in Qonversion Dash
@param options Purchase process additional options: quantity / context keys / etc.
@param completion Completion block that includes QONPurchaseResult with entitlements, error, transaction and cancellation status
*/
- (void)purchaseProductWithResult:(QONProduct *)product options:(QONPurchaseOptions *)options completion:(void(^)(QONPurchaseResult *result))completion;

/**
Restore user entitlements based on purchases
@param completion Completion block that includes entitlements dictionary and error
Expand Down
6 changes: 6 additions & 0 deletions Sources/Qonversion/Public/Qonversion.m
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ - (void)purchase:(NSString *)productID completion:(QONPurchaseCompletionHandler)
[self.productCenterManager purchase:productID purchaseOptions:nil completion:completion];
}

// MARK: - New Purchase Method with PurchaseResult

- (void)purchaseProductWithResult:(QONProduct *)product options:(QONPurchaseOptions *)options completion:(void(^)(QONPurchaseResult *result))completion {
[self.productCenterManager purchaseWithResult:product options:options completion:completion];
}

- (void)restore:(QNRestoreCompletionHandler)completion {
[self.productCenterManager restoreReceipt:completion];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
#import "QONRemoteConfigManager.h"
#import "QONRequestTrigger.h"

@class QONLaunchResult, QONStoreKit2PurchaseModel, QONFallbackService, QONPromotionalOffer, QONPurchaseOptions, SKProductDiscount;
@class QONLaunchResult, QONStoreKit2PurchaseModel, QONFallbackService, QONPromotionalOffer, QONPurchaseOptions, QONPurchaseResult, SKProductDiscount;
@protocol QONPromoPurchasesDelegate, QONEntitlementsUpdateListener, QNUserInfoServiceInterface, QNIdentityManagerInterface, QNLocalStorage;

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, QONPurchaseCompletionType) {
QONPurchaseCompletionTypeLegacy = 0,
QONPurchaseCompletionTypeResult = 1
};

@interface QNProductCenterManager : NSObject

@property (nonatomic, assign) QONLaunchMode launchMode;
Expand All @@ -30,6 +35,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)checkEntitlements:(QONEntitlementsCompletionHandler)completion;
- (void)purchase:(QONProduct * _Nonnull)product options:(QONPurchaseOptions * _Nullable)options completion:(nonnull QONPurchaseCompletionHandler)completion;
- (void)purchase:(NSString * _Nonnull)productID purchaseOptions:(QONPurchaseOptions * _Nullable)options completion:(nonnull QONPurchaseCompletionHandler)completion;

- (void)purchaseWithResult:(QONProduct * _Nonnull)product options:(QONPurchaseOptions * _Nullable)options completion:(void(^)(QONPurchaseResult *result))completion;

- (void)restoreTransactions:(QNRestoreCompletionHandler)completion;

- (void)products:(QONProductsCompletionHandler)completion;
Expand Down
Loading
Loading