6

I am developing an app using Apple Pay for a US Client from outside the US. I am using Braintree + Apple Pay. We support real credit cards to Passbook, but we can't verify them.

I successfully generated a client token, self.braintree and tried BT's both ways of integration.

  1. BTPaymentProvider - Our abstraction on payment method creation.

    if(self.braintree && ![self.braintree isKindOfClass:[NSNull class]])
    {
        self.provider = [braintree paymentProviderWithDelegate:self];
        if ([self.provider canCreatePaymentMethodWithProviderType:BTPaymentProviderTypeApplePay])
        {
            self.provider.paymentSummaryItems = @[[PKPaymentSummaryItem summaryItemWithLabel:@"XXXX" amount:[NSDecimalNumber decimalNumberWithString:@"1"]]];
        }
        [self.provider createPaymentMethod:BTPaymentProviderTypeApplePay];
    }
    

    but its not pushing "PKPaymentAuthorizationViewController". No exception too to track it down.

  2. PassKit - Apple's ApplePay APIs.

    if([PKPaymentAuthorizationViewController canMakePayments]) // It returns TRUE
    {
        PKPaymentRequest *paymentRequest = [[PKPaymentRequest alloc] init];
        paymentRequest.countryCode = @"US";
        paymentRequest.currencyCode = @"USD";
        paymentRequest.merchantCapabilities = PKMerchantCapabilityEMV | PKMerchantCapability3DS;
        paymentRequest.merchantIdentifier = MERCHANTID;
        paymentRequest.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa];
        paymentRequest.paymentSummaryItems = @[ [PKPaymentSummaryItem summaryItemWithLabel:@"TEST" amount:[NSDecimalNumber decimalNumberWithString:@"1"]] ];
    
        if([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa]]) // Returns FALSE
        {
            PKPaymentAuthorizationViewController *vc = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:paymentRequest];
            vc.delegate = self;
            [self presentViewController:vc animated:YES completion:nil];
        }
    }
    

    This gives "vc" is nil.

Correct me, if it's wrong. How do I test it on a real device?

Mohsin Khubaib Ahmed
  • 1,008
  • 16
  • 32
Femina
  • 1,239
  • 1
  • 12
  • 25
  • 2
    `BTPaymentProvider` does not itself present a `PKPaymentAuthorizationViewController`. Instead, it calls its delegate's `paymentMethodCreator:requestsPresentationOfViewController:` method, which is responsible for presentation. Can you ensure your implementation of this method presents the view controller? – Brent Jan 23 '15 at 18:40
  • [self.provider canCreatePaymentMethodWithProviderType:BTPaymentProviderTypeApplePay] returning no so can you please help me why it is returning no. I have already added a card in passbook. – Kamlesh Shingarakhiya Mar 31 '15 at 05:47

3 Answers3

10

It's likely that your app's Apple Pay entitlement is not set up correctly.

I've noticed canMakePayments returns YES and canMakePaymentsUsingNetworks: returns NO when the entitlement is not set.

(I've also noticed that they can both return YES when the merchant ID you set on your PKPaymentRequest does not match the merchant ID of your Apple Pay entitlement. In this case, your PKPaymentAuthorizationViewController will be non-nil, but presenting it logs a cryptic error in the console).

So to verify that Apple Pay is configured for your app, ensure that "Apple Pay" is "On" in the Capabilities section of your target settings, and that it has a merchant identifier (which you'll need to set up if you haven't already).

Then either:

  • If using your BTPaymentProvider integration method, ensure that the certificate and merchant identifier are correctly set up in the Braintree control panel.
  • If using your direct PassKit integration method, ensure that you are setting merchantIdentifier property to the matching merchant identifier in the entitlement.
Brent
  • 1,149
  • 8
  • 11
  • Worked!!! Appreciate that!...Actual reason, added Card to Passbook wasn't properly verified!... Any idea how to get "country, state etc..." from PKAddressFieldPostalAddress or self.provider.shippingAddress ? – Femina Jan 29 '15 at 12:48
  • ! I am proceeding with BTPaymentProvider, I got nonce. I wanted to configure ShippingServiceMethods. Where to? – Femina Feb 02 '15 at 09:50
3

Most likely this is happening because no payment cards are configured for any of those networks. From the documentation:

On devices that support making payments but don’t have any payment cards configured, the canMakePayments method returns YES because the hardware and parental controls allow making payments, but the canMakePaymentsUsingNetworks: method returns NO regardless of network.

The documentation also mentions other reasons:

User may not be able to make payments for a variety of reasons. For example, this functionality may not be supported by their hardware, or it may be restricted by parental controls.


On a separate note, if(self.braintree!=nil && self.braintree != Nil is redundant - those are the same. I would simply collapse this into if (self.braintree) { …

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
-1

In version 3.9.3 of the BraintreeSDK, I found a bug in BTClientTokenApplePayPaymentNetworksValueTransformer in which there is no case for Discover Card when deserializing BTConfiguration.applePaySupportedNetworks. This results in a PKPaymentRequest with an array containing an instance of NSNull in its supportedNetworks. Passing that array to PKPaymentAuthorizationViewController.canMakePaymentsUsingNetworks results in a NO. This method contains the bug:

- (id)transformedValue:(id)value {
    if ([PKPaymentRequest class]) {
        if ([value isEqualToString:@"amex"]) {
            return PKPaymentNetworkAmex;
        } else if ([value isEqualToString:@"visa"]) {
            return PKPaymentNetworkVisa;
        } else if ([value isEqualToString:@"mastercard"]) {
            return PKPaymentNetworkMasterCard;
        }
    }

    return [NSNull null];
}