Assisted wallet registration
Last updated: Aug 15th, 7:24am
You can allow your user to streamline their new mobile wallet registration using their PayPal profile, as illustrated by the following app screen sequence.
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.
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
1- (IBAction)registerPyPLBTNClicked:(UIButton *)sender {2 [CommonUtil showProgressIndicatorOnView:self];3 PDIssuerServiceCoordinator *utilityServiceCoordinator = [PDIssuerServiceCoordinator new];4 PDRetrieveClientTokenRequest *request = [PDRetrieveClientTokenRequest new];5 request.provider = @"PAYPAL";6 [utilityServiceCoordinator retrieveClientToken:request completionBlock:^(PDRetrieveClientTokenResponse *response) {7 // Configure success block to initialize the BTAPIClient8 } failureBlock:^(PDPaydiantError *utilityServiceManagementError)9}
Sample getClientToken for Android
1public ServiceConnection userServiceConnection = new ServiceConnection() {2 @Override3 public void onServiceConnected(ComponentName name, IBinder service) {4 userManagementService = ((LocalBinder < IUserManagementService > ) service).getService();5 if (userManagementService != null) {6 userManagementService.setUserManagementServiceListener(userManagementListenerAdapter);7 userManagementService.getClientToken("paypal");8 }9 }10 @Override11 public void onServiceDisconnected(ComponentName name) {12 userManagementService = null;13 }14};15UserManagementListenerAdapter userManagementListenerAdapter = new userManagementListenerAdapter() {16 // Configure success callback to initialize the BTAPIClient17 @Override18 public void onClientTokenRetrieveSuccess(ClientToken clientToken) {19 super.onClientTokenRetrieveSuccess(clientToken);20 initBraintree(clientToken.getClientToken());21 }22}
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 | /braintree/docs/guides/client-sdk/setup/ios/v4 |
Android | /braintree/docs/guides/client-sdk/setup/android/v3/ |
Samples
Sample initialize Braintree client for iOS
1[utilityServiceCoordinator retrieveClientToken:request completionBlock: ^(PDRetrieveClientTokenResponse * response) {2 [CommonUtil hideProgressIndicatorOnView: self];3 NSString *btClientToken = response.clientToken;4 BTAPIClient *apiClient = [[BTAPIClient alloc] initWithAuthorization: btClientToken];5 BTPayPalDriver *btPayPalDriver = [[BTPayPalDriver alloc] initWithAPIClient: apiClient];6 btPayPalDriver.appSwitchDelegate = (id) self;7 btPayPalDriver.viewControllerPresentingDelegate = (id) self;8 BTPayPalRequest *checkout = [[BTPayPalRequest alloc] init];910 [btPayPalDriver requestBillingAgreement:checkout completion: ^(BTPayPalAccountNonce * _Nullable tokenizedPayPalCheckout, NSError * _Nullable error) {1112 if (error) {13 NSLog(@"ERROR = %@", error);14 [CommonUtil hideProgressIndicatorOnView: self];15 [CommonUtil displayMessageWithTitle: @"Error"16 andDescription: @"Your PayPal account could not be linked at this time. Please try again."];17 }18 else if (tokenizedPayPalCheckout) {19 self.paymentNonce = tokenizedPayPalCheckout.nonce;20 NSLog(@"Got a nonce: %@", self.paymentNonce);21 }22 }23 }
Sample initialize Braintree client for Android
1private void initBraintree(String clientToken) {2 BraintreeFragment mBraintreeFragment;3 try {4 mBraintreeFragment = BraintreeFragment.newInstance(mActivity, clientToken);5 PayPal.requestBillingAgreement(mBraintreeFragment, new PayPalRequest());6 } catch (InvalidArgumentException e) {7 e.printStackTrace();8 }9}
Invoke the wallet registration
Map profile values
Map the profile values returned in the
BTPayPalAccountNonce
from the Braintree client to the attributes of the WLW user profile object. Implement the success and failure responses for your device.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.
Invoke the device OS-specific WLW 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 ofPDUserProfile
(iOS) orCustomer
(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.Implement the device-specific WLW 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
WLW’s unique identifier generated for the new wallet registration.Message
String
Raw data returned by the mobile gateway.Implement the device OS-specific WLW 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
1PDUserProfile * userProfile = [PDUserProfile new];2userProfile.firstName = tokenizedPayPalCheckout.firstName;3userProfile.lastName = tokenizedPayPalCheckout.lastName;4userProfile.email = tokenizedPayPalCheckout.email;5userProfile.password = kPwd;6userProfile.confirmPassword = kPwd;7userProfile.passcode = kPin;8userProfile.confirmPasscode = kPin;910if (tokenizedPayPalCheckout.phone != nil)11 userProfile.phone = tokenizedPayPalCheckout.phone;12else13 userProfile.phone = @"1234567890";1415userProfile.mfaQuestionAnswers = self.mfaQuestionsAndAnswers;1617userProfile.additionalCustomerInformation = [NSDictionary dictionaryWithObjectsAndKeys: @"key", @"value", nil];1819PDRegisterUserRequest *request = [PDRegisterUserRequest new];20request.userProfile = userProfile;2122PDUserEnrollmentCoordinator *userEnrollment = [[PDUserEnrollmentCoordinator alloc] init];23[userEnrollment registerNewUser: request24 completionBlock: ^(PDRegisterUserResponse * response){25 [CommonUtil hideProgressIndicatorOnView: self];26 [CommonUtil displayMessageWithTitle: @"Success"27 andDescription: [NSString stringWithFormat: @"%@, %@", userProfile.email, response.message]];2829 self.addPayPalAfterLogin = YES;30 self.loginBTN.hidden = YES;31 self.registerBTN.hidden = YES;32 self.registerPyPLBTN.hidden = YES;3334 [self.authenticationCoordinator loginByUsernamePassword:tokenizedPayPalCheckout.email password: kPwd];35}36 failureBlock: ^(PDPaydiantError * userEnrollmentError)37{38 ...39}
Sample registerUser for Android
1@Override2public View onCreateView(LayoutInflater inflater, ViewGroup container,3Bundle savedInstanceState) {4 View rootView = inflater.inflate(R.layout.fragment_register_by_pay_pal, container, false);5 final EditText password = (EditText) rootView.findViewById(R.id.txtPasswordRegistration);6 final EditText confirmPassword = (EditText) rootView.findViewById(R.id.txtConfirmPasswordRegistration);7 final EditText passcode = (EditText) rootView.findViewById(R.id.txtPassCodeReg);8 final EditText confirmPasscode = (EditText) rootView.findViewById(R.id.txtPassCodeConfirm);9 Button registerButton = (Button) rootView.findViewById(R.id.register_button);10 registerButton.setOnClickListener(new View.OnClickListener() {11 @Override12 public void onClick(View view) {13 if (paypalInfoRetrieved && newUser != null) {14 newUser.setPassword(password.getText().toString());15 newUser.setConfirmPassword(confirmPassword.getText().toString());16 newUser.setPasscode(passcode.getText().toString());17 newUser.setConfirmPasscode(confirmPasscode.getText().toString());18 userManagementServiuserManagementService.registerUser(CustomerTransformer.dtoToDomain(newUser));19 } else {20 CommonUtils.getInstance().showAlertDialog(mActivity, "PayPal info not retrieved.");21 }22 }23 });24 return rootView;25}
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 WLW’s SDK documentation for details about specific login calls for iOS and Android.
Automatically link PayPal as a tender
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.
Invoke the device OS-specific WLW 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 WLW will be the system of record for the payment account. For this use case, value iskPDEnrollmentTypeProvision
paymentAccountTypeUri
Required String
WLW’s unique identifier for the type of payment account.paymentAccountNetworkTypeUri
Required String
WLW’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
Implement the device OS-specific WLW 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 iskPDEnrollmentStateEnd
PaydiantCorrelationId
String
WLW’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.Implement the device OS-specific WLW 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
1PDStartPaymentAccountEnrollmentRequest *request = [[PDStartPaymentAccountEnrollmentRequest alloc] init];2request.enrollmentType = kPDEnrollmentTypeProvision;3request.paymentAccountTypeUri = @"paydiant:payment-account-management.accounttype#PayPal";4request.paymentAccountNetworkTypeUri = @"paydiant:payment-account-management.networktype#PayPal";56NSMutableArray * additionalInfo = [NSMutableArray new];78PDStartPaymentAccountEnrollmentAdditionalData *paymentMethodNonce = [PDStartPaymentAccountEnrollmentAdditionalData new];9paymentMethodNonce.additionalDataKey = @"PAYMENT_METHOD_NONCE";10paymentMethodNonce.additionalDataValue = self.paymentNonce;11[additionalInfo addObject: paymentMethodNonce];1213PDStartPaymentAccountEnrollmentAdditionalData *vaultByNonce = [PDStartPaymentAccountEnrollmentAdditionalData new];14vaultByNonce.additionalDataKey = @"VAULT_BY_NONCE";15vaultByNonce.additionalDataValue = @"true";16[additionalInfo addObject: vaultByNonce];1718PDStartPaymentAccountEnrollmentAdditionalData *nickName = [PDStartPaymentAccountEnrollmentAdditionalData new];19nickName.additionalDataKey = @"NICK_NAME";20nickName.additionalDataValue = @"PayPal";21[additionalInfo addObject: nickName];2223request.additionalData = additionalInfo;2425NSMutableArray * metaDataArray = [NSMutableArray new];26PDMetaData * metaData = [PDMetaData new];27metaData.key = @"PAYMENT_METHOD_NONCE";28metaData.value = self.paymentNonce;29[metaDataArray addObject: metaData];30request.metaData = metaDataArray;3132PDManagePaymentInstrumentsCoordinator * managePayInstr = [PDManagePaymentInstrumentsCoordinator new];33[CommonUtil showProgressIndicatorOnView:self];34[managePayInstr startPaymentAccountEnrollment:request completionBlock: ^(PDStartPaymentAccountEnrollmentResponse *response) {35 [CommonUtil displayMessageWithTitle:@"Success"36 andDescription:@"Added PayPal to your wallet"];37 [CommonUtil hideProgressIndicatorOnView:self];38 self.loginBTN.hidden = YES;39 self.registerBTN.hidden = YES;40 self.registerPyPLBTN.hidden = YES;41 self.UnlinkBarBTN.enabled = YES;42 self.logoutBarBTN.enabled = YES;43 self.walletBTN.hidden = NO;44} failureBlock: ^(PDPaydiantError * managePaymentInstrumentsError) {45 [CommonUtil hideProgressIndicatorOnView: self];46 [CommonUtil displayError: managePaymentInstrumentsError];47}];