Skip to content

Commit 951af0c

Browse files
committed
3DS 2 on Android
1 parent 921d64e commit 951af0c

File tree

6 files changed

+89
-47
lines changed

6 files changed

+89
-47
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![npm version](https://badge.fury.io/js/react-native-braintree-custom-ui.svg)](https://badge.fury.io/js/react-native-braintree-custom-ui)
33

44
An effort to update https://github.com/kraffslol/react-native-braintree-xplat.
5-
Use Braintree Android SDK V2 & IOS V4, with 3D Secure V1 on every payment.
5+
Use Braintree Android SDK V2 with 3DS & IOS V4 with 3DS 2.
66

77
## Installation
88

@@ -27,6 +27,20 @@ You will need the CardinalMobile.framework for 3DS 2 (https://developers.braintr
2727
curl -L -ubraintree-team-sdk@cardinalcommerce:220cc9476025679c4e5c843666c27d97cfb0f951 "https://cardinalcommerce.bintray.com/ios/2.1.4-2/cardinalmobilesdk.zip" -o cardinalmobile2.1.4-2.zip
2828
```
2929

30+
For Android you will need to add this to you build.gradle
31+
32+
```
33+
repositories {
34+
maven {
35+
url "https://cardinalcommerce.bintray.com/android"
36+
credentials {
37+
username 'braintree-team-sdk@cardinalcommerce'
38+
password '220cc9476025679c4e5c843666c27d97cfb0f951'
39+
}
40+
}
41+
}
42+
```
43+
3044
## Custom Integration
3145
If you only want to tokenize credit card information, you can use the following:
3246

android/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ android {
1616
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
1717
}
1818
}
19+
1920
}
2021

2122

2223
dependencies {
2324
implementation fileTree(dir: "libs", include: ["*.jar"])
2425
implementation "com.facebook.react:react-native:+"
25-
compile 'com.braintreepayments.api:braintree:2.22.0'
26+
compile 'com.braintreepayments.api:braintree:+'
2627
compile 'com.squareup.okhttp:okhttp:2.5.0'
27-
// implementation 'com.braintreepayments.api:three-d-secure:3.4.2'
28-
implementation 'com.braintreepayments.api:drop-in:2.+'
28+
implementation 'com.braintreepayments.api:three-d-secure:3.4.2'
2929
implementation group: 'com.google.code.gson', name: 'gson', version: '2.3.1'
3030
}

android/src/main/java/com/pw/droplet/braintree/Braintree.java

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import com.braintreepayments.api.interfaces.BraintreeCancelListener;
77

88
import java.io.IOException;
9-
9+
import androidx.appcompat.app.AppCompatActivity;
1010
import com.squareup.okhttp.MediaType;
1111
import com.squareup.okhttp.OkHttpClient;
1212
import com.squareup.okhttp.Request;
@@ -21,7 +21,6 @@
2121
import com.braintreepayments.api.models.ThreeDSecureRequest;
2222
import com.braintreepayments.api.models.PaymentMethodNonce;
2323
import com.braintreepayments.api.BraintreeFragment;
24-
import com.braintreepayments.api.BraintreePaymentActivity;
2524
import android.app.Activity;
2625
import com.braintreepayments.api.exceptions.InvalidArgumentException;
2726
import com.braintreepayments.api.exceptions.BraintreeError;
@@ -40,7 +39,7 @@
4039
import com.facebook.react.bridge.ReactMethod;
4140
import com.facebook.react.bridge.ReadableMap;
4241

43-
public class Braintree extends ReactContextBaseJavaModule implements ActivityEventListener {
42+
public class Braintree extends ReactContextBaseJavaModule {
4443
private static final int PAYMENT_REQUEST = 1706816330;
4544
private String token;
4645

@@ -54,7 +53,6 @@ public class Braintree extends ReactContextBaseJavaModule implements ActivityEv
5453

5554
public Braintree(ReactApplicationContext reactContext) {
5655
super(reactContext);
57-
reactContext.addActivityEventListener(this);
5856
}
5957

6058
@Override
@@ -80,12 +78,17 @@ public void setup(final String url, final Callback successCallback, final Callba
8078
Request request = new Request.Builder()
8179
.url(url)
8280
.build();
81+
Log.d("PAYMENT_REQUEST" ,url);
8382
try {
8483
Response response = client.newCall(request).execute();
85-
86-
this.mBraintreeFragment = BraintreeFragment.newInstance(getCurrentActivity(), response.body().string());
87-
}catch(IOException e){}
88-
84+
String res = response.body().string();
85+
Log.d("PAYMENT_REQUEST",res);
86+
this.mBraintreeFragment = BraintreeFragment.newInstance((AppCompatActivity) getCurrentActivity(), res);
87+
Log.d("PAYMENT_REQUEST", res);
88+
}catch(IOException e){
89+
Log.e("PAYMENT_REQUEST", "I got an error", e);
90+
}
91+
8992
this.mBraintreeFragment.addListener(new BraintreeCancelListener() {
9093
@Override
9194
public void onCancel(int requestCode) {
@@ -210,8 +213,40 @@ public void check3DSecure(final ReadableMap parameters, final Callback successCa
210213
Log.d("PAYMENT_REQUEST",parameters.getString("nonce"));
211214
this.successCallback = successCallback;
212215
this.errorCallback = errorCallback;
216+
217+
// .email("[email protected]")
218+
// .billingAddress(address);
219+
// .nonce(cardNonce.getNonce())
220+
// .versionRequested(ThreeDSecureRequest.VERSION_2)
221+
// .additionalInformation(additionalInformation);
222+
223+
// ThreeDSecurePostalAddress address = new ThreeDSecurePostalAddress()
224+
// .givenName("Jill") // ASCII-printable characters required, else will throw a validation error
225+
// .surname("Doe") // ASCII-printable characters required, else will throw a validation error
226+
// .phoneNumber("5551234567")
227+
// .streetAddress("555 Smith St")
228+
// .extendedAddress("#2")
229+
// .locality("Chicago")
230+
// .region("IL")
231+
// .postalCode("12345")
232+
// .countryCodeAlpha2("US");
233+
234+
// // For best results, provide as many additional elements as possible.
235+
// ThreeDSecureAdditionalInformation additionalInformation = new ThreeDSecureAdditionalInformation()
236+
// .shippingAddress(address);
237+
238+
// ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest()
239+
// .amount("10")
240+
// .email("[email protected]")
241+
// .billingAddress(address);
242+
// .nonce(cardNonce.getNonce())
243+
// .versionRequested(ThreeDSecureRequest.VERSION_2)
244+
// .additionalInformation(additionalInformation);
245+
213246
ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest()
214247
.nonce(parameters.getString("nonce"))
248+
.email(parameters.getString("email"))
249+
.versionRequested(ThreeDSecureRequest.VERSION_2)
215250
.amount(parameters.getString("amount"));
216251

217252
ThreeDSecure.performVerification(this.mBraintreeFragment, threeDSecureRequest);
@@ -236,34 +271,7 @@ public void paypalRequest(final Callback successCallback, final Callback errorCa
236271

237272
PayPal.requestOneTimePayment(this.mBraintreeFragment, request);
238273
}
239-
@Override
240-
public void onActivityResult(Activity activity, final int requestCode, final int resultCode, final Intent data) {
241-
Log.d("PAYMENT_REQUEST","onActivityResult");
242-
if (requestCode == PAYMENT_REQUEST) {
243-
switch (resultCode) {
244-
case Activity.RESULT_OK:
245-
PaymentMethodNonce paymentMethodNonce = data.getParcelableExtra(
246-
BraintreePaymentActivity.EXTRA_PAYMENT_METHOD_NONCE
247-
);
248-
249-
this.successCallback.invoke(paymentMethodNonce.getNonce());
250-
251-
break;
252-
case BraintreePaymentActivity.BRAINTREE_RESULT_DEVELOPER_ERROR:
253-
case BraintreePaymentActivity.BRAINTREE_RESULT_SERVER_ERROR:
254-
case BraintreePaymentActivity.BRAINTREE_RESULT_SERVER_UNAVAILABLE:
255-
this.errorCallback.invoke(
256-
data.getSerializableExtra(BraintreePaymentActivity.EXTRA_ERROR_MESSAGE)
257-
);
258-
break;
259-
case Activity.RESULT_CANCELED:
260-
this.errorCallback.invoke("USER_CANCELLATION");
261-
break;
262-
default:
263-
break;
264-
}
265-
}
266-
}
274+
267275

268276
public void onNewIntent(Intent intent){}
269277
}

ios/RCTBraintree/RCTBraintree.m

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,17 @@ - (instancetype)init
8787
});
8888
}
8989

90+
- (void)onLookupComplete:(__unused BTThreeDSecureRequest *)request result:(__unused BTThreeDSecureLookup *)lookup next:(void (^)(void))next {
91+
// Optionally inspect the lookup result and prepare UI if a challenge is required
92+
next();
93+
}
9094

9195
- (void)run3DSecureCheck:(NSDictionary *)parameters callback: (RCTResponseSenderBlock)callback {
9296
BTThreeDSecureRequest *threeDSecureRequest = [[BTThreeDSecureRequest alloc] init];
9397
threeDSecureRequest.amount = [NSDecimalNumber decimalNumberWithString: parameters[@"amount"]];
9498
threeDSecureRequest.nonce = parameters[@"nonce"];
95-
99+
// Make sure that self conforms to the BTThreeDSecureRequestDelegate protocol
100+
threeDSecureRequest.threeDSecureRequestDelegate = self;
96101
threeDSecureRequest.email = parameters[@"email"];
97102
threeDSecureRequest.versionRequested = BTThreeDSecureVersion2;
98103

@@ -115,23 +120,18 @@ - (void)run3DSecureCheck:(NSDictionary *)parameters callback: (RCTResponseSender
115120
self.paymentFlowDriver = [[BTPaymentFlowDriver alloc] initWithAPIClient:self.braintreeClient];
116121
self.paymentFlowDriver.viewControllerPresentingDelegate = self;
117122

118-
119123
[self.paymentFlowDriver startPaymentFlow:threeDSecureRequest completion:^(BTPaymentFlowResult * _Nonnull result, NSError * _Nonnull error) {
120124
NSArray *args = @[];
121125
if (error) {
122-
NSLog(@"Finally error %@", error.description);
123126
args = @[error.localizedDescription, [NSNull null]];
124127
// Handle error
125128
} else if (result) {
126-
NSLog(@"Finally %@", result);
127129
BTThreeDSecureResult *threeDSecureResult = (BTThreeDSecureResult *)result;
128-
129130
if (threeDSecureResult.tokenizedCard.threeDSecureInfo.liabilityShiftPossible) {
130131
if (threeDSecureResult.tokenizedCard.threeDSecureInfo.liabilityShifted) {
131132
args = @[[NSNull null], threeDSecureResult.tokenizedCard.nonce];
132133
} else {
133134
// 3D Secure authentication failed
134-
// args = @[serialisationErr.description, [NSNull null]];
135135
args = @[@"failed", [NSNull null]];
136136
}
137137
}else{

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-braintree-custom-ui",
3-
"version": "1.0.1",
3+
"version": "1.0.3",
44
"description": "Cross platform Braintree module",
55
"main": "index",
66
"author": {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require 'json'
2+
package = JSON.parse(File.read('./package.json'))
3+
4+
Pod::Spec.new do |s|
5+
s.name = "RCTBraintree"
6+
s.version = package["version"]
7+
s.summary = package["description"]
8+
s.requires_arc = true
9+
s.license = { :type => package["license"] }
10+
s.homepage = package["homepage"]
11+
s.authors = { package["author"]["name"] => package["author"]["email"] }
12+
s.source = { :git => s.homepage, :tag => "v#{s.version}" }
13+
s.platform = :ios, "9.0"
14+
s.source_files = 'ios/RCTBraintree/**/*.{h,m}'
15+
s.dependency 'React'
16+
s.dependency 'Braintree'
17+
s.dependency 'Braintree/DataCollector'
18+
s.dependency 'Braintree/PaymentFlow'
19+
20+
end

0 commit comments

Comments
 (0)