We are using the Braintree SDK in our application, in conjunction with PayPal, to enable users to make in-app purchases. Unfortunately, we have been unable to create nonce's from PayPal payment information or user-entered credit card information using Braintree.
Below is some context on our specific implementation:
We initialize the Braintree object using our client token in the following way:
Braintree braintree = Braintree.getInstance(context, token);
We also have set the Braintree listener to our Fragment, which implements Braintree.PaymentMethodNonceListener. On activityCreated() we initialize the Braintree object using the above code. onPause() we remove the listener, and onResume() we add the listener.
In the app, we allow users to pay either through PayPal or via credit card.
If the user chooses to use PayPal, we launch an intent to the PayPal activity using a unique request code. Using the following code block, we receive the response from the PayPal activity completion.
@Override
public void onActivityResult(int requestCode, int responseCode, Intent data) {
if (requestCode == PAYPAL_REQUEST_CODE) {
if (responseCode == FragmentActivity.RESULT_OK) {
braintree.finishPayWithPayPal(getActivity(), responseCode, data);
}
}
}
In accordance with the Braintree SDK documentation seen here,
Additionally, we provide the user the ability to enter credit card info, which we then use to construct a CardBuilder object, which is passed to the Braintree object through the "tokenize" method as seen in the below snippet:
CardBuilder cardBuilder = new CardBuilder()
.cardNumber(cardNumber)
.expirationDate(expirationDate);
braintree.tokenize(cardBuilder);
According to the Braintree developer documentation, seen here, after tokenize is called, one should expect the onPaymentMethodNonce callback; at which point, the nonce is received for the user-entered credit card information.
TL/DR:
Based on our implementation described above, we currently have (2) issues we have been unable to resolve:
1) onActivityResult()
Method is never called, despite having entered valid PayPal credentials in the PayPal activity window, and having resumed to our application. After searching the internet, we discovered a potential bug in Android, regarding the parent Activity to a Fragment not calling super.onActivityResult(). onActivityResult is not being called in Fragment onActivityResult() not called when Activity started from Fragment onActivityResult not called in fragment android https://code.google.com/p/android/issues/detail?id=15394 Unfortunately, none of the advice in these posts seemed to allows onActivityResult to ever get called in our Fragment. Which, in return, results in finishPayWithPaypal() never being called on the Braintree object. Which, finally, results in the onPaymentMethodNonce never firing for our nonce listener Fragment.
Update for the onActivityResult() callback issue:
Per Luke's recommendation in the comments section, I have implemented the resolution to the onActivityResult() callback issue:
In the Payment Activity, we override onActivityResult(), which then calls the Fragment's onActivityResult method.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.payment_fragment);
if (fragment != null){
fragment.onActivityResult(requestCode, resultCode, data);
}
}
The onActivityResult() method now gets called when the PayPal activity finishes. Thanks for your help Luke.
*Note: Be sure that the Fragment in which you are trying to reference is of the same type Fragment returned by the findFragmentById()! If the Fragment is an android.app.Fragment, then use Activity's getFragmentManager().findFragmentById() which returns app Fragment. If the Fragment is an android.support.v4.app.Fragment, then use Activity's getSupportFragmentManager().findFragmentId() which returns the v4 Fragment. Otherwise, a mismatch in Fragment types will result in a null return. While this may seem intuitive, it is very annoying to debug, given the subtle difference in types!
2) onPaymentMethodNonce()
Method is never called. After calling tokenize() or finishWithPayPal(), on the Braintree object, the call seems to get lost in "Braintree world". After setting breakpoints, and stepping through the implementation, we were unable to find any trace that Braintree had either failed or succeeded in tokenizing the card or handling the PayPal activity result.
Environment
Gradle Build Info:
- compileSdkVersion 19
- buildToolsVersion 20.0.0
- minSdkVersion 11
- targetSdkVersion 19
- versionCode 5
- versionName 1.4.1
Test Hardware:
- Samsung DUOS
- Model GT-S7582
- Android Version 4.2.2
Thank you for your help in advance.