diff --git a/AffirmSDK.xcodeproj/project.pbxproj b/AffirmSDK.xcodeproj/project.pbxproj index 2222bf1..0dad8a8 100644 --- a/AffirmSDK.xcodeproj/project.pbxproj +++ b/AffirmSDK.xcodeproj/project.pbxproj @@ -388,7 +388,7 @@ 08FA5907222D08E5007E5E4E /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1010; + LastUpgradeCheck = 1340; ORGANIZATIONNAME = "Affirm, Inc."; TargetAttributes = { 08FA590F222D08E5007E5E4E = { @@ -532,6 +532,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -558,7 +559,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -594,6 +595,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -614,7 +616,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; diff --git a/AffirmSDK.xcodeproj/xcshareddata/xcschemes/AffirmSDK.xcscheme b/AffirmSDK.xcodeproj/xcshareddata/xcschemes/AffirmSDK.xcscheme index e5b98be..19eef13 100644 --- a/AffirmSDK.xcodeproj/xcshareddata/xcschemes/AffirmSDK.xcscheme +++ b/AffirmSDK.xcodeproj/xcshareddata/xcschemes/AffirmSDK.xcscheme @@ -1,6 +1,6 @@ *)items [AffirmValidationUtils checkNotNegative:taxAmount name:@"taxAmount"]; [AffirmValidationUtils checkNotNil:shippingAmount name:@"shippingAmount"]; [AffirmValidationUtils checkNotNegative:shippingAmount name:@"shippingAmount"]; - + if (self = [super init]) { _items = [[NSArray alloc] initWithArray:items copyItems:YES]; _shipping = [shipping copy]; @@ -221,7 +221,7 @@ - (NSDecimalNumber *)calculatedTotalAmount { [AffirmValidationUtils checkNotNil:self.taxAmount name:@"taxAmount"]; [AffirmValidationUtils checkNotNil:self.shippingAmount name:@"shippingAmount"]; - + NSDecimalNumber *totalAmount = [self.taxAmount decimalNumberByAdding:self.shippingAmount]; for (AffirmItem *item in self.items) { totalAmount = [totalAmount decimalNumberByAdding:[item.unitPrice decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithInteger:item.quantity] decimalValue]]]]; @@ -258,12 +258,13 @@ - (NSDictionary *)toJSONDictionary } NSMutableDictionary *dict = [@{ - @"items": items, - @"total": [self.totalAmount toIntegerCents], - @"currency": [AffirmConfiguration sharedInstance].currency, - @"api_version" :@"v2" - } mutableCopy]; - + @"meta": @{@"locale": [AffirmConfiguration sharedInstance].locale}, + @"items": items, + @"total": [self.totalAmount toIntegerCents], + @"currency": [AffirmConfiguration sharedInstance].currency, + @"api_version" :@"v2" + } mutableCopy]; + if (self.sendShippingAddress) { if (self.shipping) { [dict addEntriesFromDictionary:[self.shipping toJSONDictionary]]; @@ -271,11 +272,11 @@ - (NSDictionary *)toJSONDictionary [[AffirmLogger sharedInstance] logException:@"Shipping addresses are required when sendShippingAddress is true."]; } } - + if (self.billing) { [dict addEntriesFromDictionary:[self.billing toJSONDictionary]]; } - + if (self.shippingAmount != nil) { [dict setValue:self.shippingAmount.toIntegerCents forKey:@"shipping_amount"]; } @@ -299,7 +300,7 @@ - (NSDictionary *)toJSONDictionary if (self.financingProgram != nil) { [dict setObject:self.financingProgram forKey:@"financing_program"]; } - + if (self.orderId != nil) { [dict setObject:self.orderId forKey:@"order_id"]; } diff --git a/AffirmSDK/AffirmClient.m b/AffirmSDK/AffirmClient.m index 0c81e69..6c75e62 100644 --- a/AffirmSDK/AffirmClient.m +++ b/AffirmSDK/AffirmClient.m @@ -96,7 +96,7 @@ + (void)send:(AffirmRequest *)request handler:(AffirmRequestHandler)handler } NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; urlRequest.HTTPMethod = method; - + NSDictionary *headers = request.headers; for (NSString *key in headers) { [urlRequest setValue:headers[key] forHTTPHeaderField:key]; @@ -104,7 +104,7 @@ + (void)send:(AffirmRequest *)request handler:(AffirmRequestHandler)handler if (request.parameters && [NSJSONSerialization isValidJSONObject:request.parameters] && request.method == AffirmHTTPMethodPOST) { urlRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:request.parameters options:NSJSONWritingPrettyPrinted error:nil]; } - + NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (handler) { NSHTTPURLResponse *result = (NSHTTPURLResponse *)response; @@ -138,7 +138,7 @@ @implementation AffirmTrackerClient + (NSString *)host { - return [NSString stringWithFormat:@"https://tracker.%@", [AffirmConfiguration sharedInstance].domain]; + return [AffirmConfiguration sharedInstance].trackerURL; } @end @@ -147,8 +147,7 @@ @implementation AffirmPromoClient + (NSString *)host { - NSString *prefix = [AffirmConfiguration sharedInstance].isProductionEnvironment ? @"www" : @"sandbox"; - return [NSString stringWithFormat:@"https://%@.%@", prefix, [AffirmConfiguration sharedInstance].domain]; + return [AffirmConfiguration sharedInstance].promosURL; } @end @@ -157,8 +156,7 @@ @implementation AffirmCheckoutClient + (NSString *)host { - NSString *prefix = [AffirmConfiguration sharedInstance].isProductionEnvironment ? @"api" : @"sandbox"; - return [NSString stringWithFormat:@"https://%@.%@", prefix, [AffirmConfiguration sharedInstance].domain]; + return [AffirmConfiguration sharedInstance].checkoutURL; } @end diff --git a/AffirmSDK/AffirmConfiguration.h b/AffirmSDK/AffirmConfiguration.h index 95ea4e6..29a5377 100644 --- a/AffirmSDK/AffirmConfiguration.h +++ b/AffirmSDK/AffirmConfiguration.h @@ -30,9 +30,14 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) AffirmEnvironment environment; /** - environment User locale. (US, CA) + environment User locale. (en_US, en_CA, fr_CA , etc.) */ -@property (nonatomic, readonly) AffirmLocale locale; +@property (nonatomic, readonly) NSString *locale; + +/** + environment User country code. (USA, CAN , etc.) + */ +@property (nonatomic, readonly) NSString *countryCode; /** environment Currency. (USD, CAD) @@ -50,7 +55,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) BOOL isProductionEnvironment; /** - creditCard Return an existing credit card. + creditCard Return an existing credit card. */ @property (nonatomic, readonly, strong, nullable) AffirmCreditCard *creditCard; @@ -94,13 +99,15 @@ NS_SWIFT_NAME(configure(publicKey:environment:)); NS_SWIFT_NAME(configure(publicKey:environment:merchantName:)); /** -Convenience constructor. See properties for more details. -*/ + Convenience constructor. See properties for more details. + */ - (void)configureWithPublicKey:(NSString *)publicKey environment:(AffirmEnvironment)environment - locale:(AffirmLocale)locale + locale:(NSString *)locale + countryCode:(NSString *)countryCode + currency:(NSString *)currency merchantName:(NSString * _Nullable )merchantName -NS_SWIFT_NAME(configure(publicKey:environment:locale:merchantName:)); +NS_SWIFT_NAME(configure(publicKey:environment:locale:countryCode:currency:merchantName:)); /** affirmSDKVersion Current Affirm SDK version. @@ -108,14 +115,24 @@ NS_SWIFT_NAME(configure(publicKey:environment:locale:merchantName:)); + (NSString *)affirmSDKVersion; /** -domain Based on currenct locale -*/ -- (NSString *)domain; + jsURL Affirm js file url + */ +- (NSString *)jsURL; /** -jsURL Affirm js file url -*/ -- (NSString *)jsURL; + promosURL Promos endpoint url + */ +- (NSString *)promosURL; + +/** + checkoutURL Checkout endpoint url + */ +- (NSString *)checkoutURL; + +/** + trackerURL Tracker endpoint url + */ +- (NSString *)trackerURL; /** environmentDescription Current environment. diff --git a/AffirmSDK/AffirmConfiguration.m b/AffirmSDK/AffirmConfiguration.m index 7e23c4c..beb65f1 100644 --- a/AffirmSDK/AffirmConfiguration.m +++ b/AffirmSDK/AffirmConfiguration.m @@ -15,9 +15,9 @@ @interface AffirmConfiguration () -@property (nonatomic, copy, readwrite) NSString *publicKey; +@property (nonatomic, copy, readwrite) NSString *publicKey, *countryCode, *currency; @property (nonatomic, readwrite) AffirmEnvironment environment; -@property (nonatomic, readwrite) AffirmLocale locale; +@property (nonatomic, readwrite) NSString *locale; @property (nonatomic, copy, readwrite, nullable) NSString *merchantName; @property (nonatomic, strong, readwrite) WKProcessPool *pool; @property (nonatomic, strong, readwrite, nullable) AffirmCreditCard *creditCard; @@ -47,7 +47,9 @@ - (instancetype)init { if (self = [super init]) { _environment = AffirmEnvironmentSandbox; - _locale = AffirmLocaleUS; + _locale = AFFIRM_DEFAULT_LOCALE; + _countryCode = AFFIRM_DEFAULT_COUNTRY_CODE; + _currency = AFFIRM_DEFAULT_CURRENCY; } return self; } @@ -79,12 +81,16 @@ - (void)configureWithPublicKey:(NSString *)publicKey - (void)configureWithPublicKey:(NSString *)publicKey environment:(AffirmEnvironment)environment - locale:(AffirmLocale)locale + locale:(NSString *)locale + countryCode:(NSString *)countryCode + currency:(NSString *)currency merchantName:(NSString * _Nullable )merchantName { self.publicKey = [publicKey copy]; self.environment = environment; self.locale = locale; + self.countryCode = countryCode; + self.currency = currency; self.merchantName = [merchantName copy]; } @@ -101,41 +107,50 @@ - (NSString *)publicKey return _publicKey; } -- (NSString *)currency ++ (NSString *)affirmSDKVersion { - switch (self.locale) { - case AffirmLocaleUS: - return @"USD"; - case AffirmLocaleCA: - return @"CAD"; - } + return [[NSBundle resourceBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; } -+ (NSString *)affirmSDKVersion +- (NSString *)jsURL { - return [[NSBundle resourceBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + switch (self.environment) { + case AffirmEnvironmentSandbox: + return AFFIRM_JS_SANDBOX_URL; + case AffirmEnvironmentProduction: + return AFFIRM_JS_PRODUCTION_URL; + } } -- (NSString *)domain +- (NSString *)promosDomain { - switch (self.locale) { - case AffirmLocaleUS: - return AFFIRM_US_DOMAIN; - case AffirmLocaleCA: - return AFFIRM_CA_DOMAIN; + if ([self.countryCode isEqualToString:@"CAN"]) { + return AFFIRM_PROMOS_CA_DOMAIN; } + return AFFIRM_PROMOS_US_DOMAIN; } -- (NSString *)jsURL +- (NSString *)promosURL +{ + NSString *prefix = self.isProductionEnvironment ? @"www" : @"sandbox"; + return [NSString stringWithFormat:@"https://%@.%@", prefix, self.promosDomain]; +} + +- (NSString *)checkoutURL { switch (self.environment) { case AffirmEnvironmentSandbox: - return [NSString stringWithFormat:@"https://cdn1-sandbox.%@/js/v2/affirm.js", self.domain]; + return AFFIRM_CHECKOUT_SANDBOX_URL; case AffirmEnvironmentProduction: - return [NSString stringWithFormat:@"https://cdn1.%@/js/v2/affirm.js", self.domain]; + return AFFIRM_CHECKOUT_PRODUCTION_URL; } } +- (NSString *)trackerURL +{ + return [NSString stringWithFormat:@"https://tracker.%@", self.promosDomain]; +} + - (NSString *)environmentDescription { switch(self.environment) { @@ -160,9 +175,12 @@ - (void)updateCreditCard:(nullable AffirmCreditCard *)creditCard { NSMutableArray *ownedCookies = [NSMutableArray array]; NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies; + NSArray *urls = @[AFFIRM_PROMOS_US_DOMAIN, AFFIRM_PROMOS_CA_DOMAIN]; for (NSHTTPCookie *cookie in cookies) { - if ([cookie.domain rangeOfString:[AffirmConfiguration sharedInstance].domain].location != NSNotFound) { - [ownedCookies addObject:cookie]; + for (NSString *url in urls) { + if ([cookie.domain rangeOfString:url].location != NSNotFound) { + [ownedCookies addObject:cookie]; + } } } return ownedCookies; diff --git a/AffirmSDK/AffirmConstants.h b/AffirmSDK/AffirmConstants.h index 61f8e25..c773a84 100644 --- a/AffirmSDK/AffirmConstants.h +++ b/AffirmSDK/AffirmConstants.h @@ -20,8 +20,18 @@ FOUNDATION_EXPORT NSString *const AffirmSDKErrorDomain; #endif -FOUNDATION_EXPORT NSString *const AFFIRM_US_DOMAIN; -FOUNDATION_EXPORT NSString *const AFFIRM_CA_DOMAIN; +FOUNDATION_EXPORT NSString *const AFFIRM_DEFAULT_LOCALE; +FOUNDATION_EXPORT NSString *const AFFIRM_DEFAULT_COUNTRY_CODE; +FOUNDATION_EXPORT NSString *const AFFIRM_DEFAULT_CURRENCY; + +FOUNDATION_EXPORT NSString *const AFFIRM_JS_SANDBOX_URL; +FOUNDATION_EXPORT NSString *const AFFIRM_JS_PRODUCTION_URL; + +FOUNDATION_EXPORT NSString *const AFFIRM_CHECKOUT_SANDBOX_URL; +FOUNDATION_EXPORT NSString *const AFFIRM_CHECKOUT_PRODUCTION_URL; + +FOUNDATION_EXPORT NSString *const AFFIRM_PROMOS_US_DOMAIN; +FOUNDATION_EXPORT NSString *const AFFIRM_PROMOS_CA_DOMAIN; FOUNDATION_EXPORT NSString *const AFFIRM_MAX_PROMO_AMOUNT; @@ -43,11 +53,6 @@ typedef NS_ENUM(NSInteger, AffirmEnvironment) { AffirmEnvironmentSandbox }; -typedef NS_ENUM(NSInteger, AffirmLocale) { - AffirmLocaleUS, - AffirmLocaleCA -}; - typedef NS_ENUM(NSInteger, AffirmPageType) { AffirmPageTypeNone, AffirmPageTypeBanner, diff --git a/AffirmSDK/AffirmConstants.m b/AffirmSDK/AffirmConstants.m index 3c295ca..50380ec 100644 --- a/AffirmSDK/AffirmConstants.m +++ b/AffirmSDK/AffirmConstants.m @@ -18,8 +18,21 @@ #endif -NSString *const AFFIRM_US_DOMAIN = @"affirm.com"; -NSString *const AFFIRM_CA_DOMAIN = @"affirm.ca"; +NSString *const AFFIRM_DEFAULT_LOCALE = @"en_US"; +NSString *const AFFIRM_DEFAULT_COUNTRY_CODE = @"USA"; +NSString *const AFFIRM_DEFAULT_CURRENCY = @"USD"; + +// Global Affirm JS URL +NSString *const AFFIRM_JS_SANDBOX_URL = @"https://cdn1-sandbox.affirm.com/js/v2/affirm.js"; +NSString *const AFFIRM_JS_PRODUCTION_URL = @"https://cdn1.affirm.com/js/v2/affirm.js"; + +// Global Checkout URL +NSString *const AFFIRM_CHECKOUT_SANDBOX_URL = @"https://api.global-sandbox.affirm.com"; +NSString *const AFFIRM_CHECKOUT_PRODUCTION_URL = @"https://api.global.affirm.com"; + +// Promos & Prequal URL +NSString *const AFFIRM_PROMOS_US_DOMAIN = @"affirm.com"; +NSString *const AFFIRM_PROMOS_CA_DOMAIN = @"affirm.ca"; NSString *const AFFIRM_MAX_PROMO_AMOUNT = @"17500"; diff --git a/AffirmSDK/AffirmEligibilityViewController.m b/AffirmSDK/AffirmEligibilityViewController.m index b7610fd..30bf698 100644 --- a/AffirmSDK/AffirmEligibilityViewController.m +++ b/AffirmSDK/AffirmEligibilityViewController.m @@ -80,7 +80,7 @@ - (void)viewDidLoad self.logoView.image = [UIImage imageNamed:@"blue-black_logo-transparent_bg" ofType:@"png" inBundle:[NSBundle resourceBundle]]; NSDecimalNumber *totalAmount = self.checkout.totalAmount; if (totalAmount && totalAmount != NSDecimalNumber.notANumber) { - self.amountField.text = [totalAmount formattedString]; + self.amountField.text = [totalAmount formattedStringWithFractionDigits:0]; } else { self.amountField.text = nil; } @@ -108,11 +108,22 @@ - (void)question:(id)sender [self presentViewController:controller animated:YES completion:nil]; } +- (NSDecimalNumber *)verifyAmount +{ + NSDecimalNumber *totalAmount = [self.amountField.text currencyDecimal]; + if (!totalAmount || totalAmount == [NSDecimalNumber notANumber]) { + return [NSDecimalNumber zero]; + } + return totalAmount; +} + - (IBAction)getStarted:(id)sender { NSCAssert(self.navigationController != nil, @"The current view controller is not contained in a navigation controller."); - NSDecimalNumber *totalAmount = [self.amountField.text currencyDecimal]; + [self.amountField resignFirstResponder]; + NSDecimalNumber *totalAmount = [self verifyAmount]; + self.checkout.totalAmount = totalAmount; AffirmCheckoutViewController *controller = [AffirmCheckoutViewController startCheckout:self.checkout useVCN:YES getReasonCodes:self.getReasonCodes delegate:self.delegate]; @@ -130,7 +141,7 @@ - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRang NSDecimalNumber *number = [term currencyDecimal]; if (number && number != [NSDecimalNumber notANumber]) { - textField.text = [number formattedString]; + textField.text = [number formattedStringWithFractionDigits:0]; } else { textField.text = nil; } diff --git a/AffirmSDK/AffirmEligibilityViewController.xib b/AffirmSDK/AffirmEligibilityViewController.xib index 66f55ff..396db4a 100644 --- a/AffirmSDK/AffirmEligibilityViewController.xib +++ b/AffirmSDK/AffirmEligibilityViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -35,26 +35,26 @@ - + - + @@ -78,7 +78,7 @@