Frequently Asked Questions

Below you will find answers to some of the most commonly asked questions about utilizing 3D Secure with Spreedly. If you don’t find the answer to your question below, feel free to contact us at support@spreedly.com.

Should customers receive a callback for every 3DS2 transaction, regardless of state?

Spreedly will not send events if the transaction comes back in a failure state or a success state before the lifecycle is created. The transaction state should be checked before creating a lifecycle event per Step 6 of the implementation guide.

Why am I receiving the error, “message”:“Callback url is not a valid url”?

The URL must be a valid https URL that is public and using port 443. If it is local, Spreedly cannot reach it. If there are concerns about security of the callback_url, you may add Spreedly’s IPs to your list of valid IPs.

Your 3DS2 guide states we are required to pass in the transaction data from the completion call. Do I have to pass in the whole transaction to this method?**

At a minimum, the following fields would need to be included in the data: state, token, required_action, checkout_form, checkout_url, device_fingerprint_form, challenge_url, and challenge_form We do however recommend sending the full response as in the future it will allow us to make enhancements without requiring changes on your end. You can send only the required fields for the time being. Should we decide to change something in the future, we’ll be sure to communicate such changes well in advance.

Is it possible to challenge multiple times in a single transaction request?

There are multiple types of challenges. The 3DS2 flow will handle the escalation of the challenges automatically.

Why don’t I see checkout_form populated?

checkout_form will only be used in the case of a 3DS1 fallback. The field should still be passed but a null value will work in this case. Spreedly will not try to validate it unless the required_action is redirect.

If I already have my own 3DS1 solution, is it possible to intercept a 3DS1 fallback and handle it on my own?

Yes, you can. You’ll know a fall back is necessary based the transaction being in a pending state and the required action is redirect, and you would not create the lifecycle object in that case.

Can the 3DS1 fallback, described here be configured to run inside an iframe?

Spreedly does not advise embedding 3DS 1 redirects in an iframe as it can lead to unexpected behavior in combination with the 3DS2 functionality.

Is there anything with a 3DS1 implementation that would conflict with 3DS2?

No, Spreedly’s 3DS1 and 3DS2 solutions are compatible.

Should we collect browser_info for all transactions, even if the card is already stored?

We recommended always collecting browser_info as certain gateways might require this in order to process an exemption.

Where should the javascript be placed?

The javascript should be placed on the page that hosts the checkout form.

Your documentation recommends sending browser_info, attempt_3dsecure: true and three_ds_version: “2”. In which cases should we send those parameters? For all transactions/merchants/regions/gateways?

These fields should only be passed when the transaction is in PSD2 scope and where Spreedly supports 3DS2 on the gateway.

What will happen if we pass three_ds_version: “2” to Spreedly for a gateway that only supports 3DS1?

Spreedly will process the transaction as V1.

How will I know if the transaction is falling back to 3ds1?

This is based on a checkout_form or checkout_url being present on the transaction. Spreedly will emit a “fallback” event from Spreedly javascript when this occurs which you can listen to: Spreedly.on(‘3ds:status’, statusUpdates) (See also //Setup event handling section of 3DS2 Step 7)

What happens if a user closes the browser after the challenge is complete but before Step 7?

There are two attributes we can look at: required_action, or where the transaction is in the 3DS flow and transaction state - pending, succeeded, gateway_processing_failed. Spreedly will handle the scenario in which a user hits refresh, however, to redirect a user to a specific page to complete a checkout you will want to make sure the required_action is not none and the transaction is in a pending state.

How can we submit the form in a reliable way for every bank, without the user having to click the Authorise button?

The user should not have to click a button, you should submit the form using javascript.