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

PayPal Launcher API #807

Merged
merged 45 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3e298a6
Bump java to 11
sarahkoop Oct 11, 2023
614a291
Update lambdas in card
sarahkoop Oct 11, 2023
7118205
Update demo to java 11
sarahkoop Oct 11, 2023
5353f99
Update localpayment to java 11
sarahkoop Oct 11, 2023
baa124a
Reformat PayPal
sarahkoop Oct 12, 2023
3ca6266
Cleanup PayPalNativeCheckout
sarahkoop Oct 12, 2023
149d823
Cleanup SEPA
sarahkoop Oct 12, 2023
3a3d5eb
Cleanup SharedUtils
sarahkoop Oct 12, 2023
9820cb6
Cleanup TestUtils
sarahkoop Oct 12, 2023
96b6a6b
Cleanup Venmo
sarahkoop Oct 12, 2023
6af8006
Remove java 8 references
sarahkoop Oct 12, 2023
1bab0c1
Reformat VisaCheckout
sarahkoop Oct 12, 2023
2302dc9
Reformat
sarahkoop Oct 12, 2023
b165952
reformat 3ds
sarahkoop Oct 12, 2023
80d248f
Update CHANGELOG an README
sarahkoop Oct 12, 2023
566e680
reformat Amex
sarahkoop Oct 12, 2023
28b07c7
create PayPalLauncher
sarahkoop Oct 12, 2023
4b52c10
Remove listener
sarahkoop Oct 12, 2023
45ec0c0
Merge branch 'v5' into paypal_launcher_api
sarahkoop Oct 13, 2023
b598fb1
Add launcher flow
sarahkoop Oct 13, 2023
55b2e45
Fix merge conflicts
sarahkoop Oct 13, 2023
86a0553
Fix demo integration
sarahkoop Oct 13, 2023
2e9734e
Fix exception handling
sarahkoop Oct 13, 2023
5099be4
fix unit tests
sarahkoop Oct 13, 2023
ea42c27
Update integration tests
sarahkoop Oct 13, 2023
cd1576f
Add PayPalLauncher unit tests
sarahkoop Oct 13, 2023
185612e
Update java docs
sarahkoop Oct 13, 2023
45a9472
Add CHANGELOG
sarahkoop Oct 13, 2023
51839cf
add migration guide
sarahkoop Oct 13, 2023
f74fb0e
clarify docs
sarahkoop Oct 13, 2023
7d3cf8d
Reformat files
sarahkoop Oct 13, 2023
9ddcffc
Add try catch to docs
sarahkoop Oct 13, 2023
acf051b
Merge branch 'v5' into paypal_launcher_api
sarahkoop Oct 16, 2023
57d2eeb
Merge branch 'v5' into paypal_launcher_api
sarahkoop Oct 17, 2023
2c01463
Refactor launcher and error handling
sarahkoop Oct 17, 2023
e92e425
Update migration guide
sarahkoop Oct 17, 2023
6fcd6ec
Update migration guide
sarahkoop Oct 18, 2023
5f93a2e
Add CHANGELOG
sarahkoop Oct 18, 2023
19ef68f
Update v5_MIGRATION_GUIDE.md
sarahkoop Oct 18, 2023
8f1c394
Merge branch 'v5' into paypal_launcher_api
sarahkoop Oct 23, 2023
3369e0b
Merge v5
sarahkoop Oct 23, 2023
b61c9ff
Fix docstring
sarahkoop Oct 24, 2023
eae3774
Fix CHANGELOG
sarahkoop Oct 24, 2023
f1608b2
Add docstring
sarahkoop Oct 24, 2023
0fe142b
Update CHANGELOG.md
sarahkoop Oct 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
* Change `ThreeDSecureClient#performVerification` and `ThreeDSecureClient#initializeChallengeWithLookupResponse` parameters
* Add `ThreeDSecureClient#onCardinalResult`
* Remove `versionRequested` from `ThreeDSecureRequest`
* PayPal
* Remove `PayPalListener`
* Add `PayPalLauncher` and `PayPalResponse`
* Add parameter to `PayPalFlowStartedCallback`
* Remove overload constructors, `setListener`, `parseBrowserSwitchResult`,
`clearActiveBrowserSwitchResult`, `requestOneTimePayment`, and `requestBillingAgreement` from
`PayPalClient`
* Change `PayPalClient#tokenizePayPalAccount` parameters

## unreleased

Expand Down

This file was deleted.

95 changes: 39 additions & 56 deletions Demo/src/main/java/com/braintreepayments/demo/PayPalFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static com.braintreepayments.demo.PayPalRequestFactory.createPayPalCheckoutRequest;
import static com.braintreepayments.demo.PayPalRequestFactory.createPayPalVaultRequest;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -16,28 +15,27 @@
import androidx.navigation.fragment.NavHostFragment;

import com.braintreepayments.api.BraintreeClient;
import com.braintreepayments.api.BrowserSwitchResult;
import com.braintreepayments.api.DataCollector;
import com.braintreepayments.api.PayPalAccountNonce;
import com.braintreepayments.api.PayPalClient;
import com.braintreepayments.api.PayPalListener;
import com.braintreepayments.api.PayPalLauncher;
import com.braintreepayments.api.PayPalRequest;
import com.braintreepayments.api.PaymentMethodNonce;

public class PayPalFragment extends BaseFragment implements PayPalListener {
public class PayPalFragment extends BaseFragment {

private String deviceData;
private String amount;

private BraintreeClient braintreeClient;
private PayPalClient payPalClient;
private PayPalLauncher payPalLauncher;

private DataCollector dataCollector;

private boolean useManualBrowserSwitch;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_paypal, container, false);
Button billingAgreementButton = view.findViewById(R.id.paypal_billing_agreement_button);
Button singlePaymentButton = view.findViewById(R.id.paypal_single_payment_button);
Expand All @@ -46,14 +44,16 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
singlePaymentButton.setOnClickListener(this::launchSinglePayment);

braintreeClient = getBraintreeClient();

useManualBrowserSwitch = Settings.isManualBrowserSwitchingEnabled(requireActivity());
if (useManualBrowserSwitch) {
payPalClient = new PayPalClient(braintreeClient);
} else {
payPalClient = new PayPalClient(this, braintreeClient);
payPalClient.setListener(this);
}
payPalClient = new PayPalClient(braintreeClient);
payPalLauncher = new PayPalLauncher(
payPalBrowserSwitchResult -> payPalClient.onBrowserSwitchResult(
payPalBrowserSwitchResult, (payPalAccountNonce, error) -> {
if (error != null) {
handleError(error);
} else if (payPalAccountNonce != null) {
handlePayPalResult(payPalAccountNonce);
}
}));

amount = RandomDollarAmount.getNext();
return view;
Expand All @@ -62,25 +62,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
@Override
public void onResume() {
super.onResume();
if (useManualBrowserSwitch) {
Activity activity = requireActivity();
BrowserSwitchResult browserSwitchResult =
payPalClient.parseBrowserSwitchResult(activity, activity.getIntent());
if (browserSwitchResult != null) {
handleBrowserSwitchResult(browserSwitchResult);
}
}
}

private void handleBrowserSwitchResult(BrowserSwitchResult browserSwitchResult) {
payPalClient.onBrowserSwitchResult(browserSwitchResult, ((payPalAccountNonce, error) -> {
if (payPalAccountNonce != null) {
handlePayPalResult(payPalAccountNonce);
} else if (error != null) {
handleError(error);
}
}));
payPalClient.clearActiveBrowserSwitchRequests(requireContext());
payPalLauncher.handleReturnToAppFromBrowser(requireContext(), requireActivity().getIntent());
}

public void launchSinglePayment(View v) {
Expand All @@ -103,42 +85,43 @@ private void launchPayPal(boolean isBillingAgreement) {
if (deviceDataResult != null) {
deviceData = deviceDataResult;
}
if (isBillingAgreement) {
payPalClient.tokenizePayPalAccount(activity, createPayPalVaultRequest(activity));
} else {
payPalClient.tokenizePayPalAccount(activity, createPayPalCheckoutRequest(activity, amount));
}
launchPayPal(activity, isBillingAgreement, amount);
});
} else {
if (isBillingAgreement) {
payPalClient.tokenizePayPalAccount(activity, createPayPalVaultRequest(activity));
} else {
payPalClient.tokenizePayPalAccount(activity, createPayPalCheckoutRequest(activity, amount));
}
launchPayPal(activity, isBillingAgreement, amount);
}
});
}

private void launchPayPal(FragmentActivity activity, boolean isBillingAgreement,
String amount) {
PayPalRequest payPalRequest;
if (isBillingAgreement) {
payPalRequest = createPayPalVaultRequest(activity);
} else {
payPalRequest = createPayPalCheckoutRequest(activity, amount);
}
payPalClient.tokenizePayPalAccount(activity, payPalRequest,
(payPalResponse, error) -> {
if (error != null) {
handleError(error);
} else {
payPalLauncher.launch(requireActivity(), payPalResponse);
}
});
}

private void handlePayPalResult(PaymentMethodNonce paymentMethodNonce) {
if (paymentMethodNonce != null) {
super.onPaymentMethodNonceCreated(paymentMethodNonce);

PayPalFragmentDirections.ActionPayPalFragmentToDisplayNonceFragment action =
PayPalFragmentDirections.actionPayPalFragmentToDisplayNonceFragment(paymentMethodNonce);
PayPalFragmentDirections.actionPayPalFragmentToDisplayNonceFragment(
paymentMethodNonce);
action.setTransactionAmount(amount);
action.setDeviceData(deviceData);

NavHostFragment.findNavController(this).navigate(action);
}
}

@Override
public void onPayPalSuccess(@NonNull PayPalAccountNonce payPalAccountNonce) {
handlePayPalResult(payPalAccountNonce);
}

@Override
public void onPayPalFailure(@NonNull Exception error) {
handleError(error);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.braintreepayments.api;

/**
* Result received from the PayPal web flow through {@link PayPalBrowserSwitchResultCallback}.
* This result should be passed to
* {@link PayPalClient#onBrowserSwitchResult(PayPalBrowserSwitchResult, PayPalBrowserSwitchResultCallback)}
* to complete the PayPal payment flow.
*/
public class PayPalBrowserSwitchResult {

private BrowserSwitchResult browserSwitchResult;
private Exception error;

PayPalBrowserSwitchResult(BrowserSwitchResult browserSwitchResult) {
this.browserSwitchResult = browserSwitchResult;
}

PayPalBrowserSwitchResult(Exception error) {
this.error = error;
}

BrowserSwitchResult getBrowserSwitchResult() {
return browserSwitchResult;
}

Exception getError() {
return error;
}
Comment on lines +22 to +28
Copy link
Contributor

Choose a reason for hiding this comment

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

Do these need to be public w/ docstrings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No the idea with this result object is that the merchant doesn't have to do anything with it / be aware of any params and just passes it directly to the PayPalClient#onBrowserSwitchResult method, which will then handle any errors and call them back to the merchant. We could break it up and allow merchants to handle errors at each step, but this seems cleaner for integrations

}
Loading
Loading