Skip to content

Commit

Permalink
Add Status flag to PaymentAuthWebViewActivity result
Browse files Browse the repository at this point in the history
Browser-based auth was previously not returning a
`StripeIntentResult.Status`.

Fixes #1253
  • Loading branch information
mshafrir-stripe committed Jul 29, 2019
1 parent 875aedb commit 6e29982
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ public void onSuccess(@NonNull PaymentIntentResult paymentIntentResult) {

final PaymentIntent paymentIntent = paymentIntentResult.getIntent();
activity.mStatusTextView.append("\n\n" +
"Auth status: " + paymentIntentResult.getStatus() + "\n\n" +
activity.getString(R.string.payment_intent_status, paymentIntent.getStatus()));
activity.onAuthComplete();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
Expand All @@ -14,17 +13,14 @@
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

import com.stripe.android.R;
import com.stripe.android.StripeIntentResult;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
* A {@link WebView} used for authenticating payment and deep-linking the user back to the
* PaymentIntent's return_url[0].
* <p>
* [0] https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-return_url
* A {@link WebView} used for authenticating payment details
*/
class PaymentAuthWebView extends WebView {
@SuppressWarnings("RedundantModifier")
Expand All @@ -45,8 +41,10 @@ public PaymentAuthWebView(@NonNull Context context, @Nullable AttributeSet attrs
configureSettings();
}

void init(@NonNull Activity activity, @NonNull String clientSecret, @NonNull String returnUrl) {
setWebViewClient(new PaymentAuthWebViewClient(activity, clientSecret, returnUrl));
void init(@NonNull PaymentAuthWebViewClient.Listener listener, @NonNull ProgressBar progressBar,
@NonNull String clientSecret, @NonNull String returnUrl) {
setWebViewClient(new PaymentAuthWebViewClient(listener, progressBar, clientSecret,
returnUrl));
}

@SuppressLint("SetJavaScriptEnabled")
Expand All @@ -65,17 +63,17 @@ static class PaymentAuthWebViewClient extends WebViewClient {
"https://hooks.stripe.com/3d_secure/complete/tdsrc_"
));

@NonNull private final Activity mActivity;
@NonNull private final String mClientSecret;
@Nullable private final Uri mReturnUrl;
@NonNull private final ProgressBar mProgressBar;
@NonNull private final Listener mListener;

PaymentAuthWebViewClient(@NonNull Activity activity, @NonNull String clientSecret,
@Nullable String returnUrl) {
mActivity = activity;
PaymentAuthWebViewClient(@NonNull Listener listener, @NonNull ProgressBar progressBar,
@NonNull String clientSecret, @Nullable String returnUrl) {
mListener = listener;
mClientSecret = clientSecret;
mReturnUrl = returnUrl != null ? Uri.parse(returnUrl) : null;
mProgressBar = activity.findViewById(R.id.auth_web_view_progress_bar);
mProgressBar = progressBar;
}

@Override
Expand All @@ -88,7 +86,7 @@ public void onPageCommitVisible(@NonNull WebView view, @NonNull String url) {
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (url != null && isCompletionUrl(url)) {
mActivity.finish();
onAuthCompleted();
}
}

Expand All @@ -107,7 +105,7 @@ public boolean shouldOverrideUrlLoading(@NonNull WebView view,
@NonNull String urlString) {
final Uri uri = Uri.parse(urlString);
if (isReturnUrl(uri)) {
mActivity.finish();
onAuthCompleted();
return true;
}

Expand Down Expand Up @@ -154,5 +152,13 @@ private boolean isReturnUrl(@NonNull Uri uri) {
private boolean isPredefinedReturnUrl(@NonNull Uri uri) {
return "stripejs://use_stripe_sdk/return_url".equals(uri.toString());
}

private void onAuthCompleted() {
mListener.onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

interface Listener {
void onAuthCompleted(@StripeIntentResult.Status int status);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ProgressBar;

import com.stripe.android.PaymentAuthWebViewStarter;
import com.stripe.android.R;
import com.stripe.android.StripeIntentResult;
import com.stripe.android.StripeTextUtils;
import com.stripe.android.stripe3ds2.init.ui.ToolbarCustomization;
import com.stripe.android.stripe3ds2.utils.CustomizeUtils;

import static com.ults.listeners.SdkChallengeInterface.UL_HANDLE_CHALLENGE_ACTION;

public class PaymentAuthWebViewActivity extends AppCompatActivity {
public class PaymentAuthWebViewActivity
extends AppCompatActivity
implements PaymentAuthWebView.PaymentAuthWebViewClient.Listener {

@Nullable private ToolbarCustomization mToolbarCustomization;
private Intent mResultIntent;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Expand All @@ -44,11 +49,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
final String returnUrl = getIntent()
.getStringExtra(PaymentAuthWebViewStarter.EXTRA_RETURN_URL);

setResult(Activity.RESULT_OK,
new Intent().putExtra(StripeIntentResultExtras.CLIENT_SECRET, clientSecret));
mResultIntent = new Intent()
.putExtra(StripeIntentResultExtras.CLIENT_SECRET, clientSecret);

final PaymentAuthWebView webView = findViewById(R.id.auth_web_view);
webView.init(this, clientSecret, returnUrl);
final ProgressBar progressBar = findViewById(R.id.auth_web_view_progress_bar);
webView.init(this, progressBar, clientSecret, returnUrl);
webView.loadUrl(getIntent().getStringExtra(PaymentAuthWebViewStarter.EXTRA_AUTH_URL));
}

Expand All @@ -65,16 +71,21 @@ public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}

@Override
public void onBackPressed() {
onAuthCompleted(StripeIntentResult.Status.CANCELED);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_close) {
finish();
onAuthCompleted(StripeIntentResult.Status.CANCELED);
return true;
}
return super.onOptionsItemSelected(item);
}

void customizeToolbar(@NonNull Toolbar toolbar) {
private void customizeToolbar(@NonNull Toolbar toolbar) {
if (mToolbarCustomization != null) {
if (!StripeTextUtils.isBlank(mToolbarCustomization.getHeaderText())) {
toolbar.setTitle(CustomizeUtils.buildStyledText(this,
Expand All @@ -90,4 +101,11 @@ void customizeToolbar(@NonNull Toolbar toolbar) {
}
}
}

@Override
public void onAuthCompleted(@StripeIntentResult.Status int status) {
setResult(Activity.RESULT_OK,
mResultIntent.putExtra(StripeIntentResultExtras.AUTH_STATUS, status));
finish();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.stripe.android.view;

import android.app.Activity;
import android.webkit.WebView;
import android.widget.ProgressBar;

import com.stripe.android.StripeIntentResult;

import org.junit.Before;
import org.junit.Test;
Expand All @@ -10,13 +12,15 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

@RunWith(RobolectricTestRunner.class)
public class PaymentAuthWebViewTest {

@Mock private Activity mActivity;
@Mock private PaymentAuthWebView.PaymentAuthWebViewClient.Listener mListener;
@Mock private ProgressBar mProgressBar;
@Mock private WebView mWebView;

@Before
Expand All @@ -29,11 +33,11 @@ public void shouldOverrideUrlLoading_withPaymentIntent_shouldSetResult() {
final String deepLink = "stripe://payment_intent_return?payment_intent=pi_123&" +
"payment_intent_client_secret=pi_123_secret_456&source_type=card";
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"pi_123_secret_456",
"stripe://payment_intent_return");
paymentAuthWebViewClient.shouldOverrideUrlLoading(mWebView, deepLink);
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

@Test
Expand All @@ -42,72 +46,72 @@ public void shouldOverrideUrlLoading_withSetupIntent_shouldSetResult() {
"&setup_intent_client_secret=seti_1234_secret_5678&source_type=card";

final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"seti_1234_secret_5678",
"stripe://payment_auth");
paymentAuthWebViewClient.shouldOverrideUrlLoading(mWebView, deepLink);
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

@Test
public void shouldOverrideUrlLoading_withoutReturnUrl_onPaymentIntentImplicitReturnUrl_shouldSetResult() {
final String deepLink = "stripe://payment_intent_return?payment_intent=pi_123&" +
"payment_intent_client_secret=pi_123_secret_456&source_type=card";
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"pi_123_secret_456", null);
paymentAuthWebViewClient.shouldOverrideUrlLoading(mWebView, deepLink);
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

@Test
public void shouldOverrideUrlLoading_withoutReturnUrl_onSetupIntentImplicitReturnUrl_shouldSetResult() {
final String deepLink = "stripe://payment_auth?setup_intent=seti_1234" +
"&setup_intent_client_secret=seti_1234_secret_5678&source_type=card";
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"seti_1234_secret_5678", null);
paymentAuthWebViewClient.shouldOverrideUrlLoading(mWebView, deepLink);
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

@Test
public void shouldOverrideUrlLoading_withoutReturnUrl_shouldNotAutoFinishActivity() {
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"pi_123_secret_456", null);
paymentAuthWebViewClient.shouldOverrideUrlLoading(mWebView,
"https://example.com");
verify(mActivity, never()).finish();
verify(mListener, never()).onAuthCompleted(anyInt());
}

@Test
public void shouldOverrideUrlLoading_witKnownReturnUrl_shouldFinish() {
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"pi_123_secret_456", null);
paymentAuthWebViewClient.shouldOverrideUrlLoading(mWebView,
"stripejs://use_stripe_sdk/return_url");
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

@Test
public void onPageFinished_wit3DSecureCompleteUrl_shouldFinish() {
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"pi_123_secret_456", null);
paymentAuthWebViewClient.onPageFinished(mWebView,
"https://hooks.stripe.com/3d_secure/complete/tdsrc_1ExLWoCRMbs6FrXfjPJRYtng");
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}

@Test
public void onPageFinished_witRedirectCompleteUrl_shouldFinish() {
final PaymentAuthWebView.PaymentAuthWebViewClient paymentAuthWebViewClient =
new PaymentAuthWebView.PaymentAuthWebViewClient(mActivity,
new PaymentAuthWebView.PaymentAuthWebViewClient(mListener, mProgressBar,
"pi_123_secret_456", null);
paymentAuthWebViewClient.onPageFinished(mWebView,
"https://hooks.stripe.com/redirect/complete/src_1ExLWoCRMbs6FrXfjPJRYtng");
verify(mActivity).finish();
verify(mListener).onAuthCompleted(StripeIntentResult.Status.SUCCEEDED);
}
}

0 comments on commit 6e29982

Please sign in to comment.