Commit 15e8ade1 by Dima Bart

Merge pull request #160 from Shopify/feature/improve-checkout-api

Improve checkout API
parents 8f4986f3 45a5cb75
//
// BUYApplePayTestToken.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import <PassKit/PassKit.h>
static NSString * const BUYTestingToken = @"7fc9b0e9-ed1c-4d77-9bac-78c904aa03c1";
@interface BUYApplePayTestToken : PKPaymentToken
+ (instancetype)validToken;
+ (instancetype)invalidToken;
@end
//
// BUYApplePayTestToken.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYApplePayTestToken.h"
@interface BUYApplePayTestToken ()
@property (strong, nonatomic) NSData *testData;
@end
@implementation BUYApplePayTestToken
+ (instancetype)validToken {
BUYApplePayTestToken *token = [BUYApplePayTestToken new];
token.testData = [BUYTestingToken dataUsingEncoding:NSUTF8StringEncoding];
return token;
}
+ (instancetype)invalidToken {
return [BUYApplePayTestToken new];
}
- (NSData *)paymentData {
return _testData;
}
@end
//
// BUYApplePayTokenTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import <PassKit/PassKit.h>
#import "BUYApplePayToken.h"
#import "BUYApplePayTestToken.h"
@interface BUYApplePayToken (Private)
- (NSString *)paymentTokenString;
@end
@interface BUYApplePayTokenTests : XCTestCase
@end
@implementation BUYApplePayTokenTests
- (void)testInitWithValidSessionID {
BUYApplePayToken *token = [[BUYApplePayToken alloc] initWithPaymentToken:[BUYApplePayTestToken validToken]];
XCTAssertNotNil(token);
XCTAssertEqualObjects(BUYTestingToken, [token paymentTokenString]);
}
- (void)testInitWithInvalidSessionID {
XCTAssertThrows([[BUYApplePayToken alloc] initWithPaymentToken:nil]);
XCTAssertThrows([[BUYApplePayToken alloc] initWithPaymentToken:[BUYApplePayTestToken invalidToken]]);
}
- (void)testJSONConversion {
BUYApplePayToken *token = [[BUYApplePayToken alloc] initWithPaymentToken:[BUYApplePayTestToken validToken]];
NSDictionary *json = @{
@"payment_token" : @{
@"type" : @"apple_pay",
@"payment_data" : BUYTestingToken,
},
};
XCTAssertEqualObjects(token.JSONDictionary, json);
}
@end
......@@ -34,6 +34,8 @@
#import "BUYShopifyErrorCodes.h"
#import "BUYAccountCredentials.h"
#import "BUYClient+Customers.h"
#import "BUYApplePayToken.h"
#import "BUYApplePayTestToken.h"
NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
......@@ -74,7 +76,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
{
BUYCart *cart = [self cart];
BUYCheckout *checkout = [[BUYCheckout alloc] initWithCart:cart];
NSURLSessionDataTask *task = [self.client createCheckout:checkout completion:nil];
NSURLSessionDataTask *task = [self.client createCheckout:checkout completion:^(BUYCheckout *checkout, NSError *error) {}];
XCTAssertNotNil(task);
NSURLRequest *request = task.originalRequest;
......@@ -106,7 +108,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
XCTAssertThrows([checkout setPartialAddressesValue:NO]);
NSURLSessionDataTask *task = [self.client createCheckout:checkout completion:nil];
NSURLSessionDataTask *task = [self.client createCheckout:checkout completion:^(BUYCheckout *checkout, NSError *error) {}];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:task.originalRequest.HTTPBody options:0 error:nil];
XCTAssertFalse([json[@"checkout"][@"partial_addresses"] boolValue]);
......@@ -120,7 +122,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
}
checkout.shippingAddress = partialAddress;
task = [self.client createCheckout:checkout completion:nil];
task = [self.client createCheckout:checkout completion:^(BUYCheckout *checkout, NSError *error) {}];
json = [NSJSONSerialization JSONObjectWithData:task.originalRequest.HTTPBody options:0 error:nil];
XCTAssertTrue([json[@"checkout"][@"partial_addresses"] boolValue]);
......@@ -130,7 +132,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
{
BUYCheckout *checkout = [[BUYCheckout alloc] initWithModelManager:self.client.modelManager JSONDictionary:@{@"token": @"abcdef", @"payment_due": @0}];
NSURLSessionDataTask *task = [self.client completeCheckout:checkout completion:nil];
NSURLSessionDataTask *task = [self.client completeCheckout:checkout paymentToken:nil completion:^(BUYCheckout *checkout, NSError *error) {}];
XCTAssertNotNil(task);
}
......@@ -146,19 +148,11 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testCheckoutBadURLParsing
{
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
NSURL *url = [NSURL URLWithString:@"sampleapp://"];
[self.client getCompletionStatusOfCheckoutURL:url completion:^(BUYStatus status, NSError *error) {
XCTAssertEqual(status, BUYStatusUnknown);
XCTAssertEqual(error.code, BUYShopifyError_InvalidCheckoutObject);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:10 handler:^(NSError *error) {
XCTAssertNil(error);
}];
XCTAssertThrows(
[self.client getCompletionStatusOfCheckoutURL:url completion:^(BUYStatus status, NSError *error) {}]
);
}
- (void)testMerchantId
......@@ -196,23 +190,15 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testCheckoutWithApplePayToken
{
__block int callbackCount = 0;
[self.client completeCheckout:nil withApplePayToken:[PKPaymentToken new] completion:^(BUYCheckout *checkout, NSError *error) {
callbackCount++;
XCTAssertEqual(error.code, BUYShopifyError_InvalidCheckoutObject);
}];
id<BUYPaymentToken> token = [[BUYApplePayToken alloc] initWithPaymentToken:[BUYApplePayTestToken validToken]];
XCTAssertThrows(
[self.client completeCheckout:[BUYCheckout new] paymentToken:token completion:^(BUYCheckout *checkout, NSError *error) {}]
);
BUYCheckout *checkout = [[BUYCheckout alloc] initWithModelManager:self.client.modelManager JSONDictionary:@{@"token": @"abcdef", @"payment_due": @0}];
[self.client completeCheckout:checkout withApplePayToken:nil completion:^(BUYCheckout *checkout, NSError *error) {
callbackCount++;
XCTAssertEqual(error.code, BUYShopifyError_NoApplePayTokenSpecified);
}];
XCTAssertEqual(callbackCount, 2);
[self testProductsInCollectionWithSortOrderCollectionDefault];
XCTAssertNoThrow(
[self.client completeCheckout:checkout paymentToken:nil completion:^(BUYCheckout *checkout, NSError *error) {}]
);
}
- (void)testQueryItemsConversion
......@@ -227,7 +213,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderCollectionDefault
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCollectionDefault completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCollectionDefault completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -239,7 +225,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderBestSelling
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortBestSelling completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortBestSelling completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -251,7 +237,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderCreatedAscending
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCreatedAscending completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCreatedAscending completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -263,7 +249,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderCreatedDescending
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCreatedDescending completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortCreatedDescending completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -275,7 +261,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderPriceAscending
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortPriceAscending completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortPriceAscending completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -287,7 +273,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderPriceDescending
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortPriceDescending completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortPriceDescending completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -299,7 +285,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderTitleAscending
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortTitleAscending completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortTitleAscending completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......@@ -311,7 +297,7 @@ NSString * const BUYFakeCustomerToken = @"dsfasdgafdg";
- (void)testProductsInCollectionWithSortOrderTitleDescending
{
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortTitleDescending completion:nil];
NSURLSessionDataTask *task = [self.client getProductsPage:1 inCollection:@1 sortOrder:BUYCollectionSortTitleDescending completion:^(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error) {}];
XCTAssertEqualObjects(task.originalRequest.HTTPMethod, @"GET");
XCTAssertEqualObjects(task.originalRequest.URL.scheme, @"https");
XCTAssertEqualObjects(task.originalRequest.URL.host, @"test_shop");
......
//
// BUYCreditCardTokenTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "BUYCreditCardToken.h"
@interface BUYCreditCardTokenTests : XCTestCase
@end
@implementation BUYCreditCardTokenTests
- (void)testInitWithValidSessionID {
BUYCreditCardToken *token = [[BUYCreditCardToken alloc] initWithPaymentSessionID:@"token"];
XCTAssertNotNil(token);
}
- (void)testInitWithInvalidSessionID {
XCTAssertThrows([[BUYCreditCardToken alloc] initWithPaymentSessionID:nil]);
XCTAssertThrows([[BUYCreditCardToken alloc] initWithPaymentSessionID:@""]);
}
- (void)testJSONConversion {
BUYCreditCardToken *token = [[BUYCreditCardToken alloc] initWithPaymentSessionID:@"token"];
NSDictionary *json = @{
@"payment_session_id" : @"token",
};
XCTAssertEqualObjects(token.JSONDictionary, json);
}
@end
......@@ -220,7 +220,7 @@
XCTAssertEqualObjects(_checkout.email, @"test@test.com");
}
- (void)addCreditCardToCheckout
- (id<BUYPaymentToken>)addCreditCardToCheckout
{
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
return [self shouldUseMocks];
......@@ -229,19 +229,23 @@
}];
BUYCreditCard *creditCard = [self creditCard];
__block id<BUYPaymentToken> token = nil;
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
[self.client storeCreditCard:creditCard checkout:_checkout completion:^(BUYCheckout *returnedCheckout, NSString *paymentSessionId, NSError *error) {
[self.client storeCreditCard:creditCard checkout:_checkout completion:^(BUYCheckout *returnedCheckout, id<BUYPaymentToken> paymentToken, NSError *error) {
XCTAssertNil(error);
XCTAssertNotNil(paymentSessionId);
XCTAssertNotNil(paymentToken);
XCTAssertNotNil(returnedCheckout);
_checkout = returnedCheckout;
token = paymentToken;
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:10 handler:^(NSError *error) {
XCTAssertNil(error);
}];
return token;
}
- (BUYCreditCard *)creditCard
......@@ -256,7 +260,7 @@
return creditCard;
}
- (void)completeCheckout
- (void)completeCheckoutWithToken:(id<BUYPaymentToken>)paymentToken
{
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
return [self shouldUseMocks];
......@@ -265,7 +269,7 @@
}];
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
[self.client completeCheckout:_checkout completion:^(BUYCheckout *returnedCheckout, NSError *error) {
[self.client completeCheckout:_checkout paymentToken:paymentToken completion:^(BUYCheckout *returnedCheckout, NSError *error) {
XCTAssertNil(error);
XCTAssertNotNil(returnedCheckout);
......@@ -905,7 +909,7 @@
return [OHHTTPStubsResponse responseWithKey:@"testInvalidIntegrationBadShopUrl_0"];
}];
self.client = [[BUYClient alloc] initWithShopDomain:@"asdfdsasdfdsasdfdsadsfowinfaoinfw.myshopify.com" apiKey:self.apiKey appId:nil];
self.client = [[BUYClient alloc] initWithShopDomain:@"asdfdsasdfdsasdfdsadsfowinfaoinfw.myshopify.com" apiKey:self.apiKey appId:@"88234"];
[self.client createCheckout:_checkout completion:^(BUYCheckout *checkout, NSError *error) {
XCTAssertNotNil(error);
XCTAssertEqualObjects(error.domain, @"shopify");
......@@ -988,8 +992,8 @@
[self createCheckout];
[self fetchShippingRates];
[self updateCheckout];
[self addCreditCardToCheckout];
[self completeCheckout];
[self completeCheckoutWithToken:[self addCreditCardToCheckout]];
[self pollUntilCheckoutIsComplete];
[self verifyCompletedCheckout];
......@@ -1036,8 +1040,9 @@
[self updateCheckout];
//We use a credit card here because we're not generating apple pay tokens in the tests
[self addCreditCardToCheckout];
[self completeCheckout];
id<BUYPaymentToken> token = [self addCreditCardToCheckout];
[self completeCheckoutWithToken:token];
[self pollUntilCheckoutIsComplete];
[self verifyCompletedCheckout];
}
......
......@@ -401,6 +401,21 @@
90F5930B1B0D5F4C0026B382 /* BUYObjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 90F592FF1B0D5F4C0026B382 /* BUYObjectTests.m */; };
9A102D1B1CDD1F960026CC43 /* BUYErrorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A102D1A1CDD1F960026CC43 /* BUYErrorTests.m */; };
9A102D1E1CDD25980026CC43 /* BUYOptionValueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A102D1D1CDD25980026CC43 /* BUYOptionValueTests.m */; };
9A47CEFD1CE39F6000A6D5BA /* BUYCreditCardToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CEFB1CE39F5B00A6D5BA /* BUYCreditCardToken.m */; };
9A47CEFE1CE39F6100A6D5BA /* BUYCreditCardToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CEFB1CE39F5B00A6D5BA /* BUYCreditCardToken.m */; };
9A47CEFF1CE39F6400A6D5BA /* BUYCreditCardToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CEFA1CE39F5B00A6D5BA /* BUYCreditCardToken.h */; };
9A47CF001CE39F6400A6D5BA /* BUYCreditCardToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CEFA1CE39F5B00A6D5BA /* BUYCreditCardToken.h */; };
9A47CF031CE3A24600A6D5BA /* BUYApplePayToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CF011CE3A24600A6D5BA /* BUYApplePayToken.h */; };
9A47CF041CE3A24600A6D5BA /* BUYApplePayToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CF011CE3A24600A6D5BA /* BUYApplePayToken.h */; };
9A47CF051CE3A24600A6D5BA /* BUYApplePayToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CF021CE3A24600A6D5BA /* BUYApplePayToken.m */; };
9A47CF061CE3A24600A6D5BA /* BUYApplePayToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CF021CE3A24600A6D5BA /* BUYApplePayToken.m */; };
9A47CF071CE3ACE000A6D5BA /* BUYPaymentToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CEF81CE39EC200A6D5BA /* BUYPaymentToken.h */; settings = {ATTRIBUTES = (Public, ); }; };
9A47CF081CE3ACE100A6D5BA /* BUYPaymentToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CEF81CE39EC200A6D5BA /* BUYPaymentToken.h */; settings = {ATTRIBUTES = (Public, ); }; };
9A47CF0D1CE4D6C600A6D5BA /* BUYCreditCardTokenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CF0C1CE4D6C600A6D5BA /* BUYCreditCardTokenTests.m */; };
9A47CF0F1CE4D7A800A6D5BA /* BUYApplePayTokenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CF0E1CE4D7A800A6D5BA /* BUYApplePayTokenTests.m */; };
9A47CF201CE50EBB00A6D5BA /* BUYApplePayTestToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A47CF1F1CE50EBB00A6D5BA /* BUYApplePayTestToken.m */; };
9A47CF221CE5112A00A6D5BA /* BUYAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CF211CE5112A00A6D5BA /* BUYAssert.h */; };
9A47CF231CE5112A00A6D5BA /* BUYAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A47CF211CE5112A00A6D5BA /* BUYAssert.h */; };
9A6B03791CDA5D4F0054C26E /* BUYAccountCredentialsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A6B03781CDA5D4F0054C26E /* BUYAccountCredentialsTests.m */; };
BE10079B1B6165EC0031CEE7 /* BUYOptionValueCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1007991B6165EC0031CEE7 /* BUYOptionValueCell.h */; };
BE10079C1B6165EC0031CEE7 /* BUYOptionValueCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BE10079A1B6165EC0031CEE7 /* BUYOptionValueCell.m */; };
......@@ -737,6 +752,16 @@
90FC31A71B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewHeaderBackgroundImageView.m; path = "Product View/BUYProductViewHeaderBackgroundImageView.m"; sourceTree = "<group>"; };
9A102D1A1CDD1F960026CC43 /* BUYErrorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYErrorTests.m; sourceTree = "<group>"; };
9A102D1D1CDD25980026CC43 /* BUYOptionValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYOptionValueTests.m; sourceTree = "<group>"; };
9A47CEF81CE39EC200A6D5BA /* BUYPaymentToken.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BUYPaymentToken.h; sourceTree = "<group>"; };
9A47CEFA1CE39F5B00A6D5BA /* BUYCreditCardToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCreditCardToken.h; sourceTree = "<group>"; };
9A47CEFB1CE39F5B00A6D5BA /* BUYCreditCardToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCreditCardToken.m; sourceTree = "<group>"; };
9A47CF011CE3A24600A6D5BA /* BUYApplePayToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYApplePayToken.h; sourceTree = "<group>"; };
9A47CF021CE3A24600A6D5BA /* BUYApplePayToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYApplePayToken.m; sourceTree = "<group>"; };
9A47CF0C1CE4D6C600A6D5BA /* BUYCreditCardTokenTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCreditCardTokenTests.m; sourceTree = "<group>"; };
9A47CF0E1CE4D7A800A6D5BA /* BUYApplePayTokenTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYApplePayTokenTests.m; sourceTree = "<group>"; };
9A47CF1E1CE50EBB00A6D5BA /* BUYApplePayTestToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYApplePayTestToken.h; sourceTree = "<group>"; };
9A47CF1F1CE50EBB00A6D5BA /* BUYApplePayTestToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYApplePayTestToken.m; sourceTree = "<group>"; };
9A47CF211CE5112A00A6D5BA /* BUYAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYAssert.h; path = ../Additions/BUYAssert.h; sourceTree = "<group>"; };
9A6B03781CDA5D4F0054C26E /* BUYAccountCredentialsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYAccountCredentialsTests.m; sourceTree = "<group>"; };
BE1007991B6165EC0031CEE7 /* BUYOptionValueCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYOptionValueCell.h; sourceTree = "<group>"; };
BE10079A1B6165EC0031CEE7 /* BUYOptionValueCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYOptionValueCell.m; sourceTree = "<group>"; };
......@@ -963,6 +988,7 @@
children = (
84980F281CB75AC200CFAB58 /* BUYObjectProtocol.h */,
84980F2B1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h */,
9A47CEF81CE39EC200A6D5BA /* BUYPaymentToken.h */,
);
name = Protocols;
sourceTree = "<group>";
......@@ -1010,6 +1036,8 @@
90F592ED1B0D5EFE0026B382 /* Mobile Buy SDK Tests */ = {
isa = PBXGroup;
children = (
9A47CF1D1CE50EAB00A6D5BA /* Test Objects */,
9A47CF0B1CE4D6A500A6D5BA /* Payment Session Providers */,
9A102D1C1CDD257D0026CC43 /* Models Tests */,
90F592F91B0D5F4C0026B382 /* BUYApplePayAdditionsTest.m */,
8491102E1CCE708900E53B93 /* BUYArrayAdditionsTests.m */,
......@@ -1131,6 +1159,35 @@
name = "Models Tests";
sourceTree = "<group>";
};
9A47CEF91CE39F1F00A6D5BA /* Payment Session Providers */ = {
isa = PBXGroup;
children = (
9A47CEFA1CE39F5B00A6D5BA /* BUYCreditCardToken.h */,
9A47CEFB1CE39F5B00A6D5BA /* BUYCreditCardToken.m */,
9A47CF011CE3A24600A6D5BA /* BUYApplePayToken.h */,
9A47CF021CE3A24600A6D5BA /* BUYApplePayToken.m */,
);
name = "Payment Session Providers";
sourceTree = "<group>";
};
9A47CF0B1CE4D6A500A6D5BA /* Payment Session Providers */ = {
isa = PBXGroup;
children = (
9A47CF0C1CE4D6C600A6D5BA /* BUYCreditCardTokenTests.m */,
9A47CF0E1CE4D7A800A6D5BA /* BUYApplePayTokenTests.m */,
);
name = "Payment Session Providers";
sourceTree = "<group>";
};
9A47CF1D1CE50EAB00A6D5BA /* Test Objects */ = {
isa = PBXGroup;
children = (
9A47CF1E1CE50EBB00A6D5BA /* BUYApplePayTestToken.h */,
9A47CF1F1CE50EBB00A6D5BA /* BUYApplePayTestToken.m */,
);
name = "Test Objects";
sourceTree = "<group>";
};
BE1007981B6165CD0031CEE7 /* Cells */ = {
isa = PBXGroup;
children = (
......@@ -1216,6 +1273,7 @@
F76CFF1E19CB7C500079C703 /* BUYSerializable.h */,
84B0A71F1CDD261100253EB0 /* BUYSerializable.m */,
84D915561CC040C300D334FB /* Mobile Buy SDK.xcdatamodeld */,
9A47CEF91CE39F1F00A6D5BA /* Payment Session Providers */,
841ADE2B1CB6F320000004B0 /* Persistent */,
84980F271CB75A7A00CFAB58 /* Protocols */,
841ADE2A1CB6F31C000004B0 /* Transient */,
......@@ -1227,6 +1285,7 @@
F773744519C779C20039681C /* Utils */ = {
isa = PBXGroup;
children = (
9A47CF211CE5112A00A6D5BA /* BUYAssert.h */,
F70CE40D1A8BF1D90055BEB8 /* BUYApplePayAdditions.h */,
F70CE40E1A8BF1D90055BEB8 /* BUYApplePayAdditions.m */,
BE33B4ED1B15FF4D0067982B /* BUYApplePayHelpers.h */,
......@@ -1313,6 +1372,7 @@
84DD12AD1CC63FE600A2442D /* _BUYProductVariant.h in Headers */,
84980F2A1CB75AC200CFAB58 /* BUYObjectProtocol.h in Headers */,
901931281BC5B9BC00D1134E /* BUYApplePayHelpers.h in Headers */,
9A47CF231CE5112A00A6D5BA /* BUYAssert.h in Headers */,
901931291BC5B9BC00D1134E /* BUYStoreViewController.h in Headers */,
9019312A1BC5B9BC00D1134E /* BUYCreditCard.h in Headers */,
9019312B1BC5B9BC00D1134E /* BUYOption.h in Headers */,
......@@ -1323,6 +1383,7 @@
9019312F1BC5B9BC00D1134E /* BUYLineItem.h in Headers */,
90C856B51BD6B0F300936926 /* Buy.h in Headers */,
8498DCAB1CDD1B2600BD12A8 /* BUYShopifyErrorCodes.h in Headers */,
9A47CF071CE3ACE000A6D5BA /* BUYPaymentToken.h in Headers */,
901931311BC5B9BC00D1134E /* BUYProductViewHeaderOverlay.h in Headers */,
901931341BC5B9BC00D1134E /* BUYViewController.h in Headers */,
901931351BC5B9BC00D1134E /* BUYDiscount.h in Headers */,
......@@ -1359,6 +1420,7 @@
841ADE101CB6C942000004B0 /* NSDictionary+BUYAdditions.h in Headers */,
841ADE1C1CB6C942000004B0 /* NSString+BUYAdditions.h in Headers */,
841ADE181CB6C942000004B0 /* NSRegularExpression+BUYAdditions.h in Headers */,
9A47CEFF1CE39F6400A6D5BA /* BUYCreditCardToken.h in Headers */,
841ADE0C1CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.h in Headers */,
84980F331CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */,
901931491BC5B9BC00D1134E /* BUYGiftCard.h in Headers */,
......@@ -1397,6 +1459,7 @@
901931681BC5B9BC00D1134E /* BUYProductViewController.h in Headers */,
901931691BC5B9BC00D1134E /* BUYProduct.h in Headers */,
9019316A1BC5B9BC00D1134E /* BUYSerializable.h in Headers */,
9A47CF041CE3A24600A6D5BA /* BUYApplePayToken.h in Headers */,
9019316B1BC5B9BC00D1134E /* BUYProductVariant.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -1427,6 +1490,7 @@
84DD128B1CC63FE600A2442D /* _BUYLineItem.h in Headers */,
84980F291CB75AC200CFAB58 /* BUYObjectProtocol.h in Headers */,
BE9A64741B503D2E0033E558 /* BUYApplePayHelpers.h in Headers */,
9A47CF221CE5112A00A6D5BA /* BUYAssert.h in Headers */,
BE9A647E1B503D930033E558 /* BUYStoreViewController.h in Headers */,
BE9A64551B503CC50033E558 /* BUYCreditCard.h in Headers */,
BE9A645F1B503CE90033E558 /* BUYOption.h in Headers */,
......@@ -1437,6 +1501,7 @@
BE9A645B1B503CDC0033E558 /* BUYLineItem.h in Headers */,
907874991B7276BA0023775B /* BUYProductViewHeaderOverlay.h in Headers */,
8498DCAA1CDD1B2500BD12A8 /* BUYShopifyErrorCodes.h in Headers */,
9A47CF081CE3ACE100A6D5BA /* BUYPaymentToken.h in Headers */,
BE9A64801B503D990033E558 /* BUYViewController.h in Headers */,
BE9A644F1B503CA90033E558 /* BUYDiscount.h in Headers */,
900396AC1B627CB900226B73 /* BUYProductView.h in Headers */,
......@@ -1473,6 +1538,7 @@
841ADDFF1CB6C942000004B0 /* NSArray+BUYAdditions.h in Headers */,
841ADE1B1CB6C942000004B0 /* NSString+BUYAdditions.h in Headers */,
841ADE171CB6C942000004B0 /* NSRegularExpression+BUYAdditions.h in Headers */,
9A47CF001CE39F6400A6D5BA /* BUYCreditCardToken.h in Headers */,
841ADE0B1CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.h in Headers */,
84980F321CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */,
BE9A64571B503CCC0033E558 /* BUYGiftCard.h in Headers */,
......@@ -1511,6 +1577,7 @@
BEB74A2D1B554E870005A300 /* BUYProductViewController.h in Headers */,
BE9A64611B503CEF0033E558 /* BUYProduct.h in Headers */,
BE9A64651B503CFE0033E558 /* BUYSerializable.h in Headers */,
9A47CF031CE3A24600A6D5BA /* BUYApplePayToken.h in Headers */,
BE9A64631B503CF70033E558 /* BUYProductVariant.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -1731,6 +1798,7 @@
901930ED1BC5B9BC00D1134E /* BUYProductViewHeader.m in Sources */,
901930EE1BC5B9BC00D1134E /* BUYNavigationController.m in Sources */,
901930EF1BC5B9BC00D1134E /* BUYVariantSelectionViewController.m in Sources */,
9A47CEFE1CE39F6100A6D5BA /* BUYCreditCardToken.m in Sources */,
901930F21BC5B9BC00D1134E /* BUYOrder.m in Sources */,
901930F41BC5B9BC00D1134E /* BUYProductViewHeaderBackgroundImageView.m in Sources */,
901930F51BC5B9BC00D1134E /* BUYProductViewHeaderOverlay.m in Sources */,
......@@ -1764,6 +1832,7 @@
84DD12C21CC63FEE00A2442D /* _BUYCheckout.m in Sources */,
901931091BC5B9BC00D1134E /* BUYCart.m in Sources */,
9019310A1BC5B9BC00D1134E /* BUYPaymentButton.m in Sources */,
9A47CF061CE3A24600A6D5BA /* BUYApplePayToken.m in Sources */,
84D915521CC03F1600D334FB /* BUYModelManager.m in Sources */,
84DD129C1CC63FE600A2442D /* _BUYCartLineItem.m in Sources */,
841ADE121CB6C942000004B0 /* NSDictionary+BUYAdditions.m in Sources */,
......@@ -1830,9 +1899,11 @@
90F5930A1B0D5F4C0026B382 /* BUYLineItemTest.m in Sources */,
8498DCCA1CDD208200BD12A8 /* BUYCollectionTests.m in Sources */,
849110321CCE708900E53B93 /* BUYRegularExpressionAdditionsTests.m in Sources */,
9A47CF201CE50EBB00A6D5BA /* BUYApplePayTestToken.m in Sources */,
90F593061B0D5F4C0026B382 /* BUYCartTest.m in Sources */,
90F593051B0D5F4C0026B382 /* BUYApplePayAdditionsTest.m in Sources */,
8498DCC91CDD208200BD12A8 /* BUYClientTest_Customer.m in Sources */,
9A47CF0D1CE4D6C600A6D5BA /* BUYCreditCardTokenTests.m in Sources */,
90F593071B0D5F4C0026B382 /* BUYCheckoutTest.m in Sources */,
90F593091B0D5F4C0026B382 /* BUYClientTest.m in Sources */,
90F5930B1B0D5F4C0026B382 /* BUYObjectTests.m in Sources */,
......@@ -1840,6 +1911,7 @@
9A102D1B1CDD1F960026CC43 /* BUYErrorTests.m in Sources */,
90F593081B0D5F4C0026B382 /* BUYClientTest_Storefront.m in Sources */,
90BBCD731B87B6BA00FCCE51 /* BUYPKContact.m in Sources */,
9A47CF0F1CE4D7A800A6D5BA /* BUYApplePayTokenTests.m in Sources */,
849110331CCE708900E53B93 /* BUYStringAdditionsTests.m in Sources */,
906CF1B11B8B66AE001F7D5B /* BUYCNPostalAddress.m in Sources */,
8498DCD01CDD208200BD12A8 /* TestModel.m in Sources */,
......@@ -1881,6 +1953,7 @@
BEB74A741B5564380005A300 /* BUYProductViewHeader.m in Sources */,
BEB74A681B55640F0005A300 /* BUYNavigationController.m in Sources */,
BEB74A7E1B5564890005A300 /* BUYVariantSelectionViewController.m in Sources */,
9A47CEFD1CE39F6000A6D5BA /* BUYCreditCardToken.m in Sources */,
90E83BC51B9F550E00C95A1B /* BUYOrder.m in Sources */,
BEB74A761B55643E0005A300 /* BUYProductViewHeaderBackgroundImageView.m in Sources */,
9078749A1B7276BA0023775B /* BUYProductViewHeaderOverlay.m in Sources */,
......@@ -1914,6 +1987,7 @@
84DD12B41CC63FEE00A2442D /* _BUYCheckout.m in Sources */,
BE9A644A1B503C980033E558 /* BUYCart.m in Sources */,
BE9A64831B503DB10033E558 /* BUYPaymentButton.m in Sources */,
9A47CF051CE3A24600A6D5BA /* BUYApplePayToken.m in Sources */,
84D915511CC03F1600D334FB /* BUYModelManager.m in Sources */,
84DD12841CC63FE600A2442D /* _BUYCartLineItem.m in Sources */,
841ADE111CB6C942000004B0 /* NSDictionary+BUYAdditions.m in Sources */,
......
//
// BUYAssert.h
// Mobile Buy SDK
//
// Created by Dima Bart on 2016-05-12.
// Copyright © 2016 Shopify Inc. All rights reserved.
//
#define BUYAssert(exp, ...) \
do { \
if (!(exp)) { \
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:__VA_ARGS__] userInfo:nil]; \
} \
} while(0)
......@@ -24,6 +24,7 @@
// THE SOFTWARE.
//
#import "BUYAssert.h"
#import "NSEntityDescription+BUYAdditions.h"
#import "BUYModelManagerProtocol.h"
......@@ -127,7 +128,7 @@
- (NSDictionary *)buy_JSONForObject:(NSObject<BUYObject> *)object
{
NSAssert([self isEqual:[object entity]], @"%@ entity cannot decode %@ objects", self.name, [object entity].name);
BUYAssert([self isEqual:[object entity]], @"%@ entity cannot decode %@ objects", self.name, [object entity].name);
// The encoding map is a block which converts property names into JSON keys.
BUYStringMap encodingMap = self.JSONKeyEncodingMap;
......@@ -158,7 +159,7 @@
- (void)buy_updateObject:(NSObject<BUYObject> *)object withJSON:(NSDictionary *)JSON
{
NSAssert([self isEqual:[object entity]], @"%@ entity cannot decode %@ objects", self.name, [object entity].name);
BUYAssert([self isEqual:[object entity]], @"%@ entity cannot decode %@ objects", self.name, [object entity].name);
NSDictionary *properties = self.propertiesByName;
// The decoding map is a block which converts the key in the JSON into a property name.
......
......@@ -24,6 +24,7 @@
// THE SOFTWARE.
//
#import "BUYAssert.h"
#import "NSString+BUYAdditions.h"
#import "NSArray+BUYAdditions.h"
#import "NSRegularExpression+BUYAdditions.h"
......@@ -140,7 +141,7 @@ static NSSet *acronyms;
- (NSString *)buy_reversedString
{
NSAssert([self canBeConvertedToEncoding:NSUTF8StringEncoding], @"Unable to reverse string; requires a string that can be encoded in UTF8");
BUYAssert([self canBeConvertedToEncoding:NSUTF8StringEncoding], @"Unable to reverse string; requires a string that can be encoded in UTF8");
const char *str = [self UTF8String];
unsigned long len = strlen(str);
......
......@@ -68,6 +68,7 @@ FOUNDATION_EXPORT const unsigned char BuyVersionString[];
#import <Buy/BUYObserver.h>
#import <Buy/BUYShopifyErrorCodes.h>
#import <Buy/BUYPaymentToken.h>
#import <Buy/BUYPaymentButton.h>
#import <Buy/BUYProductViewController.h>
#import <Buy/BUYStoreViewController.h>
......
......@@ -120,7 +120,7 @@
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (!error) {
error = [self extractErrorFromResponse:response json:json];
error = [self errorFromJSON:json response:response];
}
block(statusCode, error);
......@@ -132,7 +132,7 @@
if (self.customerToken) {
NSURLComponents *components = [self URLComponentsForTokenRenewalWithID:customerID];
return [self putRequestForURL:components.URL body:nil completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self putRequestForURL:components.URL object:nil completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSString *accessToken = nil;
if (json && !error) {
......@@ -141,7 +141,7 @@
}
if (!error) {
error = [self extractErrorFromResponse:response json:json];
error = [self errorFromJSON:json response:response];
}
block(accessToken, error);
......@@ -156,9 +156,8 @@
- (NSURLSessionDataTask *)activateCustomerWithCredentials:(BUYAccountCredentials *)credentials customerID:(NSString *)customerID customerToken:(NSString *)customerToken callback:(BUYDataCustomerTokenBlock)block
{
NSURLComponents *components = [self URLComponentsForCustomerActivationWithID:customerID customerToken:customerToken];
NSData *data = [NSJSONSerialization dataWithJSONObject:credentials.JSONRepresentation options:0 error:nil];
return [self putRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self putRequestForURL:components.URL object:credentials.JSONRepresentation completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSString *email = json[@"customer"][@"email"];
if (email && !error) {
BUYAccountCredentialItem *emailItem = [BUYAccountCredentialItem itemWithEmail:email];
......@@ -173,9 +172,8 @@
- (NSURLSessionDataTask *)resetPasswordWithCredentials:(BUYAccountCredentials *)credentials customerID:(NSString *)customerID customerToken:(NSString *)customerToken callback:(BUYDataCustomerTokenBlock)block
{
NSURLComponents *components = [self URLComponentsForCustomerPasswordResetWithCustomerID:customerID customerToken:customerToken];
NSData *data = [NSJSONSerialization dataWithJSONObject:credentials.JSONRepresentation options:0 error:nil];
return [self putRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self putRequestForURL:components.URL object:credentials.JSONRepresentation completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSString *email = json[@"customer"][@"email"];
if (email && !error) {
BUYAccountCredentialItem *emailItem = [BUYAccountCredentialItem itemWithEmail:email];
......
......@@ -26,8 +26,6 @@
@import Foundation;
@class PKPaymentToken;
@class BUYAccountCredentials;
@class BUYCart;
@class BUYCheckout;
......@@ -40,6 +38,8 @@
@class BUYOrder;
@class BUYModelManager;
@protocol BUYPaymentToken;
/**
* The sort order for products in a collection
*/
......@@ -78,9 +78,9 @@ typedef NS_ENUM(NSUInteger, BUYCollectionSort) {
BUYCollectionSortCreatedDescending
};
extern NSString * const BUYVersionString;
extern NSString * _Nonnull const BUYVersionString;
extern NSString * const BUYClientCustomerAccessToken;
extern NSString * _Nonnull const BUYClientCustomerAccessToken;
/**
* A BUYStatus is associated with the completion of an enqueued job on Shopify.
......@@ -114,13 +114,13 @@ typedef NS_ENUM(NSUInteger, BUYStatus) {
};
/**
* Return block containing a BUYCheckout, Payment Session ID and/or an NSError
* Return block containing a BUYCheckout, id<BUYPaymentToken> and/or an NSError
*
* @param checkout The returned BUYCheckout
* @param paymentSessionId The Payment Session ID associated with a credit card transaction
* @param paymentToken An opaque payment token type that wraps necessary credentials for payment
* @param error Optional NSError
*/
typedef void (^BUYDataCreditCardBlock)(BUYCheckout *checkout, NSString *paymentSessionId, NSError *error);
typedef void (^BUYDataCreditCardBlock)(BUYCheckout * _Nullable checkout, id<BUYPaymentToken> _Nullable paymentToken, NSError * _Nullable error);
/**
* Return block containing a BUYCheckout and/or an NSError
......@@ -128,7 +128,7 @@ typedef void (^BUYDataCreditCardBlock)(BUYCheckout *checkout, NSString *paymentS
* @param checkout The returned BUYCheckout
* @param error Optional NSError
*/
typedef void (^BUYDataCheckoutBlock)(BUYCheckout *checkout, NSError *error);
typedef void (^BUYDataCheckoutBlock)(BUYCheckout * _Nullable checkout, NSError * _Nullable error);
/**
* Return block containing a BUYCheckout, a BUYStatus and/or an NSError
......@@ -136,7 +136,7 @@ typedef void (^BUYDataCheckoutBlock)(BUYCheckout *checkout, NSError *error);
* @param status A BUYStatus specifying the requested job's completion status
* @param error Optional NSError
*/
typedef void (^BUYDataCheckoutStatusBlock)(BUYStatus status, NSError *error);
typedef void (^BUYDataCheckoutStatusBlock)(BUYStatus status, NSError * _Nullable error);
/**
* Return block containing BUYShippingRate objects, a BUYStatus and/or an NSError
......@@ -145,7 +145,7 @@ typedef void (^BUYDataCheckoutStatusBlock)(BUYStatus status, NSError *error);
* @param status A BUYStatus specifying the requested job's completion status
* @param error Optional NSError
*/
typedef void (^BUYDataShippingRatesBlock)(NSArray *shippingRates, BUYStatus status, NSError *error);
typedef void (^BUYDataShippingRatesBlock)(NSArray * _Nullable shippingRates, BUYStatus status, NSError * _Nullable error);
/**
* Return block containing a BUYShop and/or an NSError
......@@ -153,7 +153,7 @@ typedef void (^BUYDataShippingRatesBlock)(NSArray *shippingRates, BUYStatus stat
* @param shop A BUYShop object
* @param error Optional NSError
*/
typedef void (^BUYDataShopBlock)(BUYShop *shop, NSError *error);
typedef void (^BUYDataShopBlock)(BUYShop * _Nullable shop, NSError * _Nullable error);
/**
* Return block containing a list of BUYCollection objects and/or an NSError
......@@ -161,7 +161,7 @@ typedef void (^BUYDataShopBlock)(BUYShop *shop, NSError *error);
* @param collections An array of BUYCollection objects
* @param error Optional NSError
*/
typedef void (^BUYDataCollectionsBlock)(NSArray<BUYCollection *> *collections, NSError *error);
typedef void (^BUYDataCollectionsBlock)(NSArray<BUYCollection *> * _Nullable collections, NSError * _Nullable error);
/**
* Return block containing a BUYProduct and/or an NSError
......@@ -169,7 +169,7 @@ typedef void (^BUYDataCollectionsBlock)(NSArray<BUYCollection *> *collections, N
* @param product A BUYProduct
* @param error Optional NSError
*/
typedef void (^BUYDataProductBlock)(BUYProduct *product, NSError *error);
typedef void (^BUYDataProductBlock)(BUYProduct * _Nullable product, NSError * _Nullable error);
/**
* Return block containing a list of BUYProduct objects and/or an NSError
......@@ -177,7 +177,7 @@ typedef void (^BUYDataProductBlock)(BUYProduct *product, NSError *error);
* @param products An array of BUYProduct objects
* @param error Optional NSError
*/
typedef void (^BUYDataProductsBlock)(NSArray<BUYProduct *> *products, NSError *error);
typedef void (^BUYDataProductsBlock)(NSArray<BUYProduct *> * _Nullable products, NSError * _Nullable error);
/**
* Return block containing list of collections
......@@ -185,7 +185,7 @@ typedef void (^BUYDataProductsBlock)(NSArray<BUYProduct *> *products, NSError *e
* @param collections An array of BUYCollection objects
* @param error Optional NSError
*/
typedef void (^BUYDataCollectionsListBlock)(NSArray<BUYCollection *> *collections, NSUInteger page, BOOL reachedEnd, NSError *error);
typedef void (^BUYDataCollectionsListBlock)(NSArray<BUYCollection *> * _Nullable collections, NSUInteger page, BOOL reachedEnd, NSError * _Nullable error);
/**
* Return block containing a list of BUYProduct objects, the page requested, a boolean to determine whether the end of the list has been reach and/or an optional NSError
......@@ -195,7 +195,7 @@ typedef void (^BUYDataCollectionsListBlock)(NSArray<BUYCollection *> *collection
* @param reachedEnd Boolean indicating whether additional pages exist
* @param error An optional NSError
*/
typedef void (^BUYDataProductListBlock)(NSArray<BUYProduct *> *products, NSUInteger page, BOOL reachedEnd, NSError *error);
typedef void (^BUYDataProductListBlock)(NSArray<BUYProduct *> * _Nullable products, NSUInteger page, BOOL reachedEnd, NSError * _Nullable error);
/**
* Return block containing a list of BUYProductImage objects and/or an NSError
......@@ -203,7 +203,7 @@ typedef void (^BUYDataProductListBlock)(NSArray<BUYProduct *> *products, NSUInte
* @param images An array of BUYProductImage objects
* @param error An optional NSError
*/
typedef void (^BUYDataImagesListBlock)(NSArray *images, NSError *error);
typedef void (^BUYDataImagesListBlock)(NSArray * _Nullable images, NSError * _Nullable error);
/**
* Return block containing a BUYGiftCard
......@@ -211,7 +211,7 @@ typedef void (^BUYDataImagesListBlock)(NSArray *images, NSError *error);
* @param giftCard A BUYGiftCard
* @param error An optional NSError
*/
typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
typedef void (^BUYDataGiftCardBlock)(BUYGiftCard * _Nullable giftCard, NSError * _Nullable error);
/**
The BUYDataClient provides all requests needed to perform request on the Shopify Checkout API.
......@@ -219,6 +219,7 @@ typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
and completing Checkouts.
*/
@interface BUYClient : NSObject
NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
......@@ -236,13 +237,13 @@ typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
/**
*
*/
@property (nonatomic, strong) BUYModelManager *modelManager;
@property (nonatomic, strong, nonnull) BUYModelManager *modelManager;
/**
* Queue where callbacks will be called
* defaults to main queue
*/
@property (nonatomic, strong) dispatch_queue_t queue;
@property (nonatomic, strong, nonnull) dispatch_queue_t queue;
/**
* The page size for any paged request. This can range from 1-250. Default is 25
......@@ -252,39 +253,39 @@ typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
/**
* The shop domain set using the initializer
*/
@property (nonatomic, strong, readonly) NSString *shopDomain;
@property (nonatomic, strong, readonly, nonnull) NSString *shopDomain;
/**
* The API Key set using the initializer
*/
@property (nonatomic, strong, readonly) NSString *apiKey;
@property (nonatomic, strong, readonly, nonnull) NSString *apiKey;
/**
* The Channel ID set using the initializer
*/
@property (nonatomic, strong, readonly) NSString *appId;
@property (nonatomic, strong, readonly, nonnull) NSString *appId;
/**
* The Merchant ID is used for Apple Pay and set using `enableApplePayWithMerchantId:`
*/
@property (nonatomic, strong, readonly) NSString *merchantId NS_DEPRECATED_IOS(8_0, 9_0, "Set the `merchantId` on a BUYViewController subclass instead");
@property (nonatomic, strong, readonly, nullable) NSString *merchantId NS_DEPRECATED_IOS(8_0, 9_0, "Set the `merchantId` on a BUYViewController subclass instead");
/**
* Application name to attribute orders to. Defaults to app bundle name (CFBundleName)
*/
@property (nonatomic, strong) NSString *applicationName;
@property (nonatomic, strong, nonnull) NSString *applicationName;
/**
* The applications URLScheme, used to return to the application after a complete web checkout. Ex. @"storeApp://"
*/
@property (nonatomic, strong) NSString *urlScheme;
@property (nonatomic, strong, nullable) NSString *urlScheme;
/**
* Allows the client to hold onto the customer token
*
* @param token The token received from the create and login callbacks
*/
@property (strong, nonatomic) NSString *customerToken;
@property (strong, nonatomic, nullable) NSString *customerToken;
#pragma mark - Storefront
......@@ -444,7 +445,7 @@ typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
- (NSURLSessionDataTask *)updateCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block;
/**
* Finalizes the BUYCheckout and charges the credit card.
* Finalizes the BUYCheckout and charges the payment provider (ex: Credit Card, Apple Pay, etc).
* This enqueues a completion job on Shopify and returns immediately.
* You must get the job's status by calling checkCompletionStatusOfCheckout:block
*
......@@ -452,29 +453,12 @@ typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
* We recommended using the BUYCheckout returned in the block.
*
* @param checkout The BUYCheckout to complete
* @param paymentToken Opaque payment token object. May be nil if the total checkout amount is equal to $0.00
* @param block (^BUYDataCheckoutBlock)(BUYCheckout *checkout, NSError *error);
*
* @return The associated NSURLSessionDataTask
*/
- (NSURLSessionDataTask *)completeCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block;
/**
*/
/**
* Finalizes the checkout and charges the credit card associated with the payment token from PassKit (Apple Pay).
* This only enqueues a completion job, and will return immediately.
* You must get the job's status by calling checkCompletionStatusOfCheckout:block
*
* Note: There's no guarantee that the BUYCheckout returned will be the same as the one that is passed in.
* We recommended using the BUYCheckout returned in the block.
*
* @param checkout The BUYCheckout to complete
* @param token The PKPaymentToken
* @param block (^BUYDataCheckoutBlock)(BUYCheckout *checkout, NSError *error);
*
* @return The associated NSURLSessionDataTask
*/
- (NSURLSessionDataTask *)completeCheckout:(BUYCheckout *)checkout withApplePayToken:(PKPaymentToken *)token completion:(BUYDataCheckoutBlock)block;
- (NSURLSessionDataTask *)completeCheckout:(BUYCheckout *)checkout paymentToken:(_Nullable id<BUYPaymentToken>)paymentToken completion:(BUYDataCheckoutBlock)block;
/**
* Retrieve the status of a BUYCheckout. This checks the status of the current payment processing job for the provided checkout.
......@@ -551,4 +535,5 @@ typedef void (^BUYDataGiftCardBlock)(BUYGiftCard *giftCard, NSError *error);
*/
- (void)enableApplePayWithMerchantId:(NSString *)merchantId NS_DEPRECATED_IOS(8_0, 9_0, "Set the merchantId on a `BUYViewController` subclass instead");
NS_ASSUME_NONNULL_END
@end
......@@ -26,16 +26,19 @@
#import "BUYClient_Internal.h"
#import "BUYAssert.h"
#import "BUYAddress.h"
#import "BUYCart.h"
#import "BUYCheckout.h"
#import "BUYCreditCard.h"
#import "BUYCreditCardToken.h"
#import "BUYCollection.h"
#import "BUYError.h"
#import "BUYGiftCard.h"
#import "BUYModelManager.h"
#import "BUYOrder.h"
#import "BUYProduct.h"
#import "BUYPaymentToken.h"
#import "BUYShippingRate.h"
#import "BUYShop.h"
#import "BUYShopifyErrorCodes.h"
......@@ -43,10 +46,6 @@
#import "NSDictionary+BUYAdditions.h"
#import "NSURLComponents+BUYAdditions.h"
#if __has_include(<PassKit/PassKit.h>)
@import PassKit;
#endif
#define kGET @"GET"
#define kPOST @"POST"
#define kPATCH @"PATCH"
......@@ -57,6 +56,8 @@
#define kMinSuccessfulStatusCode 200
#define kMaxSuccessfulStatusCode 299
#define BUYAssertCheckout(checkout) BUYAssert([(checkout) hasToken], @"Checkout assertion failed. Checkout must have a valid token associated with it.")
NSString * const BUYVersionString = @"1.3";
NSString *const kShopifyError = @"shopify";
......@@ -79,14 +80,18 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
@implementation BUYClient
- (instancetype)init { return nil; }
#pragma mark - Init
- (instancetype)init {
BUYAssert(NO, @"BUYClient must be initialized using the designated initializer.");
return nil;
}
- (instancetype)initWithShopDomain:(NSString *)shopDomain apiKey:(NSString *)apiKey appId:(NSString *)appId
{
if (shopDomain.length == 0) {
NSException *exception = [NSException exceptionWithName:@"Bad shop domain" reason:@"Please ensure you initialize with a shop domain" userInfo:nil];
@throw exception;
}
BUYAssert(shopDomain.length > 0, @"Bad shop domain. Please ensure you initialize with a shop domain.");
BUYAssert(apiKey.length > 0, @"Bad API key. Please ensure you initialize with a valid API key.");
BUYAssert(appId.length > 0, @"Bad app ID. Please ensure you initialize with a valid App ID.");
self = [super init];
if (self) {
......@@ -141,8 +146,10 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getProductsPage:(NSUInteger)page completion:(BUYDataProductListBlock)block
{
NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathProductPublications
queryItems:@{@"limit" : [NSString stringWithFormat:@"%lu", (unsigned long)self.pageSize],
@"page" : [NSString stringWithFormat:@"%lu", (unsigned long)page]}];
queryItems:@{
@"limit" : @(self.pageSize).stringValue,
@"page" : @(page).stringValue,
}];
return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
......@@ -156,6 +163,8 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getProductById:(NSString *)productId completion:(BUYDataProductBlock)block;
{
BUYAssert(productId, @"Failed to get product by ID. Product ID must not be nil.");
return [self getProductsByIds:@[productId] completion:^(NSArray *products, NSError *error) {
if (products.count > 0) {
block(products[0], error);
......@@ -170,8 +179,12 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getProductsByIds:(NSArray *)productIds completion:(BUYDataProductsBlock)block
{
BUYAssert(productIds, @"Failed to get product by IDs. Product IDs array must not be nil.");
NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathProductPublications
queryItems:@{@"product_ids" : [productIds componentsJoinedByString:@","]}];
queryItems:@{
@"product_ids" : [productIds componentsJoinedByString:@","]
}];
return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
......@@ -196,8 +209,10 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getCollectionsPage:(NSUInteger)page completion:(BUYDataCollectionsListBlock)block
{
NSURLComponents *components = [self URLComponentsForChannelsAppendingPath:kBUYClientPathCollectionPublications
queryItems:@{@"limit" : [NSString stringWithFormat:@"%lu", (unsigned long)self.pageSize],
@"page" : [NSString stringWithFormat:@"%lu", (unsigned long)page]}];
queryItems:@{
@"limit" : @(self.pageSize).stringValue,
@"page" : @(page).stringValue,
}];
return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSArray *collections = nil;
......@@ -215,15 +230,17 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getProductsPage:(NSUInteger)page inCollection:(NSNumber *)collectionId sortOrder:(BUYCollectionSort)sortOrder completion:(BUYDataProductListBlock)block
{
NSURLSessionDataTask *task = nil;
if (collectionId) {
BUYAssert(collectionId, @"Failed to get products page. Invalid collectionID.");
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]}];
queryItems:@{
@"collection_id" : collectionId.stringValue,
@"limit" : @(self.pageSize).stringValue,
@"page" : @(page).stringValue,
@"sort_by" : [BUYCollection sortOrderParameterForCollectionSort:sortOrder]
}];
task = [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSArray *products = nil;
if (json && !error) {
......@@ -231,24 +248,6 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
}
block(products, page, [self hasReachedEndOfPage:products] || error, error);
}];
}
else {
block(nil, 0, NO, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_NoCollectionIdSpecified userInfo:nil]);
}
return task;
}
#pragma mark - Helpers
- (NSError *)extractErrorFromResponse:(NSURLResponse *)response json:(NSDictionary *)json
{
NSError *error = nil;
NSInteger statusCode = [((NSHTTPURLResponse *) response) statusCode];
if (statusCode < kMinSuccessfulStatusCode || statusCode > kMaxSuccessfulStatusCode) {
error = [NSError errorWithDomain:NSURLErrorDomain code:statusCode userInfo:json];
}
return error;
}
#pragma mark - URL Components
......@@ -316,6 +315,8 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)createCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
{
BUYAssert(checkout, @"Failed to create checkout. Invalid checkout object.");
// Inject channel and marketing attributions
[self configureCheckout:checkout];
......@@ -325,6 +326,7 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)createCheckoutWithCartToken:(NSString *)cartToken completion:(BUYDataCheckoutBlock)block
{
BUYAssert(cartToken, @"Failed to create checkout. Invalid cart token");
BUYCheckout *checkout = [self.modelManager checkoutwithCartToken:cartToken];
[self configureCheckout:checkout];
......@@ -334,65 +336,45 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)postCheckout:(NSDictionary *)checkoutJSON completion:(BUYDataCheckoutBlock)block
{
NSURLSessionDataTask *task = nil;
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:checkoutJSON options:0 error:&error];
if (data && !error) {
NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:nil checkoutToken:nil queryItems:nil];
task = [self postRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self postRequestForURL:components.URL object:checkoutJSON completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
[self handleCheckoutResponse:json error:error block:block];
}];
}
return task;
}
- (NSURLSessionDataTask *)applyGiftCardWithCode:(NSString *)giftCardCode toCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
{
NSURLSessionDataTask *task = nil;
if (giftCardCode.length == 0) {
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_NoGiftCardSpecified userInfo:nil]);
}
else {
BUYAssertCheckout(checkout);
BUYAssert(giftCardCode.length > 0, @"Failed to apply gift card code. Invalid gift card code.");
BUYGiftCard *giftCard = [self.modelManager giftCardWithCode:giftCardCode];
NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"gift_cards"
checkoutToken:checkout.token
queryItems:nil];
task = [self postRequestForURL:components.URL
object:giftCard
completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
if (!error) {
return [self postRequestForURL:components.URL object:giftCard completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
if (json && !error) {
[self updateCheckout:checkout withGiftCardDictionary:json[@"gift_card"] addingGiftCard:YES];
}
block(checkout, error);
}];
}
return task;
}
- (NSURLSessionDataTask *)removeGiftCard:(BUYGiftCard *)giftCard fromCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
{
NSURLSessionDataTask *task = nil;
if (giftCard.identifier) {
BUYAssertCheckout(checkout);
BUYAssert(giftCard.identifier, @"Failed to remove gift card. Gift card must have a valid identifier.");
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) {
return [self deleteRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
if (!error) {
[self updateCheckout:checkout withGiftCardDictionary:json[@"gift_card"] addingGiftCard:NO];
}
block(checkout, error);
}];
}
else {
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_NoGiftCardSpecified userInfo:nil]);
}
return task;
}
- (void)updateCheckout:(BUYCheckout *)checkout withGiftCardDictionary:(NSDictionary *)giftCardDictionary addingGiftCard:(BOOL)addingGiftCard
......@@ -414,6 +396,7 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
{
BUYAssertCheckout(checkout);
NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:nil
checkoutToken:checkout.token
queryItems:nil];
......@@ -424,118 +407,55 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)updateCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
{
NSDictionary *json = [checkout jsonDictionaryForCheckout];
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
BUYAssertCheckout(checkout);
NSURLSessionDataTask *task = nil;
if ([checkout hasToken]) {
NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:nil
checkoutToken:checkout.token
queryItems:nil];
task = [self patchRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self patchRequestForURL:components.URL object:checkout completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
[self handleCheckoutResponse:json error:error block:block];
}];
}
return task;
}
- (NSURLSessionDataTask*)completeCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
- (NSURLSessionDataTask*)completeCheckout:(BUYCheckout *)checkout paymentToken:(id<BUYPaymentToken>)paymentToken completion:(BUYDataCheckoutBlock)block
{
NSURLSessionDataTask *task = nil;
BUYAssertCheckout(checkout);
if ([checkout hasToken]) {
BOOL isFree = (checkout.paymentDue && checkout.paymentDue.floatValue == 0);
NSData *data = nil;
NSError *error = nil;
BUYAssert(paymentToken || isFree, @"Failed to complete checkout. Checkout must have a payment token or have a payment value equal to $0.00");
if (checkout.paymentSessionId.length > 0) {
NSDictionary *paymentJson = @{ @"payment_session_id" : checkout.paymentSessionId };
data = [NSJSONSerialization dataWithJSONObject:paymentJson options:0 error:&error];
}
if ((data && !error) || (checkout.paymentDue && checkout.paymentDue.floatValue == 0)) {
task = [self checkoutCompletionRequestWithCheckout:checkout body:data completion:block];
}
}
else {
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
return task;
}
- (NSURLSessionDataTask *)completeCheckout:(BUYCheckout *)checkout withApplePayToken:(PKPaymentToken *)token completion:(BUYDataCheckoutBlock)block
{
NSURLSessionDataTask *task = nil;
#if __has_include(<PassKit/PassKit.h>)
if ([checkout hasToken] == NO) {
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
else if (!token) {
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_NoApplePayTokenSpecified userInfo:nil]);
}
else {
NSString *tokenString = [[NSString alloc] initWithData:token.paymentData encoding:NSUTF8StringEncoding];
NSDictionary *paymentJson = @{ @"payment_token" : @{ @"payment_data" : tokenString, @"type" : @"apple_pay" }};
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:paymentJson options:0 error:&error];
if (data && !error) {
task = [self checkoutCompletionRequestWithCheckout:checkout body:data completion:block];
}
else {
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
}
#elif
block(nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_NoApplePayTokenSpecified userInfo:nil]);
#endif
return task;
}
- (NSURLSessionDataTask *)checkoutCompletionRequestWithCheckout:(BUYCheckout *)checkout body:(NSData *)body completion:(BUYDataCheckoutBlock)block
{
NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"complete"
checkoutToken:checkout.token
queryItems:nil];
return [self postRequestForURL:components.URL body:body completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self postRequestForURL:components.URL object:[paymentToken JSONDictionary] completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
[self handleCheckoutResponse:json error:error block:block];
}];
}
- (NSURLSessionDataTask *)getCompletionStatusOfCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutStatusBlock)block
{
NSURLSessionDataTask *task = nil;
if ([checkout hasToken]) {
task = [self getCompletionStatusOfCheckoutToken:checkout.token completion:block];
}
else {
block(BUYStatusUnknown, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
return task;
BUYAssertCheckout(checkout);
return [self getCompletionStatusOfCheckoutToken:checkout.token completion:block];
}
- (NSURLSessionDataTask *)getCompletionStatusOfCheckoutURL:(NSURL *)url completion:(BUYDataCheckoutStatusBlock)block
{
NSString *token = nil;
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
for (NSURLQueryItem *item in components.queryItems) {
NSString *token = nil;
for (NSURLQueryItem *item in components.queryItems) {
if ([item.name isEqualToString:@"checkout[token]"]) {
token = item.value;
break;
}
}
if (token) {
BUYAssert(token, @"Failed to get completion status of checkout. Checkout URL must have a valid token associated with it.");
return [self getCompletionStatusOfCheckoutToken:token completion:block];
}
else {
block(BUYStatusUnknown, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
return nil;
}
}
- (NSURLSessionDataTask *)getCompletionStatusOfCheckoutToken:(NSString *)token completion:(BUYDataCheckoutStatusBlock)block
......@@ -553,10 +473,9 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
- (NSURLSessionDataTask *)getShippingRatesForCheckout:(BUYCheckout *)checkout completion:(BUYDataShippingRatesBlock)block
{
NSURLSessionDataTask *task = nil;
if ([checkout hasToken]) {
BUYAssertCheckout(checkout);
NSURLComponents *components = [self URLComponentsForCheckoutsAppendingPath:@"shipping_rates" checkoutToken:checkout.token queryItems:@{ @"checkout" : @"" }];
task = [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
return [self getRequestForURL:components.URL completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSArray *shippingRates = nil;
if (json && !error) {
shippingRates = [self.modelManager insertShippingRatesWithJSONArray:json[@"shipping_rates"]];
......@@ -565,26 +484,15 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
block(shippingRates, [BUYClient statusForStatusCode:statusCode error:error], error);
}];
}
else {
block(nil, BUYStatusUnknown, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
return task;
}
#pragma mark - Payments
- (NSURLSessionDataTask *)storeCreditCard:(BUYCreditCard *)creditCard checkout:(BUYCheckout *)checkout completion:(BUYDataCreditCardBlock)block
- (NSURLSessionDataTask *)storeCreditCard:(BUYCreditCard *)creditCard checkout:(BUYCheckout *)checkout completion:(BUYDataCreditCardBlock)completion
{
NSURLSessionDataTask *task = nil;
BUYAssertCheckout(checkout);
BUYAssert(creditCard, @"Failed to store credit card. No credit card provided.");
if ([checkout hasToken] == NO) {
block(nil, nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
else if (!creditCard) {
block(nil, nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_NoCreditCardSpecified userInfo:nil]);
}
else {
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
json[@"token"] = checkout.token;
json[@"credit_card"] = [creditCard jsonDictionaryForCheckout];
......@@ -592,31 +500,24 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
json[@"billing_address"] = [checkout.billingAddress jsonDictionaryForCheckout];
}
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:@{ @"checkout" : json } options:0 error:&error];
if (data && !error) {
task = [self postPaymentRequestWithCheckout:checkout body:data completion:block];
}
else {
block(nil, nil, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
return [self postRequestForURL:checkout.paymentURL object:@{ @"checkout" : json } completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
id<BUYPaymentToken> token = nil;
if (!error) {
token = [[BUYCreditCardToken alloc] initWithPaymentSessionID:json[@"id"]];
}
return task;
completion(checkout, token, error);
}];
}
- (NSURLSessionDataTask *)removeProductReservationsFromCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)block
{
NSURLSessionDataTask *task = nil;
if ([checkout hasToken]) {
BUYAssertCheckout(checkout);
checkout.reservationTime = @0;
task = [self updateCheckout:checkout completion:block];
} else {
block(checkout, [NSError errorWithDomain:kShopifyError code:BUYShopifyError_InvalidCheckoutObject userInfo:nil]);
}
return task;
return [self updateCheckout:checkout completion:block];
}
#pragma mark - Helpers
#pragma mark - Error
+ (BUYStatus)statusForStatusCode:(NSUInteger)statusCode error:(NSError *)error
{
......@@ -639,32 +540,61 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
return status;
}
- (NSError *)errorFromJSON:(NSDictionary *)errorDictionary statusCode:(NSInteger)statusCode
- (NSError *)errorFromJSON:(NSDictionary *)json response:(NSURLResponse *)response
{
NSInteger statusCode = [((NSHTTPURLResponse *) response) statusCode];
if (statusCode < kMinSuccessfulStatusCode || statusCode > kMaxSuccessfulStatusCode) {
return [[NSError alloc] initWithDomain:kShopifyError code:statusCode userInfo:json];
}
return nil;
}
#pragma mark - Convenience Requests
- (NSURLSessionDataTask *)getRequestForURL:(NSURL *)url completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [[NSError alloc] initWithDomain:kShopifyError code:statusCode userInfo:errorDictionary];
return [self requestForURL:url method:kGET object:nil completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)requestForURL:(NSURL *)url method:(NSString *)method object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
- (NSURLSessionDataTask *)postRequestForURL:(NSURL *)url object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
NSDictionary *json = [object jsonDictionaryForCheckout];
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:&error];
NSURLSessionDataTask *task = nil;
if (data && !error) {
task = [self requestForURL:url method:method body:data completionHandler:completionHandler];
}
return task;
return [self requestForURL:url method:kPOST object:object completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)putRequestForURL:(NSURL *)url object:(id<BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPUT object:object completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)patchRequestForURL:(NSURL *)url object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPATCH object:object completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)deleteRequestForURL:(NSURL *)url completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kDELETE object:nil completionHandler:completionHandler];
}
#pragma mark - Generic Requests
- (void)startTask:(NSURLSessionDataTask *)task
{
[task resume];
}
- (NSURLSessionDataTask *)requestForURL:(NSURL *)url method:(NSString *)method body:(NSData *)body completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
- (NSString *)authorizationHeader
{
NSData *data = [_apiKey dataUsingEncoding:NSUTF8StringEncoding];
return [NSString stringWithFormat:@"%@ %@", @"Basic", [data base64EncodedStringWithOptions:0]];
}
- (NSURLSessionDataTask *)requestForURL:(NSURL *)url method:(NSString *)method object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPBody = body;
if (object) {
request.HTTPBody = [NSJSONSerialization dataWithJSONObject:[object jsonDictionaryForCheckout] options:0 error:nil];
}
[request addValue:[self authorizationHeader] forHTTPHeaderField:@"Authorization"];
[request addValue:kJSONType forHTTPHeaderField:@"Content-Type"];
......@@ -676,86 +606,27 @@ NSString *const BUYClientCustomerAccessToken = @"X-Shopify-Customer-Access-Token
request.HTTPMethod = method;
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
NSDictionary *json = nil;
BOOL unauthorized = statusCode == 401;
BOOL failedValidation = statusCode == 422;
if (unauthorized) {
error = [[NSError alloc] initWithDomain:kShopifyError code:statusCode userInfo:nil];
}
else {
//2 is the minimum amount of data {} for a JSON Object. Just ignore anything less.
if ((!error || failedValidation) && [data length] > 2) {
id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
json = [jsonData isKindOfClass:[NSDictionary class]] ? jsonData : nil;
NSDictionary *json = nil;
if (data.length > 2) { // 2 is the minimum amount of data {} for a JSON Object. Just ignore anything less.
json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
}
if (statusCode < kMinSuccessfulStatusCode || statusCode > kMaxSuccessfulStatusCode) {
error = [self errorFromJSON:json statusCode:statusCode];
}
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
BOOL isSuccessful = (statusCode / 100) == 2;
if (!isSuccessful && !error) { // Only generate error if request failed
error = [self errorFromJSON:json response:response];
}
dispatch_async(self.queue, ^{
completionHandler(json, response, error);
});
}];
[self startTask:task];
return task;
}
- (NSURLSessionDataTask *)postPaymentRequestWithCheckout:(BUYCheckout *)checkout body:(NSData *)body completion:(BUYDataCreditCardBlock)block
{
return [self requestForURL:checkout.paymentURL method:kPOST body:body completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
NSString *paymentSessionId = nil;
if (!error) {
paymentSessionId = json[@"id"];
checkout.paymentSessionId = paymentSessionId;
}
block(checkout, paymentSessionId, error);
}];
}
- (NSURLSessionDataTask *)getRequestForURL:(NSURL *)url completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kGET body:nil completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)postRequestForURL:(NSURL *)url object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPOST object:object completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)putRequestForURL:(NSURL *)url body:(NSData *)body completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPUT body:body completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)postRequestForURL:(NSURL *)url body:(NSData *)body completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPOST body:body completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)patchRequestForURL:(NSURL *)url object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPATCH object:object completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)patchRequestForURL:(NSURL *)url body:(NSData *)body completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kPATCH body:body completionHandler:completionHandler];
}
- (NSURLSessionDataTask *)deleteRequestForURL:(NSURL *)url completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler
{
return [self requestForURL:url method:kDELETE body:nil completionHandler:completionHandler];
}
- (NSString *)authorizationHeader
{
NSData *data = [_apiKey dataUsingEncoding:NSUTF8StringEncoding];
return [NSString stringWithFormat:@"%@ %@", @"Basic", [data base64EncodedStringWithOptions:0]];
}
#pragma mark - NSURLSessionTaskDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
......
......@@ -32,11 +32,11 @@ extern NSString *const kShopifyError;
@interface BUYClient (Internal)
- (NSURLSessionDataTask *)postRequestForURL:(NSURL *)url object:(id <BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler;
- (NSURLSessionDataTask *)putRequestForURL:(NSURL *)url body:(NSData *)body completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler;
- (NSURLSessionDataTask *)putRequestForURL:(NSURL *)url object:(id<BUYSerializable>)object completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler;
- (NSURLSessionDataTask *)getRequestForURL:(NSURL *)url completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler;
- (NSURLSessionDataTask *)requestForURL:(NSURL *)url method:(NSString *)method body:(NSData *)body additionalHeaders:(NSDictionary *)headers completionHandler:(void (^)(NSDictionary *json, NSURLResponse *response, NSError *error))completionHandler;
- (NSURLComponents *)URLComponentsForAPIPath:(NSString *)apiPath appendingPath:(NSString *)appendingPath queryItems:(NSDictionary*)queryItems;
- (NSError *)extractErrorFromResponse:(NSURLResponse *)response json:(NSDictionary *)json;
- (NSError *)errorFromJSON:(NSDictionary *)json response:(NSURLResponse *)response;
@end
......@@ -25,6 +25,7 @@
//
#import "BUYAccountCredentials.h"
#import "BUYAssert.h"
static NSString * const BUYAccountFirstNameKey = @"first_name";
static NSString * const BUYAccountLastNameKey = @"last_name";
......@@ -142,7 +143,7 @@ static NSString * const BUYAccountPasswordConfirmationKey = @"password_confirmat
{
self = [super init];
if (self) {
NSAssert(value, @"Cannot initialize BUYAccountCredentialItem with nil value.");
BUYAssert(value, @"Cannot initialize BUYAccountCredentialItem with nil value.");
_key = key;
_value = value;
......
//
// BUYApplePayToken.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import "BUYPaymentToken.h"
@class PKPaymentToken;
@interface BUYApplePayToken : NSObject <BUYPaymentToken>
@property (nonatomic, strong, readonly) PKPaymentToken *paymentToken;
- (instancetype)initWithPaymentToken:(PKPaymentToken *)paymentToken;
@end
//
// BUYApplePayToken.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#if __has_include(<PassKit/PassKit.h>)
#import <PassKit/PassKit.h>
#endif
#import "BUYAssert.h"
#import "BUYApplePayToken.h"
@implementation BUYApplePayToken
#pragma mark - Init -
- (instancetype)initWithPaymentToken:(PKPaymentToken *)paymentToken
{
BUYAssert(paymentToken.paymentData.length > 0, @"Failed to initialize BUYApplePayToken. Invalid or nil paymentToken.");
self = [super init];
if (self) {
_paymentToken = paymentToken;
}
return self;
}
- (NSString *)paymentTokenString {
return [[NSString alloc] initWithData:self.paymentToken.paymentData encoding:NSUTF8StringEncoding];
}
#pragma mark - BUYPaymentToken -
- (NSDictionary *)JSONDictionary
{
return @{
@"payment_token" : @{
@"type" : @"apple_pay",
@"payment_data" : [self paymentTokenString],
},
};
}
@end
//
// BUYCreditCardToken.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import "BUYPaymentToken.h"
@interface BUYCreditCardToken : NSObject <BUYPaymentToken>
@property (nonatomic, strong, readonly) NSString *paymentSessionID;
- (instancetype)initWithPaymentSessionID:(NSString *)paymentSessionID;
@end
//
// BUYCreditCardToken.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYAssert.h"
#import "BUYCreditCardToken.h"
@implementation BUYCreditCardToken
#pragma mark - Init -
- (instancetype)initWithPaymentSessionID:(NSString *)paymentSessionID
{
BUYAssert(paymentSessionID.length > 0, @"Failed to initialize BUYCreditCardToken. Invalid or nil payment session ID.");
self = [super init];
if (self) {
_paymentSessionID = paymentSessionID;
}
return self;
}
#pragma mark - BUYPaymentToken -
- (NSDictionary *)JSONDictionary
{
return @{
@"payment_session_id" : self.paymentSessionID,
};
}
@end
//
// BUYPaymentToken.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@protocol BUYPaymentToken <NSObject>
- (NSDictionary *)JSONDictionary;
@end
......@@ -157,11 +157,6 @@
<entry key="documentation" value="Amount of payment due on the checkout."/>
</userInfo>
</attribute>
<attribute name="paymentSessionId" optional="YES" attributeType="String" syncable="YES">
<userInfo>
<entry key="documentation" value="The Payment Session ID associated with a credit card transaction."/>
</userInfo>
</attribute>
<attribute name="paymentURL" optional="YES" attributeType="Transformable" valueTransformerName="" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="NSURL"/>
......@@ -992,7 +987,7 @@
<element name="Address" positionX="126" positionY="521" width="128" height="240"/>
<element name="Cart" positionX="-576" positionY="558" width="128" height="60"/>
<element name="CartLineItem" positionX="-380" positionY="558" width="128" height="90"/>
<element name="Checkout" positionX="333" positionY="442" width="128" height="645"/>
<element name="Checkout" positionX="333" positionY="442" width="128" height="630"/>
<element name="CheckoutAttribute" positionX="-954" positionY="594" width="128" height="90"/>
<element name="Collection" positionX="-963" positionY="772" width="128" height="210"/>
<element name="Customer" positionX="106" positionY="1263" width="128" height="330"/>
......
......@@ -42,7 +42,6 @@ extern const struct BUYCheckoutAttributes {
__unsafe_unretained NSString *note;
__unsafe_unretained NSString *partialAddresses;
__unsafe_unretained NSString *paymentDue;
__unsafe_unretained NSString *paymentSessionId;
__unsafe_unretained NSString *paymentURL;
__unsafe_unretained NSString *privacyPolicyURL;
__unsafe_unretained NSString *refundPolicyURL;
......@@ -194,11 +193,6 @@ extern const struct BUYCheckoutUserInfo {
@property (nonatomic, strong) NSDecimalNumber* paymentDue;
/**
* The Payment Session ID associated with a credit card transaction.
*/
@property (nonatomic, strong) NSString* paymentSessionId;
/**
* URL to the payment gateway.
*/
@property (nonatomic, strong) NSURL* paymentURL;
......
......@@ -40,7 +40,6 @@ const struct BUYCheckoutAttributes BUYCheckoutAttributes = {
.note = @"note",
.partialAddresses = @"partialAddresses",
.paymentDue = @"paymentDue",
.paymentSessionId = @"paymentSessionId",
.paymentURL = @"paymentURL",
.privacyPolicyURL = @"privacyPolicyURL",
.refundPolicyURL = @"refundPolicyURL",
......
......@@ -64,6 +64,7 @@
#import "BUYObserver.h"
#import "BUYShopifyErrorCodes.h"
#import "BUYPaymentToken.h"
#import "BUYPaymentButton.h"
#import "BUYProductViewController.h"
#import "BUYStoreViewController.h"
......
......@@ -33,6 +33,7 @@
#import "BUYModelManager.h"
#import "BUYShop.h"
#import "BUYShopifyErrorCodes.h"
#import "BUYApplePayToken.h"
const NSTimeInterval PollDelay = 0.5;
......@@ -113,8 +114,10 @@ const NSTimeInterval PollDelay = 0.5;
if (checkout && error == nil) {
self.checkout = checkout;
id<BUYPaymentToken> token = [[BUYApplePayToken alloc] initWithPaymentToken:payment.token];
//Now that the checkout is up to date, call complete.
[self.client completeCheckout:checkout withApplePayToken:payment.token completion:^(BUYCheckout *checkout, NSError *error) {
[self.client completeCheckout:checkout paymentToken:token completion:^(BUYCheckout *checkout, NSError *error) {
if (checkout && error == nil) {
self.checkout = checkout;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment