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);
}];
BUYCheckout *checkout = [[BUYCheckout alloc] initWithModelManager:self.client.modelManager JSONDictionary:@{@"token": @"abcdef", @"payment_due": @0}];
id<BUYPaymentToken> token = [[BUYApplePayToken alloc] initWithPaymentToken:[BUYApplePayTestToken validToken]];
XCTAssertThrows(
[self.client completeCheckout:[BUYCheckout new] paymentToken:token completion:^(BUYCheckout *checkout, NSError *error) {}]
);
[self.client completeCheckout:checkout withApplePayToken:nil completion:^(BUYCheckout *checkout, NSError *error) {
callbackCount++;
XCTAssertEqual(error.code, BUYShopifyError_NoApplePayTokenSpecified);
}];
XCTAssertEqual(callbackCount, 2);
[self testProductsInCollectionWithSortOrderCollectionDefault];
BUYCheckout *checkout = [[BUYCheckout alloc] initWithModelManager:self.client.modelManager JSONDictionary:@{@"token": @"abcdef", @"payment_due": @0}];
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];
}
......
//
// 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];
......
......@@ -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