Global
Prerequisites
- Create a Merchant Profile with Spreedly using the
/v1/merchant_profiles
endpoint.- Guide: Spreedly 3DS2 Global Guide - Spreedly Documentation
- API Reference: Spreedly API v1 Reference
- Common error/feedback:
- "What does the country code in the merchant profile mean?” Our 3DS provider defines this as the "Country Code of the Merchant.”
- “What if a merchant has multiple MCCs?” It is possible for merchants to get different MCCs but more common for merchants with multiple business lines (e.g., one part of the store is retail, and the other part of the store is a restaurant). When this is the case, create additional merchant profiles.
- Create an SCA Provider with Spreedly using the
/v1/sca/providers
endpoint with the merchant profile created in the previous step.-
API Reference: Spreedly 3DS2 Global Guide - Spreedly Documentation
-
Common error/feedback:
- If customers see an error similar to this when performing a 3DS2 Global transaction
Remote Error: Intermediate layer error - error in intermediate layer (50)
this indicates that they provided an incorrectacquirer_bin
. To verify this, Spreedly support can check the 3DS provider's dashboard to see the specific bin causing an issue. The customer will then have to create a newsca_provider
with the correctacquirer_bin
- If customers see an error similar to this when performing a 3DS2 Global transaction
- Check the Spreedly gateway guides to see if there are any additional configurations needed to successfully pass 3DS2 Global authentication data to the gateway (ex: Worldpay has a setting that merchants have to enable)
3DS2 Flow
- Load the
iFrame
orexpress
scripts on the merchant site. - Create the
browser_info
object with Javascript and Spreedly iFrame on the merchant frontend and pass this value back to the merchant’s backend
1. // Choose a browser size for your application. This will be the size of the challenge
2. // iframe that will be presented to a user. *note* If you're creating a modal, you
3. // should make the surrounding DOM node a little larger than the option selected
4. // below.
5. //
6. // '01' - 250px x 400px
7. // '02' - 390px x 300px
8. // '03' - 500px x 600px
9. // '04' - 600px x 400px
10. // '05' - fullscreen
11. var browser_size = '01';
12. // The accept header from your server side rendered page. You'll need to inject it into the page. Below is an example.
13. var acceptHeader = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
14. // The request should include the browser data collected by using `Spreedly.ThreeDS.serialize().
15. let browser_info = Spreedly.ThreeDS.serialize(
16. browser_size,
17. acceptHeader
18. );
- The merchant now needs to make a
purchase
orauthorize
request to Spreedly from their backend using the standardPOST /v1/gateways/<gateway_token>/purchase.json
HTTPS/1.1
request with theiraccess_secret
andenvironment_key
. To initiate a 3DS2 Global authentication, thesca_provider_key
andbrowser_info
must be included in the request body. - The result of this will be a gateway transaction created at Spreedly in either a
failed
,succeeded
, orpending
. For terminal states likefailed
andsucceeded
, the merchant should display an appropriate message. Forpending
states, move on to the next step.
3DS2 Global auth/purchase request body
1. {
2. "transaction": {
3. "sca_provider_key": "<sca_provider_key>",
4. "payment_method_token": "<payment_method_token>",
5. "amount": 10000,
6. "currency_code": "EUR",
7. "callback_url": "<callback_url (optional)>",
8. "browser_info": "<value from Spreedly.ThreeDS.serialize()>"
9. }
10. }
3DS2 Global Standalone Authentication
Spreedly offers a way to perform a 3DS authentication without it being linked to a specific purchase or authorize request. This is for merchants who would like to perform the 3DS challenge/request at a different stage than the purchase/auth request. The result of this will be an sca_authentication
transaction type that has standard 3DS data that a merchant can pass in to a purchase/auth request like they would for 3rd party auth. The request endpoint is /v1/sca/providers/<sca_provider_token>/authenticate
.
1. "transaction": {
2. "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
3. "currency_code": "EUR",
4. "amount": 100,
5. "browser_info": "eyJ3aWR0aCI6MjEzMywiaGVpZ2h0IjoxMjAwLCJkZXB0aCI6MjQsInRpbWV6b25lIjozMDAsInVzZXJfYWdlbnQiOiJTcHJlZWRseSBBZ2VudCIsImphdmEiOmZhbHNlLCJsYW5ndWFnZSI6ImVuLVVTIiwiYnJvd3Nlcl9zaXplIjoiMDQiLCJhY2NlcHRfaGVhZGVyIjoidGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksaW1hZ2Uvd2VicCwqLyo7cT0wLjgifQ=="
6. }
3rd Party Authentication
The merchant performs the 3DS challenge with their own provider or the 3DS2 Global Standalone authentication and passes in the field values to the purchase/auth request.
1. "transaction": {
2. "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
3. "amount": 100,
4. "currency_code": "USD",
5. "three_ds_version": "2.1.0",
6. "three_ds": {
7. "ecommerce_indicator": "06",
8. "authentication_value": "M2RzMiBpcyBzdXBlcmF3ZXNvbWU=",
9. "directory_server_transaction_id": "362DF058-6061-47F1-A504-CACCBDF422B7",
10. "xid": "YXV0aCB0eG4gaWRzIGFyZSBmdW4=",
11. "authentication_value_algorithm": "1",
12. "directory_response_status": "Y",
13. "authentication_response_status": "Y",
14. "enrolled": "Y"
15. }
16. }
Handling Pending transactions
If the transaction is pending
then this means the customer must perform a 3DS2 challenge, and the merchant must display it on their site. To do this, the merchant will pass the transaction_token
from their backend to their frontend. They will then need to perform the following steps in their frontend.
Add HTML elements for device-fingerprint
and challenge
to their site
1. <head>
2. <style>
3. .hidden {
4. display: none;
5. }
6. #challenge-modal {
7. /* style your modal here */
8. }
9. </style>
10. </head>
11. <body>
12. <div id="device-fingerprint" class="hidden">
13. <!-- Spreedly injects content into this div,
14. do not nest the challenge div inside of it -->
15. </div>
16. <div id="challenge-modal" class="hidden">
17. <div id="challenge"></div>
18. </div>
19. </body>
Define a new instance of Spreedly.ThreeDS.Lifecycle
1. var lifecycle = new Spreedly.ThreeDS.Lifecycle({
2. environmentKey: '...',
3. // The environmentKey field is required, but if omitted, you will receive a console warning message and the transaction will still succeed.
4. hiddenIframeLocation: 'device-fingerprint', (required)
5. // The DOM node that you'd like to inject hidden iframes
6. challengeIframeLocation: 'challenge', (required)
7. // The DOM node that you'd like to inject the challenge flow
8. transactionToken: '...', (required)
9. // The token for the transaction - used to poll for state
10. challengeIframeClasses: '...', (optional)
11. // The css classes that you'd like to apply to the challenge iframe.
12. //
13. // Note: This is where you'll change the height and width of the challenge
14. // iframe. You'll need to match the height and width option that you
15. // selected when collecting browser data with `Spreedly.ThreeDS.serialize`.
16. // For instance if you selected '04' for browserSize you'll need to have a
17. // CSS class that has width and height of 600px by 400px.
18. })
Define and set callback functions for statusUpdates. These will receive events that Spreedly Lifecycle issue based on the result of the attempted 3DS2 challenge.
1. var on3DSstatusUpdatesFn = function(threeDsStatusEvent) {
2. if (threeDsStatusEvent.action === 'succeeded') {
3.
4. // finish your checkout and redirect to success page
5.
6. } else if (threeDsStatusEvent.action === 'error') {
7. // present an error to the user to retry
8. } else if (threeDsStatusEvent.action === 'finalization-timeout') {
9. // present an error to the user to retry
10. } else if (threeDsStatusEvent.action === 'challenge') {
14. // show the challenge-modal
15. document.getElementById('challenge-modal').classList.remove('hidden');
16. }
17. }
18.
19. // Setup event handling and kickoff 3DSecure lifecycle
20. Spreedly.on('3ds:status', on3DSstatusUpdatesFn)
Start Spreedly Lifecycle
1. lifecycle.start()
Handle the event issued by Spreedly Lifecycle
-
After starting Lifecycle, Spreedly will handle performing any device-fingerprinting, fetch the transaction data, and determine the next course of action. Once it has determined the next step, it will issue an event object to the callback function created earlier.
- An event object will have an action property that the merchant can read, which determines what they should do next. API Reference: Spreedly iFrame v1 Reference
-
succeeded: The transaction is succeeded, and the merchant should finish the checkout
-
error: Something went wrong, and the merchant should display an error message. The merchant can learn why it failed by reading the transaction token’s message.
-
finalization-timeout: Customer authentication could not be completed within the expected window. This gets triggered 10-15 minutes after presenting a challenge without the transaction state changing. It is recommended that merchants attempt a manual completion here to attempt to continue or finalize the transaction though it is not necessary.
-
challenge: the customer must complete a 3DS2 challenge, and the merchant should remove the
hidden
class from the challenge modal HTMLdiv
element. Spreedly Lifecycle will handle injecting the challenge modal and the response from the challenge. If Spreedly Lifecycle learns about the result of the challenge, it will issue an additional event.
-
Make a manual complete request.
- If a
finalization-timeout
event is issued to the merchant’s frontend, it is recommended for the merchant to then make a/v1/transactions/<transaction_token>/complete
request to Spreedly from their backend.
After receiving the response from Spreedly on the merchant backend they should pass this to their frontend and call event.finalize(data)
if it is a pending
transaction where the data is the Spreedly response from the complete
call.
Below is an example of how a merchant might handle a finalization-timeout
event.
1. fetch(`https://your-service/complete/${purchaseToken}.json`, { method: 'POST' })
2. .then(response => response.json())
3. .then((data) => {
4. if (data.state === 'succeeded') {
5.
6. // finish your checkout and redirect to success page
7.
8. }
9.
10. if (data.state === 'pending') {
11. event.finalize(data);
12. }
13. })
Exemptions
- Spreedly supports 2 types of 3DS exemptions via 3DS2 Global. To request an exemption, the merchant must pass in
sca_authentication_parameters
.- Transactions under 30 euros are considered “low value” and are exempt from strong customer authentication (SCA). Guide: Spreedly 3DS2 Global Guide - Spreedly Documentation
Request Body
1. {
2. "transaction": {
3. "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
4. "sca_provider_key": "ZI0HsrLtnvzvNry7f3HARhnOXbA",
5. "sca_authentication_parameters": {
6. "exemption_type": "low_value_exemption"
7. },
8. "amount": 100,
9. "currency_code": "EUR",
10. "ip": "127.0.0.1",
11. "browser_info": "eyJ3aWR0aCI6MjEzMywiaGVpZ2h0IjoxMjAwLCJkZXB0aCI6MjQsInRpbWV6b25lIjozMDAsInVzZXJfYWdlbnQiOiJTcHJlZWRseSBBZ2VudCIsImphdmEiOmZhbHNlLCJsYW5ndWFnZSI6ImVuLVVTIiwiYnJvd3Nlcl9zaXplIjoiMDQiLCJhY2NlcHRfaGVhZGVyIjoidGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksaW1hZ2Uvd2VicCwqLyo7cT0wLjgifQ=="
12. }
- The Transaction Risk Analysis (TRA) exemption is a process that allows the issuing bank to make a determination if the merchant typically struggles with fraud or not. Guide: Spreedly 3DS2 Global Guide - Spreedly Documentation
Request Body
1. {
2. "transaction": {
3. "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
4. "sca_provider_key": "ZI0HsrLtnvzvNry7f3HARhnOXbA",
5. "sca_authentication_parameters": {
6. "exemption_type": "transaction_risk_analysis_exemption",
"acquiring_bank_fraud_rate": "level_one"
7. },
8. "amount": 100,
9. "currency_code": "EUR",
10. "ip": "127.0.0.1",
11 "browser_info": "eyJ3aWR0aCI6MjEzMywiaGVpZ2h0IjoxMjAwLCJkZXB0aCI6MjQsInRpbWV6b25lIjozMDAsInVzZXJfYWdlbnQiOiJTcHJlZWRseSBBZ2VudCIsImphdmEiOmZhbHNlLCJsYW5ndWFnZSI6ImVuLVVTIiwiYnJvd3Nlcl9zaXplIjoiMDQiLCJhY2NlcHRfaGVhZGVyIjoidGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksaW1hZ2Uvd2VicCwqLyo7cT0wLjgifQ=="
12. }
Helpful Links And Guides
-
Testing guide for 3DS2 Global with the Spreedly test SCA Provider: Testing your 3DS2 Global Integration - Spreedly Documentation
-
Sample 3DS2 Global test app: Spreedly Sample iFrame Payment Page
- Sample 3DS2 Global app repository: https://github.com/spreedly/sample-spreedly-3ds/blob/master/views/index.html
- 3DS2 Global frontend guide: Spreedly 3DS2 Global Integration Guide for Web - Spreedly Documentation
- 3DS2 Global backend guide: Spreedly 3DS2 Global Guide - Spreedly Documentation
- 3DS2 Third party guide: Third Party 3DS2 Guide - Spreedly Documentation