note

We are currently working on upgrading this 3D Secure integration in preparation for 3DS 2.0 and PSD2 Strong Consumer Authentication (SCA) compliance requirements in 2019.

See our 3DS 2.0 Adoption guide for details.

Payment flow

Generate a client token

important

You must generate a client token if you want to use 3D Secure. Tokenization keys can't be used when processing 3D Secure transactions.

Before you can initialize BTThreeDSecure, you will need to set up the SDK and initialize with a client token generated on your server.

Update your Podfile to include the 3D Secure subspec, like this:

Ruby
Copy
Copied
pod 'Braintree', '~> 3.9'
pod 'Braintree/3D-Secure', '~> 3.9'

To get access to the code, import Braintree-3D-Secure.h.

availability

To use 3D Secure, integrate version 3.8.1 or later of the Braintree iOS SDK.

Specify a merchant account

If you would like to use a merchant account ID other than your default, specify the merchant_account_id when generating the client token.

note

This merchant account ID must match the merchant account ID used to create the transaction.

Render a checkout page

You can structure your native checkout flow however you'd like. If you don't already have a credit card form, consider our Drop-in UI.

Start by adding an import statement:

Objective-C Swift
Copy
Copied
#import <Braintree/Braintree-3D-Secure.h>

@interface YourCheckoutViewController () <BTPaymentMethodCreationDelegate>

@property (nonatomic, strong, readwrite) BTThreeDSecure *threeDSecure;

@end

@implementation YourCheckoutViewController
Objective-C Swift
Copy
Copied
- (void)prepareForCheckout {
    // Retain both your instance of `BTThreeDSecure` and its delegate with a strong pointer to avoid memory-management bugs.
    self.threeDSecure = [[BTThreeDSecure alloc] initWithClient:self.braintree.client delegate:self];
}

Your view controller should conform to BTPaymentMethodCreationDelegate in order to respond to progress and completion notifications. Your loading indicator should be hidden when requestsPresentationOfViewController is received.

Verify a credit card

You can verify transactions with verifyCardWithNonce:amount:. This call will refer to the card data based on the payment method nonce and may challenge the cardholder with a 3D Secure authentication, if the card is enrolled in a 3D Secure program and the card-issuing bank requires this verification.

The transaction amount is required at verification for two reasons. First of all, it's an additional check to make sure the transaction being verified is the same as the one that is eventually authorized and settled. For this reason, the amount submitted for verification must match the amount sent to the Braintree server for authorization. Additionally, some issuers use the amount to help determine whether they should challenge the user to authenticate.

Objective-C Swift
Copy
Copied
- (IBAction)tappedCheckout {
  // Create a BTClientCardRequest based on the UI state
  BTClientCardRequest *details = [[BTClientCardRequest alloc] init];
  details.number = self.cardNumberField.text;
  details.expirationMonth = self.expirationMonthField.text;
  details.expirationYear = self.expirationYearField.text;

  // Tokenize the card
  [self.braintree tokenizeCard:details completion:^(NSString *nonce, NSError *error) {
    if (error) {
      // TODO: Handle errors
    }

    // Kick off 3D Secure flow
    [self.threeDSecure verifyCardWithNonce:nonce
                                    amount:[NSDecimalNumber decimalNumberWithString:@"10"]];
  }];
}

If a user-facing authentication flow is required, the delegate will receive a view controller, which you must present to the user:

Objective-C Swift
Copy
Copied
- (void)paymentMethodCreator:(id)sender requestsPresentationOfViewController:(UIViewController *)viewController {
    [self presentViewController:viewController animated:YES completion:nil];
}

- (void)paymentMethodCreator:(id)sender requestsDismissalOfViewController:(UIViewController *)viewController {
    [viewController dismissViewControllerAnimated:YES completion:nil];
}

If the user successfully completes the 3D Secure process, the delegate will receive the paymentMethodCreator:didCreatePaymentMethod: success callback. You should transmit the nonce to your server and create a transaction.

Objective-C Swift
Copy
Copied
- (void)paymentMethodCreator:(id)sender didCreatePaymentMethod:(BTPaymentMethod *)paymentMethod {
    // For 3D Secure, the payment method will always be an instance of BTCardPaymentMethod
    if ([paymentMethod isKindOfClass:[BTCardPaymentMethod class]]) {
        BTCardPaymentMethod *card = (BTCardPaymentMethod *)paymentMethod;
        // (Optional:) Update your UI with card details
        self.yourCardNumberLabel.text = card.lastTwo;
        self.yourCardTypeLabel.text = card.typeString;

        // Transmit the payment method nonce to your server
        NSString *paymentMethodNonce = card.nonce;
        // TODO: Upload paymentMethodNonce
    }
}

If the user cancels the 3D Secure authentication, the delegate will receive paymentMethodCreatorDidCancel:. In order to perform 3D Secure again, a new nonce or the same card details will need to be supplied to -[BTThreeDSecure verifyCardWithNonce:amount:] or -[BTThreeDSecure verifyCardWithDetails:amount:]

If the 3D Secure process fails, the delegate will receive the paymentMethodCreator:didFailWithError: failure callback.

For each request to verify a card, your BTPaymentMethodCreationDelegate will receive exactly one of the three possible callbacks: paymentMethodCreatorDidCancel:, paymentMethodCreator:didCreatePaymentMethod:, and paymentMethodCreator:didFailWithError:.

Verify a vaulted credit card

First, on the server, generate and return a payment method nonce for the vaulted credit card.

Then on the client, you can use the verifyCardWithNonce:amount: method just as before and pass it the newly-generated nonce.

Verify a card from raw details or a payment method

For integration styles that generate a BTCardPaymentMethod when the user selects a payment method, such as Drop-in and direct usage of BTClient, we provide a convenience method:

Objective-C Swift
Copy
Copied
BTCardPaymentMethod *card = PAYMENT_METHOD_FROM_YOUR_IOS_CODE;
[self.threeDSecure verifyCard:card
                       amount:[NSDecimalNumber decimalNumberWithString:@"10"]];

Similarly, you can pipe raw card details straight into BTThreeDSecure if that is easier:

Objective-C Swift
Copy
Copied
BTClientCardRequest *details = [[BTClientCardRequest alloc] init];
details.number = @"4111111111111111";
details.expirationDate = @"12/2020";
[self.threeDSecure verifyCardWithDetails:details
                                  amount:[NSDecimalNumber decimalNumberWithString:@"10"]];

Please read the iOS header documentation for more details.

Advanced client-side options

We expose additional information about the authentication request that you can use for more advanced UI flows or risk assessment. You should be aware that making such assessments may result in accepting the liability for fraudulent transactions.

These parameters pass through the client-side first and should not be trusted for your server-side risk assessment. They should be used for UI flow only.

Objective-C Swift
Copy
Copied
- (void)paymentMethodCreator:(__unused id)sender didCreatePaymentMethod:(BTPaymentMethod *)paymentMethod {

    if ([paymentMethod isKindOfClass:[BTCardPaymentMethod class]]) {
        BTCardPaymentMethod *cardPaymentMethod = (BTCardPaymentMethod *)paymentMethod;
        if (cardPaymentMethod.threeDSecureInfo.liabilityShiftPossible &&
            cardPaymentMethod.threeDSecureInfo.liabilityShifted) {

            NSLog(@"liability shift possible and liability shifted");

        } else {

            NSLog(@"3D Secure authentication was attempted but liability shift is not possible");

        }
    }
}
  1. liabilityShifted indicates that 3D Secure worked and authentication succeeded. This will also be true if the issuing bank does not support 3D Secure, but the payment method does. In both cases, the liability for fraud has been shifted to the bank. You should go on creating a transaction using the new nonce.
  2. liabilityShiftPossible indicates that the payment method was eligible for 3D Secure. If liabilityShifted is false, then the user failed 3D Secure authentication. In this situation, the card brands recommend asking the user for another form of payment. However, if you have server-side risk assessment processes that allow for it, you can still use the new nonce to create a transaction. If you want to use a nonce that did not pass 3D Secure authentication, you need to set the required option to false in your server integration.
  3. If both of the above values are false then this card was ineligible for 3D Secure. You can continue to create the transaction with the new nonce. However, liability shift will not apply to this transaction. This case may be useful if you would like to ask the user for additional verification (AVS, etc).
important

For American Express SafeKey, liabilityShifted may be returned as true but Amex may later revoke the liability shift for the transaction based on your merchant behavior and fraud rate.

Next Page: Server-side →

Still have questions?

If you can’t find an answer, contact us