Skip to content

Commit

Permalink
feat: add fetchMostRecentPaymentMethod method
Browse files Browse the repository at this point in the history
  • Loading branch information
mlazari committed Jan 6, 2023
1 parent e44ad0f commit 833b82c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 48 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}

Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ type ShowResult = {|

declare module.exports: {
show: (options: ShowOptions) => Promise<ShowResult>,
fetchMostRecentPaymentMethod: (clientToken: string) => Promise<ShowResult>,
};
15 changes: 15 additions & 0 deletions ios/RNBraintreeDropIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 833b82c

Please sign in to comment.