diff --git a/RadarSDK.podspec b/RadarSDK.podspec index 1d7d1106c..3e17d8b7a 100644 --- a/RadarSDK.podspec +++ b/RadarSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'RadarSDK' - s.version = '3.16.0' + s.version = '3.16.1' s.summary = 'iOS SDK for Radar, the leading geofencing and location tracking platform' s.homepage = 'https://radar.com' s.author = { 'Radar Labs, Inc.' => 'support@radar.com' } diff --git a/RadarSDK.xcodeproj/project.pbxproj b/RadarSDK.xcodeproj/project.pbxproj index 485bd9495..5260c3442 100644 --- a/RadarSDK.xcodeproj/project.pbxproj +++ b/RadarSDK.xcodeproj/project.pbxproj @@ -462,7 +462,6 @@ DD236C792308797B00EB88F9 /* Info.plist */, 532FC303277A783900989279 /* Radar+Internal.h */, DD236C9023087A3500EB88F9 /* Radar.m */, - F667F8282BFBF3D1001F2F67 /* RadarSdkConfiguration.h */, DD236C9823087F9200EB88F9 /* RadarAPIClient.h */, DD236C9923087F9200EB88F9 /* RadarAPIClient.m */, DD633EC1237C5B800026C91A /* RadarAPIHelper.h */, @@ -495,6 +494,7 @@ 82D04ABA29722ED20036619F /* RadarReplayBuffer.h */, 82D04AB929722ED20036619F /* RadarReplayBuffer.m */, DD236C782308797B00EB88F9 /* RadarSDK.h */, + F667F8282BFBF3D1001F2F67 /* RadarSdkConfiguration.h */, F667F8262BFBF3C8001F2F67 /* RadarSdkConfiguration.m */, DD236CFB230895D400EB88F9 /* RadarSettings.h */, DD236CFC230895D400EB88F9 /* RadarSettings.m */, @@ -1022,7 +1022,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MARKETING_VERSION = 3.16.0; + MARKETING_VERSION = 3.16.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1080,7 +1080,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MARKETING_VERSION = 3.16.0; + MARKETING_VERSION = 3.16.1; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_CFLAGS = "-fembed-bitcode"; diff --git a/RadarSDK/Include/Radar.h b/RadarSDK/Include/Radar.h index 7e5904d3f..6fe32258a 100644 --- a/RadarSDK/Include/Radar.h +++ b/RadarSDK/Include/Radar.h @@ -492,6 +492,14 @@ typedef void (^_Nonnull RadarLogConversionCompletionHandler)(RadarStatus status, */ + (void)getVerifiedLocationToken:(RadarTrackVerifiedCompletionHandler _Nullable)completionHandler NS_SWIFT_NAME(getVerifiedLocationToken(completionHandler:)); +/** + Optionally sets the user's expected country and state for jurisdiction checks. + + @param countryCode The user's expected two-letter country code. + @param stateCode The user's expected two-letter state code. + */ ++ (void)setExpectedJurisdictionWithCountryCode:(NSString *_Nullable)countryCode stateCode:(NSString *_Nullable)stateCode NS_SWIFT_NAME(setExpectedJurisdiction(countryCode:stateCode:)); + /** Starts tracking the user's location in the background with configurable tracking options. diff --git a/RadarSDK/Include/RadarVerifiedLocationToken.h b/RadarSDK/Include/RadarVerifiedLocationToken.h index 57f96e172..fd79f0dfa 100644 --- a/RadarSDK/Include/RadarVerifiedLocationToken.h +++ b/RadarSDK/Include/RadarVerifiedLocationToken.h @@ -46,6 +46,16 @@ */ @property (assign, nonatomic, readonly) bool passed; +/** + An array of failure reasons for jurisdiction and fraud detection checks. + */ +@property (nullable, copy, nonatomic, readonly) NSArray *failureReasons; + +/** + The Radar ID of the location check. + */ +@property (nullable, copy, nonatomic, readonly) NSString *_id; + - (NSDictionary *_Nonnull)dictionaryValue; @end diff --git a/RadarSDK/Radar.m b/RadarSDK/Radar.m index 5d9759261..d82d099e4 100644 --- a/RadarSDK/Radar.m +++ b/RadarSDK/Radar.m @@ -284,6 +284,12 @@ + (void)getVerifiedLocationToken:(RadarTrackVerifiedCompletionHandler)completion getVerifiedLocationTokenWithCompletionHandler:completionHandler]; } ++ (void)setExpectedJurisdictionWithCountryCode:(NSString *)countryCode stateCode:(NSString *)stateCode { + [[RadarLogger sharedInstance] logWithLevel:RadarLogLevelInfo type:RadarLogTypeSDKCall message:@"setExpectedJurisdiction()"]; + [[RadarVerificationManager sharedInstance] + setExpectedJurisdictionWithCountryCode:countryCode stateCode:stateCode]; +} + + (void)startTrackingWithOptions:(RadarTrackingOptions *)options { [[RadarLogger sharedInstance] logWithLevel:RadarLogLevelInfo type:RadarLogTypeSDKCall message:@"startTracking()"]; [[RadarLocationManager sharedInstance] startTrackingWithOptions:options]; diff --git a/RadarSDK/RadarAPIClient.h b/RadarSDK/RadarAPIClient.h index 5cc27b47b..160b1fabe 100644 --- a/RadarSDK/RadarAPIClient.h +++ b/RadarSDK/RadarAPIClient.h @@ -91,6 +91,8 @@ typedef void (^_Nonnull RadarSyncLogsAPICompletionHandler)(RadarStatus status); keyId:(NSString *_Nullable)keyId attestationError:(NSString *_Nullable)attestationError encrypted:(BOOL)encrypted + expectedCountryCode:(NSString *_Nullable)expectedCountryCode + expectedStateCode:(NSString *_Nullable)expectedStateCode completionHandler:(RadarTrackAPICompletionHandler _Nonnull)completionHandler; - (void)flushReplays:(NSArray *_Nonnull)replays completionHandler:(RadarFlushReplaysAPICompletionHandler _Nonnull)completionHandler; diff --git a/RadarSDK/RadarAPIClient.m b/RadarSDK/RadarAPIClient.m index 590b93e9f..583730aa1 100644 --- a/RadarSDK/RadarAPIClient.m +++ b/RadarSDK/RadarAPIClient.m @@ -83,7 +83,7 @@ + (NSDictionary *)headersWithPublishableKey:(NSString *)publishableKey { - (void)getConfigForUsage:(NSString *_Nullable)usage verified:(BOOL)verified completionHandler:(RadarConfigAPICompletionHandler _Nonnull)completionHandler { NSString *publishableKey = [RadarSettings publishableKey]; if (!publishableKey) { - return; + return completionHandler(RadarStatusErrorPublishableKey, nil); } NSMutableString *queryString = [NSMutableString new]; @@ -185,6 +185,8 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location keyId:nil attestationError:nil encrypted:NO + expectedCountryCode:nil + expectedStateCode:nil completionHandler:completionHandler]; } @@ -199,6 +201,8 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location keyId:(NSString *_Nullable)keyId attestationError:(NSString *_Nullable)attestationError encrypted:(BOOL)encrypted + expectedCountryCode:(NSString * _Nullable)expectedCountryCode + expectedStateCode:(NSString * _Nullable)expectedStateCode completionHandler:(RadarTrackAPICompletionHandler _Nonnull)completionHandler { NSString *publishableKey = [RadarSettings publishableKey]; if (!publishableKey) { @@ -324,6 +328,12 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location if (jailbroken) { [fraudFailureReasons addObject:@"fraud_compromised_jailbroken"]; } + if (expectedCountryCode) { + params[@"expectedCountryCode"] = expectedCountryCode; + } + if (expectedStateCode) { + params[@"expectedStateCode"] = expectedStateCode; + } } params[@"appId"] = [[NSBundle mainBundle] bundleIdentifier]; diff --git a/RadarSDK/RadarUtils.m b/RadarSDK/RadarUtils.m index bc68c701f..c010d66b0 100644 --- a/RadarSDK/RadarUtils.m +++ b/RadarSDK/RadarUtils.m @@ -45,7 +45,7 @@ + (NSNumber *)timeZoneOffset { } + (NSString *)sdkVersion { - return @"3.16.0"; + return @"3.16.1"; } + (NSString *)deviceId { diff --git a/RadarSDK/RadarVerificationManager.h b/RadarSDK/RadarVerificationManager.h index a62c817d9..a44f3f52d 100644 --- a/RadarSDK/RadarVerificationManager.h +++ b/RadarSDK/RadarVerificationManager.h @@ -20,6 +20,7 @@ typedef void (^_Nullable RadarVerificationCompletionHandler)(NSString *_Nullable - (void)startTrackingVerifiedWithInterval:(NSTimeInterval)interval beacons:(BOOL)beacons; - (void)stopTrackingVerified; - (void)getVerifiedLocationTokenWithCompletionHandler:(RadarTrackVerifiedCompletionHandler _Nullable)completionHandler; +- (void)setExpectedJurisdictionWithCountryCode:(NSString *)countryCode stateCode:(NSString *)stateCode; - (void)getAttestationWithNonce:(NSString *)nonce completionHandler:(RadarVerificationCompletionHandler)completionHandler; - (BOOL)isJailbroken; diff --git a/RadarSDK/RadarVerificationManager.m b/RadarSDK/RadarVerificationManager.m index ec5dffc01..13aa554bc 100644 --- a/RadarSDK/RadarVerificationManager.m +++ b/RadarSDK/RadarVerificationManager.m @@ -42,6 +42,8 @@ @interface RadarVerificationManager () @property (assign, nonatomic) NSTimeInterval lastTokenSystemUptime; @property (assign, nonatomic) BOOL lastTokenBeacons; @property (strong, nonatomic) NSString *lastIPs; +@property (copy, nonatomic) NSString *expectedCountryCode; +@property (copy, nonatomic) NSString *expectedStateCode; @end @@ -103,6 +105,8 @@ - (void)trackVerifiedWithBeacons:(BOOL)beacons completionHandler:(RadarTrackVeri keyId:keyId attestationError:attestationError encrypted:NO + expectedCountryCode:self.expectedCountryCode + expectedStateCode:self.expectedStateCode completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, RadarUser *_Nullable user, NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config, RadarVerifiedLocationToken *_Nullable token) { @@ -194,6 +198,11 @@ - (void)startTrackingVerifiedWithInterval:(NSTimeInterval)interval beacons:(BOOL minInterval = minInterval - 10; } + // min interval is 10 seconds + if (minInterval < 10) { + minInterval = 10; + } + if (self.scheduled) { [[RadarLogger sharedInstance] logWithLevel:RadarLogLevelDebug message:@"Token request already scheduled"]; @@ -288,6 +297,11 @@ - (void)getVerifiedLocationTokenWithCompletionHandler:(RadarTrackVerifiedComplet [self trackVerifiedWithBeacons:self.lastTokenBeacons completionHandler:completionHandler]; } +- (void)setExpectedJurisdictionWithCountryCode:(NSString *)countryCode stateCode:(NSString *)stateCode { + self.expectedCountryCode = countryCode; + self.expectedStateCode = stateCode; +} + - (void)getAttestationWithNonce:(NSString *)nonce completionHandler:(RadarVerificationCompletionHandler)completionHandler { if (@available(iOS 14.0, *)) { DCAppAttestService *service = [DCAppAttestService sharedService]; diff --git a/RadarSDK/RadarVerifiedLocationToken+Internal.h b/RadarSDK/RadarVerifiedLocationToken+Internal.h index b6045ae20..216cb664c 100644 --- a/RadarSDK/RadarVerifiedLocationToken+Internal.h +++ b/RadarSDK/RadarVerifiedLocationToken+Internal.h @@ -15,7 +15,9 @@ token:(NSString *_Nonnull)token expiresAt:(NSDate *_Nonnull)expiresAt expiresIn:(NSTimeInterval)expiresIn - passed:(BOOL)passed; + passed:(BOOL)passed + failureReasons:(NSArray *_Nonnull)failureReasons + _id:(NSString *_Nonnull)_id; - (instancetype _Nullable)initWithObject:(id _Nonnull)object; @end diff --git a/RadarSDK/RadarVerifiedLocationToken.m b/RadarSDK/RadarVerifiedLocationToken.m index aca97a4ea..594a21f2e 100644 --- a/RadarSDK/RadarVerifiedLocationToken.m +++ b/RadarSDK/RadarVerifiedLocationToken.m @@ -18,7 +18,9 @@ - (instancetype _Nullable)initWithUser:(RadarUser *_Nonnull)user token:(NSString *_Nonnull)token expiresAt:(NSDate *_Nonnull)expiresAt expiresIn:(NSTimeInterval)expiresIn - passed:(BOOL)passed { + passed:(BOOL)passed + failureReasons:(NSArray * _Nonnull)failureReasons + _id:(NSString * _Nonnull)_id { self = [super init]; if (self) { _user = user; @@ -27,6 +29,8 @@ - (instancetype _Nullable)initWithUser:(RadarUser *_Nonnull)user _expiresAt = expiresAt; _expiresIn = expiresIn; _passed = passed; + _failureReasons = failureReasons; + __id = _id; } return self; } @@ -44,6 +48,8 @@ - (instancetype _Nullable)initWithObject:(id _Nonnull)object { NSDate *expiresAt; NSTimeInterval expiresIn = 0; BOOL passed = NO; + NSArray *failureReasons = @[]; + NSString *_id; id tokenObj = dict[@"token"]; if (tokenObj && [tokenObj isKindOfClass:[NSString class]]) { @@ -74,8 +80,18 @@ - (instancetype _Nullable)initWithObject:(id _Nonnull)object { events = [RadarEvent eventsFromObject:eventsObj]; } + id failureReasonsObj = dict[@"failureReasons"]; + if (failureReasonsObj && [failureReasonsObj isKindOfClass:[NSArray class]]) { + failureReasons = (NSArray *)failureReasonsObj; + } + + id idObj = dict[@"_id"]; + if (idObj && [idObj isKindOfClass:[NSString class]]) { + _id = (NSString *)idObj; + } + if (user && events && token && expiresAt) { - return [[RadarVerifiedLocationToken alloc] initWithUser:user events:events token:token expiresAt:expiresAt expiresIn:expiresIn passed:passed]; + return [[RadarVerifiedLocationToken alloc] initWithUser:user events:events token:token expiresAt:expiresAt expiresIn:expiresIn passed:passed failureReasons:failureReasons _id:_id]; } return nil;