-
Notifications
You must be signed in to change notification settings - Fork 238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Instantiate BraintreeClient Within Clients #830
Conversation
Open question for this PR: Is this cleaner/preferred over having merchants instantiate |
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) | ||
open class BraintreeClient @VisibleForTesting internal constructor( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this change impact DropIn at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't - drop-in uses the BraintreeClient
constructor with BraintreeOptions
param, and has the same "com.braintreepayments.api" group ID as the core libraries, so they all can share these "package-private"/library group methods.
|
||
import android.content.Context | ||
|
||
data class ClientParams(val context: Context, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it would be more clear to require the <Feature>Client
constructors to require each param individually, versus encapsulating them all into this additional ClientParams
class. Also that lets the feature clients that actually need the returnURL to enforce it's requirement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah ClientParams
is more tech-debt than API. It's internal in v4
, it can be removed in v5
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, the parameter object pattern here can be useful. We created too many convenience initializers in v4
to support multiple integration patterns. With v5
we do get to wipe the slate clean and have a single constructor, but theoretically a param object like ClientParams
can help to keep the constructor count low as we add new features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that just plain auth and context as direct constructor parameters is definitely the cleanest - but yeah in v4 we ended up with too many overloads I wanted to avoid that with ClientParams. Return URL isn't a required param for any clients, it's optional for some. But hopefully we won't add a bunch of params to client constructors in this version, so maybe we are safe to just go with auth and context as the main constructor and one overload for the clients that can accept return URL. What do you all think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there's definitely a middle ground. Thinking on it more, our request objects can also be considered parameter objects. It may make sense to move properties like returnUrl
from ClientParams
to <FEATURE>Request
. That will cause some redundancy, but it also allows us to make returnUrl
required (or optional to allow merchant overrides) on a per-feature basis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea I think that's a good compromise here - I'll go with that
v5_MIGRATION_GUIDE.md
Outdated
braintreClient = BraintreeClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") | ||
- braintreClient = BraintreeClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") | ||
- localPaymentClient = LocalPaymentClient(this, braintreeClient) | ||
+ localPaymentClient = LocalPaymentClient(braintreeClient) | ||
+ localPaymentClient = LocalPaymentClient(ClientParams(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") | ||
- localPaymentClient.setListener(this) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this! It's a change we can make on iOS too (in a major version), dropping the merchant step to instantiate a BTAPIClient
. It always felt redundant to me to have merchants instantiate that class when there was no public functionality on it they would ever use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be great to coordinate this major version alongside the package
access modifier in Swift 5.9+ (proposal here) as a whole. But totally agree having merchant just access the client like this would be dope:
// iOS v6
let apiClient = BTAPIClient(authorization: "AUTHORIZATION")
let cardClient = BTCardClient(apiClient: apiClient)
// iOS v7
let cardClient = BTCardClient(authorization: "AUTHORIZATION")
Added this to our v7 doc!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMG if package
is approved that will benefit us in so many ways! 🤞
Updated this PR to remove the For the overload parameters (currently just browser switching params like |
@@ -46,16 +50,11 @@ protected void onCreate(Bundle savedInstanceState) { | |||
|
|||
public BraintreeClient getBraintreeClient() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to remove the getBrainreeClient()
eventually. If it can be removed in this PR that would be a nice win. Generally the less DemoActivity
does the better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call - removed
+ venmoClient = VenmoClient(braintreeClient) | ||
+ venmoClient = VenmoClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 So clean!
@VisibleForTesting | ||
SEPADirectDebitClient(@NonNull BraintreeClient braintreeClient) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we planning to remove these in a follow-up? Or are we keeping for ease of unit testing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now they are nice to keep for unit testing since we pass in a MockBraintreeClient
with responses to various API calls
@@ -57,27 +53,13 @@ public View onCreateView(@NonNull LayoutInflater inflater, | |||
public void onResume() { | |||
super.onResume(); | |||
|
|||
braintreeClient.getConfiguration((configuration, error) -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious - why were we doing config fetches in the demo app?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we probably could've deleted this a while back. This has roots in v3. I remember removing it from the Core SDK since it would require a runtime dependency on the Google Pay SDK, but we probably kept it in when we went to GA because we needed to get a release out quickly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few small questions, but LGTM!
protected void fetchAuthorization(BraintreeAuthorizationCallback callback) { | ||
DemoActivity demoActivity = getDemoActivity(); | ||
if (demoActivity != null) { | ||
return demoActivity.getBraintreeClient(); | ||
demoActivity.fetchAuthorization(callback); | ||
} | ||
return null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2cents: I always felt like phasing out BaseFragment
would be the best call. We should be able to fetch client tokens within each feature fragment. Do you feel like it makes sense to remove eventually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed - will look into that in another demo refactor PR
Summary of changes
BraintreeClient
public constructors and instead instantiateBraintreeClient
under the hood within each payment method clientClientParams
object to be configurable with parameters required to instantiate clients (and BraintreeClient)ClientParams
Checklist
Authors