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 Result Object Refactor #836

Merged
merged 11 commits into from
Dec 4, 2023
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
* PayPal
* Remove `PayPalListener`
* Add `PayPalLauncher`, `PayPalPaymentAuthRequest`, `PayPalPaymentAuthResult`,
`PayPalPaymentAuthCallback`, and `PayPalTokenizeCallback`
`PayPalPaymentAuthCallback`, `PayPalTokenizeCallback`, and `PayPalResult`
* Remove`PayPalFlowStartedCallback`
* Remove overload constructors, `setListener`, `parseBrowserSwitchResult`,
`clearActiveBrowserSwitchResult`, `requestOneTimePayment`, and `requestBillingAgreement` from
Expand Down
23 changes: 13 additions & 10 deletions Demo/src/main/java/com/braintreepayments/demo/PayPalFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import com.braintreepayments.api.DataCollector;
import com.braintreepayments.api.PayPalClient;
import com.braintreepayments.api.PayPalLauncher;
import com.braintreepayments.api.PayPalPaymentAuthRequest;
import com.braintreepayments.api.PayPalRequest;
import com.braintreepayments.api.PayPalResult;
import com.braintreepayments.api.PaymentMethodNonce;

public class PayPalFragment extends BaseFragment {
Expand All @@ -44,11 +46,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
payPalClient = new PayPalClient(requireContext(), super.getAuthStringArg());
payPalLauncher = new PayPalLauncher(
paymentAuthResult -> payPalClient.tokenize(
paymentAuthResult, (payPalAccountNonce, error) -> {
if (error != null) {
handleError(error);
} else if (payPalAccountNonce != null) {
handlePayPalResult(payPalAccountNonce);
paymentAuthResult, (payPalResult) -> {
if (payPalResult instanceof PayPalResult.Failure) {
handleError(((PayPalResult.Failure) payPalResult).getError());
} else if (payPalResult instanceof PayPalResult.Success) {
handlePayPalResult(((PayPalResult.Success) payPalResult).getNonce());
}
}));

Expand Down Expand Up @@ -97,11 +99,12 @@ private void launchPayPal(FragmentActivity activity, boolean isBillingAgreement,
payPalRequest = createPayPalCheckoutRequest(activity, amount);
}
payPalClient.createPaymentAuthRequest(activity, payPalRequest,
(paymentAuthRequest, error) -> {
if (error != null) {
handleError(error);
} else {
payPalLauncher.launch(requireActivity(), paymentAuthRequest);
(paymentAuthRequest) -> {
if (paymentAuthRequest instanceof PayPalPaymentAuthRequest.Failure) {
handleError(((PayPalPaymentAuthRequest.Failure) paymentAuthRequest).getError());
} else if (paymentAuthRequest instanceof PayPalPaymentAuthRequest.ReadyToLaunch){
payPalLauncher.launch(requireActivity(),
((PayPalPaymentAuthRequest.ReadyToLaunch) paymentAuthRequest).getRequestParams());
}
});
}
Expand Down
42 changes: 23 additions & 19 deletions PayPal/src/main/java/com/braintreepayments/api/PayPalClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ private static Exception createBrowserSwitchError(BrowserSwitchException excepti
}

/**
* Starts the PayPal payment flow by creating a {@link PayPalPaymentAuthRequest} to be used to
* Starts the PayPal payment flow by creating a {@link PayPalPaymentAuthRequestParams} to be used to
* launch the PayPal web authentication flow in
* {@link PayPalLauncher#launch(FragmentActivity, PayPalPaymentAuthRequest)}.
* {@link PayPalLauncher#launch(FragmentActivity, PayPalPaymentAuthRequestParams)}.
*
* @param activity Android FragmentActivity
* @param payPalRequest a {@link PayPalRequest} used to customize the request.
Expand All @@ -96,7 +96,7 @@ private void sendCheckoutRequest(final FragmentActivity activity,
braintreeClient.getConfiguration((configuration, error) -> {
if (payPalConfigInvalid(configuration)) {
Exception configInvalidError = createPayPalError();
callback.onResult(null, configInvalidError);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.Failure(configInvalidError));
return;
}

Expand All @@ -106,7 +106,7 @@ private void sendCheckoutRequest(final FragmentActivity activity,
braintreeClient.sendAnalyticsEvent("paypal.invalid-manifest");
Exception manifestInvalidError =
createBrowserSwitchError(browserSwitchException);
callback.onResult(null, manifestInvalidError);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.Failure(manifestInvalidError));
return;
}
sendPayPalRequest(activity, payPalCheckoutRequest, callback);
Expand All @@ -125,7 +125,7 @@ private void sendVaultRequest(final FragmentActivity activity,
braintreeClient.getConfiguration((configuration, error) -> {
if (payPalConfigInvalid(configuration)) {
Exception configInvalidError = createPayPalError();
callback.onResult(null, configInvalidError);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.Failure(configInvalidError));
return;
}

Expand All @@ -135,7 +135,7 @@ private void sendVaultRequest(final FragmentActivity activity,
braintreeClient.sendAnalyticsEvent("paypal.invalid-manifest");
Exception manifestInvalidError =
createBrowserSwitchError(browserSwitchException);
callback.onResult(null, manifestInvalidError);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.Failure(manifestInvalidError));
return;
}
sendPayPalRequest(activity, payPalVaultRequest, callback);
Expand All @@ -156,18 +156,18 @@ private void sendPayPalRequest(final FragmentActivity activity,
BrowserSwitchOptions options =
buildBrowserSwitchOptions(payPalResponse);
payPalResponse.setBrowserSwitchOptions(options);
callback.onResult(payPalResponse, null);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.ReadyToLaunch(payPalResponse));
} catch (JSONException exception) {
callback.onResult(null, exception);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.Failure(exception));
}
} else {
callback.onResult(null, error);
callback.onPayPalPaymentAuthRequest(new PayPalPaymentAuthRequest.Failure(error));
}
});
}

private BrowserSwitchOptions buildBrowserSwitchOptions(
PayPalPaymentAuthRequest paymentAuthRequest)
PayPalPaymentAuthRequestParams paymentAuthRequest)
throws JSONException {
JSONObject metadata = new JSONObject();
metadata.put("approval-url", paymentAuthRequest.getApprovalUrl());
Expand Down Expand Up @@ -209,18 +209,18 @@ public void tokenize(@NonNull PayPalPaymentAuthResult paymentAuthResult,
@NonNull final PayPalTokenizeCallback callback) {
//noinspection ConstantConditions
if (paymentAuthResult == null) {
callback.onResult(null,
new BraintreeException("PayPalBrowserSwitchResult cannot be null"));
callback.onPayPalResult(new PayPalResult.Failure(
new BraintreeException("PayPalBrowserSwitchResult cannot be null")));
return;
}
BrowserSwitchResult browserSwitchResult =
paymentAuthResult.getBrowserSwitchResult();
if (browserSwitchResult == null && paymentAuthResult.getError() != null) {
callback.onResult(null, paymentAuthResult.getError());
callback.onPayPalResult(new PayPalResult.Failure(paymentAuthResult.getError()));
return;
}
if (browserSwitchResult == null) {
callback.onResult(null, new BraintreeException("An unexpected error occurred"));
callback.onPayPalResult(new PayPalResult.Failure(new BraintreeException("An unexpected error occurred")));
return;
}
JSONObject metadata = browserSwitchResult.getRequestMetadata();
Expand All @@ -239,7 +239,7 @@ public void tokenize(@NonNull PayPalPaymentAuthResult paymentAuthResult,
int result = browserSwitchResult.getStatus();
switch (result) {
case BrowserSwitchStatus.CANCELED:
callback.onResult(null, new UserCanceledException("User canceled PayPal."));
callback.onPayPalResult(PayPalResult.Cancel.INSTANCE);
braintreeClient.sendAnalyticsEvent(
String.format("%s.browser-switch.canceled", analyticsPrefix));
break;
Expand Down Expand Up @@ -272,20 +272,24 @@ public void tokenize(@NonNull PayPalPaymentAuthResult paymentAuthResult,
braintreeClient.sendAnalyticsEvent(
"paypal.credit.accepted");
}
callback.onResult(payPalAccountNonce, error);
if (payPalAccountNonce != null) {
callback.onPayPalResult(new PayPalResult.Success(payPalAccountNonce));
} else if (error != null) {
callback.onPayPalResult(new PayPalResult.Failure(error));
}
});

braintreeClient.sendAnalyticsEvent(
String.format("%s.browser-switch.succeeded", analyticsPrefix));
} else {
callback.onResult(null, new BraintreeException("Unknown error"));
callback.onPayPalResult(new PayPalResult.Failure(new BraintreeException("Unknown error")));
}
} catch (UserCanceledException e) {
callback.onResult(null, e);
callback.onPayPalResult(PayPalResult.Cancel.INSTANCE);
braintreeClient.sendAnalyticsEvent(
String.format("%s.browser-switch.canceled", analyticsPrefix));
} catch (JSONException | PayPalBrowserSwitchException e) {
callback.onResult(null, e);
callback.onPayPalResult(new PayPalResult.Failure(e));
braintreeClient.sendAnalyticsEvent(
String.format("%s.browser-switch.failed", analyticsPrefix));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ void sendRequest(final Context context, final PayPalRequest payPalRequest,
(responseBody, httpError) -> {
if (responseBody != null) {
try {
PayPalPaymentAuthRequest paymentAuthRequest =
new PayPalPaymentAuthRequest(payPalRequest)
PayPalPaymentAuthRequestParams paymentAuthRequest =
new PayPalPaymentAuthRequestParams(payPalRequest)
.successUrl(successUrl);

PayPalPaymentResource paypalPaymentResource =
Expand Down Expand Up @@ -112,7 +112,7 @@ void sendRequest(final Context context, final PayPalRequest payPalRequest,
});
}

void tokenize(PayPalAccount payPalAccount, final PayPalTokenizeCallback callback) {
void tokenize(PayPalAccount payPalAccount, final PayPalInternalTokenizeCallback callback) {
apiClient.tokenizeREST(payPalAccount, (tokenizationResponse, exception) -> {
if (tokenizationResponse != null) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import androidx.annotation.Nullable;

interface PayPalInternalClientCallback {
void onResult(@Nullable PayPalPaymentAuthRequest paymentAuthRequest, @Nullable Exception error);
void onResult(@Nullable PayPalPaymentAuthRequestParams paymentAuthRequest, @Nullable Exception error);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.braintreepayments.api;

import androidx.annotation.Nullable;

interface PayPalInternalTokenizeCallback {

void onResult(@Nullable PayPalAccountNonce payPalAccountNonce, @Nullable Exception error);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class PayPalLauncher {
* Used to launch the PayPal flow in a web browser and deliver results to your Activity
*
* @param callback a {@link PayPalLauncherCallback} to handle the result of
* {@link PayPalLauncher#launch(FragmentActivity, PayPalPaymentAuthRequest)}
* {@link PayPalLauncher#launch(FragmentActivity, PayPalPaymentAuthRequestParams)}
*/
public PayPalLauncher(@NonNull PayPalLauncherCallback callback) {
this(new BrowserSwitchClient(), callback);
Expand All @@ -45,7 +45,7 @@ public PayPalLauncher(@NonNull PayPalLauncherCallback callback) {
* PayPalRequest, PayPalPaymentAuthCallback)}
*/
public void launch(@NonNull FragmentActivity activity,
@NonNull PayPalPaymentAuthRequest paymentAuthRequest) {
@NonNull PayPalPaymentAuthRequestParams paymentAuthRequest) {
try {
browserSwitchClient.start(activity, paymentAuthRequest.getBrowserSwitchOptions());
} catch (BrowserSwitchException e) {
Expand All @@ -57,7 +57,7 @@ public void launch(@NonNull FragmentActivity activity,
* Captures and delivers the result of a the browser-based PayPal authentication flow.
* <p>
* For most integrations, this method should be invoked in the onResume method of the Activity
* used to invoke {@link PayPalLauncher#launch(FragmentActivity, PayPalPaymentAuthRequest)}.
* used to invoke {@link PayPalLauncher#launch(FragmentActivity, PayPalPaymentAuthRequestParams)}.
* <p>
* If the Activity used to launch the PayPal flow has is configured with
* android:launchMode="singleTop", this method should be invoked in the onNewIntent method of
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.braintreepayments.api;

import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;

/**
Expand All @@ -11,7 +10,6 @@ public interface PayPalPaymentAuthCallback {

/**
* @param paymentAuthRequest a request used to launch the PayPal web authentication flow
* @param error an exception that occurred while initiating a PayPal transaction
*/
void onResult(PayPalPaymentAuthRequest paymentAuthRequest, @Nullable Exception error);
void onPayPalPaymentAuthRequest(PayPalPaymentAuthRequest paymentAuthRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.braintreepayments.api

/**
* A request used to launch the Venmo app for continuation of the PayPal payment flow.
*/
sealed class PayPalPaymentAuthRequest {

/**
* The request was successfully created and is ready to be launched by [PayPalLauncher]
*/
class ReadyToLaunch(val requestParams: PayPalPaymentAuthRequestParams) :
PayPalPaymentAuthRequest()

/**
* There was an [error] creating the request
*/
class Failure(val error: Exception) : PayPalPaymentAuthRequest()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.braintreepayments.api;

public class PayPalPaymentAuthRequest {
public class PayPalPaymentAuthRequestParams {

private String approvalUrl;
private String clientMetadataId;
Expand All @@ -11,15 +11,15 @@ public class PayPalPaymentAuthRequest {

private BrowserSwitchOptions browserSwitchOptions;

PayPalPaymentAuthRequest(PayPalRequest payPalRequest) {
PayPalPaymentAuthRequestParams(PayPalRequest payPalRequest) {
this.payPalRequest = payPalRequest;
}

String getApprovalUrl() {
return approvalUrl;
}

PayPalPaymentAuthRequest approvalUrl(String value) {
PayPalPaymentAuthRequestParams approvalUrl(String value) {
approvalUrl = value;
return this;
}
Expand All @@ -28,7 +28,7 @@ String getClientMetadataId() {
return clientMetadataId;
}

PayPalPaymentAuthRequest clientMetadataId(String value) {
PayPalPaymentAuthRequestParams clientMetadataId(String value) {
clientMetadataId = value;
return this;
}
Expand Down Expand Up @@ -59,7 +59,7 @@ String getPairingId() {
return pairingId;
}

PayPalPaymentAuthRequest pairingId(String value) {
PayPalPaymentAuthRequestParams pairingId(String value) {
pairingId = value;
return this;
}
Expand All @@ -68,7 +68,7 @@ String getSuccessUrl() {
return successUrl;
}

PayPalPaymentAuthRequest successUrl(String value) {
PayPalPaymentAuthRequestParams successUrl(String value) {
successUrl = value;
return this;
}
Expand Down
22 changes: 22 additions & 0 deletions PayPal/src/main/java/com/braintreepayments/api/PayPalResult.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.braintreepayments.api

/**
* Result of tokenizing a PayPal account
*/
sealed class PayPalResult {

/**
* The PayPal flow completed successfully. This [nonce] should be sent to your server.
*/
class Success(val nonce: PayPalAccountNonce) : PayPalResult()

/**
* There was an [error] in the PayPal payment flow.
*/
class Failure(val error: Exception) : PayPalResult()

/**
* The user canceled the PayPal payment flow.
*/
object Cancel : PayPalResult()
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.braintreepayments.api;

import androidx.annotation.Nullable;
import androidx.annotation.NonNull;

/**
* Callback for receiving result of
* {@link PayPalClient#onBrowserSwitchResult(BrowserSwitchResult, PayPalTokenizeCallback)}.
* {@link PayPalClient#tokenize(PayPalPaymentAuthResult, PayPalTokenizeCallback)}.
*/
public interface PayPalTokenizeCallback {

/**
* @param payPalAccountNonce {@link PayPalAccountNonce}
* @param error an exception that occurred while processing a PayPal result
*
* @param payPalResult a success, failure, or cancel result from the PayPal flow
*/
void onResult(@Nullable PayPalAccountNonce payPalAccountNonce, @Nullable Exception error);
void onPayPalResult(@NonNull PayPalResult payPalResult);
}
Loading
Loading