@xbenjii/react-native-braintree-dropin-ui 2.8.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,366 +1,396 @@
1
- package com.xbenjii.RNBraintreeDropIn;
2
-
3
- import android.app.Activity;
4
-
5
- import androidx.annotation.NonNull;
6
- import androidx.fragment.app.FragmentActivity;
7
-
8
- import com.braintreepayments.api.BraintreeClient;
9
- import com.braintreepayments.api.DataCollector;
10
- import com.braintreepayments.api.Card;
11
- import com.braintreepayments.api.CardClient;
12
- import com.braintreepayments.api.DropInClient;
13
- import com.braintreepayments.api.DropInListener;
14
- import com.braintreepayments.api.DropInPaymentMethod;
15
- import com.braintreepayments.api.ThreeDSecureRequest;
16
- import com.braintreepayments.api.ThreeDSecureAdditionalInformation;
17
- import com.braintreepayments.api.ThreeDSecurePostalAddress;
18
- import com.braintreepayments.api.UserCanceledException;
19
- import com.braintreepayments.api.PayPalAccountNonce;
20
- import com.braintreepayments.api.GooglePayCardNonce;
21
- import com.braintreepayments.api.PostalAddress;
22
- import com.facebook.react.bridge.ReactApplicationContext;
23
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
24
- import com.facebook.react.bridge.ReactMethod;
25
- import com.facebook.react.bridge.ReadableMap;
26
- import com.facebook.react.bridge.Arguments;
27
- import com.facebook.react.bridge.WritableMap;
28
- import com.facebook.react.bridge.Promise;
29
- import com.braintreepayments.api.DropInRequest;
30
- import com.braintreepayments.api.DropInResult;
31
- import com.braintreepayments.api.PaymentMethodNonce;
32
- import com.braintreepayments.api.CardNonce;
33
- import com.braintreepayments.api.ThreeDSecureInfo;
34
- import com.braintreepayments.api.GooglePayRequest;
35
- import com.google.android.gms.wallet.TransactionInfo;
36
- import com.google.android.gms.wallet.WalletConstants;
37
-
38
- import java.util.Objects;
39
-
40
- public class RNBraintreeDropInModule extends ReactContextBaseJavaModule {
41
- private boolean isVerifyingThreeDSecure = false;
42
- private static DropInClient dropInClient = null;
43
- private static String clientToken = null;
44
- public static final int GPAY_BILLING_ADDRESS_FORMAT_FULL = 1;
45
-
46
- public static void initDropInClient(FragmentActivity activity) {
47
- dropInClient = new DropInClient(activity, callback -> {
48
- if (clientToken != null) {
49
- callback.onSuccess(clientToken);
50
- } else {
51
- callback.onFailure(new Exception("Client token is null"));
52
- }
53
- });
54
- }
55
-
56
- public RNBraintreeDropInModule(ReactApplicationContext reactContext) {
57
- super(reactContext);
58
- }
59
-
60
- @ReactMethod
61
- public void show(final ReadableMap options, final Promise promise) {
62
- isVerifyingThreeDSecure = false;
63
-
64
- if (!options.hasKey("clientToken")) {
65
- promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
66
- return;
67
- }
68
-
69
- FragmentActivity currentActivity = (FragmentActivity) getCurrentActivity();
70
- if (currentActivity == null) {
71
- promise.reject("NO_ACTIVITY", "There is no current activity");
72
- return;
73
- }
74
-
75
- DropInRequest dropInRequest = new DropInRequest();
76
-
77
- if(options.hasKey("vaultManager")) {
78
- dropInRequest.setVaultManagerEnabled(options.getBoolean("vaultManager"));
79
- }
80
-
81
- if(options.hasKey("googlePay") && options.getBoolean("googlePay")){
82
- GooglePayRequest googlePayRequest = new GooglePayRequest();
83
- googlePayRequest.setTransactionInfo(TransactionInfo.newBuilder()
84
- .setTotalPrice(Objects.requireNonNull(options.getString("orderTotal")))
85
- .setTotalPriceStatus(WalletConstants.TOTAL_PRICE_STATUS_FINAL)
86
- .setCurrencyCode(Objects.requireNonNull(options.getString("currencyCode")))
87
- .build());
88
- googlePayRequest.setBillingAddressRequired(true);
89
- googlePayRequest.setEmailRequired(true);
90
- googlePayRequest.setBillingAddressFormat(GPAY_BILLING_ADDRESS_FORMAT_FULL);
91
- googlePayRequest.setGoogleMerchantId(options.getString("googlePayMerchantId"));
92
-
93
- dropInRequest.setGooglePayDisabled(false);
94
- dropInRequest.setGooglePayRequest(googlePayRequest);
95
- }else{
96
- dropInRequest.setGooglePayDisabled(true);
97
- }
98
-
99
- if(options.hasKey("cardDisabled")) {
100
- dropInRequest.setCardDisabled(options.getBoolean("cardDisabled"));
101
- }
102
-
103
- if (options.hasKey("threeDSecure")) {
104
- final ReadableMap threeDSecureOptions = options.getMap("threeDSecure");
105
- if (threeDSecureOptions == null || !threeDSecureOptions.hasKey("amount")) {
106
- promise.reject("NO_3DS_AMOUNT", "You must provide an amount for 3D Secure");
107
- return;
108
- }
109
-
110
- isVerifyingThreeDSecure = true;
111
-
112
- String amount = String.valueOf(threeDSecureOptions.getDouble("amount"));
113
-
114
- ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest();
115
- threeDSecureRequest.setAmount(amount);
116
- threeDSecureRequest.setVersionRequested(ThreeDSecureRequest.VERSION_2);
117
-
118
- if (threeDSecureOptions.hasKey("email")) {
119
- threeDSecureRequest.setEmail(threeDSecureOptions.getString("email"));
120
- }
121
-
122
- if(threeDSecureOptions.hasKey("billingAddress")) {
123
- final ReadableMap threeDSecureBillingAddress = threeDSecureOptions.getMap("billingAddress");
124
- ThreeDSecurePostalAddress billingAddress = new ThreeDSecurePostalAddress();
125
-
126
- if(threeDSecureBillingAddress.hasKey("givenName")) {
127
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("givenName"));
128
- }
129
-
130
- if(threeDSecureBillingAddress.hasKey("surname")) {
131
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("surname"));
132
- }
133
-
134
- if(threeDSecureBillingAddress.hasKey("streetAddress")) {
135
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("streetAddress"));
136
- }
137
-
138
- if(threeDSecureBillingAddress.hasKey("extendedAddress")) {
139
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("extendedAddress"));
140
- }
141
-
142
- if(threeDSecureBillingAddress.hasKey("locality")) {
143
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("locality"));
144
- }
145
-
146
- if(threeDSecureBillingAddress.hasKey("region")) {
147
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("region"));
148
- }
149
-
150
- if(threeDSecureBillingAddress.hasKey("countryCodeAlpha2")) {
151
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("countryCodeAlpha2"));
152
- }
153
-
154
- if(threeDSecureBillingAddress.hasKey("postalCode")) {
155
- billingAddress.setGivenName(threeDSecureBillingAddress.getString("postalCode"));
156
- }
157
-
158
- threeDSecureRequest.setBillingAddress(billingAddress);
159
- }
160
-
161
- dropInRequest.setThreeDSecureRequest(threeDSecureRequest);
162
- }
163
-
164
- dropInRequest.setPayPalDisabled(!options.hasKey("payPal") || !options.getBoolean("payPal"));
165
-
166
- clientToken = options.getString("clientToken");
167
-
168
- if (dropInClient == null) {
169
- promise.reject(
170
- "DROP_IN_CLIENT_UNINITIALIZED",
171
- "Did you forget to call RNBraintreeDropInModule.initDropInClient(this) in MainActivity.onCreate?"
172
- );
173
- return;
174
- }
175
- dropInClient.setListener(new DropInListener() {
176
- @Override
177
- public void onDropInSuccess(@NonNull DropInResult dropInResult) {
178
- PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce();
179
-
180
- if (isVerifyingThreeDSecure && paymentMethodNonce instanceof CardNonce) {
181
- CardNonce cardNonce = (CardNonce) paymentMethodNonce;
182
- ThreeDSecureInfo threeDSecureInfo = cardNonce.getThreeDSecureInfo();
183
- if (!threeDSecureInfo.isLiabilityShiftPossible()) {
184
- promise.reject("3DSECURE_NOT_ABLE_TO_SHIFT_LIABILITY", "3D Secure liability cannot be shifted");
185
- } else if (!threeDSecureInfo.isLiabilityShifted()) {
186
- promise.reject("3DSECURE_LIABILITY_NOT_SHIFTED", "3D Secure liability was not shifted");
187
- } else {
188
- resolvePayment(dropInResult, promise);
189
- }
190
- } else {
191
- resolvePayment(dropInResult, promise);
192
- }
193
- }
194
-
195
- @Override
196
- public void onDropInFailure(@NonNull Exception exception) {
197
- if (exception instanceof UserCanceledException) {
198
- promise.reject("USER_CANCELLATION", "The user cancelled");
199
- } else {
200
- promise.reject(exception.getMessage(), exception.getMessage());
201
- }
202
- }
203
- });
204
- dropInClient.launchDropIn(dropInRequest);
205
- }
206
-
207
- @ReactMethod
208
- public void getDeviceData(final String clientToken, final Promise promise) {
209
- BraintreeClient braintreeClient = new BraintreeClient(getCurrentActivity(), clientToken);
210
- DataCollector dataCollector = new DataCollector(braintreeClient);
211
- dataCollector.collectDeviceData(getCurrentActivity(), (deviceData, error) -> {
212
- if (error != null) {
213
- promise.reject("ERROR", "Error collecting device data");
214
- } else {
215
- promise.resolve(deviceData);
216
- }
217
- });
218
- }
219
-
220
- @ReactMethod
221
- public void fetchMostRecentPaymentMethod(final String clientToken, final Promise promise) {
222
- FragmentActivity currentActivity = (FragmentActivity) getCurrentActivity();
223
-
224
- if (currentActivity == null) {
225
- promise.reject("NO_ACTIVITY", "There is no current activity");
226
- return;
227
- }
228
-
229
- if (dropInClient == null) {
230
- promise.reject(
231
- "DROP_IN_CLIENT_UNINITIALIZED",
232
- "Did you forget to call RNBraintreeDropInModule.initDropInClient(this) in MainActivity.onCreate?"
233
- );
234
- return;
235
- }
236
-
237
- RNBraintreeDropInModule.clientToken = clientToken;
238
-
239
- dropInClient.fetchMostRecentPaymentMethod(currentActivity, (dropInResult, error) -> {
240
- if (error != null) {
241
- promise.reject(error.getMessage(), error.getMessage());
242
- } else if (dropInResult == null) {
243
- promise.reject("NO_DROP_IN_RESULT", "dropInResult is null");
244
- } else {
245
- resolvePayment(dropInResult, promise);
246
- }
247
- });
248
- }
249
-
250
- @ReactMethod
251
- public void tokenizeCard(final String clientToken, final ReadableMap cardInfo, final Promise promise) {
252
- if (clientToken == null) {
253
- promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
254
- return;
255
- }
256
-
257
- if (
258
- !cardInfo.hasKey("number") ||
259
- !cardInfo.hasKey("expirationMonth") ||
260
- !cardInfo.hasKey("expirationYear") ||
261
- !cardInfo.hasKey("cvv") ||
262
- !cardInfo.hasKey("postalCode")
263
- ) {
264
- promise.reject("INVALID_CARD_INFO", "Invalid card info");
265
- return;
266
- }
267
-
268
- Activity currentActivity = getCurrentActivity();
269
-
270
- if (currentActivity == null) {
271
- promise.reject("NO_ACTIVITY", "There is no current activity");
272
- return;
273
- }
274
-
275
- BraintreeClient braintreeClient = new BraintreeClient(getCurrentActivity(), clientToken);
276
- CardClient cardClient = new CardClient(braintreeClient);
277
-
278
- Card card = new Card();
279
- card.setNumber(cardInfo.getString("number"));
280
- card.setExpirationMonth(cardInfo.getString("expirationMonth"));
281
- card.setExpirationYear(cardInfo.getString("expirationYear"));
282
- card.setCvv(cardInfo.getString("cvv"));
283
- card.setPostalCode(cardInfo.getString("postalCode"));
284
-
285
- cardClient.tokenize(card, (cardNonce, error) -> {
286
- if (error != null) {
287
- promise.reject(error.getMessage(), error.getMessage());
288
- } else if (cardNonce == null) {
289
- promise.reject("NO_CARD_NONCE", "Card nonce is null");
290
- } else {
291
- promise.resolve(cardNonce.getString());
292
- }
293
- });
294
- }
295
-
296
- private void resolvePayment(DropInResult dropInResult, Promise promise) {
297
- String deviceData = dropInResult.getDeviceData();
298
- PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce();
299
-
300
- WritableMap jsResult = Arguments.createMap();
301
-
302
- if (paymentMethodNonce == null) {
303
- promise.resolve(null);
304
- return;
305
- }
306
-
307
- Activity currentActivity = getCurrentActivity();
308
- if (currentActivity == null) {
309
- promise.reject("NO_ACTIVITY", "There is no current activity");
310
- return;
311
- }
312
-
313
- DropInPaymentMethod dropInPaymentMethod = dropInResult.getPaymentMethodType();
314
- if (dropInPaymentMethod == null) {
315
- promise.reject("NO_PAYMENT_METHOD", "There is no payment method");
316
- return;
317
- }
318
-
319
- PostalAddress billingAddress = null;
320
- if(paymentMethodNonce instanceof PayPalAccountNonce) {
321
- PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
322
- jsResult.putString("firstName", payPalAccountNonce.getFirstName());
323
- jsResult.putString("lastName", payPalAccountNonce.getLastName());
324
- jsResult.putString("email", payPalAccountNonce.getEmail());
325
- billingAddress = payPalAccountNonce.getBillingAddress();
326
- } else if (paymentMethodNonce instanceof GooglePayCardNonce) {
327
- GooglePayCardNonce googlePayCardNonce = (GooglePayCardNonce) paymentMethodNonce;
328
- billingAddress = googlePayCardNonce.getBillingAddress();
329
- jsResult.putString("email", googlePayCardNonce.getEmail());
330
- if(billingAddress != null) {
331
- String name = billingAddress.getRecipientName();
332
- if(!name.equals("")) {
333
- short lastIndexOfSpace = (short) name.lastIndexOf(" ");
334
- if(lastIndexOfSpace == -1) {
335
- jsResult.putString("firstName", name.trim());
336
- } else {
337
- jsResult.putString("firstName", name.substring(0, lastIndexOfSpace));
338
- jsResult.putString("lastName", name.substring(lastIndexOfSpace));
339
- }
340
- }
341
- }
342
- }
343
- if(billingAddress != null) {
344
- jsResult.putString("addressLine1", billingAddress.getStreetAddress());
345
- jsResult.putString("addressLine2", billingAddress.getExtendedAddress());
346
- jsResult.putString("city", billingAddress.getLocality());
347
- jsResult.putString("state", billingAddress.getRegion());
348
- jsResult.putString("country", billingAddress.getCountryCodeAlpha2());
349
- jsResult.putString("zip1", billingAddress.getPostalCode());
350
- }
351
-
352
- jsResult.putString("nonce", paymentMethodNonce.getString());
353
- jsResult.putString("type", currentActivity.getString(dropInPaymentMethod.getLocalizedName()));
354
- jsResult.putString("description", dropInResult.getPaymentDescription());
355
- jsResult.putBoolean("isDefault", paymentMethodNonce.isDefault());
356
- jsResult.putString("deviceData", deviceData);
357
-
358
- promise.resolve(jsResult);
359
- }
360
-
361
- @NonNull
362
- @Override
363
- public String getName() {
364
- return "RNBraintreeDropIn";
365
- }
366
- }
1
+ package com.xbenjii.RNBraintreeDropIn;
2
+
3
+ import android.app.Activity;
4
+
5
+ import androidx.annotation.NonNull;
6
+ import androidx.fragment.app.FragmentActivity;
7
+
8
+ import com.braintreepayments.api.BraintreeClient;
9
+ import com.braintreepayments.api.DataCollector;
10
+ import com.braintreepayments.api.Card;
11
+ import com.braintreepayments.api.CardClient;
12
+ import com.braintreepayments.api.DropInClient;
13
+ import com.braintreepayments.api.DropInListener;
14
+ import com.braintreepayments.api.DropInPaymentMethod;
15
+ import com.braintreepayments.api.ThreeDSecureRequest;
16
+ import com.braintreepayments.api.ThreeDSecureAdditionalInformation;
17
+ import com.braintreepayments.api.ThreeDSecurePostalAddress;
18
+ import com.braintreepayments.api.UserCanceledException;
19
+ import com.braintreepayments.api.PayPalAccountNonce;
20
+ import com.braintreepayments.api.GooglePayCardNonce;
21
+ import com.braintreepayments.api.PostalAddress;
22
+ import com.facebook.react.bridge.ReactApplicationContext;
23
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
24
+ import com.facebook.react.bridge.ReactMethod;
25
+ import com.facebook.react.bridge.ReadableMap;
26
+ import com.facebook.react.bridge.Arguments;
27
+ import com.facebook.react.bridge.WritableMap;
28
+ import com.facebook.react.bridge.Promise;
29
+ import com.braintreepayments.api.DropInRequest;
30
+ import com.braintreepayments.api.DropInResult;
31
+ import com.braintreepayments.api.PaymentMethodNonce;
32
+ import com.braintreepayments.api.CardNonce;
33
+ import com.braintreepayments.api.ThreeDSecureInfo;
34
+ import com.braintreepayments.api.GooglePayRequest;
35
+ import com.google.android.gms.wallet.TransactionInfo;
36
+ import com.google.android.gms.wallet.WalletConstants;
37
+
38
+ import java.util.Objects;
39
+
40
+ public class RNBraintreeDropInModule extends ReactContextBaseJavaModule {
41
+ private boolean isVerifyingThreeDSecure = false;
42
+ private static DropInClient dropInClient = null;
43
+ private static String clientToken = null;
44
+ public static final int GPAY_BILLING_ADDRESS_FORMAT_FULL = 1;
45
+
46
+ public static void initDropInClient(FragmentActivity activity) {
47
+ dropInClient = new DropInClient(activity, callback -> {
48
+ if (clientToken != null) {
49
+ callback.onSuccess(clientToken);
50
+ } else {
51
+ callback.onFailure(new Exception("Client token is null"));
52
+ }
53
+ });
54
+ }
55
+
56
+ public RNBraintreeDropInModule(ReactApplicationContext reactContext) {
57
+ super(reactContext);
58
+ }
59
+
60
+ @ReactMethod
61
+ private void collectDeviceData(final String clientToken, final Promise promise) {
62
+ if (clientToken == null) {
63
+ promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
64
+ return;
65
+ }
66
+ Activity currentActivity = getCurrentActivity();
67
+ if (currentActivity == null) {
68
+ promise.reject("NO_ACTIVITY", "There is no current activity");
69
+ return;
70
+ }
71
+
72
+ BraintreeClient braintreeClient = new BraintreeClient(currentActivity, clientToken);
73
+ DataCollector dataCollector = new DataCollector(braintreeClient);
74
+
75
+ dataCollector.collectDeviceData(currentActivity, (deviceData, error) -> {
76
+ String data = deviceData;
77
+ if (data == null) {
78
+ data = "";
79
+ }
80
+ WritableMap jsResult = Arguments.createMap();
81
+ jsResult.putString("deviceData", data);
82
+ promise.resolve(jsResult);
83
+ });
84
+ }
85
+
86
+ @ReactMethod
87
+ public void show(final ReadableMap options, final Promise promise) {
88
+ isVerifyingThreeDSecure = false;
89
+
90
+ if (!options.hasKey("clientToken")) {
91
+ promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
92
+ return;
93
+ }
94
+
95
+ FragmentActivity currentActivity = (FragmentActivity) getCurrentActivity();
96
+ if (currentActivity == null) {
97
+ promise.reject("NO_ACTIVITY", "There is no current activity");
98
+ return;
99
+ }
100
+
101
+ DropInRequest dropInRequest = new DropInRequest();
102
+
103
+ if(options.hasKey("vaultManager")) {
104
+ dropInRequest.setVaultManagerEnabled(options.getBoolean("vaultManager"));
105
+ }
106
+
107
+ if(options.hasKey("vaultCardDefaultValue")) {
108
+ dropInRequest.setVaultCardDefaultValue(options.getBoolean("vaultCardDefaultValue"));
109
+ }
110
+
111
+ if(options.hasKey("googlePay") && options.getBoolean("googlePay")){
112
+ GooglePayRequest googlePayRequest = new GooglePayRequest();
113
+ googlePayRequest.setTransactionInfo(TransactionInfo.newBuilder()
114
+ .setTotalPrice(Objects.requireNonNull(options.getString("orderTotal")))
115
+ .setTotalPriceStatus(WalletConstants.TOTAL_PRICE_STATUS_FINAL)
116
+ .setCurrencyCode(Objects.requireNonNull(options.getString("currencyCode")))
117
+ .build());
118
+ googlePayRequest.setBillingAddressRequired(true);
119
+ googlePayRequest.setEmailRequired(true);
120
+ googlePayRequest.setBillingAddressFormat(GPAY_BILLING_ADDRESS_FORMAT_FULL);
121
+ googlePayRequest.setGoogleMerchantId(options.getString("googlePayMerchantId"));
122
+
123
+ dropInRequest.setGooglePayDisabled(false);
124
+ dropInRequest.setGooglePayRequest(googlePayRequest);
125
+ }else{
126
+ dropInRequest.setGooglePayDisabled(true);
127
+ }
128
+
129
+ if(options.hasKey("cardDisabled")) {
130
+ dropInRequest.setCardDisabled(options.getBoolean("cardDisabled"));
131
+ }
132
+
133
+ if (options.hasKey("threeDSecure")) {
134
+ final ReadableMap threeDSecureOptions = options.getMap("threeDSecure");
135
+ if (threeDSecureOptions == null || !threeDSecureOptions.hasKey("amount")) {
136
+ promise.reject("NO_3DS_AMOUNT", "You must provide an amount for 3D Secure");
137
+ return;
138
+ }
139
+
140
+ isVerifyingThreeDSecure = true;
141
+
142
+ String amount = String.valueOf(threeDSecureOptions.getDouble("amount"));
143
+
144
+ ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest();
145
+ threeDSecureRequest.setAmount(amount);
146
+ threeDSecureRequest.setVersionRequested(ThreeDSecureRequest.VERSION_2);
147
+
148
+ if (threeDSecureOptions.hasKey("email")) {
149
+ threeDSecureRequest.setEmail(threeDSecureOptions.getString("email"));
150
+ }
151
+
152
+ if(threeDSecureOptions.hasKey("billingAddress")) {
153
+ final ReadableMap threeDSecureBillingAddress = threeDSecureOptions.getMap("billingAddress");
154
+ ThreeDSecurePostalAddress billingAddress = new ThreeDSecurePostalAddress();
155
+
156
+ if(threeDSecureBillingAddress.hasKey("givenName")) {
157
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("givenName"));
158
+ }
159
+
160
+ if(threeDSecureBillingAddress.hasKey("surname")) {
161
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("surname"));
162
+ }
163
+
164
+ if(threeDSecureBillingAddress.hasKey("streetAddress")) {
165
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("streetAddress"));
166
+ }
167
+
168
+ if(threeDSecureBillingAddress.hasKey("extendedAddress")) {
169
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("extendedAddress"));
170
+ }
171
+
172
+ if(threeDSecureBillingAddress.hasKey("locality")) {
173
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("locality"));
174
+ }
175
+
176
+ if(threeDSecureBillingAddress.hasKey("region")) {
177
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("region"));
178
+ }
179
+
180
+ if(threeDSecureBillingAddress.hasKey("countryCodeAlpha2")) {
181
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("countryCodeAlpha2"));
182
+ }
183
+
184
+ if(threeDSecureBillingAddress.hasKey("postalCode")) {
185
+ billingAddress.setGivenName(threeDSecureBillingAddress.getString("postalCode"));
186
+ }
187
+
188
+ threeDSecureRequest.setBillingAddress(billingAddress);
189
+ }
190
+
191
+ dropInRequest.setThreeDSecureRequest(threeDSecureRequest);
192
+ }
193
+
194
+ dropInRequest.setPayPalDisabled(!options.hasKey("payPal") || !options.getBoolean("payPal"));
195
+
196
+ clientToken = options.getString("clientToken");
197
+
198
+ if (dropInClient == null) {
199
+ promise.reject(
200
+ "DROP_IN_CLIENT_UNINITIALIZED",
201
+ "Did you forget to call RNBraintreeDropInModule.initDropInClient(this) in MainActivity.onCreate?"
202
+ );
203
+ return;
204
+ }
205
+ dropInClient.setListener(new DropInListener() {
206
+ @Override
207
+ public void onDropInSuccess(@NonNull DropInResult dropInResult) {
208
+ PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce();
209
+
210
+ if (isVerifyingThreeDSecure && paymentMethodNonce instanceof CardNonce) {
211
+ CardNonce cardNonce = (CardNonce) paymentMethodNonce;
212
+ ThreeDSecureInfo threeDSecureInfo = cardNonce.getThreeDSecureInfo();
213
+ if (!threeDSecureInfo.isLiabilityShiftPossible()) {
214
+ promise.reject("3DSECURE_NOT_ABLE_TO_SHIFT_LIABILITY", "3D Secure liability cannot be shifted");
215
+ } else if (!threeDSecureInfo.isLiabilityShifted()) {
216
+ promise.reject("3DSECURE_LIABILITY_NOT_SHIFTED", "3D Secure liability was not shifted");
217
+ } else {
218
+ resolvePayment(dropInResult, promise);
219
+ }
220
+ } else {
221
+ resolvePayment(dropInResult, promise);
222
+ }
223
+ }
224
+
225
+ @Override
226
+ public void onDropInFailure(@NonNull Exception exception) {
227
+ if (exception instanceof UserCanceledException) {
228
+ promise.reject("USER_CANCELLATION", "The user cancelled");
229
+ } else {
230
+ promise.reject(exception.getMessage(), exception.getMessage());
231
+ }
232
+ }
233
+ });
234
+ dropInClient.launchDropIn(dropInRequest);
235
+ }
236
+
237
+ @ReactMethod
238
+ public void getDeviceData(final String clientToken, final Promise promise) {
239
+ BraintreeClient braintreeClient = new BraintreeClient(getCurrentActivity(), clientToken);
240
+ DataCollector dataCollector = new DataCollector(braintreeClient);
241
+ dataCollector.collectDeviceData(getCurrentActivity(), (deviceData, error) -> {
242
+ if (error != null) {
243
+ promise.reject("ERROR", "Error collecting device data");
244
+ } else {
245
+ promise.resolve(deviceData);
246
+ }
247
+ });
248
+ }
249
+
250
+ @ReactMethod
251
+ public void fetchMostRecentPaymentMethod(final String clientToken, final Promise promise) {
252
+ FragmentActivity currentActivity = (FragmentActivity) getCurrentActivity();
253
+
254
+ if (currentActivity == null) {
255
+ promise.reject("NO_ACTIVITY", "There is no current activity");
256
+ return;
257
+ }
258
+
259
+ if (dropInClient == null) {
260
+ promise.reject(
261
+ "DROP_IN_CLIENT_UNINITIALIZED",
262
+ "Did you forget to call RNBraintreeDropInModule.initDropInClient(this) in MainActivity.onCreate?"
263
+ );
264
+ return;
265
+ }
266
+
267
+ RNBraintreeDropInModule.clientToken = clientToken;
268
+
269
+ dropInClient.fetchMostRecentPaymentMethod(currentActivity, (dropInResult, error) -> {
270
+ if (error != null) {
271
+ promise.reject(error.getMessage(), error.getMessage());
272
+ } else if (dropInResult == null) {
273
+ promise.reject("NO_DROP_IN_RESULT", "dropInResult is null");
274
+ } else {
275
+ resolvePayment(dropInResult, promise);
276
+ }
277
+ });
278
+ }
279
+
280
+ @ReactMethod
281
+ public void tokenizeCard(final String clientToken, final ReadableMap cardInfo, final Promise promise) {
282
+ if (clientToken == null) {
283
+ promise.reject("NO_CLIENT_TOKEN", "You must provide a client token");
284
+ return;
285
+ }
286
+
287
+ if (
288
+ !cardInfo.hasKey("number") ||
289
+ !cardInfo.hasKey("expirationMonth") ||
290
+ !cardInfo.hasKey("expirationYear") ||
291
+ !cardInfo.hasKey("cvv") ||
292
+ !cardInfo.hasKey("postalCode")
293
+ ) {
294
+ promise.reject("INVALID_CARD_INFO", "Invalid card info");
295
+ return;
296
+ }
297
+
298
+ Activity currentActivity = getCurrentActivity();
299
+
300
+ if (currentActivity == null) {
301
+ promise.reject("NO_ACTIVITY", "There is no current activity");
302
+ return;
303
+ }
304
+
305
+ BraintreeClient braintreeClient = new BraintreeClient(getCurrentActivity(), clientToken);
306
+ CardClient cardClient = new CardClient(braintreeClient);
307
+
308
+ Card card = new Card();
309
+ card.setNumber(cardInfo.getString("number"));
310
+ card.setExpirationMonth(cardInfo.getString("expirationMonth"));
311
+ card.setExpirationYear(cardInfo.getString("expirationYear"));
312
+ card.setCvv(cardInfo.getString("cvv"));
313
+ card.setPostalCode(cardInfo.getString("postalCode"));
314
+
315
+ cardClient.tokenize(card, (cardNonce, error) -> {
316
+ if (error != null) {
317
+ promise.reject(error.getMessage(), error.getMessage());
318
+ } else if (cardNonce == null) {
319
+ promise.reject("NO_CARD_NONCE", "Card nonce is null");
320
+ } else {
321
+ promise.resolve(cardNonce.getString());
322
+ }
323
+ });
324
+ }
325
+
326
+ private void resolvePayment(DropInResult dropInResult, Promise promise) {
327
+ String deviceData = dropInResult.getDeviceData();
328
+ PaymentMethodNonce paymentMethodNonce = dropInResult.getPaymentMethodNonce();
329
+
330
+ WritableMap jsResult = Arguments.createMap();
331
+
332
+ if (paymentMethodNonce == null) {
333
+ promise.resolve(null);
334
+ return;
335
+ }
336
+
337
+ Activity currentActivity = getCurrentActivity();
338
+ if (currentActivity == null) {
339
+ promise.reject("NO_ACTIVITY", "There is no current activity");
340
+ return;
341
+ }
342
+
343
+ DropInPaymentMethod dropInPaymentMethod = dropInResult.getPaymentMethodType();
344
+ if (dropInPaymentMethod == null) {
345
+ promise.reject("NO_PAYMENT_METHOD", "There is no payment method");
346
+ return;
347
+ }
348
+
349
+ PostalAddress billingAddress = null;
350
+ if(paymentMethodNonce instanceof PayPalAccountNonce) {
351
+ PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
352
+ jsResult.putString("firstName", payPalAccountNonce.getFirstName());
353
+ jsResult.putString("lastName", payPalAccountNonce.getLastName());
354
+ jsResult.putString("email", payPalAccountNonce.getEmail());
355
+ billingAddress = payPalAccountNonce.getBillingAddress();
356
+ } else if (paymentMethodNonce instanceof GooglePayCardNonce) {
357
+ GooglePayCardNonce googlePayCardNonce = (GooglePayCardNonce) paymentMethodNonce;
358
+ billingAddress = googlePayCardNonce.getBillingAddress();
359
+ jsResult.putString("email", googlePayCardNonce.getEmail());
360
+ if(billingAddress != null) {
361
+ String name = billingAddress.getRecipientName();
362
+ if(!name.equals("")) {
363
+ short lastIndexOfSpace = (short) name.lastIndexOf(" ");
364
+ if(lastIndexOfSpace == -1) {
365
+ jsResult.putString("firstName", name.trim());
366
+ } else {
367
+ jsResult.putString("firstName", name.substring(0, lastIndexOfSpace));
368
+ jsResult.putString("lastName", name.substring(lastIndexOfSpace));
369
+ }
370
+ }
371
+ }
372
+ }
373
+ if(billingAddress != null) {
374
+ jsResult.putString("addressLine1", billingAddress.getStreetAddress());
375
+ jsResult.putString("addressLine2", billingAddress.getExtendedAddress());
376
+ jsResult.putString("city", billingAddress.getLocality());
377
+ jsResult.putString("state", billingAddress.getRegion());
378
+ jsResult.putString("country", billingAddress.getCountryCodeAlpha2());
379
+ jsResult.putString("zip1", billingAddress.getPostalCode());
380
+ }
381
+
382
+ jsResult.putString("nonce", paymentMethodNonce.getString());
383
+ jsResult.putString("type", currentActivity.getString(dropInPaymentMethod.getLocalizedName()));
384
+ jsResult.putString("description", dropInResult.getPaymentDescription());
385
+ jsResult.putBoolean("isDefault", paymentMethodNonce.isDefault());
386
+ jsResult.putString("deviceData", deviceData);
387
+
388
+ promise.resolve(jsResult);
389
+ }
390
+
391
+ @NonNull
392
+ @Override
393
+ public String getName() {
394
+ return "RNBraintreeDropIn";
395
+ }
396
+ }