diff --git a/Mobile Buy SDK/Mobile Buy SDK Tests/BUYClientTest.m b/Mobile Buy SDK/Mobile Buy SDK Tests/BUYClientTest.m index 9a2b4d0..755f7eb 100644 --- a/Mobile Buy SDK/Mobile Buy SDK Tests/BUYClientTest.m +++ b/Mobile Buy SDK/Mobile Buy SDK Tests/BUYClientTest.m @@ -227,6 +227,7 @@ - (void)testProductsInCollectionWithSortOrderCollectionDefault { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCollectionDefault completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -238,6 +239,7 @@ - (void)testProductsInCollectionWithSortOrderBestSelling { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortBestSelling completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -249,6 +251,7 @@ - (void)testProductsInCollectionWithSortOrderCreatedAscending { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCreatedAscending completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -260,6 +263,7 @@ - (void)testProductsInCollectionWithSortOrderCreatedDescending { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCreatedDescending completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -271,6 +275,7 @@ - (void)testProductsInCollectionWithSortOrderPriceAscending { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortPriceAscending completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -282,6 +287,7 @@ - (void)testProductsInCollectionWithSortOrderPriceDescending { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortPriceDescending completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -293,6 +299,7 @@ - (void)testProductsInCollectionWithSortOrderTitleAscending { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortTitleAscending completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); @@ -304,6 +311,7 @@ - (void)testProductsInCollectionWithSortOrderTitleDescending { NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortTitleDescending completion:nil]; + XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET"); XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https"); XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop"); XCTAssertEqualObjects(task.originalRequest.URL.path, @"/api/channels/api_key/product_publications.json"); diff --git a/Mobile Buy SDK/Mobile Buy SDK/Data/BUYClient.m b/Mobile Buy SDK/Mobile Buy SDK/Data/BUYClient.m index 54cb8e9..1b46dc2 100644 --- a/Mobile Buy SDK/Mobile Buy SDK/Data/BUYClient.m +++ b/Mobile Buy SDK/Mobile Buy SDK/Data/BUYClient.m @@ -56,6 +56,9 @@ NSString * const BUYVersionString = @"1.2.3"; +static NSString *const kBUYClientPathProductPublications = @"product_publications"; +static NSString *const kBUYClientPathCollectionPublications = @"collection_publications"; + @interface BUYClient () <NSURLSessionDelegate> @property (nonatomic, strong) NSString *shopDomain; @@ -124,15 +127,15 @@ NSString * const BUYVersionString = @"1.2.3"; - (NSURLSessionDataTask *)getProductsPage:(NSUInteger)page completion:(BUYDataProductListBlock)block { - NSURLComponents *components = [self URLComponentsForChannelsWithEndPoint:@"product_publications.json" - queryItems:@{@"limit" : [NSString stringWithFormat:@"%lu", (unsigned long)self.pageSize], - @"page" : [NSString stringWithFormat:@"%lu", (unsigned long)page]}]; + NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathProductPublications + queryItems:@{@"limit" : [NSString stringWithFormat:@"%lu", (unsigned long)self.pageSize], + @"page" : [NSString stringWithFormat:@"%lu", (unsigned long)page]}]; return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { NSArray *products = nil; if (json && error == nil) { - products = [BUYProduct convertJSONArray:json[@"product_publications"]]; + products = [BUYProduct convertJSONArray:json[kBUYClientPathProductPublications]]; } block(products, page, [self hasReachedEndOfPage:products] || error, error); }]; @@ -154,14 +157,14 @@ NSString * const BUYVersionString = @"1.2.3"; - (NSURLSessionDataTask *)getProductsByIds:(NSArray *)productIds completion:(BUYDataProductsBlock)block { - NSURLComponents *components = [self URLComponentsForChannelsWithEndPoint:@"product_publications.json" - queryItems:@{@"product_ids" : [productIds componentsJoinedByString:@","]}]; + NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathProductPublications + queryItems:@{@"product_ids" : [productIds componentsJoinedByString:@","]}]; return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { NSArray *products = nil; if (json && error == nil) { - products = [BUYProduct convertJSONArray:json[@"product_publications"]]; + products = [BUYProduct convertJSONArray:json[kBUYClientPathProductPublications]]; } if (error == nil && [products count] == 0) { error = [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidProductID userInfo:@{ NSLocalizedDescriptionKey : @"Product IDs are not valid. Confirm the product IDs on your shop's admin and also ensure that the visibility is on for the Mobile App channel." }]; @@ -172,13 +175,13 @@ NSString * const BUYVersionString = @"1.2.3"; - (NSURLSessionDataTask *)getCollections:(BUYDataCollectionsBlock)block { - NSURLComponents *components = [self URLComponentsForChannelsWithEndPoint:@"collection_publications.json" queryItems:nil]; + NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathCollectionPublications queryItems:nil]; return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { NSArray *collections = nil; if (json && error == nil) { - collections = [BUYCollection convertJSONArray:json[@"collection_publications"]]; + collections = [BUYCollection convertJSONArray:json[kBUYClientPathCollectionPublications]]; } block(collections, error); }]; @@ -193,17 +196,17 @@ NSString * const BUYVersionString = @"1.2.3"; { NSURLSessionDataTask *task = nil; if (collectionId) { - NSURLComponents *components = [self URLComponentsForChannelsWithEndPoint:@"product_publications.json" - queryItems:@{@"collection_id" : [NSString stringWithFormat:@"%lu", collectionId.longValue], - @"limit" : [NSString stringWithFormat:@"%lu", (unsigned long)self.pageSize], - @"page" : [NSString stringWithFormat:@"%lu", (unsigned long)page], - @"sort_by" : [BUYCollection sortOrderParameterForCollectionSort:sortOrder]}]; + NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathProductPublications + queryItems:@{@"collection_id" : [NSString stringWithFormat:@"%lu", collectionId.longValue], + @"limit" : [NSString stringWithFormat:@"%lu", (unsigned long)self.pageSize], + @"page" : [NSString stringWithFormat:@"%lu", (unsigned long)page], + @"sort_by" : [BUYCollection sortOrderParameterForCollectionSort:sortOrder]}]; task = [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { NSArray *products = nil; if (json && error == nil) { - products = [BUYProduct convertJSONArray:json[@"product_publications"]]; + products = [BUYProduct convertJSONArray:json[kBUYClientPathProductPublications]]; } block(products, page, [self hasReachedEndOfPage:products] || error, error); }]; @@ -229,36 +232,34 @@ NSString * const BUYVersionString = @"1.2.3"; #pragma mark - URL Components -- (NSURLComponents *)URLComponentsForChannelsWithEndPoint:(NSString *)endPoint queryItems:(NSDictionary*)queryItems +- (NSURLComponents *)URLComponentsForChannelsAppendingPath:(NSString *)appendingPath queryItems:(NSDictionary*)queryItems { - return [self URLComponentsForAPIPath:[NSString stringWithFormat:@"channels/%@", self.channelId] endPoint:endPoint queryItems:queryItems]; + return [self URLComponentsForAPIPath:[NSString stringWithFormat:@"channels/%@", self.channelId] appendingPath:appendingPath queryItems:queryItems]; } -- (NSURLComponents *)URLComponentsForCheckoutsWithToken:(NSString *)checkoutToken endPoint:(NSString *)endPoint queryItems:(NSDictionary*)queryItems +- (NSURLComponents *)URLComponentsForCheckoutsAppendingPath:(NSString *)appendingPath checkoutToken:(NSString *)checkoutToken queryItems:(NSDictionary*)queryItems { - NSMutableString *apiPath = [NSMutableString stringWithString:@"checkouts"]; + NSString *apiPath = @"checkouts"; if (checkoutToken) { - [apiPath appendFormat:@"/%@", checkoutToken]; - } else { - [apiPath appendString:@".json"]; + apiPath = [NSString pathWithComponents:@[apiPath, checkoutToken]]; } - return [self URLComponentsForAPIPath:[apiPath copy] endPoint:endPoint queryItems:queryItems]; + return [self URLComponentsForAPIPath:[apiPath copy] appendingPath:appendingPath queryItems:queryItems]; } -- (NSURLComponents *)URLComponentsForAPIPath:(NSString *)apiPath endPoint:(NSString *)endPoint queryItems:(NSDictionary*)queryItems +- (NSURLComponents *)URLComponentsForAPIPath:(NSString *)apiPath appendingPath:(NSString *)appendingPath queryItems:(NSDictionary*)queryItems { NSMutableArray *pathComponents = [NSMutableArray array]; - [pathComponents addObject:@"api"]; + [pathComponents addObject:@"/api"]; [pathComponents addObject:apiPath]; - if (endPoint) { - [pathComponents addObject:endPoint]; + if (appendingPath) { + [pathComponents addObject:appendingPath]; } return [self URLComponentsForPathComponents:pathComponents queryItems:queryItems]; } - (NSURLComponents *)URLComponentsForShop { - return [self URLComponentsForPathComponents:@[@"meta.json"] queryItems:nil]; + return [self URLComponentsForPathComponents:@[@"/meta"] queryItems:nil]; } - (NSURLComponents *)URLComponentsForPathComponents:(NSArray*)pathComponents queryItems:(NSDictionary*)queryItems @@ -266,7 +267,7 @@ NSString * const BUYVersionString = @"1.2.3"; NSURLComponents *components = [[NSURLComponents alloc] init]; components.scheme = @"https"; components.host = self.shopDomain; - components.path = [NSString stringWithFormat:@"/%@", [pathComponents componentsJoinedByString:@"/"]]; + components.path = [[NSString pathWithComponents:pathComponents] stringByAppendingPathExtension:@"json"]; [components setQueryItemsWithDictionary:queryItems]; return components; } @@ -319,7 +320,7 @@ NSString * const BUYVersionString = @"1.2.3"; NSData *data = [NSJSONSerialization dataWithJSONObject:checkoutJSON options:0 error:&error]; if (data && error == nil) { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:nil endPoint:nil queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:nil checkoutToken:nil queryItems:nil]; task = [self postRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { [self handleCheckoutResponse:json error:error block:block]; @@ -337,9 +338,9 @@ NSString * const BUYVersionString = @"1.2.3"; } else { BUYGiftCard *giftCard = [[BUYGiftCard alloc] initWithDictionary:@{ @"code" : giftCardCode }]; - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:checkout.token - endPoint:@"gift_cards.json" - queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"gift_cards" + checkoutToken:checkout.token + queryItems:nil]; task = [self postRequestForURL:components.URL object:giftCard @@ -358,7 +359,9 @@ NSString * const BUYVersionString = @"1.2.3"; { NSURLSessionDataTask *task = nil; if (giftCard.identifier) { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:checkout.token endPoint:[NSString stringWithFormat:@"gift_cards/%@.json", giftCard.identifier] queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:[NSString stringWithFormat:@"gift_cards/%@", giftCard.identifier] + checkoutToken:checkout.token + queryItems:nil]; task = [self deleteRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { if (error == nil) { [self updateCheckout:checkout withGiftCardDictionary:json[@"gift_card"] addingGiftCard:NO]; @@ -393,7 +396,9 @@ NSString * const BUYVersionString = @"1.2.3"; - (NSURLSessionDataTask *)getCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:checkout.token endPoint:nil queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:nil + checkoutToken:checkout.token + queryItems:nil]; return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { [self handleCheckoutResponse:json error:error block:block]; }]; @@ -406,7 +411,9 @@ NSString * const BUYVersionString = @"1.2.3"; NSURLSessionDataTask *task = nil; if ([checkout hasToken]) { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:checkout.token endPoint:nil queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:nil + checkoutToken:checkout.token + queryItems:nil]; task = [self patchRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { [self handleCheckoutResponse:json error:error block:block]; }]; @@ -472,7 +479,9 @@ NSString * const BUYVersionString = @"1.2.3"; - (NSURLSessionDataTask *)checkoutCompletionRequestWithCheckout:(BUYCheckout *)checkout body:(NSData *)body completion:(BUYDataCheckoutBlock)block { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:checkout.token endPoint:@"complete.json" queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"complete" + checkoutToken:checkout.token + queryItems:nil]; return [self postRequestForURL:components.URL body:body completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { [self handleCheckoutResponse:json error:error block:block]; }]; @@ -513,7 +522,9 @@ NSString * const BUYVersionString = @"1.2.3"; - (NSURLSessionDataTask *)getCompletionStatusOfCheckoutToken:(NSString *)token completion:(BUYDataCheckoutStatusBlock)block { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:token endPoint:@"processing.json" queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"processing" + checkoutToken:token + queryItems:nil]; return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; block([BUYClient statusForStatusCode:statusCode error:error], error); @@ -526,7 +537,7 @@ NSString * const BUYVersionString = @"1.2.3"; { NSURLSessionDataTask *task = nil; if ([checkout hasToken]) { - NSURLComponents *components = [self URLComponentsForCheckoutsWithToken:checkout.token endPoint:@"shipping_rates.json?checkout" queryItems:nil]; + NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"shipping_rates" checkoutToken:checkout.token queryItems:@{ @"checkout" : @"" }]; task = [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { NSArray *shippingRates = nil; if (error == nil && json) { diff --git a/Mobile Buy SDK/Mobile Buy SDK/Utils/NSURLComponents+BUYAdditions.m b/Mobile Buy SDK/Mobile Buy SDK/Utils/NSURLComponents+BUYAdditions.m index 10f11f9..b73173c 100644 --- a/Mobile Buy SDK/Mobile Buy SDK/Utils/NSURLComponents+BUYAdditions.m +++ b/Mobile Buy SDK/Mobile Buy SDK/Utils/NSURLComponents+BUYAdditions.m @@ -33,7 +33,8 @@ if (dictionary) { NSMutableArray *queryItems = [NSMutableArray array]; for (NSString *key in [dictionary allKeys]) { - [queryItems addObject:[[NSURLQueryItem alloc] initWithName:key value:dictionary[key]]]; + NSString *value = [dictionary[key] length] ? dictionary[key] : nil; + [queryItems addObject:[[NSURLQueryItem alloc] initWithName:key value:value]]; } self.queryItems = [queryItems copy]; }