From 34ada90772bd4cd71c913650e9edfdd29b036922 Mon Sep 17 00:00:00 2001 From: Mihai Date: Wed, 4 Jan 2023 16:54:31 +0200 Subject: [PATCH] chore: update Braintree Android SDK to v4 --- android/build.gradle | 15 +- ...oid-react-native-braintree-dropin-ui~1.iml | 169 ---------------- .../RNBraintreeDropInModule.java | 187 +++++++++++------- 3 files changed, 126 insertions(+), 245 deletions(-) delete mode 100644 android/node_modules-react-native-braintree-dropin-ui-android-react-native-braintree-dropin-ui~1.iml diff --git a/android/build.gradle b/android/build.gradle index 58245d32..6809b44c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,23 +1,23 @@ buildscript { repositories { - jcenter() google() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:7.3.1' } } apply plugin: 'com.android.library' android { - compileSdkVersion 28 - buildToolsVersion '28.0.3' + compileSdkVersion 33 + buildToolsVersion '33.0.1' defaultConfig { minSdkVersion 21 - targetSdkVersion 27 + targetSdkVersion 33 versionCode 1 versionName "1.0" } @@ -32,10 +32,7 @@ repositories { } dependencies { - implementation 'com.braintreepayments.api:google-payment:3.2.0' - implementation 'com.google.android.gms:play-services-wallet:16.0.1' - implementation 'com.braintreepayments.api:data-collector:2.+' - implementation 'com.braintreepayments.api:drop-in:5.+' + implementation 'com.braintreepayments.api:drop-in:6.6.0' implementation 'com.facebook.react:react-native:+' } diff --git a/android/node_modules-react-native-braintree-dropin-ui-android-react-native-braintree-dropin-ui~1.iml b/android/node_modules-react-native-braintree-dropin-ui-android-react-native-braintree-dropin-ui~1.iml deleted file mode 100644 index 187164d4..00000000 --- a/android/node_modules-react-native-braintree-dropin-ui-android-react-native-braintree-dropin-ui~1.iml +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java b/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java index 37ad2d42..00697f1b 100644 --- a/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java +++ b/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java @@ -1,36 +1,54 @@ package tech.power.RNBraintreeDropIn; import android.app.Activity; -import android.content.Intent; + +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; + +import com.braintreepayments.api.DropInClient; +import com.braintreepayments.api.DropInListener; +import com.braintreepayments.api.DropInPaymentMethod; +import com.braintreepayments.api.ThreeDSecureRequest; +import com.braintreepayments.api.UserCanceledException; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.ActivityEventListener; -import com.facebook.react.bridge.BaseActivityEventListener; import com.facebook.react.bridge.Promise; -import com.braintreepayments.api.dropin.DropInActivity; -import com.braintreepayments.api.dropin.DropInRequest; -import com.braintreepayments.api.dropin.DropInResult; -import com.braintreepayments.api.models.PaymentMethodNonce; -import com.braintreepayments.api.models.CardNonce; -import com.braintreepayments.api.models.ThreeDSecureInfo; -import com.braintreepayments.api.models.GooglePaymentRequest; +import com.braintreepayments.api.DropInRequest; +import com.braintreepayments.api.DropInResult; +import com.braintreepayments.api.PaymentMethodNonce; +import com.braintreepayments.api.CardNonce; +import com.braintreepayments.api.ThreeDSecureInfo; +import com.braintreepayments.api.GooglePayRequest; import com.google.android.gms.wallet.TransactionInfo; import com.google.android.gms.wallet.WalletConstants; +import java.util.Objects; + public class RNBraintreeDropInModule extends ReactContextBaseJavaModule { private Promise mPromise; - private static final int DROP_IN_REQUEST = 0x444; private boolean isVerifyingThreeDSecure = false; + private static DropInClient dropInClient = null; + private static String clientToken = null; + + public static void initDropInClient(FragmentActivity activity) { + dropInClient = new DropInClient(activity, callback -> { + if (clientToken != null) { + callback.onSuccess(clientToken); + } else { + callback.onFailure(new Exception("Client token is null")); + } + }); + } + public RNBraintreeDropInModule(ReactApplicationContext reactContext) { super(reactContext); - reactContext.addActivityEventListener(mActivityListener); } @ReactMethod @@ -42,92 +60,106 @@ public void show(final ReadableMap options, final Promise promise) { return; } - Activity currentActivity = getCurrentActivity(); + FragmentActivity currentActivity = (FragmentActivity) getCurrentActivity(); if (currentActivity == null) { promise.reject("NO_ACTIVITY", "There is no current activity"); return; } - DropInRequest dropInRequest = new DropInRequest().clientToken(options.getString("clientToken")); + DropInRequest dropInRequest = new DropInRequest(); if(options.hasKey("vaultManager")) { - dropInRequest.vaultManager(options.getBoolean("vaultManager")); + dropInRequest.setVaultManagerEnabled(options.getBoolean("vaultManager")); } - dropInRequest.collectDeviceData(true); - - if(options.getBoolean("googlePay")){ - GooglePaymentRequest googlePaymentRequest = new GooglePaymentRequest() - .transactionInfo(TransactionInfo.newBuilder() - .setTotalPrice(options.getString("orderTotal")) + if(options.hasKey("googlePay") && options.getBoolean("googlePay")){ + GooglePayRequest googlePayRequest = new GooglePayRequest(); + googlePayRequest.setTransactionInfo(TransactionInfo.newBuilder() + .setTotalPrice(Objects.requireNonNull(options.getString("orderTotal"))) .setTotalPriceStatus(WalletConstants.TOTAL_PRICE_STATUS_FINAL) - .setCurrencyCode(options.getString("currencyCode")) - .build()) - .billingAddressRequired(true) - .googleMerchantId(options.getString("googlePayMerchantId")); + .setCurrencyCode(Objects.requireNonNull(options.getString("currencyCode"))) + .build()); + googlePayRequest.setBillingAddressRequired(true); + googlePayRequest.setGoogleMerchantId(options.getString("googlePayMerchantId")); - dropInRequest.googlePaymentRequest(googlePaymentRequest); + dropInRequest.setGooglePayDisabled(false); + dropInRequest.setGooglePayRequest(googlePayRequest); }else{ - dropInRequest.disableGooglePayment(); + dropInRequest.setGooglePayDisabled(true); } - // if(options.hasKey("cardDisabled")) { - // dropInRequest.disableCard(); - // } + if(options.hasKey("cardDisabled")) { + dropInRequest.setCardDisabled(true); + } if (options.hasKey("threeDSecure")) { final ReadableMap threeDSecureOptions = options.getMap("threeDSecure"); - if (!threeDSecureOptions.hasKey("amount")) { + if (threeDSecureOptions == null || !threeDSecureOptions.hasKey("amount")) { promise.reject("NO_3DS_AMOUNT", "You must provide an amount for 3D Secure"); return; } isVerifyingThreeDSecure = true; - dropInRequest - .amount(String.valueOf(threeDSecureOptions.getDouble("amount"))) - .requestThreeDSecureVerification(true); - } - - if(!options.getBoolean("payPal")){ //disable paypal - dropInRequest.disablePayPal(); + ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest(); + threeDSecureRequest.setAmount(threeDSecureOptions.getString("amount")); + + dropInRequest.setThreeDSecureRequest(threeDSecureRequest); } + dropInRequest.setPayPalDisabled(!options.hasKey("payPal") || !options.getBoolean("payPal")); + mPromise = promise; - currentActivity.startActivityForResult(dropInRequest.getIntent(currentActivity), DROP_IN_REQUEST); + + clientToken = options.getString("clientToken"); + + if (dropInClient == null) { + mPromise.reject( + "DROP_IN_CLIENT_UNINITIALIZED", + "Did you forget to call RNBraintreeDropInModule.initDropInClient(this) in MainActivity.onCreate?" + ); + mPromise = null; + return; + } + dropInClient.setListener(mDropInListener); + dropInClient.launchDropIn(dropInRequest); } - private final ActivityEventListener mActivityListener = new BaseActivityEventListener() { + private final DropInListener mDropInListener = new DropInListener() { @Override - public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode != DROP_IN_REQUEST || mPromise == null) { + public void onDropInSuccess(@NonNull DropInResult dropInResult) { + if (mPromise == null) { return; } - - if (resultCode == Activity.RESULT_OK) { - DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT); - PaymentMethodNonce paymentMethodNonce = result.getPaymentMethodNonce(); - String deviceData = result.getDeviceData(); - - if (isVerifyingThreeDSecure && paymentMethodNonce instanceof CardNonce) { - CardNonce cardNonce = (CardNonce) paymentMethodNonce; - ThreeDSecureInfo threeDSecureInfo = cardNonce.getThreeDSecureInfo(); - if (!threeDSecureInfo.isLiabilityShiftPossible()) { - mPromise.reject("3DSECURE_NOT_ABLE_TO_SHIFT_LIABILITY", "3D Secure liability cannot be shifted"); - } else if (!threeDSecureInfo.isLiabilityShifted()) { - mPromise.reject("3DSECURE_LIABILITY_NOT_SHIFTED", "3D Secure liability was not shifted"); - } else { - resolvePayment(paymentMethodNonce, deviceData); - } + PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce(); + String deviceData = dropInResult.getDeviceData(); + + if (isVerifyingThreeDSecure && paymentMethodNonce instanceof CardNonce) { + CardNonce cardNonce = (CardNonce) paymentMethodNonce; + ThreeDSecureInfo threeDSecureInfo = cardNonce.getThreeDSecureInfo(); + if (!threeDSecureInfo.isLiabilityShiftPossible()) { + mPromise.reject("3DSECURE_NOT_ABLE_TO_SHIFT_LIABILITY", "3D Secure liability cannot be shifted"); + } else if (!threeDSecureInfo.isLiabilityShifted()) { + mPromise.reject("3DSECURE_LIABILITY_NOT_SHIFTED", "3D Secure liability was not shifted"); } else { - resolvePayment(paymentMethodNonce, deviceData); + resolvePayment(dropInResult, deviceData); } - } else if (resultCode == Activity.RESULT_CANCELED) { + } else { + resolvePayment(dropInResult, deviceData); + } + + mPromise = null; + } + + @Override + public void onDropInFailure(@NonNull Exception exception) { + if (mPromise == null) { + return; + } + + if (exception instanceof UserCanceledException) { mPromise.reject("USER_CANCELLATION", "The user cancelled"); } else { - Exception exception = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR); mPromise.reject(exception.getMessage(), exception.getMessage()); } @@ -135,17 +167,38 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode, } }; - private final void resolvePayment(PaymentMethodNonce paymentMethodNonce, String deviceData) { + private void resolvePayment(DropInResult dropInResult, String deviceData) { + PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce(); + WritableMap jsResult = Arguments.createMap(); - jsResult.putString("nonce", paymentMethodNonce.getNonce()); - jsResult.putString("type", paymentMethodNonce.getTypeLabel()); - jsResult.putString("description", paymentMethodNonce.getDescription()); + + if (paymentMethodNonce == null) { + mPromise.reject("NO_PAYMENT_METHOD_NONCE", "Payment method nonce is missing"); + return; + } + + Activity currentActivity = getCurrentActivity(); + if (currentActivity == null) { + mPromise.reject("NO_ACTIVITY", "There is no current activity"); + return; + } + + DropInPaymentMethod dropInPaymentMethod = dropInResult.getPaymentMethodType(); + if (dropInPaymentMethod == null) { + mPromise.reject("NO_PAYMENT_METHOD", "There is no payment method"); + return; + } + + jsResult.putString("nonce", paymentMethodNonce.getString()); + jsResult.putString("type", currentActivity.getString(dropInPaymentMethod.getLocalizedName())); + jsResult.putString("description", dropInResult.getPaymentDescription()); jsResult.putBoolean("isDefault", paymentMethodNonce.isDefault()); jsResult.putString("deviceData", deviceData); mPromise.resolve(jsResult); } + @NonNull @Override public String getName() { return "RNBraintreeDropIn";