diff --git a/android/build.gradle b/android/build.gradle index ab9a1085..29856007 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -23,4 +23,5 @@ dependencies { compile "com.facebook.react:react-native:+" compile 'com.braintreepayments.api:braintree:2.+' compile 'com.braintreepayments.api:drop-in:2.+' + compile group: 'com.google.code.gson', name: 'gson', version: '2.3.1' } diff --git a/android/src/main/java/com/pw/droplet/braintree/Braintree.java b/android/src/main/java/com/pw/droplet/braintree/Braintree.java index 68d38948..3d8ebe3f 100644 --- a/android/src/main/java/com/pw/droplet/braintree/Braintree.java +++ b/android/src/main/java/com/pw/droplet/braintree/Braintree.java @@ -1,5 +1,10 @@ package com.pw.droplet.braintree; +import java.util.Map; +import java.util.HashMap; + +import com.google.gson.Gson; + import android.content.Intent; import android.content.Context; import android.app.Activity; @@ -9,10 +14,13 @@ import com.braintreepayments.api.BraintreePaymentActivity; import com.braintreepayments.api.BraintreeFragment; import com.braintreepayments.api.exceptions.InvalidArgumentException; +import com.braintreepayments.api.exceptions.BraintreeError; +import com.braintreepayments.api.exceptions.ErrorWithResponse; import com.braintreepayments.api.models.CardBuilder; import com.braintreepayments.api.Card; import com.braintreepayments.api.PayPal; import com.braintreepayments.api.interfaces.PaymentMethodNonceCreatedListener; +import com.braintreepayments.api.interfaces.BraintreeErrorListener; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; @@ -59,6 +67,41 @@ public void onPaymentMethodNonceCreated(PaymentMethodNonce paymentMethodNonce) { nonceCallback(paymentMethodNonce.getNonce()); } }); + this.mBraintreeFragment.addListener(new BraintreeErrorListener() { + @Override + public void onError(Exception error) { + if (error instanceof ErrorWithResponse) { + ErrorWithResponse errorWithResponse = (ErrorWithResponse) error; + BraintreeError cardErrors = errorWithResponse.errorFor("creditCard"); + if (cardErrors != null) { + Gson gson = new Gson(); + final Map errors = new HashMap<>(); + BraintreeError numberError = cardErrors.errorFor("number"); + BraintreeError cvvError = cardErrors.errorFor("cvv"); + BraintreeError expirationDateError = cardErrors.errorFor("expirationDate"); + BraintreeError expirationYearError = cardErrors.errorFor("expirationYear"); + + if (numberError != null) { + errors.put("card_number", numberError.getMessage()); + } + + if (cvvError != null) { + errors.put("cvv", cvvError.getMessage()); + } + + if (expirationDateError != null) { + errors.put("expiration_date", expirationDateError.getMessage()); + } + + if (expirationYearError != null) { + errors.put("expiration_year", expirationYearError.getMessage()); + } + + nonceErrorCallback(gson.toJson(errors)); + } + } + } + }); this.setToken(token); successCallback.invoke(this.getToken()); } catch (InvalidArgumentException e) { @@ -76,7 +119,7 @@ public void getCardNonce(final String cardNumber, final String expirationMonth, .expirationMonth(expirationMonth) .expirationYear(expirationYear) .cvv(cvv) - .validate(false); + .validate(true); Card.tokenize(this.mBraintreeFragment, cardBuilder); } @@ -85,6 +128,10 @@ public void nonceCallback(String nonce) { this.successCallback.invoke(nonce); } + public void nonceErrorCallback(String error) { + this.errorCallback.invoke(error); + } + @ReactMethod public void paymentRequest(final String callToActionText, final Callback successCallback, final Callback errorCallback) { this.successCallback = successCallback;