Skip to content
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

Add deep link support as a fallback to app links #1223

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

tdchow
Copy link
Collaborator

@tdchow tdchow commented Nov 22, 2024

Summary of changes

  • Add optional returnUrlScheme property to the PayPalClient constructor, which is used for deep linking back to the merchant app if the user has unchecked "Open supported links".
  • Add GetReturnLinkTypeUseCase that returns which link type should be sent to the PayPal request and payment URL

Checklist

  • Added a changelog entry
  • Relevant test coverage
  • Tested and confirmed payment flows affected by this change are functioning as expected

Authors

List GitHub usernames for everyone who contributed to this pull request.

* will be returned.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class GetReturnLinkTypeUseCase(private val merchantRepository: MerchantRepository) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on adding a domain layer / use case pattern to the SDK? I wasn't able to find an existing pattern to share business logic outside of creating additional Client classes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you expand on what you envision for adding a domain layer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! I see it as a layer that encapsulates business logic that can be reused across the SDK. It's also the layer between the UI and the data layer, where it reads data from the repository and applies some sort of business logic.

https://developer.android.com/topic/architecture/domain-layer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok this looks good to me 👍 - @saperi22 @jaxdesmarais any thoughts on this pattern?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with this pattern. At some point we should consider documenting the Android and iOS patterns internally since they have diverged quite a bit in recent major versions. Unless this is more of a best practice in Android, in which case probably fine to leave undocumented and just slowly migrate to each languages best practices!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say MVVM is the architecture pattern that Google is pushing since they have entire doc sections on the different layers of MVVM. That said, it wouldn't hurt to have a callout somewhere in the repo of the architecture patterns the SDK is using.

appLinkReturnUrl: Uri
) : this(BraintreeClient(context, authorization, null, appLinkReturnUrl))
appLinkReturnUrl: Uri,
returnUrlScheme: String? = null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should include doc strings noting that if this parameter exists, it will be used as a fallback when app links are not available - merchants should be aware that they are opting in to not using app links in all cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, let me update the kdoc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to consider any type of okay from security for adding this back? I know we were moving towards removing url schemes across the SDKs for security reasons but wasn't sure what applied with it as an opt in.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to run this by security as our other modules are still relying on deep links for navigating back to the merchant app. I also don't think security originally required the switch to app links. @sarahkoop - do you have context on if security was originally involved with the switch to app links?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think since we are still supporting deep links across multiple flows it's fine to add back in - this originated as a merchant request not an internal security mandate

}

GetReturnLinkTypeUseCase.ReturnLinkType.DEEP_LINK -> {
returnUrlScheme(merchantRepository.returnUrlScheme)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check that returnUrlScheme isn't null?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I think we should check if returnUrlScheme is non-null. However, how should we handle the null case?

If the buyer has the Open supported links unchecked, and the merchant passes a null returnUrlScheme the deep link would fail. Maybe we should throw an error before the app switch/CCT is launched and fail fast?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think fail fast and let the merchant decide if they want to tell the user to turn on that setting or how they want to handle it if they don't want to support deep links

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're actually defaulting the returnUrlScheme to the merchant's package name appended with .braintree, if a null value is passed in.

?: "${getAppPackageNameWithoutUnderscores(context.applicationContext)}.braintree",

So the returnUrlScheme in MerchantRepository is non null. I believe this was the existing deep link behavior.

val returnLinkType = getReturnLinkTypeUseCase()
val navigationLink = when (returnLinkType) {
GetReturnLinkTypeUseCase.ReturnLinkType.APP_LINK -> merchantRepository.appLinkReturnUri
GetReturnLinkTypeUseCase.ReturnLinkType.DEEP_LINK -> merchantRepository.returnUrlScheme
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here - should we be checking that the merchant has included a returnUrlScheme? If a merchant only wants to support app links and app links are not enabled on the device we should have an error scenario I assume

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep I agree, we'd want to throw an error to prevent a broken flow. I'll update this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the comment above, we're defaulting the returnUrlScheme to the merchant's package name. Did we want to change this behavior?

@saperi22
Copy link
Contributor

saperi22 commented Dec 2, 2024

QQ: would it be possible to use the already sent in app link url for deeplink return url?

@tdchow
Copy link
Collaborator Author

tdchow commented Dec 2, 2024

QQ: would it be possible to use the already sent in app link url for deeplink return url?

The original deep link implementation only set the scheme in the intent filter:

<data android:scheme="${applicationId}.braintree" />

While the app link approach requires http/https as the scheme:

<data android:scheme="https" />

So I don't think we'll be able to reuse the app link URI for the deep link fallback.

@tdchow tdchow marked this pull request as ready for review December 2, 2024 21:35
@tdchow tdchow requested a review from a team as a code owner December 2, 2024 21:35
@tdchow tdchow changed the title WIP - Add deep link support as a fallback to app links Add deep link support as a fallback to app links Dec 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants