Assisted wallet registration

You can allow your user to streamline their new mobile wallet registration using their PayPal profile, as illustrated by the following app screen sequence.

Assisted registration screen flow

Figure 1: Assisted registration screen flow

As shown in Figure 1, the app provides a PayPal registration operator, which, when selected, triggers the PayPal Braintree SDK client. When the app switch URL is invoked, the Braintree client checks whether the One-Touch client is installed on the device, which determines whether the PayPal login and consent screens are displayed within the app or launched in a browser. In either case, once the user consents to the integration, the focus returns to the mobile wallet app.

Figure 2 shows the data process flow involved in the assisted registration.

Assisted registration sequence diagram

Figure 2: Assisted registration sequence diagram

As indicated in Figure 2, once the wallet registration is complete, the app can invoke an applicable login method stipulated by the Issuer, and also use the BTPaymentAccountNonce returned by the v.zero client to automatically link PayPal to the wallet as a registered tender.

The next sections provide implementation and samples for each of the relevant calls depicted in Figure 2.

Request the clientToken

Use these commands to request the token and handle the success and failure responses for your device's OS.

OS Command
iOS retrieveClientToken:(PDRetrieveClientTokenRequest *)request
Android getClientToken(ClientTokenParameters clientTokenParameters)

Within each of the parameter objects, the following data must be passed.

Property Description
provider Required String
The processor for which the token is valid. The value for this integration is PAYPAL.
token Optional String
Some providers require an authorization token from the app to obtain a clientToken. This property is not relevant for this use case

Success response

OS Command
iOS fetchClientTokenCompletionBlock:(PDRetrieveClientTokenResponse *)response
Android onClientTokenRetrieveSuccess (ClientToken clientToken)

Within each of the parameter objects, the following data may be returned:

Property Description
clientToken String
The btClientToken required to initialize the Braintree SDK client.
additionalInformation
(iOS ONLY)
String
A container for custom property values that may be required or relevant for the integration. Not supported at this time.

Configure the success response to initialize the Braintree SDK client.

Failure response

OS Command
iOS fetchClientTokenFailureBlock:(PDPaydiantError *utilityServiceManagementError);
Android onUserRegistrationError (PaydiantException exception)

Within each of the parameter objects, the following data may be returned:

Property Description
Description String
The basic error description returned by the SDK.
statusMessage String
The Mobile Gateway description associated with the returned statusCode.
statusCode Integer
The numerical code representing the reason for failure from the Mobile Gateway.
rawErrorDescription String
An error description reported by the device system.
localizedDescription String
A custom message relevant to the error.
errorInformation String
An object containing error information as obtained from an external party, such as the response from a payment provider.

Samples

Sample retrieveClientToken for iOS

- (IBAction)registerPyPLBTNClicked:(UIButton *)sender {
    [CommonUtil showProgressIndicatorOnView:self];
    PDIssuerServiceCoordinator *utilityServiceCoordinator = [PDIssuerServiceCoordinator new];
    PDRetrieveClientTokenRequest *request = [PDRetrieveClientTokenRequest new];
    request.provider = @"PAYPAL";
    [utilityServiceCoordinator retrieveClientToken:request completionBlock:^(PDRetrieveClientTokenResponse *response) {
        // Configure success block to initialize the BTAPIClient
    } failureBlock:^(PDPaydiantError *utilityServiceManagementError)
}

Sample getClientToken for Android

public ServiceConnection userServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        userManagementService = ((LocalBinder < IUserManagementService > ) service).getService();
        if (userManagementService != null) {
            userManagementService.setUserManagementServiceListener(userManagementListenerAdapter);
            userManagementService.getClientToken("paypal");
        }
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
        userManagementService = null;
  }
};
UserManagementListenerAdapter userManagementListenerAdapter = new userManagementListenerAdapter() {
    // Configure success callback to initialize the BTAPIClient
    @Override
    public void onClientTokenRetrieveSuccess(ClientToken clientToken) {
        super.onClientTokenRetrieveSuccess(clientToken);
        initBraintree(clientToken.getClientToken());
    }
}

Initialize Braintree SDK client

Call the Braintree API client, passing the btClientToken returned in the response of the Request the clientToken call.

Note: Make sure you have completed the Braintree client integration in your app.

Depending on your device, see:

OS Command
iOS https://developers.braintreepayments.com/guides/client-sdk/ios/v4
Android https://developers.braintreepayments.com/guides/client-sdk/android/v2

Samples

Sample initialize Braintree client for iOS

[utilityServiceCoordinator retrieveClientToken:request completionBlock: ^(PDRetrieveClientTokenResponse * response) {
    [CommonUtil hideProgressIndicatorOnView: self];
    NSString *btClientToken = response.clientToken;
    BTAPIClient *apiClient = [[BTAPIClient alloc] initWithAuthorization: btClientToken];
    BTPayPalDriver *btPayPalDriver = [[BTPayPalDriver alloc] initWithAPIClient: apiClient];
    btPayPalDriver.appSwitchDelegate = (id) self;
    btPayPalDriver.viewControllerPresentingDelegate = (id) self;
    BTPayPalRequest *checkout = [[BTPayPalRequest alloc] init];

    [btPayPalDriver requestBillingAgreement:checkout completion: ^(BTPayPalAccountNonce * _Nullable tokenizedPayPalCheckout, NSError * _Nullable error) {

        if (error) {
            NSLog(@"ERROR = %@", error);
            [CommonUtil hideProgressIndicatorOnView: self];
            [CommonUtil displayMessageWithTitle: @"Error"
                                 andDescription: @"Your PayPal account could not be linked at this time. Please try again."];
        }
        else if (tokenizedPayPalCheckout) {
            self.paymentNonce = tokenizedPayPalCheckout.nonce;
            NSLog(@"Got a nonce: %@", self.paymentNonce);
        }
    }
     }

Sample initialize Braintree client for Android

private void initBraintree(String clientToken) {
    BraintreeFragment mBraintreeFragment;
    try {
        mBraintreeFragment = BraintreeFragment.newInstance(mActivity, clientToken);
        PayPal.requestBillingAgreement(mBraintreeFragment, new PayPalRequest());
    } catch (InvalidArgumentException e) {
        e.printStackTrace();
    }
}

Invoke the wallet registration

Map profile values

  1. Map the profile values returned in the BTPayPalAccountNonce from the Braintree client to the attributes of the Paydiant user profile object. Implement the success and failure responses for your device.

  2. Display the registration form in the app, pre-populating profile fields with the mapped values, and prompt user to enter values for wallet credentials not populated by the PayPal profile.

  3. Invoke the device OS-specific Paydiant SDK call to create a new wallet registration using the completed user profile data.

    OS Command
    iOS registerNewUser:(PDRegisterUserRequest *)request
    Android registerUser(CreateCustomer customer)

    Within each of the parameter objects, the following data must be passed:

    iOS Property Android Property Description
    userProfile customer Required Object
    An instance of PDUserProfile (iOS) or Customer (Android) populated with the values retrieved from the PayPal profile and the login credential values provided by the user. Attributes include:
    firstName
    lastName
    email
    password
    confirmPassword
    passcode
    confirmPasscode
    mfaAnswers
    phone
    additionalInformation
    Use this array of key/value definitions to pass other relevant data collected in the form, such as address or zip code or gender, according to Issuer registration specifications. Refer to the code sample for OS-specific syntax.
  4. Implement the device-specific Paydiant SDK callback to handle the success response:

    OS Command
    iOS registerUserCompletionBlock:(PDRegisterUserResponse *)response
    Android onRegisterUserSuccess (CreatedCustomer createdCustomer)

    Within each of the parameter objects, the following data will be returned:

    Property Description
    nonce String
    A one-time access token that can be passed with the LoginByNonce method of the SDK, if applicable.
    customerUri String
    Paydiant’s unique identifier generated for the new wallet registration.
    Message String
    Raw data returned by the mobile gateway.
  5. Implement the device OS-specific Paydiant SDK callback to handle the failure response.

    OS Command
    iOS registerUserFailureBlock:(PDPaydiantError *userEnrollmentError);
    Android onUserRegistrationError (PaydiantException exception)

    Within each of the parameter objects, the following data may be returned:

    Property Description
    Description String
    The basic error description returned by the SDK.
    statusMessage String
    The Mobile Gateway description associated with the returned statusCode.
    statusCode Integer
    The numerical code representing the reason for failure from the Mobile Gateway.
    rawErrorDescription String
    An error description reported by the device system.
    localizedDescription String
    A custom message relevant to the error.
    errorInformation String
    An object containing error information as obtained from an external party, such as the response from a payment provider.

Samples

Sample registerNewUser for iOS

PDUserProfile * userProfile = [PDUserProfile new];
userProfile.firstName = tokenizedPayPalCheckout.firstName;
userProfile.lastName = tokenizedPayPalCheckout.lastName;
userProfile.email = tokenizedPayPalCheckout.email;
userProfile.password = kPwd;
userProfile.confirmPassword = kPwd;
userProfile.passcode = kPin;
userProfile.confirmPasscode = kPin;

if (tokenizedPayPalCheckout.phone != nil) 
    userProfile.phone = tokenizedPayPalCheckout.phone;
else
    userProfile.phone = @"1234567890";

userProfile.mfaQuestionAnswers = self.mfaQuestionsAndAnswers;

userProfile.additionalCustomerInformation = [NSDictionary dictionaryWithObjectsAndKeys: @"key", @"value", nil];

PDRegisterUserRequest *request = [PDRegisterUserRequest new];
request.userProfile = userProfile;

PDUserEnrollmentCoordinator *userEnrollment = [[PDUserEnrollmentCoordinator alloc] init];
[userEnrollment registerNewUser: request
                completionBlock: ^(PDRegisterUserResponse * response){
    [CommonUtil hideProgressIndicatorOnView: self];
    [CommonUtil displayMessageWithTitle: @"Success"
                         andDescription: [NSString stringWithFormat: @"%@, %@", userProfile.email, response.message]];

    self.addPayPalAfterLogin = YES;
    self.loginBTN.hidden = YES;
    self.registerBTN.hidden = YES;
    self.registerPyPLBTN.hidden = YES;

    [self.authenticationCoordinator loginByUsernamePassword:tokenizedPayPalCheckout.email password: kPwd];
}
                   failureBlock: ^(PDPaydiantError * userEnrollmentError)
{
    ...
}

Sample registerUser for Android

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_register_by_pay_pal, container, false);
    final EditText password = (EditText) rootView.findViewById(R.id.txtPasswordRegistration);
    final EditText confirmPassword = (EditText) rootView.findViewById(R.id.txtConfirmPasswordRegistration);
    final EditText passcode = (EditText) rootView.findViewById(R.id.txtPassCodeReg);
    final EditText confirmPasscode = (EditText) rootView.findViewById(R.id.txtPassCodeConfirm);
    Button registerButton = (Button) rootView.findViewById(R.id.register_button);
    registerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (paypalInfoRetrieved && newUser != null) {
                newUser.setPassword(password.getText().toString());
                newUser.setConfirmPassword(confirmPassword.getText().toString());
                newUser.setPasscode(passcode.getText().toString());
                newUser.setConfirmPasscode(confirmPasscode.getText().toString());
                userManagementServiuserManagementService.registerUser(CustomerTransformer.dtoToDomain(newUser));
            } else {
                CommonUtils.getInstance().showAlertDialog(mActivity, "PayPal info not retrieved.");
            }
        }
    });
    return rootView;
}

Invoke user authentication

Once the wallet registration successfully completes, invoke whichever login method is supported by your app’s issuing partner. Some options include:

  • LoginByNonce – Pass the nonce returned with the registration success response (not the payment nonce returned by the Braintree client) to complete authentication in the back end, without requiring the user to enter credentials.
  • LoginByPin – Display the PIN Login screen and prompt the user to enter the passcode to complete authentication.
  • LoginByUsernamePassword (+MFA) – Display the Password Login screen and prompt the user to enter credentials and, if applicable, security question responses, to complete authentication.

Refer to Paydiant’s SDK documentation for details about specific login calls for iOS and Android.

Since the user has already consented to the PayPal payment integration through the Braintree client, you can invoke payment account enrollment to automatically link the user’s PayPal account as a payment tender in the wallet as part of the entire registration process, providing a seamless experience for the user.

  1. Invoke the device OS-specific Paydiant SDK call to start payment account enrollment.

    OS Command
    iOS startPaymentAccountEnrollment:(PDStartPaymentAccountEnrollmentRequest *)request
    Android startPaymentAccountEnrollment(StartPaymentAccountEnrollment startPaymentAccountEnrollment)

    Within each of the parameter objects, the following data must be passed:

    Property Description
    enrollmentType Required String
    A value specifying whether Paydiant will be the system of record for the payment account. For this use case, value is kPDEnrollmentTypeProvision
    paymentAccountTypeUri Required String
    Paydiant’s unique identifier for the type of payment account.
    paymentAccountNetworkTypeUri Required String
    Paydiant’s unique identifier for the payment processor.
    additionalData Required Array
    A set of property instances that define other data required for the enrollment. For this use case, you must define the following:

    key = PAYMENT_METHOD_NONCE
    value = BTPayPalAccountNonce value returned by the Braintree client (not the login nonce returned in the registration response)

    key = NICKNAME
    value = PayPal

    key = VAULT_BY_NONCE
    value = TRUE
  2. Implement the device OS-specific Paydiant SDK callback to handle the success response.

    OS Command
    iOS startPaymentAccountEnrollmentCompletionBlock:(PDStartPaymentAccountEnrollmentResponse *)response
    Android onRegisterUserSuccess (CreatedCustomer createdCustomer)

    Within each of the parameter objects, the following data will be returned:

    Property Description
    enrollmentState String
    A value indicating the status of the enrollment operation. In this case, the only successful value is kPDEnrollmentStateEnd
    PaydiantCorrelationId String
    Paydiant’s unique identifier for the enrollment operation, which is expected to be passed in subsequent calls related to this enrollment, such as continue or cancel. This value is not applicable for this use case.
  3. Implement the device OS-specific Paydiant SDK callback to handle the failure response.

    OS Command
    iOS startPaymentAccountEnrollmentFailureBlock:(PDPaydiantError *managePaymentInstrumentError);
    Android onUserRegistrationError (PaydiantException exception)

    Within each of the parameter objects, the following data may be returned:

    Property Description
    Description String
    The basic error description returned by the SDK.
    statusMessage String
    The Mobile Gateway description associated with the returned statusCode.
    statusCode Integer
    The numerical code representing the reason for failure.
    rawErrorDescription String
    An error description reported by the device system.
    localizedDescription String
    A custom message relevant to the error.
    errorInformation String
    An object containing error information as obtained from an external party, such as the response from a payment provider.

Samples

Sample auto-enroll PayPal tender for iOS

PDStartPaymentAccountEnrollmentRequest *request = [[PDStartPaymentAccountEnrollmentRequest alloc] init];
request.enrollmentType = kPDEnrollmentTypeProvision;
request.paymentAccountTypeUri = @"paydiant:payment-account-management.accounttype#PayPal";
request.paymentAccountNetworkTypeUri = @"paydiant:payment-account-management.networktype#PayPal";

NSMutableArray * additionalInfo = [NSMutableArray new];

PDStartPaymentAccountEnrollmentAdditionalData *paymentMethodNonce = [PDStartPaymentAccountEnrollmentAdditionalData new];
paymentMethodNonce.additionalDataKey = @"PAYMENT_METHOD_NONCE";
paymentMethodNonce.additionalDataValue = self.paymentNonce;
[additionalInfo addObject: paymentMethodNonce];

PDStartPaymentAccountEnrollmentAdditionalData *vaultByNonce = [PDStartPaymentAccountEnrollmentAdditionalData new];
vaultByNonce.additionalDataKey = @"VAULT_BY_NONCE";
vaultByNonce.additionalDataValue = @"true";
[additionalInfo addObject: vaultByNonce];

PDStartPaymentAccountEnrollmentAdditionalData *nickName = [PDStartPaymentAccountEnrollmentAdditionalData new];
nickName.additionalDataKey = @"NICK_NAME";
nickName.additionalDataValue = @"PayPal";
[additionalInfo addObject: nickName];

request.additionalData = additionalInfo;

NSMutableArray * metaDataArray = [NSMutableArray new];
PDMetaData * metaData = [PDMetaData new];
metaData.key = @"PAYMENT_METHOD_NONCE";
metaData.value = self.paymentNonce;
[metaDataArray addObject: metaData];
request.metaData = metaDataArray;

PDManagePaymentInstrumentsCoordinator * managePayInstr = [PDManagePaymentInstrumentsCoordinator new];
[CommonUtil showProgressIndicatorOnView:self];
[managePayInstr startPaymentAccountEnrollment:request completionBlock: ^(PDStartPaymentAccountEnrollmentResponse *response) {
    [CommonUtil displayMessageWithTitle:@"Success"
                         andDescription:@"Added PayPal to your wallet"];
    [CommonUtil hideProgressIndicatorOnView:self];
    self.loginBTN.hidden = YES;
    self.registerBTN.hidden = YES;
    self.registerPyPLBTN.hidden = YES;
    self.UnlinkBarBTN.enabled = YES;
    self.logoutBarBTN.enabled = YES;
    self.walletBTN.hidden = NO;
} failureBlock: ^(PDPaydiantError * managePaymentInstrumentsError) {
    [CommonUtil hideProgressIndicatorOnView: self];
    [CommonUtil displayError: managePaymentInstrumentsError];
}];

Next

Feedback

Have feedback?

Let us know.