Skip to content

Commit 2dc16d7

Browse files
msasinowskiMaciej Sasinowski
andauthored
Google Pay Feature (#47)
* google pay feature * google pay feature * google pay feature --------- Co-authored-by: Maciej Sasinowski <maciej.sasinowski2@frontdoor.com>
1 parent 518dad3 commit 2dc16d7

21 files changed

+436
-84
lines changed

INTEGRATION_3.X_EXPO.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ In Your `app.config.ts` or `app.config.json` or `app.config.js` please add expo-
1818
pathPrefix: "/braintree-payments" // Optional,
1919
// Depending on which payment do you really need in the project initialize only required one
2020
initialize3DSecure: "true",
21+
initializeGooglePay: "true",
2122
addFallbackUrlScheme: "true",
2223
appDelegateLanguage?: "swift"; // Optional if you are still using AppDelegate.mm / AppDelegate.m
2324
},
@@ -31,6 +32,7 @@ In Your `app.config.ts` or `app.config.json` or `app.config.js` please add expo-
3132

3233
`pathPrefix` - Path prefix, in case of you want to separate path only to handle the context switch (Optional)
3334
`initialize3DSecure` - Boolean that determines if 3D Secure is used/needed (Values "true" | "false")
35+
`initializeGooglePay` - Boolean that determines if Google Pay is used/needed (Values "true" | "false")
3436
`addFallbackUrlScheme` - Boolean that determines if we should add a scheme for a fallback url used in venmo
3537
`appDelegateLanguage` - Indicator that tell's the plugin logic if you are still using Objective C file for AppDelegate (Optional)
3638

INTEGRATION_3.X_REACT_NATIVE_CLI.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,30 @@ override fun onCreate() {
118118

119119
---
120120

121+
### C. For:
122+
123+
- `requestGooglePayPayment`
124+
125+
Add the following instead:
126+
127+
```kotlin
128+
import com.expobraintree.ExpoBraintreeModule
129+
130+
override fun onCreate() {
131+
...
132+
ExpoBraintreeModule.initGooglePay(this)
133+
...
134+
}
135+
```
136+
137+
---
138+
139+
### D. If you use **all methods**
140+
141+
You must add **all initialization methods**.
142+
143+
---
144+
121145
# 3. Update `build.gradle`
122146

123147
If you use **3D Secure**, add the following repository to:

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ A high-performance, native implementation of the [Braintree SDK](https://develop
2020

2121
| Package Version | Braintree Android | Braintree iOS | Min Android SDK | Min iOS |
2222
| :---------------- | :---------------: | :-----------: | :-------------: | :-----: |
23+
| **3.4.0** | v5.19.0 | v6.41.0 | 23 | 15.1 |
2324
| **3.3.0** | v5.19.0 | v6.41.0 | 23 | 15.1 |
2425
| **3.2.0 - 3.2.2** | v5.19.0 | v6.41.0 | 23 | 15.1 |
2526
| **3.1.0** | v5.9.x | v6.31.0 | 23 | 14.0 |
@@ -38,6 +39,15 @@ A high-performance, native implementation of the [Braintree SDK](https://develop
3839

3940
---
4041

42+
### Feature List
43+
44+
| Package Version | Supported Expo SDK |
45+
| :-------------- | :----------------------- |
46+
| **3.4.0** | Google Pay Feature Added |
47+
| **3.3.0** | 3D Secure Feature Added |
48+
49+
---
50+
4151
## 🛠️ Demos
4252

4353
![iOS](assets/ios_demo_with_3d_secure.gif)
@@ -143,6 +153,6 @@ You can find implementation details in the [Example App](example/src/App.tsx) or
143153
## Roadmap
144154

145155
- [x] Venmo Integration
146-
- [x] 3D-Secure (Alpha)
147-
- [ ] Apple Pay
148-
- [ ] Google Pay
156+
- [x] 3D-Secure (Implemented in 3.3.0)
157+
- [x] Google Pay (Implemented in 3.4.0)
158+
- [ ] Apple Pay (TBD)

android/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,5 @@ dependencies {
104104
implementation 'com.braintreepayments.api:card:5.19.0'
105105
implementation 'com.braintreepayments.api:venmo:5.19.0'
106106
implementation 'com.braintreepayments.api:three-d-secure:5.19.0'
107+
implementation "com.braintreepayments.api:google-pay:5.19.0"
107108
}

android/src/main/java/com/expobraintree/BrainTreeEnums.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ enum class PAYPAL_ERROR_TYPES(val value: String) {
3434
enum class VENMO_ERROR_TYPES(val value: String) {
3535
VENMO_DISABLED_IN_CONFIGURATION("VENMO_DISABLED_IN_CONFIGURATION_ERROR")
3636
}
37+
38+
enum class GOOGLE_PAY_ERROR_TYPES(val value: String) {
39+
GOOGLE_PAY_NOT_AVAILABLE("GOOGLE_PAY_NOT_AVAILABLE"),
40+
GOOGLE_PAY_FAILED("GOOGLE_PAY_FAILED")
41+
}

android/src/main/java/com/expobraintree/CardDataConverter.kt

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,20 @@ class CardDataConverter {
1515

1616
companion object {
1717

18+
/**
19+
* Converts a basic CardNonce into a WritableMap for React Native.
20+
*/
1821
fun createTokenizeCardDataNonce(cardNonce: CardNonce): WritableMap {
1922
val result: WritableMap = Arguments.createMap()
2023
result.putString("nonce", cardNonce.string)
24+
25+
// Handling unknown card types for consistent JS reporting
2126
if (cardNonce.cardType == "Unknown") {
2227
result.putString("cardNetwork", "")
2328
} else {
2429
result.putString("cardNetwork", cardNonce.cardType)
2530
}
31+
2632
result.putString("lastFour", cardNonce.lastFour)
2733
result.putString("lastTwo", cardNonce.lastTwo)
2834
result.putString("expirationMonth", cardNonce.expirationMonth)
@@ -32,7 +38,7 @@ class CardDataConverter {
3238

3339
/**
3440
* Converts the 3D Secure result nonce into a WritableMap to be sent back to JavaScript.
35-
* This includes card details and the critical threeDSecureInfo object.
41+
* Includes liability shift details required for security checks.
3642
*/
3743
fun createThreeDSecureDataNonce(cardNonce: ThreeDSecureNonce): WritableMap {
3844
val result: WritableMap = Arguments.createMap()
@@ -53,18 +59,20 @@ class CardDataConverter {
5359
val infoMap: WritableMap = Arguments.createMap()
5460
val info = cardNonce.threeDSecureInfo
5561

56-
if (info != null) {
57-
infoMap.putBoolean("liabilityShifted", info.liabilityShifted)
58-
infoMap.putBoolean("liabilityShiftPossible", info.liabilityShiftPossible)
59-
infoMap.putString("status", info.status)
60-
infoMap.putBoolean("wasVerified", info.wasVerified)
61-
}
62+
// REMOVED: if (info != null) check because threeDSecureInfo is NonNull in SDK v5+
63+
infoMap.putBoolean("liabilityShifted", info.liabilityShifted)
64+
infoMap.putBoolean("liabilityShiftPossible", info.liabilityShiftPossible)
65+
infoMap.putString("status", info.status)
66+
infoMap.putBoolean("wasVerified", info.wasVerified)
6267

6368
result.putMap("threeDSecureInfo", infoMap)
6469

6570
return result
6671
}
6772

73+
/**
74+
* Creates a Card object from JS options for basic tokenization.
75+
*/
6876
fun createTokenizeCardRequest(options: ReadableMap): Card {
6977
val card: Card = Card()
7078
if (options.hasKey("number")) {
@@ -85,29 +93,30 @@ class CardDataConverter {
8593
return card
8694
}
8795

96+
/**
97+
* Maps JS options to a ThreeDSecureRequest.
98+
* Includes address mapping to satisfy 3DS 2.0 risk assessment requirements.
99+
*/
88100
fun create3DSecureRequest(options: ReadableMap): ThreeDSecureRequest {
89101
val address = ThreeDSecurePostalAddress()
90102

91-
// Map personal names - Note: Braintree v6 uses givenName and surname
103+
// Personal details mapping
92104
if (options.hasKey("givenName")) {
93105
address.givenName = options.getString("givenName")
94106
}
95107
if (options.hasKey("surName")) {
96108
address.surname = options.getString("surName")
97109
}
98110

99-
// Map contact details
100111
if (options.hasKey("phoneNumber")) {
101112
address.phoneNumber = options.getString("phoneNumber")
102113
}
103114

104-
// CRITICAL: countryCodeAlpha2 MUST be provided if 'region' is present.
105-
// This prevents the "The region cannot be provided without a corresponding country code" (422) error.
115+
// Required by Braintree to avoid 422 errors if region is provided
106116
if (options.hasKey("countryCodeAlpha2")) {
107117
address.countryCodeAlpha2 = options.getString("countryCodeAlpha2")
108118
}
109119

110-
// Map geographic location details
111120
if (options.hasKey("city")) {
112121
address.locality = options.getString("city")
113122
}
@@ -124,21 +133,18 @@ class CardDataConverter {
124133
address.extendedAddress = options.getString("streetAddress2")
125134
}
126135

127-
// 3D Secure 2.0 requires additional info for better risk assessment
128136
val additionalInformation = ThreeDSecureAdditionalInformation()
129137
additionalInformation.shippingAddress = address
130138

131139
val threeDSecureRequest = ThreeDSecureRequest()
132-
// Use elvis operator to ensure non-null values for the SDK
133140
threeDSecureRequest.nonce = options.getString("nonce") ?: ""
134141
threeDSecureRequest.email = options.getString("email") ?: ""
135142
threeDSecureRequest.amount = options.getString("amount") ?: "0.00"
136143

137-
// Attach the objects to the main request
138144
threeDSecureRequest.billingAddress = address
139145
threeDSecureRequest.additionalInformation = additionalInformation
140146

141147
return threeDSecureRequest
142148
}
143149
}
144-
}
150+
}

0 commit comments

Comments
 (0)