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

How to close Secure Checkout when needed #2478

Closed
abedsh opened this issue May 12, 2020 · 15 comments
Closed

How to close Secure Checkout when needed #2478

abedsh opened this issue May 12, 2020 · 15 comments
Assignees
Labels
triaged Issue has been reviewed by Stripe and is being tracked internally

Comments

@abedsh
Copy link

abedsh commented May 12, 2020

Summary

Is there a way to check if the Secure Checkout form has opened so I can handle session time out on the app by closing it in case the user is idle on it for a specific period of time ?

Code to reproduce

I am following the basic accept payment tutorial with the test card that triggers the secure checkout process (4000002500003155)

Android version

21+

Impacted devices

no

Installation method

Gradle

SDK version

14.4.0

Other information

@mshafrir-stripe
Copy link
Collaborator

@abedsh thanks for filing. By "Secure Checkout" do you mean the 3DS2 challenge screen?

@mshafrir-stripe mshafrir-stripe added the triaged Issue has been reviewed by Stripe and is being tracked internally label May 13, 2020
@mshafrir-stripe mshafrir-stripe self-assigned this May 13, 2020
@abedsh
Copy link
Author

abedsh commented May 13, 2020 via email

@mshafrir-stripe
Copy link
Collaborator

@abedsh does configuring a timeout as explained in https://stripe.com/docs/payments/3d-secure#when-to-use-3d-secure work for you?

@abedsh
Copy link
Author

abedsh commented May 14, 2020 via email

@mshafrir-stripe
Copy link
Collaborator

You can be notified of the event in onActivityResult() via Stripe#onPaymentResult(). The outcome value will be Outcome.TIMEDOUT.

@abedsh
Copy link
Author

abedsh commented May 18, 2020 via email

@mshafrir-stripe
Copy link
Collaborator

@abedsh can you share code so I can see your implementation?

@abedsh
Copy link
Author

abedsh commented May 19, 2020

@mshafrir-stripe sure,

public class PackageOrderStripePaymentWorkflow implements ApiResultCallback<PaymentIntentResult> {

    private CardInputWidget cardInputWidget;
    private LoadingButton payBtn;
    private String secretKey;
    private Stripe stripe;
    private String apiUsername;


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_booking_stripe_payment, container, false);

                PaymentConfiguration.init(
                        mActivity,
                        idMerchant
                );
                payBtn.setOnClickListener(v -> confirmPayment());

            }


        } catch (Exception e) {
            e.printStackTrace();
        }


        return view;
    }

    private void confirmPayment() {
        try {
            PaymentMethodCreateParams params = cardInputWidget.getPaymentMethodCreateParams();
            if (params != null) {
                ConfirmPaymentIntentParams confirmParams = ConfirmPaymentIntentParams
                        .createWithPaymentMethodCreateParams(params, secretKey);
                initPaymentAuthConfig();
                stripe = initStripe();
                stripe.confirmPayment(this, confirmParams);
                setBusy(true);
                stopTimer();
            }
        } catch (Exception ex) {
            Crashlytics.logException(ex);
            ex.printStackTrace();
            mActivity.showMessage(getString(R.string.stripe_service_fail), true, true);

        }
    }
	
	


    private void initPaymentAuthConfig() {
        PaymentAuthConfig.init(new PaymentAuthConfig.Builder()
                .set3ds2Config(new PaymentAuthConfig.Stripe3ds2Config.Builder()
                        .setTimeout(5)
                        .build())
                .build());
    }

    @NotNull
    private Stripe initStripe() {
        if (!CodeUtils.isEmpty(apiUsername)) {
            return new Stripe(
                    mActivity.getApplicationContext(),
                    PaymentConfiguration.getInstance(mActivity).getPublishableKey(), apiUsername);
        } else {
            return new Stripe(
                    mActivity.getApplicationContext(),
                    PaymentConfiguration.getInstance(mActivity).getPublishableKey());
        }

    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Handle the result of stripe.confirmPayment
        stripe.onPaymentResult(requestCode, data, this);
    }


    @Override
    public void onSuccess(PaymentIntentResult paymentIntentResult) {
        PaymentIntent paymentIntent = paymentIntentResult.getIntent();
        PaymentIntent.Status status = paymentIntent.getStatus();
        if (status == PaymentIntent.Status.Succeeded) {
            // Payment completed successfully
      
        } else if (status == PaymentIntent.Status.RequiresPaymentMethod) {
            // Payment failed
           
         
        } 
    }

}

@mshafrir-stripe
Copy link
Collaborator

Use PaymentIntentResult#getOutcome(), and then compare the value against the Outcome constants. Specifically, Outcome.TIMEDOUT.

@abedsh
Copy link
Author

abedsh commented May 19, 2020

@mshafrir I am not even receiving any events that triggers a call to onActivityResult when the form closes by itself on timeout

@mshafrir-stripe
Copy link
Collaborator

@abedsh I can't reproduce this issue - I get a callback when I cancel the 3DS2 challenge screen. Can you try reproducing with our example app?

@abedsh
Copy link
Author

abedsh commented May 19, 2020

@mshafrir-stripe I am not sure if all the test card are supposed to behave the same, I just need a way to consistently tell when a challenge screen is closed either by the user or automatically (by time out) so I can probably integrate it in the payment flow of my app

With card (4000002500003155):

  • onActivityResult is called when I press on the close button of the challenge screen
  • The challenge screen is not closed automatically after time out are elapsed

With card (4000000000003220):

  • onActivityResult is not triggered when I press on the cancel button on the top right of the challenge screen
  • The challenge screen is closed automatically after time out, but onActivityResult is not called

@mshafrir-stripe
Copy link
Collaborator

mshafrir-stripe commented May 19, 2020

@abedsh in your example, what is the superclass of PackageOrderStripePaymentWorkflow? Is it possible that the reference to the Activity is being released?

@abedsh
Copy link
Author

abedsh commented May 19, 2020

@mshafrir-stripe PackageOrderStripePaymentWorkflow is a Fragment with a BottomSheetDialogFragment parent

@mshafrir-stripe
Copy link
Collaborator

There is a bug where the 3DS2 challenge flow is launched from the Fragment's Activity instead of from the Fragment itself. This was fixed in #2494 but hasn't been released yet. In the mean time, you can override onActivityResult in your Activity and pass to the Fragment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triaged Issue has been reviewed by Stripe and is being tracked internally
Projects
None yet
Development

No branches or pull requests

2 participants