Skip to content

Commit 706c842

Browse files
authored
Expose private suspend funs in clients (#1628)
* feat(ThreeDS): Add suspend equivalent for createPaymentAuthRequest * feat: Expose suspend function equivalents for public callback based functions. * Update KDoc to improve clarity and accuracy. # Conflicts: # CHANGELOG.md * chore: Clean up warnings for unused parameters. * fix: Respond to PR comments * Whitespace clean up * Grammar fixes * fix: Respond to PR comments * Whitespace clean up * Comment verbiage updates
1 parent 3fb8a63 commit 706c842

11 files changed

Lines changed: 360 additions & 94 deletions

File tree

AmericanExpress/src/main/java/com/braintreepayments/api/americanexpress/AmericanExpressClient.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,14 @@ class AmericanExpressClient internal constructor(
5151
}
5252
}
5353

54-
private suspend fun getRewardsBalance(
54+
/**
55+
* Gets the rewards balance associated with a Braintree nonce. Only for American Express cards.
56+
*
57+
* @param nonce A nonce representing a card that will be used to look up the rewards balance
58+
* @param currencyIsoCode The currencyIsoCode to use. Example: 'USD'
59+
* @return result [AmericanExpressResult]
60+
*/
61+
suspend fun getRewardsBalance(
5562
nonce: String,
5663
currencyIsoCode: String
5764
): AmericanExpressResult {

CHANGELOG.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
11
# Braintree Android SDK Release Notes
22

3-
## 5.29.0 (2026-06-30)
3+
## unreleased
44

5+
* AmericanExpress
6+
* Expose `getRewardsBalance` as a public suspend function
7+
* Card
8+
* Expose `tokenize` as a public suspend function
9+
* GooglePay
10+
* Expose `isReadyToPay` as a public suspend function
11+
* Expose `getTokenizationParameters` as a public suspend function
12+
* Expose `createPaymentAuthRequest` as a public suspend function
13+
* LocalPayment
14+
* Expose `createPaymentAuthRequest` as a public suspend function
15+
* Expose `tokenize` as a public suspend function
16+
* PayPal
17+
* Expose `createPaymentAuthRequest` as a public suspend function
18+
* Expose `tokenize` as a public suspend function
19+
* SEPADirectDebit
20+
* Expose `createPaymentAuthRequest` as a public suspend function
21+
* Expose `tokenize` as a public suspend function
22+
* ShopperInsights
23+
* Expose `createCustomerSession` as a public suspend function
24+
* Expose `updateCustomerSession` as a public suspend function
25+
* Expose `generateCustomerRecommendations` as a public suspend function
26+
* ThreeDSecure
27+
* Expose `createPaymentAuthRequest` as a public suspend function
28+
* Expose `prepareLookup` as a public suspend function
29+
* Expose `initializeChallengeWithLookupResponse` as a public suspend function
30+
* Expose `tokenize` as a public suspend function
31+
* Venmo
32+
* Expose `createPaymentAuthRequest` as a public suspend function
33+
* Expose `tokenize` as a public suspend function
34+
35+
## 5.29.0 (2026-06-30)
536
* GooglePay
637
* Remove requirement for `GooglePayActivity` to be declared in the Android manifest (fixes #1572)
738
* Note: If upgrading from v4, any manual `GooglePayActivity` declaration in your app's manifest should be removed

Card/src/main/java/com/braintreepayments/api/card/CardClient.kt

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,15 @@ class CardClient internal constructor(
4242
)
4343

4444
/**
45-
* Create a [CardNonce].
45+
* Creates a [CardNonce].
4646
*
4747
* The tokenization result is returned via a [CardTokenizeCallback] callback.
4848
*
49-
* On success, the [CardTokenizeCallback.onCardResult] method will be
50-
* invoked with a [CardResult.Success] including a nonce.
49+
* On success the [CardTokenizeCallback.onCardResult] method will be
50+
* invoked with a [CardResult.Success] containing a nonce.
5151
*
52-
* If creation fails validation, the [CardTokenizeCallback.onCardResult]
53-
* method will be invoked with a [CardResult.Failure] including an exception.
54-
*
55-
* If an error not due to validation (server error, network issue, etc.) occurs, the
56-
* [CardTokenizeCallback.onCardResult] method will be invoked with a
57-
* [CardResult.Failure] with an [Exception] describing the error.
52+
* On failure the [CardTokenizeCallback.onCardResult] method will be
53+
* invoked with a [CardResult.Failure] containing an exception.
5854
*
5955
* @param card [Card]
6056
* @param callback [CardTokenizeCallback]
@@ -66,7 +62,17 @@ class CardClient internal constructor(
6662
}
6763
}
6864

69-
private suspend fun tokenize(card: Card): CardResult {
65+
/**
66+
* Creates a [CardNonce].
67+
*
68+
* On success [CardResult.Success] containing a [CardNonce] is returned.
69+
*
70+
* On failure [CardResult.Failure] containing an exception is returned.
71+
*
72+
* @param card [Card]
73+
* @return [CardResult]
74+
*/
75+
suspend fun tokenize(card: Card): CardResult {
7076
analyticsParamRepository.reset()
7177
braintreeClient.sendAnalyticsEvent(CardAnalytics.CARD_TOKENIZE_STARTED)
7278
return try {

GooglePay/src/main/java/com/braintreepayments/api/googlepay/GooglePayClient.kt

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import kotlinx.coroutines.launch
3131
import org.json.JSONArray
3232
import org.json.JSONException
3333
import org.json.JSONObject
34-
import kotlin.toString
3534

3635
/**
3736
* Used to create and tokenize Google Pay payment methods. For more information see the [documentation](https://developer.paypal.com/braintree/docs/guides/google-pay/overview)
@@ -76,8 +75,10 @@ class GooglePayClient internal constructor(
7675

7776
/**
7877
* Before starting the Google Pay flow, use this method to check whether the Google Pay API is
79-
* supported and set up on the device. When the callback is called with `true`, show the
80-
* Google Pay button. When it is called with `false`, display other checkout options.
78+
* supported and set up on the device.
79+
*
80+
* When [callback] is called with [GooglePayReadinessResult.ReadyToPay], show the Google Pay Button.
81+
* When [callback] is called with [GooglePayReadinessResult.NotReadyToPay], display other checkout options.
8182
*
8283
* @param context Android Context
8384
* @param request [ReadyForGooglePayRequest]
@@ -95,9 +96,20 @@ class GooglePayClient internal constructor(
9596
}
9697
}
9798

98-
private suspend fun isReadyToPay(context: Context, request: ReadyForGooglePayRequest?): GooglePayReadinessResult {
99+
/**
100+
* Before starting the Google Pay flow, use this method to check whether the Google Pay API is
101+
* supported and set up on the device.
102+
*
103+
* When the return value is [GooglePayReadinessResult.ReadyToPay], show the Google Pay Button.
104+
* When the Return value is [GooglePayReadinessResult.NotReadyToPay], display other checkout options.
105+
*
106+
* @param context Android Context
107+
* @param request [ReadyForGooglePayRequest]
108+
* @return [GooglePayReadinessResult]
109+
*/
110+
suspend fun isReadyToPay(context: Context, request: ReadyForGooglePayRequest?): GooglePayReadinessResult {
99111
return try {
100-
Class.forName(PaymentsClient::class.java.name)
112+
verifyGoogleWalletOnClasspath()
101113
val configuration = braintreeClient.getConfiguration()
102114
if (!configuration.isGooglePayEnabled) {
103115
NotReadyToPay(null)
@@ -125,7 +137,7 @@ class GooglePayClient internal constructor(
125137
request.isExistingPaymentMethodRequired
126138
)
127139
}
128-
} catch (ignored: JSONException) {
140+
} catch (_: JSONException) {
129141
}
130142
val readyToPayRequest = IsReadyToPayRequest.fromJson(json.toString())
131143
internalGooglePayClient.isReadyToPay(
@@ -140,6 +152,15 @@ class GooglePayClient internal constructor(
140152
}
141153
}
142154

155+
@Throws(
156+
LinkageError::class,
157+
ExceptionInInitializerError::class,
158+
ClassNotFoundException::class
159+
)
160+
private fun verifyGoogleWalletOnClasspath() {
161+
Class.forName(PaymentsClient::class.java.name)
162+
}
163+
143164
/**
144165
* Get Braintree specific tokenization parameters for a Google Pay. Useful for when full control
145166
* over the [PaymentDataRequest] is required.
@@ -150,7 +171,7 @@ class GooglePayClient internal constructor(
150171
* [PaymentDataRequest.Builder.setPaymentMethodTokenizationParameters]
151172
* and [allowedCardNetworks] should be supplied to the
152173
* [CardRequirements] via
153-
* [CardRequirements.Builder.addAllowedCardNetworks]}.
174+
* [CardRequirements.Builder.addAllowedCardNetworks].
154175
*
155176
* @param callback [GooglePayGetTokenizationParametersCallback]
156177
*/
@@ -163,7 +184,21 @@ class GooglePayClient internal constructor(
163184
}
164185
}
165186

166-
private suspend fun getTokenizationParameters(): GooglePayTokenizationParameters {
187+
/**
188+
* Get Braintree specific tokenization parameters for a Google Pay. Useful for when full control
189+
* over the [PaymentDataRequest] is required.
190+
*
191+
*
192+
* [PaymentMethodTokenizationParameters] should be supplied to the
193+
* [PaymentDataRequest] via
194+
* [PaymentDataRequest.Builder.setPaymentMethodTokenizationParameters]
195+
* and [allowedCardNetworks] should be supplied to the
196+
* [CardRequirements] via
197+
* [CardRequirements.Builder.addAllowedCardNetworks].
198+
*
199+
* @return [GooglePayTokenizationParameters]
200+
*/
201+
suspend fun getTokenizationParameters(): GooglePayTokenizationParameters {
167202
return try {
168203
val configuration = braintreeClient.getConfiguration()
169204
GooglePayTokenizationParameters.Success(
@@ -181,7 +216,7 @@ class GooglePayClient internal constructor(
181216
* used to present Google Pay payment sheet in
182217
* [GooglePayLauncher.launch]
183218
*
184-
* @param request The [GooglePayRequest] containing options for the transaction.
219+
* @param request The [GooglePayRequest] containing options for the transaction.
185220
* @param callback [GooglePayPaymentAuthRequestCallback]
186221
*/
187222
fun createPaymentAuthRequest(
@@ -203,7 +238,15 @@ class GooglePayClient internal constructor(
203238
}
204239
}
205240

206-
private suspend fun createPaymentAuthRequest(request: GooglePayRequest): GooglePayPaymentAuthRequest {
241+
/**
242+
* Start the Google Pay payment flow. This will return [GooglePayPaymentAuthRequestParams] that are
243+
* used to present Google Pay payment sheet in
244+
* [GooglePayLauncher.launch]
245+
*
246+
* @param request The [GooglePayRequest] containing options for the transaction.
247+
* @return [GooglePayPaymentAuthRequest]
248+
*/
249+
suspend fun createPaymentAuthRequest(request: GooglePayRequest): GooglePayPaymentAuthRequest {
207250
analyticsParamRepository.reset()
208251
braintreeClient.sendAnalyticsEvent(GooglePayAnalytics.PAYMENT_REQUEST_STARTED)
209252

@@ -238,13 +281,16 @@ class GooglePayClient internal constructor(
238281
/**
239282
* Call this method when you've received a successful [PaymentData] response from a
240283
* direct Google Play Services integration to get a [GooglePayCardNonce] or
241-
* [PayPalAccountNonce].
284+
* [com.braintreepayments.api.paypal.PayPalAccountNonce].
242285
*
243286
* @param paymentData [PaymentData] retrieved from directly integrating with Google Play
244287
* Services through [PaymentsClient.loadPaymentData]
245288
* @param callback [GooglePayTokenizeCallback]
246289
*/
247-
fun tokenize(paymentData: PaymentData, callback: GooglePayTokenizeCallback) {
290+
fun tokenize(
291+
paymentData: PaymentData,
292+
callback: GooglePayTokenizeCallback
293+
) {
248294
val result = tokenize(paymentData)
249295
when (result) {
250296
is GooglePayResult.Success -> callbackTokenizeSuccess(result, callback)
@@ -258,7 +304,7 @@ class GooglePayClient internal constructor(
258304
return try {
259305
val result = JSONObject(paymentData.toJson())
260306
GooglePayResult.Success(fromJSON(result))
261-
} catch (e: JSONException) {
307+
} catch (_: JSONException) {
262308
try {
263309
val token =
264310
JSONObject(paymentData.toJson()).getJSONObject("paymentMethodData")
@@ -267,7 +313,7 @@ class GooglePayClient internal constructor(
267313
} catch (e: Exception) {
268314
GooglePayResult.Failure(e)
269315
}
270-
} catch (e: NullPointerException) {
316+
} catch (_: NullPointerException) {
271317
try {
272318
val token =
273319
JSONObject(paymentData.toJson()).getJSONObject("paymentMethodData")
@@ -283,7 +329,7 @@ class GooglePayClient internal constructor(
283329
* After a user successfully authorizes Google Pay payment via
284330
* [GooglePayClient.createPaymentAuthRequest], this
285331
* method should be invoked to tokenize the payment method to retrieve a
286-
* [PaymentMethodNonce]
332+
* [com.braintreepayments.api.core.PaymentMethodNonce]
287333
*
288334
* @param paymentAuthResult the result of [GooglePayLauncher.launch]
289335
* @param callback [GooglePayTokenizeCallback]
@@ -335,7 +381,7 @@ class GooglePayClient internal constructor(
335381

336382
val version = try {
337383
metadata.getString("version")
338-
} catch (e: JSONException) {
384+
} catch (_: JSONException) {
339385
com.braintreepayments.api.core.BuildConfig.VERSION_NAME
340386
}
341387

@@ -440,7 +486,7 @@ class GooglePayClient internal constructor(
440486
.put("phoneNumberRequired", request.isPhoneNumberRequired)
441487
)
442488
}
443-
} catch (ignored: JSONException) {
489+
} catch (_: JSONException) {
444490
}
445491
return defaultParameters
446492
}
@@ -462,7 +508,7 @@ class GooglePayClient internal constructor(
462508
)
463509

464510
defaultParameters.put("purchase_context", purchaseContext)
465-
} catch (ignored: JSONException) {
511+
} catch (_: JSONException) {
466512
}
467513

468514
return defaultParameters
@@ -495,12 +541,12 @@ class GooglePayClient internal constructor(
495541
configuration.googlePayAuthorizationFingerprint
496542
parameters.put("braintree:authorizationFingerprint", googlePayAuthFingerprint)
497543
}
498-
} catch (ignored: JSONException) {
544+
} catch (_: JSONException) {
499545
}
500546

501547
try {
502548
cardJson.put("type", "PAYMENT_GATEWAY").put("parameters", parameters)
503-
} catch (ignored: JSONException) {
549+
} catch (_: JSONException) {
504550
}
505551

506552
return cardJson
@@ -528,7 +574,7 @@ class GooglePayClient internal constructor(
528574
.put("platform", "android").toString()
529575
)
530576
)
531-
} catch (ignored: JSONException) {
577+
} catch (_: JSONException) {
532578
}
533579

534580
return json

LocalPayment/src/main/java/com/braintreepayments/api/localpayment/LocalPaymentClient.kt

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class LocalPaymentClient internal constructor(
5858
* [LocalPaymentAuthRequestParams] on success that should be used to launch the user
5959
* authentication flow.
6060
*
61-
* @param request [LocalPaymentRequest] with the payment details.
61+
* @param request [LocalPaymentRequest] with the payment details.
6262
* @param callback [LocalPaymentAuthCallback]
6363
*/
6464
fun createPaymentAuthRequest(
@@ -71,7 +71,15 @@ class LocalPaymentClient internal constructor(
7171
}
7272
}
7373

74-
private suspend fun createPaymentAuthRequest(
74+
/**
75+
* Starts the payment flow for a [LocalPaymentRequest] and returns a
76+
* [LocalPaymentAuthRequest] on success that should be used to launch the user
77+
* authentication flow.
78+
*
79+
* @param request [LocalPaymentRequest] with the payment details.
80+
* @return [LocalPaymentAuthRequest] that can be used to launch the user authentication flow.
81+
*/
82+
suspend fun createPaymentAuthRequest(
7583
request: LocalPaymentRequest,
7684
): LocalPaymentAuthRequest {
7785
analyticsParamRepository.reset()
@@ -133,7 +141,7 @@ class LocalPaymentClient internal constructor(
133141
.put("payment-type", localPaymentAuthRequestParams.request.paymentType)
134142
.put("has-user-location-consent", hasUserLocationConsent)
135143
)
136-
} catch (e: JSONException) {
144+
} catch (_: JSONException) {
137145
return authRequestFailure(
138146
BraintreeException("Error parsing local payment request")
139147
)
@@ -174,7 +182,18 @@ class LocalPaymentClient internal constructor(
174182
}
175183
}
176184

177-
private suspend fun tokenize(
185+
/**
186+
* After receiving a result from the web authentication flow via
187+
* [LocalPaymentLauncher.handleReturnToApp], pass the
188+
* [LocalPaymentAuthResult.Success] returned to this method to tokenize the local
189+
* payment method and receive a [LocalPaymentNonce] on success.
190+
*
191+
* @param context Android Context
192+
* @param localPaymentAuthResult a [LocalPaymentAuthResult.Success] received from
193+
* [LocalPaymentLauncher.handleReturnToApp]
194+
* @return [LocalPaymentResult]
195+
*/
196+
suspend fun tokenize(
178197
context: Context,
179198
localPaymentAuthResult: LocalPaymentAuthResult.Success,
180199
): LocalPaymentResult {

0 commit comments

Comments
 (0)