stripe-archive/ApplePayStubs

memory issue, second purchase

Closed this issue · 2 comments

Suz commented

EXC_BAD_ACCESS on 2nd purchase in the simulator. I'm not sure where the problem is exactly, but let's start here...

I've just tried to integrate Apple Pay into our existing app that uses Stripe. We were using Stripe version 1.1, so I've also updated to the latest. So now I'm using Stripe, PaymentKit, and ApplePayStubs.

Our existing app checks the Billing address for sales tax purposes with Avalara. This is a delegate-based workflow, that basically has to be incorporated into the middle of the block-based workflows of Apple Pay and Stripe. Unfortunately, the billing address isn't available from Apple Pay until near the end of the delegate protocol:

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus)) completion

In this method, I create an AvaTaxAddress and verify it with a call to [avaTaxInterface validateAddress:taxAddress callback:self];. The problem is the completion function. I need to somehow pass this through to the later AvaTax delegate methods so that it can be called properly. Right now I'm keeping references to the PKPayment and the completion block by defining them as instance variables and setting them in the didAuthorizePayment method.

typedef void(^ApplePayCompletionBlock)(PKPaymentAuthorizationStatus);

@interface DPArtDetailViewController () <PKPaymentAuthorizationViewControllerDelegate, AvaTaxValidateAddressDelegate> {
    PKPayment *applePayPayment;
    ApplePayCompletionBlock applePayCompletion;
}
@property (nonatomic,copy) ApplePayCompletionBlock applePayCompletion;

@end

@implementation DPArtDetailViewController
@synthesize applePayCompletion;

Then, in the didAuthorizePayment method, I have

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus)) completion {
    self->applePayPayment = payment;
    self->applePayCompletion = (ApplePayCompletionBlock)completion;
    ....
    [avaTaxInterface validateAddress:taxAddress callback:self];
}

When the address verification returns, I get either - (void)taxAddressValidated:(NSNotification*)notification or - (void)taxAddressFailure:(NSNotification*)notification. At this point, I need to create the stripe token and then call the applePayCompletion block with a PKPaymentAuthroizationStatus in order to finally dismiss the ApplePay UI.

This works fine for the first purchase, but on the second purchase, the applePayCompletion block seems to be deallocated before it is called: It's NULL and the app crashes. With breakpoints in the debugger, I can see that the reference is valid when I call [[STPAPIClient sharedClient] createTokenWithCard:card completion:^(STPToken *token, NSError *error) {}], but when control reaches the completion block of that call, the applePayCompletion block has been deallocated.

What a mess. Any suggestions?

Suz commented

Ahhh. Found it.
I was 'resetting' the values of the applePayCompletion and the applePayPayment to nil in -paymentAuthorizationViewControllerDidFinish. Bad idea. Removed those lines and now it works.

Great, glad you figured things out.

On Friday, April 24, 2015, S Kiihne <notifications@github.com
javascript:_e(%7B%7D,'cvml','notifications@github.com');> wrote:

EXC_BAD_ACCESS on 2nd purchase in the simulator. I'm not sure where the
problem is exactly, but let's start here...

I've just tried to integrate Apple Pay into our existing app that uses
Stripe. We were using Stripe version 1.1, so I've also updated to the
latest. So now I'm using Stripe, PaymentKit, and ApplePayStubs.

Our existing app checks the Billing address for sales tax purposes with
Avalara. This is a delegate-based workflow, that basically has to be
incorporated into the middle of the block-based workflows of Apple Pay and
Stripe. Unfortunately, the billing address isn't available from Apple Pay
until near the end of the delegate protocol:

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus)) completion

In this method, I create an AvaTaxAddress and verify it with a call to [avaTaxInterface
validateAddress:taxAddress callback:self];. The problem is the completion
function. I need to somehow pass this through to the later AvaTax delegate
methods so that it can be called properly. Right now I'm keeping references
to the PKPayment and the completion block by defining them as instance
variables and setting them in the didAuthorizePayment method.

typedef void(^ApplePayCompletionBlock)(PKPaymentAuthorizationStatus);

@interface DPArtDetailViewController () <PKPaymentAuthorizationViewControllerDelegate, AvaTaxValidateAddressDelegate> {
PKPayment *applePayPayment;
ApplePayCompletionBlock applePayCompletion;
}
@Property (nonatomic,copy) ApplePayCompletionBlock applePayCompletion;

@EnD

@implementation DPArtDetailViewController
@synthesize applePayCompletion;

Then, in the didAuthorizePayment method, I have

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus)) completion {
self->applePayPayment = payment;
self->applePayCompletion = (ApplePayCompletionBlock)completion;
....
[avaTaxInterface validateAddress:taxAddress callback:self];
}

When the address verification returns, I get either -
(void)taxAddressValidated:(NSNotification_)notification or -
(void)taxAddressFailure:(NSNotification_)notification. At this point, I
need to create the stripe token and then call the applePayCompletion
block with a PKPaymentAuthroizationStatus in order to finally dismiss the
ApplePay UI.

This works fine for the first purchase, but on the second purchase, the
applePayCompletion block seems to be deallocated before it is called:
It's NULL and the app crashes. With breakpoints in the debugger, I can
see that the reference is valid when I call [[STPAPIClient sharedClient]
createTokenWithCard:card completion:^(STPToken *token, NSError *error) {}],
but when control reaches the completion block of that call, the
applePayCompletion block has been deallocated.

What a mess. Any suggestions?


Reply to this email directly or view it on GitHub
#16.