Commit 0c2a0a2d by Brent Gulanowski Committed by GitHub

Merge pull request #228 from Shopify/task/remove-polling

Remove left over polling in BUYApplePayAuthorizationDelegate.
parents ef2635a2 9e50f380
...@@ -38,10 +38,11 @@ ...@@ -38,10 +38,11 @@
const NSTimeInterval PollDelay = 0.5; const NSTimeInterval PollDelay = 0.5;
typedef void (^AddressUpdateCompletion)(PKPaymentAuthorizationStatus, NSArray<PKShippingMethod *> * _Nonnull, NSArray<PKPaymentSummaryItem *> * _Nonnull);
@interface BUYApplePayAuthorizationDelegate () @interface BUYApplePayAuthorizationDelegate ()
@property (nonatomic, strong) BUYCheckout *checkout; @property (nonatomic, strong) BUYCheckout *checkout;
@property (nonatomic, strong) NSArray *shippingRates; @property (nonatomic, strong) NSArray *shippingRates;
@property (nonatomic, strong) NSError *lastError; @property (nonatomic, strong) NSError *lastError;
...@@ -102,10 +103,8 @@ const NSTimeInterval PollDelay = 0.5; ...@@ -102,10 +103,8 @@ const NSTimeInterval PollDelay = 0.5;
[self.client completeCheckoutWithToken:checkout.token paymentToken:token completion:^(BUYCheckout *checkout, NSError *error) { [self.client completeCheckoutWithToken:checkout.token paymentToken:token completion:^(BUYCheckout *checkout, NSError *error) {
if (checkout && error == nil) { if (checkout && error == nil) {
self.checkout = checkout; self.checkout = checkout;
completion(PKPaymentAuthorizationStatusSuccess);
[self pollUntilCheckoutIsComplete:self.checkout completion:completion]; } else {
}
else {
self.lastError = error; self.lastError = error;
completion(PKPaymentAuthorizationStatusFailure); completion(PKPaymentAuthorizationStatusFailure);
} }
...@@ -133,16 +132,20 @@ const NSTimeInterval PollDelay = 0.5; ...@@ -133,16 +132,20 @@ const NSTimeInterval PollDelay = 0.5;
[controller dismissViewControllerAnimated:YES completion:nil]; [controller dismissViewControllerAnimated:YES completion:nil];
} }
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<PKShippingMethod *> * _Nonnull, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion -(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(AddressUpdateCompletion)completion
{ {
self.checkout.shippingAddress = [self buyAddressWithABRecord:address]; self.checkout.shippingAddress = [self buyAddressWithABRecord:address];
if ([self.checkout.shippingAddress isValidAddressForShippingRates]) {
[self updateCheckoutWithAddressCompletion:completion]; [self updateCheckoutWithAddressCompletion:completion];
}
} }
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingContact:(PKContact *)contact completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<PKShippingMethod *> * _Nonnull, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion -(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingContact:(PKContact *)contact completion:(AddressUpdateCompletion)completion
{ {
self.checkout.shippingAddress = [self buyAddressWithContact:contact]; self.checkout.shippingAddress = [self buyAddressWithContact:contact];
if ([self.checkout.shippingAddress isValidAddressForShippingRates]) {
[self updateCheckoutWithAddressCompletion:completion]; [self updateCheckoutWithAddressCompletion:completion];
}
} }
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingMethod:(PKShippingMethod *)shippingMethod completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion -(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingMethod:(PKShippingMethod *)shippingMethod completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion
...@@ -163,7 +166,7 @@ const NSTimeInterval PollDelay = 0.5; ...@@ -163,7 +166,7 @@ const NSTimeInterval PollDelay = 0.5;
#pragma mark - #pragma mark -
- (void)updateCheckoutWithAddressCompletion:(void (^)(PKPaymentAuthorizationStatus, NSArray *shippingMethods, NSArray *summaryItems))completion - (void)updateCheckoutWithAddressCompletion:(AddressUpdateCompletion)completion
{ {
// This method call is internal to selection of shipping address that are returned as partial from PKPaymentAuthorizationViewController // This method call is internal to selection of shipping address that are returned as partial from PKPaymentAuthorizationViewController
// However, to ensure we never set partialAddresses to NO, we want to guard the setter. Should PKPaymentAuthorizationViewController ever // However, to ensure we never set partialAddresses to NO, we want to guard the setter. Should PKPaymentAuthorizationViewController ever
...@@ -172,108 +175,59 @@ const NSTimeInterval PollDelay = 0.5; ...@@ -172,108 +175,59 @@ const NSTimeInterval PollDelay = 0.5;
self.checkout.partialAddresses = @YES; self.checkout.partialAddresses = @YES;
} }
if ([self.checkout.shippingAddress isValidAddressForShippingRates]) {
[self.client updateCheckout:self.checkout completion:^(BUYCheckout *checkout, NSError *error) { [self.client updateCheckout:self.checkout completion:^(BUYCheckout *checkout, NSError *error) {
if (checkout && error == nil) { if (checkout && !error) {
self.checkout = checkout; self.checkout = checkout;
[self getShippingRates:self.checkout completion:completion];
} }
else { else if (error) {
self.lastError = error; self.lastError = error;
completion(PKPaymentAuthorizationStatusInvalidShippingPostalAddress, nil, [self.checkout buy_summaryItemsWithShopName:self.shopName]);
} }
}]; if (checkout.requiresShipping) {
self.shippingRates = @[];
[self updateShippingRatesCompletion:completion];
} }
else { else {
completion(PKPaymentAuthorizationStatusInvalidShippingPostalAddress, nil, [self.checkout buy_summaryItemsWithShopName:self.shopName]); completion(PKPaymentAuthorizationStatusSuccess, @[], [self.checkout buy_summaryItemsWithShopName:self.shopName]);
} }
}];
} }
#pragma mark - internal - (void)updateShippingRatesCompletion:(AddressUpdateCompletion)completion
- (BUYShippingRate *)rateForShippingMethod:(PKShippingMethod *)method
{ {
BUYShippingRate *rate = nil; [self.client getShippingRatesForCheckoutWithToken:self.checkout.token completion:^(NSArray *shippingRates, BUYStatus status, NSError *error) {
NSString *identifier = [method identifier];
for (BUYShippingRate *method in _shippingRates) {
if ([[method shippingRateIdentifier] isEqual:identifier]) {
rate = method;
break;
}
}
return rate;
}
- (void)getShippingRates:(BUYCheckout *)checkout completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray *shippingMethods, NSArray *summaryItems))completion self.shippingRates = shippingRates;
{ NSArray *shippingMethods = [BUYShippingRate buy_convertShippingRatesToShippingMethods:shippingRates];
// We're now fetching the rates from Shopify. This will will calculate shipping rates very similarly to how our web checkout.
// We then turn our BUYShippingRate objects into PKShippingMethods for Apple to present to the user.
if ([self.checkout requiresShipping] == NO) { if (shippingMethods.count > 0) {
completion(PKPaymentAuthorizationStatusSuccess, nil, [self.checkout buy_summaryItemsWithShopName:self.shopName]);
}
else {
[self fetchShippingRates:^(PKPaymentAuthorizationStatus status, NSArray *methods, NSArray *summaryItems) {
NSArray *shippingMethods = [BUYShippingRate buy_convertShippingRatesToShippingMethods:_shippingRates];
if ([shippingMethods count] > 0) {
[self selectShippingMethod:shippingMethods[0] completion:^(BUYCheckout *checkout, NSError *error) { [self selectShippingMethod:shippingMethods[0] completion:^(BUYCheckout *checkout, NSError *error) {
if (checkout && error == nil) { if (checkout && !error) {
self.checkout = checkout; self.checkout = checkout;
} }
completion(error ? PKPaymentAuthorizationStatusFailure : PKPaymentAuthorizationStatusSuccess, shippingMethods, [self.checkout buy_summaryItemsWithShopName:self.shopName]); completion(error ? PKPaymentAuthorizationStatusFailure : PKPaymentAuthorizationStatusSuccess, shippingMethods, [self.checkout buy_summaryItemsWithShopName:self.shopName]);
}]; }];
}
else { } else {
self.lastError = [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_NoShippingMethodsToAddress userInfo:nil]; self.lastError = [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_NoShippingMethodsToAddress userInfo:nil];
completion(status, nil, [self.checkout buy_summaryItemsWithShopName:self.shopName]); completion(PKPaymentAuthorizationStatusInvalidShippingPostalAddress, @[], [self.checkout buy_summaryItemsWithShopName:self.shopName]);
} }
}]; }];
}
} }
- (void)fetchShippingRates:(void (^)(PKPaymentAuthorizationStatus, NSArray *, NSArray *))completion #pragma mark - Internal -
{
// Fetch shipping rates. This may take several seconds to get back from our shipping providers. You have to poll here.
self.shippingRates = @[];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block BUYStatus shippingStatus = BUYStatusUnknown;
do {
[self.client getShippingRatesForCheckoutWithToken:self.checkout.token completion:^(NSArray *shippingRates, BUYStatus status, NSError *error) {
shippingStatus = status;
if (error) {
completion(PKPaymentAuthorizationStatusInvalidShippingPostalAddress, nil, [self.checkout buy_summaryItemsWithShopName:self.shopName]);
}
else if (shippingStatus == BUYStatusComplete) {
self.shippingRates = shippingRates;
if ([self.shippingRates count] == 0) {
// Shipping address is not supported and no shipping rates were returned
if (completion) {
completion(PKPaymentAuthorizationStatusInvalidShippingPostalAddress, nil, [self.checkout buy_summaryItemsWithShopName:self.shopName]);
}
} else {
if (completion) {
completion(PKPaymentAuthorizationStatusSuccess, self.shippingRates, [self.checkout buy_summaryItemsWithShopName:self.shopName]);
}
}
- (BUYShippingRate *)rateForShippingMethod:(PKShippingMethod *)method
{
BUYShippingRate *rate = nil;
NSString *identifier = [method identifier];
for (BUYShippingRate *method in self.shippingRates) {
if ([[method shippingRateIdentifier] isEqual:identifier]) {
rate = method;
break;
} }
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (shippingStatus != BUYStatusComplete && shippingStatus != BUYStatusUnknown) {
// Adjust as you see fit for your polling rate.
[NSThread sleepForTimeInterval:PollDelay];
} }
} while (shippingStatus == BUYStatusProcessing); return rate;
});
} }
- (void)selectShippingMethod:(PKShippingMethod *)shippingMethod completion:(BUYDataCheckoutBlock)block - (void)selectShippingMethod:(PKShippingMethod *)shippingMethod completion:(BUYDataCheckoutBlock)block
...@@ -284,32 +238,4 @@ const NSTimeInterval PollDelay = 0.5; ...@@ -284,32 +238,4 @@ const NSTimeInterval PollDelay = 0.5;
[self.client updateCheckout:self.checkout completion:block]; [self.client updateCheckout:self.checkout completion:block];
} }
- (void)pollUntilCheckoutIsComplete:(BUYCheckout *)checkout completion:(void (^)(PKPaymentAuthorizationStatus status))completion
{
// Poll until done. At this point, we've sent the payment information to the Payment Gateway for your shop, and we're waiting for it to come back.
// This is sometimes a slow process, so we need to poll until we've received confirmation that money has been authorized or captured.
__block BUYStatus checkoutStatus = BUYStatusUnknown;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
while (checkout.token && checkoutStatus != BUYStatusFailed && checkoutStatus != BUYStatusComplete) {
[self.client getCompletionStatusOfCheckoutWithToken:self.checkout.token completion:^(BUYStatus status, NSError *error) {
checkoutStatus = status;
self.lastError = error;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (checkoutStatus != BUYStatusComplete) {
[NSThread sleepForTimeInterval:PollDelay];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completion(checkoutStatus == BUYStatusComplete ? PKPaymentAuthorizationStatusSuccess : PKPaymentAuthorizationStatusFailure);
});
});
}
@end @end
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