Spreedly 3D2 Global Guide

Spreedly 3DS2 Global is currently in beta. Documentation and API usage are subject to change before final release. Please contact Spreedly support if you encounter any problems with your Spreedly 3DS2 Global integration.

Before getting started on your integration, please visit the Introduction to Spreedly 3DS2 Global guide for more information on the entities involved in a Spreedly 3DS2 Global transaction. To recap the steps needed:

  1. Create a Merchant Profile in your production Spreedly environment.
  2. Create a Spreedly SCA Provider on that Merchant Profile.
  3. For any transaction that should be 3DS2 authenticated, provide the SCA Provider key and all relevant device or browser info.
  4. Make sure your frontend is able to handle asynchronous 3DS2 flows.

Creating a Merchant Profile

To create a Merchant Profile that will hold your SCA Provider, you can make a request to the following endpoint. All fields shown below are required per card brand, but not all card brands are required.

Note: For information on how to obtain the Merchant Profile fields, please see our Merchant Profile Onboarding guide here.

curl https://core.spreedly.com/v1/merchant_profiles.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "merchant_profile": {
          "visa": {
            "acquirer_merchant_id": "spreedlys_mid",
            "merchant_name": "Spreedly",
            "country_code": "840",
            "mcc": "5978"
          },
          "mastercard": {
            "acquirer_merchant_id": "spreedlys_mid",
            "merchant_name": "Spreedly",
            "country_code": "840",
            "mcc": "5978"
          },
          "amex": {
            "acquirer_merchant_id": "spreedlys_mid",
            "merchant_name": "Spreedly",
            "country_code": "840",
            "mcc": "5978"
          }
        }
      }'
curl https://core.spreedly.com/v1/merchant_profiles.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<merchant_profile>
          <visa>
              <acquirer_merchant_id>spreedlys_mid</acquirer_merchant_id>
              <merchant_name>Spreedly</merchant_name>
              <country_code>840</country_code>
              <mcc>5978</mcc>
          </visa>
          <mastercard>
              <acquirer_merchant_id>spreedlys_mid</acquirer_merchant_id>
              <merchant_name>Spreedly</merchant_name>
              <country_code>840</country_code>
              <mcc>5978</mcc>
          </mastercard>
          <amex>
              <acquirer_merchant_id>spreedlys_mid</acquirer_merchant_id>
              <merchant_name>Spreedly</merchant_name>
              <country_code>840</country_code>
              <mcc>5978</mcc>
          </amex>
      </merchant_profile>'

If your request is successful, Spreedly will respond with a new Merchant Profile object. The token field from this response will be used in later steps:

{
  "merchant_profile": {
    "token": "IIDQE4RpociNnWiUUqcng7BkHpZ",
    "created_at": "2020-11-09T18:48:01Z",
    "updated_at": "2020-11-09T18:48:01Z",
    "card_networks": {
      "visa": {
        "acquirer_merchant_id": "spreedlys_mid",
        "mcc": "5978",
        "merchant_name": "Spreedly",
        "country_code": "840"
      },
      "mastercard": {
        "acquirer_merchant_id": "spreedlys_mid",
        "mcc": "5978",
        "merchant_name": "Spreedly",
        "country_code": "840"
      },
      "amex": {
        "acquirer_merchant_id": "spreedlys_mid",
        "mcc": "5978",
        "merchant_name": "Spreedly",
        "country_code": "840"
      }
    }
  }
}
<merchant_profile>
  <card_networks>
    <visa>
      <acquirer_merchant_id>spreedlys_mid</acquirer_merchant_id>
      <mcc>5978</mcc>
      <merchant_name>Spreedly</merchant_name>
      <country_code>840</country_code>
    </visa>
    <mastercard>
      <acquirer_merchant_id>spreedlys_mid</acquirer_merchant_id>
      <mcc>5978</mcc>
      <merchant_name>Spreedly</merchant_name>
      <country_code>840</country_code>
    </mastercard>
    <amex>
      <acquirer_merchant_id>spreedlys_mid</acquirer_merchant_id>
      <mcc>5978</mcc>
      <merchant_name>Spreedly</merchant_name>
      <country_code>840</country_code>
    </amex>
  </card_networks>
  <token>LsExVd1sJFsomL4zthCymHMj9hS</token>
  <created_at type="dateTime">2020-11-09T18:48:01Z</created_at>
  <updated_at type="dateTime">2020-11-09T18:48:01Z</updated_at>
</merchant_profile>

Creating an SCA Provider

Using the Merchant Profile object created in the previous request, you can make a request to the following endpoint to build a Spreedly SCA Provider. Some things to note for this request:

  • There is currently only one type accepted: spreedly (case sensitive).
  • Spreedly highly recommends that new integrators start with a sandbox Spreedly SCA Provider to test their integration before trying their system in production. For more information on card values and scenarios to use with a Sandbox Spreedly SCA Provider, please see our Spreedly SCA Provider guide for details.
  • The merchant_password field is optional.
curl https://core.spreedly.com/v1/sca/providers.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "sca_provider": {
          "merchant_profile_key": "Ke4Ybltto744p0mdSnXmaOxBeeK",
          "type": "spreedly",
          "sandbox": true,
          "mastercard": {
              "acquirer_bin": "4444444444",
              "merchant_url": "https://spreedly.com",
              "merchant_password": "optional"
          },
          "visa": {
              "acquirer_bin": "4444444444",
              "merchant_url": "https://spreedly.com",
              "merchant_password": "optional"
          },
          "amex": {
              "acquirer_bin": "4444444444",
              "merchant_url": "https://spreedly.com",
              "merchant_password": "optional"
          }
        }
      }'
curl https://core.spreedly.com/v1/sca/providers.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<sca_provider>
        <merchant_profile_key>Ke4Ybltto744p0mdSnXmaOxBeeK</merchant_profile_key>
        <type>spreedly</type>
        <sandbox>true</sandbox>
        <mastercard>
            <acquirer_bin>4444444444</acquirer_bin>
            <merchant_url>https://spreedly.com</merchant_url>
            <merchant_password>optional</merchant_password>
        </mastercard>
        <visa>
            <acquirer_bin>4444444444</acquirer_bin>
            <merchant_url>https://spreedly.com</merchant_url>
            <merchant_password>optional</merchant_password>
        </visa>
        <amex>
            <acquirer_bin>4444444444</acquirer_bin>
            <merchant_url>https://spreedly.com</merchant_url>
            <merchant_password>optional</merchant_password>
        </amex>
    </sca_provider>'

If the request is successful, Spreedly will respond with an SCA Provider object that can now be used to run 3DS2 authentication as part of purchase and authorize gateway actions.

{
  "sca_provider": {
    "token": "K4uIC4CJEmnQzuwcpUy5XthiQJn",
    "sandbox": true,
    "mastercard": {
      "acquirer_bin": "4444444444",
      "merchant_url": "https://spreedly.com",
      "merchant_password": "optional"
    },
    "visa": {
      "acquirer_bin": "4444444444",
      "merchant_url": "https://spreedly.com",
      "merchant_password": "optional"
    },
    "amex": {
      "acquirer_bin": "4444444444",
      "merchant_url": "https://spreedly.com",
      "merchant_password": "optional"
    },
    "created_at": "2020-11-12T15:29:05Z",
    "updated_at": "2020-11-12T15:29:05Z",
    "type": "spreedly"
  }
}
<sca_provider>
  <token>WbwuMzFP1ZNLs93Jh5F5SWoCl5L</token>
  <sandbox type="boolean">true</sandbox>
  <mastercard>
    <acquirer_bin>4444444444</acquirer_bin>
    <merchant_url>https://spreedly.com</merchant_url>
    <merchant_password>optional</merchant_password>
  </mastercard>
  <visa>
    <acquirer_bin>4444444444</acquirer_bin>
    <merchant_url>https://spreedly.com</merchant_url>
    <merchant_password>optional</merchant_password>
  </visa>
  <amex>
    <acquirer_bin>4444444444</acquirer_bin>
    <merchant_url>https://spreedly.com</merchant_url>
    <merchant_password>optional</merchant_password>
  </amex>
  <created_at type="dateTime">2020-11-12T15:29:04Z</created_at>
  <updated_at type="dateTime">2020-11-12T15:29:05Z</updated_at>
  <type>spreedly</type>
</sca_provider>

Using an SCA Provider On Gateway Transactions

The inclusion of an sca_provider_key on an authorize or purchase transaction tells Spreedly to perform a 3DS2 authentication with that provider before performing the gateway transaction. There are three possible outcomes for the initial message:

  1. The authentication succeeds without the need for a challenge. Spreedly will apply the authentication values to the gateway transaction and make a request to the gateway immediately. This is equivalent to supplying third-party 3DS2 values via the Third Party 3DS2 feature. Spreedly 3DS2 Global Successful Request
  2. The authentication fails immediately without the need for a challenge. In this case, Spreedly automatically fails the gateway transaction and will not reach out to the gateway. It is the Merchant’s responsibility to retry the transaction in the case of failure.
  3. The authentication requires a challenge and is put in a pending state. Once the user completes this challenge:
    • Spreedly will perform the gateway transaction in the case of success. If the authentication failed, Spreedly will fail the gateway transaction and it is up to the Merchant to try again if applicable.
    • Spreedly will perform a callback if a callback_url was provided in the transaction.
    • Spreedly’s Lifecycle object will emit an event that denotes that the transaction has completed.

It is also important to note that the sca_provider_key field is mutually exclusive with the attempt_3dsecure flag. The sca_provider_key is used to run 3DS2 authentication with a third party 3DS server and pass those results into the gateway. The attempt_3dsecure flag is used to run 3DS authentication on the gateway itself during the transaction.

In addition to the sca_provider_key, the Spreedly SCA Provider requires the IP address of a customer as well as a browser_info field for web or a device_info field for mobile. Information on collecting these fields can be found in our Spreedly 3DS2 Global Integration Guide for Web.

curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "transaction": {
          "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
          "amount": 100,
          "currency_code": "USD",
          "sca_provider_key": "6JXUReoA9KgnYoSchcJU0OAA6N0",
          "ip": "127.0.0.1",
          "browser_info": "eyJ3aWR0aCI6MjEzMywiaGVpZ2h0IjoxMjAwLCJkZXB0aCI6MjQsInRpbWV6b25lIjozMDAsInVzZXJfYWdlbnQiOiJTcHJlZWRseSBBZ2VudCIsImphdmEiOmZhbHNlLCJsYW5ndWFnZSI6ImVuLVVTIiwiYnJvd3Nlcl9zaXplIjoiMDQiLCJhY2NlcHRfaGVhZGVyIjoidGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksaW1hZ2Uvd2VicCwqLyo7cT0wLjgifQ=="
        }
      }'
curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>56wyNnSmuA6CWYP7w0MiYCVIbW6</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
        <sca_provider_key>6JXUReoA9KgnYoSchcJU0OAA6N0</sca_provider_key>
        <ip>127.0.0.1</ip>
        <browser_info>
          eyJ3aWR0aCI6MjEzMywiaGVpZ2h0IjoxMjAwLCJkZXB0aCI6MjQsInRpbWV6b25lIjozMDAsInVzZXJfYWdlbnQiOiJTcHJlZWRseSBBZ2VudCIsImphdmEiOmZhbHNlLCJsYW5ndWFnZSI6ImVuLVVTIiwiYnJvd3Nlcl9zaXplIjoiMDQiLCJhY2NlcHRfaGVhZGVyIjoidGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksaW1hZ2Uvd2VicCwqLyo7cT0wLjgifQ==
        </browser_info>
      </transaction>'

The response will look similar to other purchase and authorize requests with one key difference: there is now an sca_authentication object included in the response that details the state of the 3DS2 authentication. For a successful authentication, it will also show the 3DS2 (or 3DS1 if the transaction had to fallback) authentication information from the 3DS Server. These fields are passed into the gateway transaction automatically and shown here for informational purposes only.

{
  "transaction": {
    "on_test_gateway": false,
    "created_at": "2020-11-12T15:28:15Z",
    "updated_at": "2020-11-12T15:28:16Z",
    "succeeded": false,
    "state": "pending",
    "token": "VvplgnvtAWAoa38801a7e24qAHI",
    "transaction_type": "Purchase",
    "order_id": null,
    "ip": "127.0.0.1",
    "description": null,
    "email": null,
    "merchant_name_descriptor": null,
    "merchant_location_descriptor": null,
    "gateway_specific_fields": null,
    "gateway_specific_response_fields": {
    },
    "gateway_transaction_id": null,
    "gateway_latency_ms": null,
    "stored_credential_initiator": null,
    "stored_credential_reason_type": null,
    "warning": null,
    "amount": 100,
    "currency_code": "USD",
    "retain_on_success": false,
    "payment_method_added": false,
    "smart_routed": false,
    "message_key": "messages.transaction_pending",
    "message": "Pending",
    "gateway_token": "T11bJAANtTWnxl36GYjKWvbNK0g",
    "gateway_type": "test",
    "shipping_address": {
      "name": "Newfirst Newlast",
      "address1": null,
      "address2": null,
      "city": null,
      "state": null,
      "zip": null,
      "country": null,
      "phone_number": null
    },
    "api_urls": [
      {
        "referencing_transaction": [

        ]
      },
      {
        "failover_transaction": [

        ]
      }
    ],
    "attempt_3dsecure": false,
    "payment_method": {
      "token": "1rpKvP8zOUhj4Y9EDrIoIYQzzD5",
      "created_at": "2017-06-26T17:04:38Z",
      "updated_at": "2020-11-10T19:38:14Z",
      "email": "joey@example.com",
      "data": {
        "my_payment_method_identifier": "448",
        "extra_stuff": {
          "some_other_things": "Can be anything really"
        }
      },
      "storage_state": "retained",
      "test": true,
      "metadata": {
        "key": "string value"
      },
      "callback_url": null,
      "last_four_digits": "1111",
      "first_six_digits": "411111",
      "card_type": "visa",
      "first_name": "Newfirst",
      "last_name": "Newlast",
      "month": 3,
      "year": 2032,
      "address1": null,
      "address2": null,
      "city": null,
      "state": null,
      "zip": null,
      "country": null,
      "phone_number": null,
      "company": null,
      "full_name": "Newfirst Newlast",
      "eligible_for_card_updater": true,
      "shipping_address1": null,
      "shipping_address2": null,
      "shipping_city": null,
      "shipping_state": null,
      "shipping_zip": null,
      "shipping_country": null,
      "shipping_phone_number": null,
      "payment_method_type": "credit_card",
      "errors": [

      ],
      "fingerprint": "e3cef43464fc832f6e04f187df25af497994",
      "verification_value": "",
      "number": "XXXX-XXXX-XXXX-1111"
    },
    "sca_authentication": {
      "created_at": "2020-11-12T15:28:15Z",
      "updated_at": "2020-11-12T15:28:16Z",
      "succeeded": false,
      "state": "pending",
      "token": "INP4rU2jLObOPm1tnzXfGo2tuH1",
      "flow_performed": "challenge",
      "message": null,
      "sca_provider_key": "6JXUReoA9KgnYoSchcJU0OAA6N0",
      "three_ds_version": "2.2.0",
      "ecommerce_indicator": null,
      "authentication_value": null,
      "directory_server_transaction_id": "5c06e665-3675-494e-9ccf-cc078ebd8dc9",
      "authentication_value_algorithm": null,
      "directory_response_status": "C",
      "authentication_response_status": "C",
      "required_action": "challenge",
      "acs_reference_number": null,
      "acs_rendering_type": null,
      "acs_signed_content": null,
      "acs_transaction_id": null,
      "sdk_transaction_id": null,
      "challenge_form": "<form action=\"https://testds3.seglan.com/server/authentication/load\" method=\"POST\">\n  <input name=\"browserChallengeToken\" value=\"b3055a53-7c4d-4f71-bb33-742af0daa96f\" type=\"hidden\"/>\n</form>",
      "challenge_form_embed_url": null,
      "three_ds_server_trans_id": "b3055a53-7c4d-4f71-bb33-742af0daa96f",
      "xid": null,
      "enrolled": null,
      "transaction_type": "Sca::Authentication"
    }
  }
}
<transaction>
  <on_test_gateway type="boolean">false</on_test_gateway>
  <created_at type="dateTime">2020-11-12T15:10:37Z</created_at>
  <updated_at type="dateTime">2020-11-12T15:10:38Z</updated_at>
  <succeeded type="boolean">false</succeeded>
  <state>pending</state>
  <token>X3WSJdOofHm4tJL84l3ZW8dtDal</token>
  <transaction_type>Purchase</transaction_type>
  <order_id nil="true"></order_id>
  <ip>127.0.0.1</ip>
  <description nil="true"></description>
  <email nil="true"></email>
  <merchant_name_descriptor nil="true"></merchant_name_descriptor>
  <merchant_location_descriptor nil="true"></merchant_location_descriptor>
  <gateway_specific_fields nil="true"></gateway_specific_fields>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <gateway_transaction_id nil="true"></gateway_transaction_id>
  <gateway_latency_ms nil="true"></gateway_latency_ms>
  <stored_credential_initiator nil="true"></stored_credential_initiator>
  <stored_credential_reason_type nil="true"></stored_credential_reason_type>
  <warning nil="true"></warning>
  <amount type="integer">100</amount>
  <currency_code>USD</currency_code>
  <retain_on_success type="boolean">false</retain_on_success>
  <payment_method_added type="boolean">false</payment_method_added>
  <smart_routed type="boolean">false</smart_routed>
  <message key="messages.transaction_pending">Pending</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <gateway_type>test</gateway_type>
  <shipping_address>
    <name>Newfirst Newlast</name>
    <address1 nil="true"></address1>
    <address2 nil="true"></address2>
    <city nil="true"></city>
    <state nil="true"></state>
    <zip nil="true"></zip>
    <country nil="true"></country>
    <phone_number nil="true"></phone_number>
  </shipping_address>
  <api_urls>
  </api_urls>
  <payment_method>
    <token>1rpKvP8zOUhj4Y9EDrIoIYQzzD5</token>
    <created_at type="dateTime">2017-06-26T17:04:38Z</created_at>
    <updated_at type="dateTime">2020-11-10T19:38:14Z</updated_at>
    <email>joey@example.com</email>
    <data>
      <my_payment_method_identifier>448</my_payment_method_identifier>
      <extra_stuff>
        <some_other_things>Can be anything really</some_other_things>
      </extra_stuff>
    </data>
    <storage_state>retained</storage_state>
    <test type="boolean">true</test>
    <metadata>
      <key>string value</key>
    </metadata>
    <callback_url nil="true"></callback_url>
    <last_four_digits>1111</last_four_digits>
    <first_six_digits>411111</first_six_digits>
    <card_type>visa</card_type>
    <first_name>Newfirst</first_name>
    <last_name>Newlast</last_name>
    <month type="integer">3</month>
    <year type="integer">2032</year>
    <address1 nil="true"></address1>
    <address2 nil="true"></address2>
    <city nil="true"></city>
    <state nil="true"></state>
    <zip nil="true"></zip>
    <country nil="true"></country>
    <phone_number nil="true"></phone_number>
    <company nil="true"></company>
    <full_name>Newfirst Newlast</full_name>
    <eligible_for_card_updater type="boolean">true</eligible_for_card_updater>
    <shipping_address1 nil="true"></shipping_address1>
    <shipping_address2 nil="true"></shipping_address2>
    <shipping_city nil="true"></shipping_city>
    <shipping_state nil="true"></shipping_state>
    <shipping_zip nil="true"></shipping_zip>
    <shipping_country nil="true"></shipping_country>
    <shipping_phone_number nil="true"></shipping_phone_number>
    <payment_method_type>credit_card</payment_method_type>
    <errors>
    </errors>
    <verification_value></verification_value>
    <number>XXXX-XXXX-XXXX-1111</number>
    <fingerprint>e3cef43464fc832f6e04f187df25af497994</fingerprint>
  </payment_method>
  <sca_authentication>
    <created_at type="dateTime">2020-11-12T15:10:37Z</created_at>
    <updated_at type="dateTime">2020-11-12T15:10:38Z</updated_at>
    <succeeded type="boolean">false</succeeded>
    <state>pending</state>
    <token>IemZcePeA1wuhZh3IVJpFZLN1JB</token>
    <flow_performed>challenge</flow_performed>
    <message nil="true"></message>
    <sca_provider_key>6JXUReoA9KgnYoSchcJU0OAA6N0</sca_provider_key>
    <three_ds_version>2.2.0</three_ds_version>
    <ecommerce_indicator nil="true"></ecommerce_indicator>
    <authentication_value nil="true"></authentication_value>
    <directory_server_transaction_id>b307301e-5ddc-476e-b4da-586327cfe9e9</directory_server_transaction_id>
    <authentication_value_algorithm nil="true"></authentication_value_algorithm>
    <directory_response_status>C</directory_response_status>
    <authentication_response_status>C</authentication_response_status>
    <required_action>challenge</required_action>
    <acs_reference_number nil="true"></acs_reference_number>
    <acs_rendering_type nil="true"></acs_rendering_type>
    <acs_signed_content nil="true"></acs_signed_content>
    <acs_transaction_id nil="true"></acs_transaction_id>
    <sdk_transaction_id nil="true"></sdk_transaction_id>
    <challenge_form>&lt;form action="https://testds3.seglan.com/server/authentication/load" method="POST"&gt;
  &lt;input name="browserChallengeToken" value="116e1940-c712-4b78-9f2c-0a6f976184d7" type="hidden"/&gt;
&lt;/form&gt;</challenge_form>
    <challenge_form_embed_url nil="true"></challenge_form_embed_url>
    <three_ds_server_trans_id>116e1940-c712-4b78-9f2c-0a6f976184d7</three_ds_server_trans_id>
    <xid nil="true"></xid>
    <enrolled nil="true"></enrolled>
    <transaction_type>Sca::Authentication</transaction_type>
  </sca_authentication>
  <attempt_3dsecure type="boolean">false</attempt_3dsecure>
</transaction>

Preparing your Frontend for Spreedly 3DS2 Global

While those are all of the requests required for a 3DS2 transaction, additional work is required on the frontend for handling asynchronous 3DS2 transactions. The guides below cover frontend integrations for different platforms:

Additional information on the Spreedly SCA Provider can be found below: