From 833b82c25bb0cbc1b349aacf528d86de1f23af7d Mon Sep 17 00:00:00 2001 From: Mihai Date: Fri, 6 Jan 2023 17:35:55 +0200 Subject: [PATCH] feat: add fetchMostRecentPaymentMethod method --- README.md | 12 ++ .../RNBraintreeDropInModule.java | 106 ++++++++++-------- index.js.flow | 1 + ios/RNBraintreeDropIn.m | 15 +++ 4 files changed, 86 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index fa4062e..2ced92d 100644 --- a/README.md +++ b/README.md @@ -311,6 +311,18 @@ BraintreeDropIn.show({ }); ``` +### Fetch more recent payment method + +```javascript +import BraintreeDropIn from 'react-native-braintree-dropin-ui'; + +BraintreeDropIn.fetchMostRecentPaymentMethod(clientToken) +.then(result => console.log(result)) +.catch((error) => { + // Handle error +}); +``` + ### Custom Fonts ``` BraintreeDropIn.show({ diff --git a/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java b/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java index 00697f1..e59b8f7 100644 --- a/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java +++ b/android/src/main/java/tech/power/RNBraintreeDropIn/RNBraintreeDropInModule.java @@ -29,11 +29,7 @@ import java.util.Objects; public class RNBraintreeDropInModule extends ReactContextBaseJavaModule { - - private Promise mPromise; - private boolean isVerifyingThreeDSecure = false; - private static DropInClient dropInClient = null; private static String clientToken = null; @@ -109,83 +105,97 @@ public void show(final ReadableMap options, final Promise promise) { dropInRequest.setPayPalDisabled(!options.hasKey("payPal") || !options.getBoolean("payPal")); - mPromise = promise; - clientToken = options.getString("clientToken"); if (dropInClient == null) { - mPromise.reject( + promise.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 DropInListener mDropInListener = new DropInListener() { - @Override - public void onDropInSuccess(@NonNull DropInResult dropInResult) { - if (mPromise == null) { - return; + dropInClient.setListener(new DropInListener() { + @Override + public void onDropInSuccess(@NonNull DropInResult dropInResult) { + PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce(); + + if (isVerifyingThreeDSecure && paymentMethodNonce instanceof CardNonce) { + CardNonce cardNonce = (CardNonce) paymentMethodNonce; + ThreeDSecureInfo threeDSecureInfo = cardNonce.getThreeDSecureInfo(); + if (!threeDSecureInfo.isLiabilityShiftPossible()) { + promise.reject("3DSECURE_NOT_ABLE_TO_SHIFT_LIABILITY", "3D Secure liability cannot be shifted"); + } else if (!threeDSecureInfo.isLiabilityShifted()) { + promise.reject("3DSECURE_LIABILITY_NOT_SHIFTED", "3D Secure liability was not shifted"); + } else { + resolvePayment(dropInResult, promise); + } + } else { + resolvePayment(dropInResult, promise); + } } - 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"); + + @Override + public void onDropInFailure(@NonNull Exception exception) { + if (exception instanceof UserCanceledException) { + promise.reject("USER_CANCELLATION", "The user cancelled"); } else { - resolvePayment(dropInResult, deviceData); + promise.reject(exception.getMessage(), exception.getMessage()); } - } else { - resolvePayment(dropInResult, deviceData); } + }); + dropInClient.launchDropIn(dropInRequest); + } + + @ReactMethod + public void fetchMostRecentPaymentMethod(final String clientToken, final Promise promise) { + FragmentActivity currentActivity = (FragmentActivity) getCurrentActivity(); - mPromise = null; + if (currentActivity == null) { + promise.reject("NO_ACTIVITY", "There is no current activity"); + return; } - @Override - public void onDropInFailure(@NonNull Exception exception) { - if (mPromise == null) { - return; - } + if (dropInClient == null) { + promise.reject( + "DROP_IN_CLIENT_UNINITIALIZED", + "Did you forget to call RNBraintreeDropInModule.initDropInClient(this) in MainActivity.onCreate?" + ); + return; + } - if (exception instanceof UserCanceledException) { - mPromise.reject("USER_CANCELLATION", "The user cancelled"); + RNBraintreeDropInModule.clientToken = clientToken; + + dropInClient.fetchMostRecentPaymentMethod(currentActivity, (dropInResult, error) -> { + if (error != null) { + promise.reject(error.getMessage(), error.getMessage()); + } else if (dropInResult == null) { + promise.reject("NO_DROP_IN_RESULT", "dropInResult is null"); } else { - mPromise.reject(exception.getMessage(), exception.getMessage()); + resolvePayment(dropInResult, promise); } + }); + } - mPromise = null; - } - }; - - private void resolvePayment(DropInResult dropInResult, String deviceData) { + private void resolvePayment(DropInResult dropInResult, Promise promise) { + String deviceData = dropInResult.getDeviceData(); PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce(); WritableMap jsResult = Arguments.createMap(); if (paymentMethodNonce == null) { - mPromise.reject("NO_PAYMENT_METHOD_NONCE", "Payment method nonce is missing"); + promise.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"); + promise.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"); + promise.reject("NO_PAYMENT_METHOD", "There is no payment method"); return; } @@ -195,7 +205,7 @@ private void resolvePayment(DropInResult dropInResult, String deviceData) { jsResult.putBoolean("isDefault", paymentMethodNonce.isDefault()); jsResult.putString("deviceData", deviceData); - mPromise.resolve(jsResult); + promise.resolve(jsResult); } @NonNull diff --git a/index.js.flow b/index.js.flow index 18fdc4a..579e6f4 100644 --- a/index.js.flow +++ b/index.js.flow @@ -29,4 +29,5 @@ type ShowResult = {| declare module.exports: { show: (options: ShowOptions) => Promise, + fetchMostRecentPaymentMethod: (clientToken: string) => Promise, }; diff --git a/ios/RNBraintreeDropIn.m b/ios/RNBraintreeDropIn.m index 068f203..17ea5a4 100644 --- a/ios/RNBraintreeDropIn.m +++ b/ios/RNBraintreeDropIn.m @@ -146,6 +146,21 @@ - (dispatch_queue_t)methodQueue } } +RCT_EXPORT_METHOD(fetchMostRecentPaymentMethod:(NSString*)clientToken + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + [BTDropInResult mostRecentPaymentMethodForClientToken:clientToken completion:^(BTDropInResult * _Nullable result, NSError * _Nullable error) { + if (error != nil) { + reject(error.localizedDescription, error.localizedDescription, error); + } else if (result.canceled) { + reject(@"USER_CANCELLATION", @"The user cancelled", nil); + } else { + [[self class] resolvePayment:result deviceData:result.deviceData resolver:resolve]; + } + }]; +} + - (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment handler:(nonnull void (^)(PKPaymentAuthorizationResult * _Nonnull))completion