Skip to content

Commit 0f34f35

Browse files
authored
Merge pull request #768 from adjust/v542
Version 5.4.2
2 parents a21eccc + d6d7a90 commit 0f34f35

19 files changed

+129
-100
lines changed

Adjust.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22
s.name = "Adjust"
33
s.module_name = "AdjustSdk"
4-
s.version = "5.4.1"
4+
s.version = "5.4.2"
55
s.summary = "This is the iOS SDK of Adjust. You can read more about it at https://adjust.com."
66
s.homepage = "https://github.com/adjust/ios_sdk"
77
s.license = { :type => 'MIT', :file => 'LICENSE' }

Adjust/Adjust.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Adjust.h
33
// Adjust SDK
44
//
5-
// V5.4.1
5+
// V5.4.2
66
// Created by Christian Wellenbrock (@wellle) on 23rd July 2013.
77
// Copyright (c) 2012-Present Adjust GmbH. All rights reserved.
88
//

Adjust/Internal/ADJActivityHandler.m

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,19 +1599,21 @@ - (void)launchAttributionResponseTasksI:(ADJActivityHandler *)selfI
15991599
}
16001600

16011601
- (void)launchPurchaseVerificationResponseTasksI:(ADJActivityHandler *)selfI
1602-
purchaseVerificationResponseData:(ADJPurchaseVerificationResponseData *)purchaseVerificationResponseData {
1602+
purchaseVerificationResponseData:(ADJPurchaseVerificationResponseData *)responseData {
16031603
[selfI.logger debug:
1604-
@"Got purchase_verification JSON response with message: %@", purchaseVerificationResponseData.message];
1605-
ADJPurchaseVerificationResult *verificationResult = [[ADJPurchaseVerificationResult alloc] init];
1606-
verificationResult.verificationStatus = purchaseVerificationResponseData.jsonResponse[@"verification_status"];
1607-
verificationResult.code = [(NSNumber *)purchaseVerificationResponseData.jsonResponse[@"code"] intValue];
1608-
verificationResult.message = purchaseVerificationResponseData.jsonResponse[@"message"];
1609-
purchaseVerificationResponseData.purchaseVerificationPackage.purchaseVerificationCallback(verificationResult);
1610-
1611-
if (purchaseVerificationResponseData.purchaseVerificationPackage &&
1612-
purchaseVerificationResponseData.purchaseVerificationPackage.event)
1613-
{
1614-
[self trackEvent:purchaseVerificationResponseData.purchaseVerificationPackage.event];
1604+
@"Got purchase_verification JSON response with message: %@", responseData.message];
1605+
if (responseData.error == nil) {
1606+
ADJPurchaseVerificationResult *verificationResult = [[ADJPurchaseVerificationResult alloc] init];
1607+
verificationResult.verificationStatus = responseData.jsonResponse[@"verification_status"];
1608+
verificationResult.code = [(NSNumber *)responseData.jsonResponse[@"code"] intValue];
1609+
verificationResult.message = responseData.jsonResponse[@"message"];
1610+
responseData.purchaseVerificationPackage.purchaseVerificationCallback(verificationResult);
1611+
} else {
1612+
responseData.purchaseVerificationPackage.purchaseVerificationCallback(responseData.error);
1613+
}
1614+
1615+
if (responseData.purchaseVerificationPackage && responseData.purchaseVerificationPackage.event) {
1616+
[self trackEvent:responseData.purchaseVerificationPackage.event];
16151617
}
16161618
}
16171619

Adjust/Internal/ADJAdjustFactory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
+ (double)sessionInterval;
1919
+ (double)subsessionInterval;
2020
+ (double)requestTimeout;
21+
+ (double)verifyRequestTimeout;
2122
+ (NSNumber *)attStatus;
2223
+ (NSString *)idfa;
2324
+ (NSTimeInterval)timerInterval;

Adjust/Internal/ADJAdjustFactory.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,14 @@ + (double)subsessionInterval {
5353

5454
+ (double)requestTimeout {
5555
if (internalRequestTimeout == -1) {
56-
return 60; // 60 second
56+
return 60; // 60 seconds
57+
}
58+
return internalRequestTimeout;
59+
}
60+
61+
+ (double)verifyRequestTimeout {
62+
if (internalRequestTimeout == -1) {
63+
return 30; // 30 seconds
5764
}
5865
return internalRequestTimeout;
5966
}

Adjust/Internal/ADJPurchaseVerificationHandler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//
22
// ADJPurchaseVerificationHandler.h
3-
// Adjust
3+
// Adjust SDK
44
//
55
// Created by Uglješa Erceg (@uerceg) on May 25th 2023.
6-
// Copyright © 2023 Adjust. All rights reserved.
6+
// Copyright © 2023-Present Adjust. All rights reserved.
77
//
88

99
#import <Foundation/Foundation.h>

Adjust/Internal/ADJPurchaseVerificationHandler.m

Lines changed: 79 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#import "ADJUtil.h"
1111
#import "ADJLogger.h"
1212
#import "ADJAdjustFactory.h"
13-
#import "ADJBackoffStrategy.h"
1413
#import "ADJUserDefaults.h"
1514
#import "ADJPackageBuilder.h"
1615
#import "ADJPurchaseVerificationResult.h"
@@ -24,12 +23,11 @@ @interface ADJPurchaseVerificationHandler()
2423
@property (nonatomic, strong) ADJRequestHandler *requestHandler;
2524

2625
@property (nonatomic, assign) BOOL paused;
27-
@property (nonatomic, strong) ADJBackoffStrategy *backoffStrategy;
26+
@property (nonatomic, assign) BOOL isSendingPurchaseVerificationPackage;
2827

2928
@property (nonatomic, weak) id<ADJLogger> logger;
3029
@property (nonatomic, weak) id<ADJActivityHandler> activityHandler;
3130

32-
@property (nonatomic, assign) NSInteger lastPackageRetriesCount;
3331
@property (nonatomic, strong) NSNumber *lastPackageRetryInMilli;
3432

3533
@end
@@ -48,12 +46,12 @@ - (id)initWithActivityHandler:(id<ADJActivityHandler>)activityHandler
4846

4947
self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL);
5048
self.logger = ADJAdjustFactory.logger;
51-
self.lastPackageRetriesCount = 0;
5249

53-
self.requestHandler = [[ADJRequestHandler alloc] initWithResponseCallback:self
54-
urlStrategy:urlStrategy
55-
requestTimeout:[ADJAdjustFactory requestTimeout]
56-
adjustConfiguration:activityHandler.adjustConfig];
50+
self.requestHandler =
51+
[[ADJRequestHandler alloc] initWithResponseCallback:self
52+
urlStrategy:urlStrategy
53+
requestTimeout:[ADJAdjustFactory verifyRequestTimeout]
54+
adjustConfiguration:activityHandler.adjustConfig];
5755

5856
[ADJUtil launchInQueue:self.internalQueue
5957
selfInject:self
@@ -68,6 +66,8 @@ - (void)pauseSending {
6866
selfInject:self
6967
block:^(ADJPurchaseVerificationHandler *selfI) {
7068
selfI.paused = YES;
69+
selfI.isSendingPurchaseVerificationPackage = NO;
70+
selfI.lastPackageRetryInMilli = nil;
7171
}];
7272
}
7373

@@ -114,9 +114,10 @@ - (void)teardown {
114114

115115
self.internalQueue = nil;
116116
self.logger = nil;
117-
self.backoffStrategy = nil;
118117
self.packageQueue = nil;
119118
self.activityHandler = nil;
119+
self.isSendingPurchaseVerificationPackage = NO;
120+
self.lastPackageRetryInMilli = nil;
120121
}
121122

122123
#pragma mark - Private & helper methods
@@ -126,7 +127,8 @@ - (void)initI:(ADJPurchaseVerificationHandler *)selfI
126127
startsSending:(BOOL)startsSending {
127128
selfI.activityHandler = activityHandler;
128129
selfI.paused = !startsSending;
129-
selfI.backoffStrategy = [ADJAdjustFactory sdkClickHandlerBackoffStrategy];
130+
selfI.isSendingPurchaseVerificationPackage = NO;
131+
selfI.lastPackageRetryInMilli = nil;
130132
selfI.packageQueue = [NSMutableArray array];
131133
}
132134

@@ -143,63 +145,47 @@ - (void)sendNextPurchaseVerificationPackageI:(ADJPurchaseVerificationHandler *)s
143145
[selfI.logger debug:@"Purchase verification handler is paused"];
144146
return;
145147
}
146-
NSUInteger queueSize = selfI.packageQueue.count;
147-
if (queueSize == 0) {
148+
if (selfI.isSendingPurchaseVerificationPackage) {
149+
[selfI.logger debug:@"Purchase verification handler is already sending a package"];
150+
return;
151+
}
152+
if (selfI.packageQueue.count == 0) {
148153
return;
149154
}
150155
if ([selfI.activityHandler isGdprForgotten]) {
151-
[selfI.logger debug:@"purchase_verification request won't be fired for forgotten user"];
156+
[selfI.logger debug:@"purchase_verification request won't be sent for GDPR forgotten user"];
157+
return;
158+
}
159+
160+
// check if we need to wait for backend-requested retry_in delay
161+
NSNumber *waitTime = [selfI waitTimeTimeInterval];
162+
if (waitTime != nil) {
163+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)([waitTime doubleValue] * NSEC_PER_SEC)),
164+
selfI.internalQueue, ^{
165+
// clear the retry delay after waiting
166+
selfI.lastPackageRetryInMilli = nil;
167+
[selfI sendNextPurchaseVerificationPackage];
168+
});
152169
return;
153170
}
154171

172+
// get the package but keep it in the queue until processing is complete
155173
ADJActivityPackage *purchaseVerificationPackage = [self.packageQueue objectAtIndex:0];
156-
[self.packageQueue removeObjectAtIndex:0];
157174

158175
if (![purchaseVerificationPackage isKindOfClass:[ADJActivityPackage class]]) {
159176
[selfI.logger error:@"Failed to read purchase_verification package"];
177+
// remove the bad package to prevent infinite loop
178+
[selfI.packageQueue removeObjectAtIndex:0];
179+
selfI.isSendingPurchaseVerificationPackage = NO;
160180
[selfI sendNextPurchaseVerificationPackage];
161181
return;
162182
}
163183

164-
dispatch_block_t work = ^{
165-
[selfI.requestHandler sendPackageByPOST:purchaseVerificationPackage
166-
sendingParameters:nil];
167-
[selfI sendNextPurchaseVerificationPackage];
168-
};
169-
170-
NSNumber *waitTimeSecondsDouble = [selfI waitTimeTimeInterval];
171-
172-
if (waitTimeSecondsDouble != nil) {
173-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
174-
(int64_t)(waitTimeSecondsDouble.doubleValue * NSEC_PER_SEC)),
175-
self.internalQueue, work);
176-
} else {
177-
work();
178-
}
179-
}
180-
- (NSNumber *)waitTimeTimeInterval {
181-
if (self.lastPackageRetriesCount > 0) {
182-
NSTimeInterval waitTime = [ADJUtil waitingTime:self.lastPackageRetriesCount
183-
backoffStrategy:self.backoffStrategy];
184-
185-
[self.logger verbose:
186-
@"Waiting for %@ seconds before retrying purchase_verification for the %d time",
187-
[ADJUtil secondsNumberFormat:waitTime], self.lastPackageRetriesCount];
188-
189-
return @(waitTime);
190-
}
191-
192-
if (self.lastPackageRetryInMilli != nil) {
193-
NSTimeInterval waitTime = [self.lastPackageRetryInMilli intValue] / 1000.0;
194-
195-
[self.logger verbose:
196-
@"Waiting for %@ seconds before retrying purchase_verification with retry_in",
197-
[ADJUtil secondsNumberFormat:waitTime]];
198-
199-
return @(waitTime);
200-
}
184+
// set flag to indicate we're sending a package
185+
selfI.isSendingPurchaseVerificationPackage = YES;
201186

202-
return nil;
187+
[selfI.requestHandler sendPackageByPOST:purchaseVerificationPackage
188+
sendingParameters:nil];
203189
}
204190

205191
- (void)updatePackagesTrackingI:(ADJPurchaseVerificationHandler *)selfI
@@ -220,50 +206,65 @@ - (void)updatePackagesTrackingI:(ADJPurchaseVerificationHandler *)selfI
220206
}
221207

222208
- (void)responseCallback:(ADJResponseData *)responseData {
209+
// reset flag to indicate we're done processing this package
210+
self.isSendingPurchaseVerificationPackage = NO;
211+
223212
if (!responseData.jsonResponse) {
224213
[self.logger error:
225214
@"Could not get purchase_verification JSON response with message: %@", responseData.message];
226215
ADJPurchaseVerificationResult *verificationResult = [[ADJPurchaseVerificationResult alloc] init];
227216
verificationResult.verificationStatus = @"not_verified";
228217
verificationResult.code = 102;
229218
verificationResult.message = responseData.message;
230-
responseData.purchaseVerificationPackage.purchaseVerificationCallback(verificationResult);
231-
}
232-
// Check if any package response contains information that user has opted out.
233-
// If yes, disable SDK and flush any potentially stored packages that happened afterwards.
234-
if (responseData.trackingState == ADJTrackingStateOptedOut) {
235-
self.lastPackageRetriesCount = 0;
219+
((ADJPurchaseVerificationResponseData *)responseData).error = verificationResult;
220+
} else {
221+
// check if any package response contains information that user has opted out.
222+
// if yes, disable SDK and flush any potentially stored packages that happened afterwards.
223+
if (responseData.trackingState == ADJTrackingStateOptedOut) {
224+
[self.activityHandler setTrackingStateOptedOut];
225+
return;
226+
}
227+
228+
// check if backend requested retry_in delay
229+
if (responseData.retryInMilli != nil) {
230+
self.lastPackageRetryInMilli = responseData.retryInMilli;
231+
[self.logger error:@"Retrying purchase_verification package with retry in %d ms",
232+
[responseData.retryInMilli intValue]];
233+
234+
// package stays in queue - schedule retry
235+
[self sendNextPurchaseVerificationPackage];
236+
return;
237+
}
238+
239+
// reset retry counter after successful response
236240
self.lastPackageRetryInMilli = nil;
237-
[self.activityHandler setTrackingStateOptedOut];
238-
return;
239241
}
240242

241-
if ([self retryPackageWithResponse:responseData]) {
242-
[self sendPurchaseVerificationPackage:responseData.purchaseVerificationPackage];
243-
return;
243+
// processing is complete - remove the package from queue
244+
if (self.packageQueue.count > 0) {
245+
[self.packageQueue removeObjectAtIndex:0];
244246
}
245247

246-
self.lastPackageRetriesCount = 0;
247-
self.lastPackageRetryInMilli = nil;
248+
// finish package tracking without retrying / backoff
248249
[self.activityHandler finishedTracking:responseData];
250+
251+
// process next package in queue if any
252+
[self sendNextPurchaseVerificationPackage];
249253
}
250254

251-
- (BOOL)retryPackageWithResponse:(ADJResponseData *)responseData {
252-
if (responseData.jsonResponse == nil) {
253-
self.lastPackageRetriesCount++;
254-
[self.logger error:@"Retrying purchase_verification package for the %d time",
255-
self.lastPackageRetriesCount];
256-
return YES;
257-
}
255+
- (NSNumber *)waitTimeTimeInterval {
256+
// handle backend-requested retry_in delay
257+
if (self.lastPackageRetryInMilli != nil) {
258+
NSTimeInterval waitTime = [self.lastPackageRetryInMilli intValue] / 1000.0;
258259

259-
if (responseData.retryInMilli != nil) {
260-
self.lastPackageRetryInMilli = responseData.retryInMilli;
261-
[self.logger error:@"Retrying purchase_verification package with retry in %d ms",
262-
[responseData.retryInMilli intValue]];
263-
return YES;
260+
[self.logger verbose:
261+
@"Waiting for %@ seconds before retrying purchase_verification with retry_in",
262+
[ADJUtil secondsNumberFormat:waitTime]];
263+
264+
return @(waitTime);
264265
}
265266

266-
return NO;
267+
return nil;
267268
}
268269

269270
@end

Adjust/Internal/ADJResponseData.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#import "ADJSessionFailure.h"
1616
#import "ADJActivityPackage.h"
1717

18+
@class ADJPurchaseVerificationResult;
19+
1820
typedef NS_ENUM(int, ADJTrackingState) {
1921
ADJTrackingStateOptedOut = 1
2022
};
@@ -72,6 +74,9 @@ typedef NS_ENUM(int, ADJTrackingState) {
7274
@end
7375

7476
@interface ADJPurchaseVerificationResponseData : ADJResponseData
77+
78+
@property (nonatomic, strong) ADJPurchaseVerificationResult *error;
79+
7580
@end
7681

7782
@interface ADJEventResponseData : ADJResponseData

Adjust/Internal/ADJUtil.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
static NSRegularExpression *goLinkUniversalLinkRegex = nil;
3232
static NSRegularExpression *excludedDeeplinkRegex = nil;
3333

34-
static NSString * const kClientSdk = @"ios5.4.1";
34+
static NSString * const kClientSdk = @"ios5.4.2";
3535
static NSString * const kDeeplinkParam = @"deep_link=";
3636
static NSString * const kSchemeDelimiter = @"://";
3737
static NSString * const kDefaultScheme = @"AdjustUniversalScheme";

AdjustBridge/AdjustBridgeRegister.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ function canSend(okCheck, errReason) {
176176
if (this.sdkPrefix) {
177177
return this.sdkPrefix;
178178
} else {
179-
return 'web-bridge5.4.1';
179+
return 'web-bridge5.4.2';
180180
}
181181
},
182182

0 commit comments

Comments
 (0)