paypal / paypal-here-sdk-ios-distribution

Add credit card (tap, insert, swipe & key-in) capabilities to your iOS app
Other
81 stars 91 forks source link

[1.6] Can't process card swipe w/o reattach card reader #62

Closed rleiwang closed 8 years ago

rleiwang commented 8 years ago

Can you help me to look at why I can't process second swipe. The first swipe would be fine, but the time time, the card swipe never come through.

Here are the steps. 1) initWithResponse

2) call chargeCard, swipe Card, follow the screen flow, processing and done

3) call chargeCard second time, swiper Card, nothing happens.

can someone give a pointer where I did wrong?

@implementation PayPalPOS

- (id) initWithResponse:(NSDictionary *)JSON thenAfterSetupCallback:(void (^)(BOOL))afterSetup
{
  self = [super init];
  if (self)
  {
    self.cardWatcher = [[PPHCardReaderWatcher alloc] initWithDelegate:self];
    [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
      NSLog(@"permission : %d", granted);
    }];

    NSLog(@"%@ version", [PayPalHereSDK sdkVersion]);
    [PayPalHereSDK selectEnvironmentWithType:ePPHSDKServiceType_Sandbox];

    self.sdkLogger = [PayPalHereSDK loggingDelegate];
    [PayPalHereSDK setLoggingDelegate:self];

    [PayPalHereSDK setReferrerCode:@"App, Inc"];

    if ([PayPalHereSDK askForLocationAccess])
    {
      [PayPalHereSDK startWatchingLocation];
    }
    else
    {
      NSLog(@"no location");
    }

    [PayPalHereSDK setupWithCredentials: [JSON objectForKey:@"access_token"]
                             refreshUrl: [JSON objectForKey:@"refresh_url"]
                       tokenExpiryOrNil: [JSON objectForKey:@"expires_in"]
                  thenCompletionHandler:^(PPHInitResultType status, PPHError *error, PPHMerchantInfo *info)
     {
       if (status == ePPHAccessResultSuccess)
       {
         //self.merchant = info;
       }
       else
       {
         NSLog(@"%ld here %@", (long)status, error);
       }
       afterSetup(status == ePPHAccessResultSuccess);
     }];
  }
  return self;
}

-(void) chargeCard:(NSDictionary *)JSON thenProcessingStatusCallback:(void (^)(NSString *))processingStatusCallback
{
  [[PayPalHereSDK sharedTransactionManager] cancelPayment];

  self.invoice = [self createInvoice];
  [[PayPalHereSDK sharedTransactionManager] beginPaymentUsingUIWithInvoice:self.invoice
                                                     transactionController:self];
}

- (PPHInvoice *) createInvoice
{
  //PPHInvoice *invoice = [[PPHInvoice alloc] initWithCurrency:@"USD"];
  PPHInvoice *invoice = [[PPHInvoice alloc] init];

  NSString *taxRate = [[NSUserDefaults standardUserDefaults] objectForKey:@"taxRate"];
  NSDecimalNumber *taxRateNumber;
  if (taxRate) {
    taxRateNumber = [NSDecimalNumber decimalNumberWithString:taxRate];
  } else {
    taxRateNumber = [NSDecimalNumber decimalNumberWithString:@".10"];
  }

  //for (NSString *item in self.shoppingCart) {
  [invoice addItemWithId:@"1" detailId:nil name:@"itemName"
                quantity:[NSDecimalNumber one]
               unitPrice:[NSDecimalNumber decimalNumberWithString:@"10"]
                 taxRate:nil taxRateName:nil];
  //}

  return invoice;
}

- (void)userDidSelectPaymentMethod:(PPHPaymentMethod) paymentOption
{
  // When the customer either taps, inserts or swipes their card, SDK would call you with this.
  // Update your invoice here, if needed, before we proceed with the transaction.
  // IMPORTANT NOTE : For a contactless transaction, refrain from updating the invoice once the card is tapped.
  __weak typeof(self) weakSelf = self;
  NSLog(@"payment option %u", paymentOption);
  // STEP #3 to take an EMV paymen
  [self getCurrentNavigationController].navigationBar.hidden = FALSE;
  [[PayPalHereSDK sharedTransactionManager] processPaymentUsingUIWithPaymentType:paymentOption
                                                               completionHandler:^(PPHTransactionResponse *response)
   {
     [self getCurrentNavigationController].navigationBar.hidden = true;

     NSLog(@"%lu status", response.record.transactionStatus);
     if (response.error)
     {
       //self.processingStatusCallback([NSString stringWithFormat:@"PayPal Error: %@", response.error.apiMessage]);
     }
     else
     {
       //self.processingStatusCallback([NSString stringWithFormat:@"Transaction %@ Succeed", response.record.transactionId]);
     }
     [[weakSelf getCurrentNavigationController] popViewControllerAnimated:YES];
   }];
}

- (void)userDidSelectRefundMethod:(PPHPaymentMethod) refundOption
{
  NSLog(@"refund");
}

/*!
 * Mandatory if you are using the EMVSDK. Returns a reference to a
 * navigation controller we drive UI off of.
 */
- (UINavigationController *)getCurrentNavigationController
{
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  return (UINavigationController *) appDelegate.window.rootViewController;
}

@end
mpavlinsky commented 8 years ago

I don't see anything wrong with the code immediately. Can you share a log of what the SDK is outputting in this case?

rleiwang commented 8 years ago

@mpavlinsky I found out this afternoon it is threading issue. I moved the code to TakePayment example and it worked there. I am using react native with this SDK, react native uses another thread to invoke SDK api, for some reason, the audio session thread can't notify the card swipe event unless this SDK invoked from main thread.

rleiwang commented 8 years ago

@mpavlinsky Thanks for reviewing the code. I am unable to login to PayPal sandbox env since yesterday's noon time. Only got it resolved this afternoon after waiting almost 30 mins on the phone for tech support. Do you have any suggestions how can I dev/test code with SDK w/o sandbox?

djMax commented 8 years ago

Is it working now? If you do a transaction and refund it, you should end up 100% whole, so that's one way to test in a pinch.

ppmtscory commented 8 years ago

Closing - feel free to open a new issue if you encounter any further problems.