Skip to content

Commit

Permalink
Merge pull request #1 from copartit/mmm-12392
Browse files Browse the repository at this point in the history
Braintree DropIn ios v5, Android v4 migration
  • Loading branch information
pruthvi-kasina authored Jan 19, 2024
2 parents 6dc32cd + 31e761c commit 1493319
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
import com.braintreepayments.api.DropInPaymentMethod;
import com.braintreepayments.api.ThreeDSecureRequest;
import com.braintreepayments.api.UserCanceledException;
import com.braintreepayments.api.DataCollector;
import com.braintreepayments.api.PayPalAccountNonce;
import com.braintreepayments.api.GooglePayCardNonce;
import com.braintreepayments.api.PostalAddress;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
Expand All @@ -35,6 +39,7 @@ public class RNBraintreeDropInModule extends ReactContextBaseJavaModule {
private boolean isVerifyingThreeDSecure = false;
private static DropInClient dropInClient = null;
private static String clientToken = null;
public static final int GPAY_BILLING_ADDRESS_FORMAT_FULL = 1;

public static void initDropInClient(FragmentActivity activity) {
dropInClient = new DropInClient(activity, callback -> {
Expand All @@ -50,6 +55,32 @@ public RNBraintreeDropInModule(ReactApplicationContext reactContext) {
super(reactContext);
}

@ReactMethod
private void collectDeviceData(final String clientToken, final Promise promise) {
if (clientToken == null) {
promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
return;
}
Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
promise.reject("NO_ACTIVITY", "There is no current activity");
return;
}

BraintreeClient braintreeClient = new BraintreeClient(currentActivity, clientToken);
DataCollector dataCollector = new DataCollector(braintreeClient);

dataCollector.collectDeviceData(currentActivity, (deviceData, error) -> {
String data = deviceData;
if (data == null) {
data = "";
}
WritableMap jsResult = Arguments.createMap();
jsResult.putString("deviceData", data);
promise.resolve(jsResult);
});
}

@ReactMethod
public void show(final ReadableMap options, final Promise promise) {
isVerifyingThreeDSecure = false;
Expand Down Expand Up @@ -79,6 +110,8 @@ public void show(final ReadableMap options, final Promise promise) {
.setCurrencyCode(Objects.requireNonNull(options.getString("currencyCode")))
.build());
googlePayRequest.setBillingAddressRequired(true);
googlePayRequest.setEmailRequired(true);
googlePayRequest.setBillingAddressFormat(GPAY_BILLING_ADDRESS_FORMAT_FULL);
googlePayRequest.setGoogleMerchantId(options.getString("googlePayMerchantId"));

dropInRequest.setGooglePayDisabled(false);
Expand Down Expand Up @@ -247,7 +280,38 @@ private void resolvePayment(DropInResult dropInResult, Promise promise) {
promise.reject("NO_PAYMENT_METHOD", "There is no payment method");
return;
}

PostalAddress billingAddress = null;
if(paymentMethodNonce instanceof PayPalAccountNonce) {
PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
jsResult.putString("firstName", payPalAccountNonce.getFirstName());
jsResult.putString("lastName", payPalAccountNonce.getLastName());
jsResult.putString("email", payPalAccountNonce.getEmail());
billingAddress = payPalAccountNonce.getBillingAddress();
} else if (paymentMethodNonce instanceof GooglePayCardNonce) {
GooglePayCardNonce googlePayCardNonce = (GooglePayCardNonce) paymentMethodNonce;
billingAddress = googlePayCardNonce.getBillingAddress();
jsResult.putString("email", googlePayCardNonce.getEmail());
if(billingAddress != null) {
String name = billingAddress.getRecipientName();
if(!name.equals("")) {
short lastIndexOfSpace = (short) name.lastIndexOf(" ");
if(lastIndexOfSpace == -1) {
jsResult.putString("firstName", name.trim());
} else {
jsResult.putString("firstName", name.substring(0, lastIndexOfSpace));
jsResult.putString("lastName", name.substring(lastIndexOfSpace));
}
}
}
}
if(billingAddress != null) {
jsResult.putString("addressLine1", billingAddress.getStreetAddress());
jsResult.putString("addressLine2", billingAddress.getExtendedAddress());
jsResult.putString("city", billingAddress.getLocality());
jsResult.putString("state", billingAddress.getRegion());
jsResult.putString("country", billingAddress.getCountryCodeAlpha2());
jsResult.putString("zip1", billingAddress.getPostalCode());
}
jsResult.putString("nonce", paymentMethodNonce.getString());
jsResult.putString("type", currentActivity.getString(dropInPaymentMethod.getLocalizedName()));
jsResult.putString("description", dropInResult.getPaymentDescription());
Expand Down
70 changes: 65 additions & 5 deletions ios/RNBraintreeDropIn.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "RNBraintreeDropIn.h"
#import <React/RCTUtils.h>
#import "BTThreeDSecureRequest.h"
#import "BTPayPalAccountNonce.h"

@implementation RNBraintreeDropIn

Expand All @@ -10,6 +11,22 @@ - (dispatch_queue_t)methodQueue
}
RCT_EXPORT_MODULE(RNBraintreeDropIn)

RCT_EXPORT_METHOD(collectDeviceData:(NSString*)clientToken resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
if (!clientToken) {
reject(@"NO_CLIENT_TOKEN", @"You must provide a client token", nil);
return;
}
BTAPIClient *apiClient = [[BTAPIClient alloc] initWithAuthorization:clientToken];
self.dataCollector = [[BTDataCollector alloc] initWithAPIClient:apiClient];

[self.dataCollector collectDeviceData:^(NSString * _Nonnull deviceData) {
NSMutableDictionary* jsResult = [NSMutableDictionary new];
[jsResult setObject:deviceData forKey:@"deviceData"];
resolve(jsResult);
}];
}

RCT_EXPORT_METHOD(show:(NSDictionary*)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
BTDropInColorScheme colorScheme;
Expand Down Expand Up @@ -97,7 +114,11 @@ - (dispatch_queue_t)methodQueue
@[
[PKPaymentSummaryItem summaryItemWithLabel:merchantName amount:orderTotal]
];

if (@available(iOS 11.0, *)) {
self.paymentRequest.requiredBillingContactFields = [[NSSet<PKContactField> alloc] initWithObjects: PKContactFieldPostalAddress, PKContactFieldEmailAddress, PKContactFieldName, nil];
} else {
reject(@"MISSING_OPTIONS", @"Not all required Apple Pay options were provided", nil);
}
self.viewController = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest: self.paymentRequest];
self.viewController.delegate = self;
}else{
Expand Down Expand Up @@ -222,7 +243,23 @@ - (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController
[result setObject:[NSString stringWithFormat: @"%@ %@", @"", tokenizedApplePayPayment.type] forKey:@"description"];
[result setObject:[NSNumber numberWithBool:false] forKey:@"isDefault"];
[result setObject:self.deviceDataCollector forKey:@"deviceData"];

if(payment.billingContact && payment.billingContact.postalAddress) {
[result setObject:payment.billingContact.name.givenName forKey:@"firstName"];
[result setObject:payment.billingContact.name.familyName forKey:@"lastName"];
if(payment.billingContact.emailAddress) {
[result setObject:payment.billingContact.emailAddress forKey:@"email"];
}
NSString *street = payment.billingContact.postalAddress.street;
NSArray *splitArray = [street componentsSeparatedByString:@"\n"];
[result setObject:splitArray[0] forKey:@"addressLine1"];
if([splitArray count] > 1 && splitArray[1]) {
[result setObject:splitArray[1] forKey:@"addressLine2"];
}
[result setObject:payment.billingContact.postalAddress.city forKey:@"city"];
[result setObject:payment.billingContact.postalAddress.state forKey:@"state"];
[result setObject:payment.billingContact.postalAddress.ISOCountryCode forKey:@"country"];
[result setObject:payment.billingContact.postalAddress.postalCode forKey:@"zip1"];
}
self.resolve(result);

} else {
Expand Down Expand Up @@ -252,9 +289,32 @@ + (void)resolvePayment:(BTDropInResult* _Nullable)result deviceData:(NSString *

NSMutableDictionary* jsResult = [NSMutableDictionary new];

//NSLog(@"paymentMethod = %@", result.paymentMethod);
//NSLog(@"paymentIcon = %@", result.paymentIcon);

if(result.paymentMethodType == BTDropInPaymentMethodTypePayPal) {
BTPayPalAccountNonce *paypalNonce = (BTPayPalAccountNonce *)result.paymentMethod;
[jsResult setObject:paypalNonce.firstName forKey:@"firstName"];
[jsResult setObject:paypalNonce.lastName forKey:@"lastName"];
[jsResult setObject:paypalNonce.email forKey:@"email"];
if(paypalNonce.billingAddress != nil) {
if(paypalNonce.billingAddress.streetAddress != nil) {
[jsResult setObject:paypalNonce.billingAddress.streetAddress forKey:@"addressLine1"];
}
if(paypalNonce.billingAddress.extendedAddress != nil) {
[jsResult setObject:paypalNonce.billingAddress.extendedAddress forKey:@"addressLine2"];
}
if(paypalNonce.billingAddress.locality != nil) {
[jsResult setObject:paypalNonce.billingAddress.locality forKey:@"city"];
}
if(paypalNonce.billingAddress.region != nil) {
[jsResult setObject:paypalNonce.billingAddress.region forKey:@"state"];
}
if(paypalNonce.billingAddress.countryCodeAlpha2 != nil) {
[jsResult setObject:paypalNonce.billingAddress.countryCodeAlpha2 forKey:@"country"];
}
if(paypalNonce.billingAddress.postalCode != nil) {
[jsResult setObject:paypalNonce.billingAddress.postalCode forKey:@"zip1"];
}
}
}
[jsResult setObject:result.paymentMethod.nonce forKey:@"nonce"];
[jsResult setObject:result.paymentMethod.type forKey:@"type"];
[jsResult setObject:result.paymentDescription forKey:@"description"];
Expand Down

0 comments on commit 1493319

Please sign in to comment.