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

Local Payment Single Result Object #851

Merged
merged 16 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
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
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
* LocalPayment
* Remove `LocalPaymentListener`
* Add `LocalPaymentLauncher`, `LocalPaymentLauncherCallback`, `LocalPaymentTokenizeCallback`,
and `LocalPaymentAuthRequest`
* Rename `LocalPaymentResult` to `LocalPaymentAuthResult`
`LocalPaymentAuthRequest`, `LocalPaymentAuthRequestCallback` and `LocalPaymentAuthResult`
* Change `LocalPaymentResult` type
* Remove overload constructors, `setListener`, `parseBrowserSwitchResult`,
`clearActiveBrowserSwitchResult`, `approveLocalPayment`, and `approvePayment` from
`LocalPaymentClient`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public void getClientToken(@NonNull BraintreeAuthorizationCallback callback) {
callback.onResult(null);
}
});
} else {
callback.onResult(Settings.getTokenizationKey(appContext));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;

import com.braintreepayments.api.LocalPaymentAuthRequest;
import com.braintreepayments.api.LocalPaymentAuthResult;
import com.braintreepayments.api.LocalPaymentClient;
import com.braintreepayments.api.LocalPaymentLauncher;
import com.braintreepayments.api.LocalPaymentNonce;
import com.braintreepayments.api.LocalPaymentRequest;
import com.braintreepayments.api.LocalPaymentResult;
import com.braintreepayments.api.PostalAddress;
import com.braintreepayments.api.UserCanceledException;

public class LocalPaymentFragment extends BaseFragment {

Expand Down Expand Up @@ -69,22 +73,28 @@ public void launchIdeal(View v) {
request.setMerchantAccountId("altpay_eur");
request.setCurrencyCode("EUR");

localPaymentClient.createPaymentAuthRequest(request, (localPaymentResult, error) -> {
if (localPaymentResult != null) {
localPaymentLauncher.launch(requireActivity(), localPaymentResult);
} else {
handleError(error);
localPaymentClient.createPaymentAuthRequest(request, (paymentAuthRequest) -> {
if (paymentAuthRequest instanceof LocalPaymentAuthRequest.ReadyToLaunch) {
localPaymentLauncher.launch(requireActivity(),
(LocalPaymentAuthRequest.ReadyToLaunch) paymentAuthRequest);
} else if (paymentAuthRequest instanceof LocalPaymentAuthRequest.Failure) {
handleError(((LocalPaymentAuthRequest.Failure) paymentAuthRequest).getError());
}
});
}

protected void handleLocalPaymentResult(LocalPaymentNonce localPaymentNonce, Exception error) {
super.onPaymentMethodNonceCreated(localPaymentNonce);

if (error != null) {
handleError(error);
return;
protected void handleLocalPaymentResult(LocalPaymentResult localPaymentResult) {
if (localPaymentResult instanceof LocalPaymentResult.Success) {
onPaymentMethodNonceCreated(((LocalPaymentResult.Success) localPaymentResult).getNonce());
} else if (localPaymentResult instanceof LocalPaymentResult.Failure) {
handleError(((LocalPaymentResult.Failure) localPaymentResult).getError());
} else if (localPaymentResult instanceof LocalPaymentResult.Cancel) {
handleError(new UserCanceledException("User canceled Local Payment"));
}
}

protected void onPaymentMethodNonceCreated(LocalPaymentNonce localPaymentNonce) {
super.onPaymentMethodNonceCreated(localPaymentNonce);

LocalPaymentFragmentDirections.ActionLocalPaymentFragmentToDisplayNonceFragment action =
LocalPaymentFragmentDirections.actionLocalPaymentFragmentToDisplayNonceFragment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static junit.framework.Assert.assertNotNull;

import static org.junit.Assert.assertTrue;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;

Expand Down Expand Up @@ -43,9 +45,10 @@ public void createPaymentAuthRequest_callsBack_withApprovalUrl_andPaymentId() th
request.setCurrencyCode("EUR");

LocalPaymentClient sut = new LocalPaymentClient(braintreeClient);
sut.createPaymentAuthRequest(request, (localPaymentResult, error) -> {
assertNotNull(localPaymentResult.getApprovalUrl());
assertNotNull(localPaymentResult.getPaymentId());
sut.createPaymentAuthRequest(request, (localPaymentAuthRequest) -> {
assertTrue(localPaymentAuthRequest instanceof LocalPaymentAuthRequest.ReadyToLaunch);
assertNotNull(((LocalPaymentAuthRequest.ReadyToLaunch) localPaymentAuthRequest).getRequestParams().getApprovalUrl());
assertNotNull(((LocalPaymentAuthRequest.ReadyToLaunch) localPaymentAuthRequest).getRequestParams().getPaymentId());
countDownLatch.countDown();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class LocalPaymentApi {
}

void createPaymentMethod(final LocalPaymentRequest request,
final LocalPaymentAuthRequestCallback callback) {
final LocalPaymentInternalAuthRequestCallback callback) {
String returnUrl = braintreeClient.getReturnUrlScheme() + "://" + LOCAL_PAYMENT_SUCCESS;
String cancel = braintreeClient.getReturnUrlScheme() + "://" + LOCAL_PAYMENT_CANCEL;

Expand All @@ -30,8 +30,8 @@ void createPaymentMethod(final LocalPaymentRequest request,
String paymentToken = responseJson.getJSONObject("paymentResource")
.getString("paymentToken");

LocalPaymentAuthRequest transaction =
new LocalPaymentAuthRequest(request, redirectUrl, paymentToken);
LocalPaymentAuthRequestParams transaction =
new LocalPaymentAuthRequestParams(request, redirectUrl, paymentToken);
callback.onResult(transaction, null);
} catch (JSONException e) {
callback.onResult(null, e);
Expand All @@ -43,7 +43,7 @@ void createPaymentMethod(final LocalPaymentRequest request,
}

void tokenize(String merchantAccountId, String responseString, String clientMetadataID,
final LocalPaymentTokenizeCallback callback) {
final LocalPaymentInternalTokenizeCallback callback) {
JSONObject payload = new JSONObject();

try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.braintreepayments.api

/**
* Callback for receiving result of
* [LocalPaymentClient.createPaymentAuthRequest].
*/
interface LocalPaymentAuthCallback {
sarahkoop marked this conversation as resolved.
Show resolved Hide resolved
/**
* @param paymentAuthRequest a request used to launch the PayPal web authentication flow
*/
fun onLocalPaymentAuthRequest(paymentAuthRequest: LocalPaymentAuthRequest)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.braintreepayments.api

/**
* A request used to launch the continuation of the local payment flow.
*/
sealed class LocalPaymentAuthRequest {

/**
* The request was successfully created and is ready to be launched by [LocalPaymentLauncher]
*/
class ReadyToLaunch(val requestParams: LocalPaymentAuthRequestParams) :
LocalPaymentAuthRequest()

/**
* There was an [error] creating the request
*/
class Failure(val error: Exception) : LocalPaymentAuthRequest()
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
/**
* Local payment result information.
*/
public class LocalPaymentAuthRequest {
public class LocalPaymentAuthRequestParams {

private final LocalPaymentRequest request;
private final String approvalUrl;
private final String paymentId;

private BrowserSwitchOptions browserSwitchOptions;

LocalPaymentAuthRequest(LocalPaymentRequest request, String approvalUrl, String paymentId) {
LocalPaymentAuthRequestParams(LocalPaymentRequest request, String approvalUrl, String paymentId) {
this.request = request;
this.approvalUrl = approvalUrl;
this.paymentId = paymentId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

/**
* Result received from the local payment web flow through
* {@link LocalPaymentTokenizeCallback}. This result should be passed to
* {@link LocalPaymentClient#tokenize(Context, LocalPaymentAuthResult, LocalPaymentTokenizeCallback)}
* {@link LocalPaymentInternalTokenizeCallback}. This result should be passed to
* {@link LocalPaymentClient#tokenize(Context, LocalPaymentAuthResult, LocalPaymentInternalTokenizeCallback)}
* to complete the local payment flow.
*/
public class LocalPaymentAuthResult {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ public LocalPaymentClient(@NonNull Context context, @NonNull String authorizatio

/**
* Starts the payment flow for a {@link LocalPaymentRequest} and calls back a
* {@link LocalPaymentAuthRequest} on success that should be used to launch the user
* {@link LocalPaymentAuthRequestParams} on success that should be used to launch the user
* authentication flow.
*
* @param request {@link LocalPaymentRequest} with the payment details.
* @param callback {@link LocalPaymentAuthRequestCallback}
* @param callback {@link LocalPaymentInternalAuthRequestCallback}
*/
public void createPaymentAuthRequest(@NonNull final LocalPaymentRequest request,
@NonNull final LocalPaymentAuthRequestCallback callback) {
@NonNull final LocalPaymentAuthCallback callback) {
Exception exception = null;

//noinspection ConstantConditions
Expand All @@ -74,13 +74,13 @@ public void createPaymentAuthRequest(@NonNull final LocalPaymentRequest request,
}

if (exception != null) {
callback.onResult(null, exception);
callback.onLocalPaymentAuthRequest(new LocalPaymentAuthRequest.Failure(exception));
} else {
braintreeClient.getConfiguration((configuration, error) -> {
if (configuration != null) {
if (!configuration.isPayPalEnabled()) {
callback.onResult(null, new ConfigurationException(
"Local payments are not enabled for this merchant."));
callback.onLocalPaymentAuthRequest(new LocalPaymentAuthRequest.Failure(new ConfigurationException(
"Local payments are not enabled for this merchant.")));
return;
}

Expand All @@ -94,40 +94,41 @@ public void createPaymentAuthRequest(@NonNull final LocalPaymentRequest request,
sendAnalyticsEvent(request.getPaymentType(),
"local-payment.create.succeeded");
} else if (createPaymentMethodError != null) {
callback.onResult(null, new BraintreeException("An error " +
"occurred creating the local payment method."));
callback.onLocalPaymentAuthRequest(new LocalPaymentAuthRequest.Failure(new BraintreeException("An error " +
"occurred creating the local payment method.")));
sendAnalyticsEvent(request.getPaymentType(),
"local-payment.webswitch.initiate.failed");
}
});
} else {
callback.onResult(null, error);
callback.onLocalPaymentAuthRequest(new LocalPaymentAuthRequest.Failure(error));
}
});
}
}

void buildBrowserSwitchOptions(@NonNull LocalPaymentAuthRequest localPaymentAuthRequest,
@NonNull LocalPaymentAuthRequestCallback callback) {
void buildBrowserSwitchOptions(@NonNull
LocalPaymentAuthRequestParams localPaymentAuthRequestParams,
@NonNull LocalPaymentAuthCallback callback) {
BrowserSwitchOptions browserSwitchOptions = new BrowserSwitchOptions()
.requestCode(BraintreeRequestCodes.LOCAL_PAYMENT)
.returnUrlScheme(braintreeClient.getReturnUrlScheme())
.launchAsNewTask(braintreeClient.launchesBrowserSwitchAsNewTask())
.url(Uri.parse(localPaymentAuthRequest.getApprovalUrl()));
.url(Uri.parse(localPaymentAuthRequestParams.getApprovalUrl()));

String paymentType = localPaymentAuthRequest.getRequest().getPaymentType();
String paymentType = localPaymentAuthRequestParams.getRequest().getPaymentType();

try {
browserSwitchOptions.metadata(new JSONObject()
.put("merchant-account-id",
localPaymentAuthRequest.getRequest().getMerchantAccountId())
.put("payment-type", localPaymentAuthRequest.getRequest().getPaymentType()));
localPaymentAuthRequestParams.getRequest().getMerchantAccountId())
.put("payment-type", localPaymentAuthRequestParams.getRequest().getPaymentType()));
} catch (JSONException e) {
callback.onResult(null, new BraintreeException("Error parsing local payment request"));
callback.onLocalPaymentAuthRequest(new LocalPaymentAuthRequest.Failure(new BraintreeException("Error parsing local payment request")));
}

localPaymentAuthRequest.setBrowserSwitchOptions(browserSwitchOptions);
callback.onResult(localPaymentAuthRequest, null);
localPaymentAuthRequestParams.setBrowserSwitchOptions(browserSwitchOptions);
callback.onLocalPaymentAuthRequest(new LocalPaymentAuthRequest.ReadyToLaunch(localPaymentAuthRequestParams));
sendAnalyticsEvent(paymentType, "local-payment.webswitch.initiate.succeeded");
}

Expand All @@ -140,22 +141,22 @@ void buildBrowserSwitchOptions(@NonNull LocalPaymentAuthRequest localPaymentAuth
* @param context Android Context
* @param localPaymentAuthResult a {@link LocalPaymentAuthResult} received
* in the callback of {@link LocalPaymentLauncher}
* @param callback {@link LocalPaymentTokenizeCallback}
* @param callback {@link LocalPaymentInternalTokenizeCallback}
*/
public void tokenize(@NonNull final Context context,
@Nullable LocalPaymentAuthResult localPaymentAuthResult,
@NonNull final LocalPaymentTokenizeCallback callback) {
//noinspection ConstantConditions
if (localPaymentAuthResult == null) {
callback.onResult(null, new BraintreeException("LocalPaymentAuthResult " +
"cannot be null"));
callback.onLocalPaymentResult(new LocalPaymentResult.Failure(new BraintreeException("LocalPaymentAuthResult " +
"cannot be null")));
return;
}

BrowserSwitchResult browserSwitchResult =
localPaymentAuthResult.getBrowserSwitchResult();
if (browserSwitchResult == null && localPaymentAuthResult.getError() != null) {
callback.onResult(null, localPaymentAuthResult.getError());
callback.onLocalPaymentResult(new LocalPaymentResult.Failure(localPaymentAuthResult.getError()));
return;
}

Expand All @@ -168,23 +169,22 @@ public void tokenize(@NonNull final Context context,
switch (result) {
case BrowserSwitchStatus.CANCELED:
sendAnalyticsEvent(paymentType, "local-payment.webswitch.canceled");
callback.onResult(null, new UserCanceledException("User canceled Local Payment."));
callback.onLocalPaymentResult(LocalPaymentResult.Cancel.INSTANCE);
return;
case BrowserSwitchStatus.SUCCESS:
Uri deepLinkUri = browserSwitchResult.getDeepLinkUrl();
if (deepLinkUri == null) {
sendAnalyticsEvent(paymentType, "local-payment.webswitch-response.invalid");
callback.onResult(null,
callback.onLocalPaymentResult(new LocalPaymentResult.Failure(
new BraintreeException("LocalPayment encountered an error, " +
"return URL is invalid."));
"return URL is invalid.")));
return;
}

final String responseString = deepLinkUri.toString();
if (responseString.toLowerCase().contains(LOCAL_PAYMENT_CANCEL.toLowerCase())) {
sendAnalyticsEvent(paymentType, "local-payment.webswitch.canceled");
callback.onResult(null,
new UserCanceledException("User canceled Local Payment."));
callback.onLocalPaymentResult(LocalPaymentResult.Cancel.INSTANCE);
return;
}
braintreeClient.getConfiguration((configuration, error) -> {
Expand All @@ -195,14 +195,15 @@ public void tokenize(@NonNull final Context context,
if (localPaymentNonce != null) {
sendAnalyticsEvent(paymentType,
"local-payment.tokenize.succeeded");
callback.onLocalPaymentResult(new LocalPaymentResult.Success(localPaymentNonce));
} else if (localPaymentError != null) {
sendAnalyticsEvent(paymentType,
"local-payment.tokenize.failed");
callback.onLocalPaymentResult(new LocalPaymentResult.Failure(localPaymentError));
}
callback.onResult(localPaymentNonce, localPaymentError);
});
} else if (error != null) {
callback.onResult(null, error);
callback.onLocalPaymentResult(new LocalPaymentResult.Failure(error));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.braintreepayments.api;

import androidx.annotation.Nullable;

/**
* Callback for receiving result of
* {@link LocalPaymentClient#createPaymentAuthRequest(LocalPaymentRequest, LocalPaymentAuthCallback)}.
*/
public interface LocalPaymentInternalAuthRequestCallback {

/**
* @param localPaymentAuthRequestParams {@link LocalPaymentAuthRequestParams}
* @param error an exception that occurred while initiating a Local Payment
*/
void onResult(@Nullable LocalPaymentAuthRequestParams localPaymentAuthRequestParams, @Nullable Exception error);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.braintreepayments.api;


import androidx.annotation.Nullable;

interface LocalPaymentInternalTokenizeCallback {

void onResult(@Nullable LocalPaymentNonce localPaymentNonce, @Nullable Exception error);
}
Loading
Loading