Spreedly 3DS2 Global Integration Guide for Mobile Webview
Prerequisites
Before you begin integrating the 3DS2 flow, please ensure the following steps are completed:
- Complete Merchant Profile and Sca Provider Setup: You must have your Merchant Profile and SCA Provider configured. Refer to our Spreedly 3DS2 Global guide for detailed instructions on this setup.
- Obtain a Spreedly Test Gateway Token: You'll need a Spreedly Test gateway token to interact with the simulated 3DS2 flows.
- If you already have a Spreedly Test gateway set up, you can likely proceed.
- If not, or if you wish to create a new one specifically for 3DS2 testing, follow the Spreedly Test gateway guide Note: Alternatively, you can test against a specific real gateway by creating it in sandbox mode.
- Verify Gateway Connectivity (Non-3DS): Before implementing 3DS, confirm that your test gateway can successfully process a standard purchase without 3DS authentication. This initial verification will help ensure that any future troubleshooting is limited to 3DS-specific issues.
- Confirm Spreedly iFrame Version: Make sure you are using a compatible iFrame version. You should be using one of the following:
- iframe-v1
- iframe-candidate
- iframe-stable
- A specific tagged version v1.177 or higher.
Please refer to the iFrame payment form documentation for details on updating or selecting your iFrame version.
Guide companion sample app
The way your application interacts with our system, especially handling our events and the communication between your backend and frontend, will vary based on your project's structure. This is especially true if you are using a frontend framework (like Angular, React, or Vue) or a custom project layout.
To help illustrate the core concepts described in this guide, we've created a sample application:
Spreedly 3DS Reference Implementation: This is a standalone, pure HTML/JavaScript/CSS application. It simulates two simple checkout experiences using our iFrame and Express API to demonstrate all necessary integration steps.
Integration Guide
Step 1: Include Spreedly JavaScript Library
First, include the appropriate Spreedly JavaScript library on your checkout page. Choose either the iFrame or Express library based on your implementation:
<head>
<script src="https://core.spreedly.com/iframe/iframe-v1.min.js"></script>
</head><head>
<script src="https://core.spreedly.com/iframe/express-3.min.js"></script>
</head>Step 2: Prepare Your HTML Structure for the Webview
Set up the DOM elements that Spreedly will use for 3DS authentication:
<head>
<style>
.hidden {
display: none;
}
#challenge-modal {
/* Style your modal container here */
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
border: 1px solid #ccc;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
</style>
</head>
<body>
<!-- Modal container for challenge authentication -->
<div id="challenge-modal" class="hidden">
<div id="challenge"></div>
</div>
</body>Step 3: Generate Payment Method Token
Ensure you have a payment method token ready. You can generate this using:
- Spreedly's iFrame payment form
- Spreedly's Express library
- Direct API calls to Spreedly
For more details, see Spreedly's Payment Method API reference.
Step 4: Collect Browser Information and Initiate Transaction
When your customer is ready to complete their purchase, collect the required browser information and post the message to your native mobile application:
<!doctype html>
<html lang="en">
<head>
<!-- load spreedly iframe -->
<script src="https://core.spreedly.com/iframe/iframe-v1.min.js"></script>
</head>
<body>
<script type="text/javascript">
(function() {
var challengeWindowSize = "05";
var browserInfo = Spreedly.ThreeDS.serialize(challengeWindowSize);
// Post a message to your native application. postMessageToNativeApp is an
// example function. Depending on platform IOS, Android, etc you'll need to
// replace it with a platform specific call.
postMessageToNativeApp(browserInfo);
})();
</script>
</body>
</html>In your native mobile code you'll accept the message posted with browser info and then make your purchase request to your backend
// Send transaction request to your backend
fetch('/api/process-payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
payment_method_token: 'your-payment-method-token',
amount: 10000, // Amount in cents
browser_info: browser_info,
// Add any other parameters your backend needs
})
});Step 5: Backend Transaction Processing
In your backend, create the transaction with Spreedly using the collected browser information:
POST /v1/gateways/<gateway_token>/purchase.json HTTPS/1.1
Host: core.spreedly.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: application/json
{
"transaction": {
"sca_provider_key": "<your_sca_provider_key>",
"payment_method_token": "<payment_method_token>",
"amount": 10000,
"currency_code": "EUR",
"callback_url": "<optional_callback_url>",
"browser_info": "<browser_info_from_frontend>"
}
}Your backend should then return the transaction response to your frontend. The transaction will typically have a state of "pending" when 3DS authentication is required.
Step 6: Handle the Authentication Flow
Set Up 3DS Status Event Handling
First, create a function to handle status updates throughout the 3DS authentication process. This function will respond to various events that occur during authentication:
// Set up event handling for 3DS status updates
function handle3DSStatusUpdates(event) {
switch (event.action) {
case 'succeeded':
// Authentication successful - redirect to success page
window.location.href = '/payment-success';
break;
case 'error':
case 'finalization-timeout':
// Authentication failed or timed out - show error message
alert('Payment authentication failed. Please try again.');
// Consider redirecting back to payment form or offering retry
break;
case 'challenge':
// Challenge required - show the challenge modal
document.getElementById('challenge-modal').classList.remove('hidden');
break;
}
}
// Register the event handler (only call this once per page load)
Spreedly.on('3ds:status', handle3DSStatusUpdates);Important: The Spreedly.on('3ds:status', handler) should only be called once per page load. Calling it multiple times will register duplicate event handlers.
Initialize and Start the Lifecycle
After setting up event handling, initialize the Lifecycle object with your transaction data and start the authentication process:
// Initialize the Lifecycle object with your transaction
var lifecycle = new Spreedly.ThreeDS.Lifecycle({
// Highly recommended - helps catch all update events
environmentKey: 'your-environment-key',
// Required: DOM elements for 3DS process
hiddenIframeLocation: 'device-fingerprint',
challengeIframeLocation: 'challenge',
// Required: Transaction token from Spreedly API response
transactionToken: 'transaction-token-from-backend',
// Optional: CSS classes for styling the challenge iframe
challengeIframeClasses: 'custom-challenge-styles'
});
// Start the authentication process
lifecycle.start();Important: Call lifecycle.start() immediately after receiving a pending transaction (within 30 seconds per 3DS specification requirements).
Understanding Transaction Flows
3DS2 Transaction Flow Types
Understanding these flows will help you better handle different scenarios:
Frictionless Flow The ideal scenario where the transaction completes without user intervention. The device fingerprint and browser data provide sufficient verification, and the user experiences no interruption.
Challenge Flow When additional verification is needed, the customer sees an authentication form from their bank (rendered in an iframe). This might include:
- SMS verification codes
- Biometric authentication
- Security questions
- Bank app notifications
Authentication Denied If authentication fails or is rejected, Spreedly fails the transaction without sending it to the payment gateway. You may want to offer the customer the option to retry or use a different payment method.
3DS Not Available When the card or issuer doesn't support 3DS, Spreedly fails the transaction. Consider retrying the transaction without 3DS authentication if your business rules allow it.
Note: These Spreedly 3DS2 Global Flow Diagrams might help!
Troubleshooting
-
For security reasons you should never make api requests from your frontend application directly to Spreedly. For this reason the authorize/purchase and complete transaction requests need to be made from your backend application.
-
Ensure that the Spreedly Javascript library has loaded properly. You can do so by looking at your browser developer tools and looking at the network traffic.
-
Ensure that you're collecting the accept header from your server side rendered page correctly (
console.log). It might be best to inject the accept header as a hidden form field and grab it with javascript. -
Ensure that the ordering of interactions with the Spreedly Javascript library are correct. Create a function to listen to events, then register that event handler with Spreedly and issue your purchase request (with browser info). Finally, issue start on the lifecycle object you've created.
-
Ensure that the
challengeIframeLocationis present on the page before callinglifecycle.start() -
You can also check where things are at by doing a
console.diron the event object in the statusUpdate event handler. -
If all else fails, please reach out! Contact us at [email protected] - we'd love to help.
Want to learn more about 3DS2?
You can read more about the regulations behind these changes on our blog or see the full specification details at the source, EMVco.
FAQs
See a list of all 3DS frequently asked questions in the Help Center.
Updated 1 day ago
