Standalone 3-D Secure

Besides executing 3-D Secure with a regular payment, you can also perform a standalone 3-D Secure request using Server-to-Server.

📘

You must be fully PCI compliant to perform a standalone 3-D Secure request, as this requires collecting card data.

1. Send a 3-D Secure request

Use the /v1/threeDSecure endpoint to start a standalone 3-D Secure authentication flow.

📘

Collect and submit all mandatory browser parameters with the request.

curl https://sandbox-card.peachpayments.com/v1/threeDSecure \
 -d "entityId=8a8294174e735d0c014e78cf26461790" \
 -d "amount=12.50" \
 -d "currency=EUR" \
 -d "paymentBrand=VISA" \
 -d "merchantTransactionId=order99234" \
 -d "transactionCategory=EC" \
 -d "card.holder=John Smith" \
 -d "card.number=4200000000000042" \
 -d "card.expiryMonth=12" \
 -d "card.expiryYear=2026" \
 -d "card.cvv=123" \
 -d "merchant.name=MerchantCo" \
 -d "merchant.city=Munich" \
 -d "merchant.country=DE" \
 -d "merchant.mcc=5399" \
 -d "shopperResultUrl=https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status" \
 -d "customer.ip=192.168.0.1" \
 -d "customer.browser.acceptHeader=text/html" \
 -d "customer.browser.screenColorDepth=48" \
 -d "customer.browser.javaEnabled=false" \
 -d "customer.browser.language=de" \
 -d "customer.browser.screenHeight=1200" \
 -d "customer.browser.screenWidth=1600" \
 -d "customer.browser.timezone=60" \
 -d "customer.browser.challengeWindow=4" \
 -d "customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" \
 -d "testMode=EXTERNAL" \
 -H "Authorization: Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ="
public Dictionary<string, dynamic> Request() {
    Dictionary<string, dynamic> responseData;
    string data="entityId=8a8294174e735d0c014e78cf26461790" +
        "&amount=12.50" +
        "&currency=EUR" +
        "&paymentBrand=VISA" +
        "&merchantTransactionId=order99234" +
        "&transactionCategory=EC" +
        "&card.holder=John Smith" +
        "&card.number=4200000000000042" +
        "&card.expiryMonth=12" +
        "&card.expiryYear=2026" +
        "&card.cvv=123" +
        "&merchant.name=MerchantCo" +
        "&merchant.city=Munich" +
        "&merchant.country=DE" +
        "&merchant.mcc=5399" +
        "&shopperResultUrl=https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status" +
        "&customer.ip=192.168.0.1" +
        "&customer.browser.acceptHeader=text/html" +
        "&customer.browser.screenColorDepth=48" +
        "&customer.browser.javaEnabled=false" +
        "&customer.browser.language=de" +
        "&customer.browser.screenHeight=1200" +
        "&customer.browser.screenWidth=1600" +
        "&customer.browser.timezone=60" +
        "&customer.browser.challengeWindow=4" +
        "&customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" +
        "&testMode=EXTERNAL";
    string url = "https://sandbox-card.peachpayments.com/v1/threeDSecure";
    byte[] buffer = Encoding.ASCII.GetBytes(data);
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
    request.Method = "POST";
    request.Headers["Authorization"] = "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=";
    request.ContentType = "application/x-www-form-urlencoded";
    Stream PostData = request.GetRequestStream();
    PostData.Write(buffer, 0, buffer.Length);
    PostData.Close();
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        Stream dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);
        var s = new JavaScriptSerializer();
        responseData = s.Deserialize<Dictionary<string, dynamic>>(reader.ReadToEnd());
        reader.Close();
        dataStream.Close();
    }
    return responseData;
}

responseData = Request()["result"]["description"];
import groovy.json.JsonSlurper

public static String request() {
  def data = "entityId=8a8294174e735d0c014e78cf26461790" +
  "&amount=12.50" +
  "&currency=EUR" +
  "&paymentBrand=VISA" +
  "&merchantTransactionId=order99234" +
  "&transactionCategory=EC" +
  "&card.holder=John Smith" +
  "&card.number=4200000000000042" +
  "&card.expiryMonth=12" +
  "&card.expiryYear=2026" +
  "&card.cvv=123" +
  "&merchant.name=MerchantCo" +
  "&merchant.city=Munich" +
  "&merchant.country=DE" +
  "&merchant.mcc=5399" +
  "&shopperResultUrl=https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status" +
  "&customer.ip=192.168.0.1" +
  "&customer.browser.acceptHeader=text/html" +
  "&customer.browser.screenColorDepth=48" +
  "&customer.browser.javaEnabled=false" +
  "&customer.browser.language=de" +
  "&customer.browser.screenHeight=1200" +
  "&customer.browser.screenWidth=1600" +
  "&customer.browser.timezone=60" +
  "&customer.browser.challengeWindow=4" +
  "&customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" +
  "&testMode=EXTERNAL"
  def url = "https://sandbox-card.peachpayments.com/v1/threeDSecure".toURL()
  def connection = url.openConnection()
  connection.setRequestMethod("POST")
  connection.setRequestProperty("Authorization","Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=")
  connection.doOutput = true
  connection.outputStream << data
  def json = new JsonSlurper().parseText(connection.inputStream.text)
  json
}
println request()
private String request() throws IOException {
    URL url = new URL("https://sandbox-card.peachpayments.com/v1/threeDSecure");
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=");
    conn.setDoInput(true);
    conn.setDoOutput(true);

    String data = ""
        + "entityId=8a8294174e735d0c014e78cf26461790"
        + "&amount=12.50"
        + "&currency=EUR"
        + "&paymentBrand=VISA"
        + "&merchantTransactionId=order99234"
        + "&transactionCategory=EC"
        + "&card.holder=John Smith"
        + "&card.number=4200000000000042"
        + "&card.expiryMonth=12"
        + "&card.expiryYear=2026"
        + "&card.cvv=123"
        + "&merchant.name=MerchantCo"
        + "&merchant.city=Munich"
        + "&merchant.country=DE"
        + "&merchant.mcc=5399"
        + "&shopperResultUrl=https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status"
        + "&customer.ip=192.168.0.1"
        + "&customer.browser.acceptHeader=text/html"
        + "&customer.browser.screenColorDepth=48"
        + "&customer.browser.javaEnabled=false"
        + "&customer.browser.language=de"
        + "&customer.browser.screenHeight=1200"
        + "&customer.browser.screenWidth=1600"
        + "&customer.browser.timezone=60"
        + "&customer.browser.challengeWindow=4"
        + "&customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)"
        + "&testMode=EXTERNAL";

    DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
    wr.writeBytes(data);
    wr.flush();
    wr.close();
    int responseCode = conn.getResponseCode();
    InputStream is;

    if (responseCode >= 400) is = conn.getErrorStream();
    else is = conn.getInputStream();

    return IOUtils.toString(is);
}
const https = require('https');
const querystring = require('querystring');

const request = async () => {
    const path='/v1/threeDSecure';
    const data = querystring.stringify({
        'entityId':'8a8294174e735d0c014e78cf26461790',
        'amount':'12.50',
        'currency':'EUR',
        'paymentBrand':'VISA',
        'merchantTransactionId':'order99234',
        'transactionCategory':'EC',
        'card.holder':'John Smith',
        'card.number':'4200000000000042',
        'card.expiryMonth':'12',
        'card.expiryYear':'2026',
        'card.cvv':'123',
        'merchant.name':'MerchantCo',
        'merchant.city':'Munich',
        'merchant.country':'DE',
        'merchant.mcc':'5399',
        'shopperResultUrl':'https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status',
        'customer.ip':'192.168.0.1',
        'customer.browser.acceptHeader':'text/html',
        'customer.browser.screenColorDepth':'48',
        'customer.browser.javaEnabled':'false',
        'customer.browser.language':'de',
        'customer.browser.screenHeight':'1200',
        'customer.browser.screenWidth':'1600',
        'customer.browser.timezone':'60',
        'customer.browser.challengeWindow':'4',
        'customer.browser.userAgent':'Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)',
        'testMode':'EXTERNAL'
    });
    const options = {
        port: 443,
        host: 'sandbox-card.peachpayments.com',
        path: path,
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': data.length,
            'Authorization':'Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ='
        }
    };
    return new Promise((resolve, reject) => {
        const postRequest = https.request(options, function(res) {
            const buf = [];
            res.on('data', chunk => {
                buf.push(Buffer.from(chunk));
            });
            res.on('end', () => {
                const jsonString = Buffer.concat(buf).toString('utf8');
                try {
                    resolve(JSON.parse(jsonString));
                } catch (error) {
                    reject(error);
                }
            });
        });
        postRequest.on('error', reject);
        postRequest.write(data);
        postRequest.end();
    });
};

request().then(console.log).catch(console.error);
function request() {
    $url = "https://sandbox-card.peachpayments.com/v1/threeDSecure";

    $data = http_build_query([
        'entityId' => '8a8294174e735d0c014e78cf26461790',
        'amount' => '12.50',
        'currency' => 'EUR',
        'paymentBrand' => 'VISA',
        'merchantTransactionId' => 'order99234',
        'transactionCategory' => 'EC',
        'card.holder' => 'John Smith',
        'card.number' => '4200000000000042',
        'card.expiryMonth' => '12',
        'card.expiryYear' => '2026',
        'card.cvv' => '123',
        'merchant.name' => 'MerchantCo',
        'merchant.city' => 'Munich',
        'merchant.country' => 'DE',
        'merchant.mcc' => '5399',
        'shopperResultUrl' => 'https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status',
        'customer.ip' => '192.168.0.1',
        'customer.browser.acceptHeader' => 'text/html',
        'customer.browser.screenColorDepth' => '48',
        'customer.browser.javaEnabled' => 'false',
        'customer.browser.language' => 'de',
        'customer.browser.screenHeight' => '1200',
        'customer.browser.screenWidth' => '1600',
        'customer.browser.timezone' => '60',
        'customer.browser.challengeWindow' => '4',
        'customer.browser.userAgent' => 'Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)',
        'testMode' => 'EXTERNAL'
    ]);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_HTTPHEADER => ['Authorization: Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ='],
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $data,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false // Set to true in production
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (curl_errno($ch)) {
        $error = curl_error($ch);
        curl_close($ch);
        return "cURL Error: $error";
    }

    curl_close($ch);

    // Decode JSON response
    $responseData = json_decode($response, true);
    
    if ($httpCode >= 400) {
        return "HTTP Error $httpCode: " . json_encode($responseData);
    }

    return $responseData;
}

$responseData = request();
print_r($responseData);
try:
    from urllib.parse import urlencode
    from urllib.request import build_opener, Request, HTTPHandler
    from urllib.error import HTTPError, URLError
except ImportError:
    from urllib import urlencode
    from urllib2 import build_opener, Request, HTTPHandler, HTTPError, URLError
import json

def request():
    url = "https://sandbox-card.peachpayments.com/v1/threeDSecure"
    data = {
        'entityId': '8a8294174e735d0c014e78cf26461790',
        'amount': '12.50',
        'currency': 'EUR',
        'paymentBrand': 'VISA',
        'merchantTransactionId': 'order99234',
        'transactionCategory': 'EC',
        'card.holder': 'John Smith',
        'card.number': '4200000000000042',
        'card.expiryMonth': '12',
        'card.expiryYear': '2026',
        'card.cvv': '123',
        'merchant.name': 'MerchantCo',
        'merchant.city': 'Munich',
        'merchant.country': 'DE',
        'merchant.mcc': '5399',
        'shopperResultUrl': 'https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status',
        'customer.ip': '192.168.0.1',
        'customer.browser.acceptHeader': 'text/html',
        'customer.browser.screenColorDepth': '48',
        'customer.browser.javaEnabled': 'false',
        'customer.browser.language': 'de',
        'customer.browser.screenHeight': '1200',
        'customer.browser.screenWidth': '1600',
        'customer.browser.timezone': '60',
        'customer.browser.challengeWindow': '4',
        'customer.browser.userAgent': 'Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)',
        'testMode': 'EXTERNAL'
    }

    try:
        opener = build_opener(HTTPHandler)
        request = Request(url, data=urlencode(data).encode('utf-8'))
        request.add_header('Authorization', 'Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=')
        request.get_method = lambda: 'POST'
        response = opener.open(request)
        return json.loads(response.read())
    except HTTPError as e:
        return json.loads(e.read())
    except URLError as e:
        return e.reason

responseData = request()
print(responseData)
require 'net/https'
require 'uri'
require 'json'

def request()
  uri = URI('https://sandbox-card.peachpayments.com/v1/threeDSecure')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  req = Net::HTTP::Post.new(uri.path)
  req.set_form_data({
    'entityId' => '8a8294174e735d0c014e78cf26461790',
    'amount' => '12.50',
    'currency' => 'EUR',
    'paymentBrand' => 'VISA',
    'merchantTransactionId' => 'order99234',
    'transactionCategory' => 'EC',
    'card.holder' => 'John Smith',
    'card.number' => '4200000000000042',
    'card.expiryMonth' => '12',
    'card.expiryYear' => '2026',
    'card.cvv' => '123',
    'merchant.name' => 'MerchantCo',
    'merchant.city' => 'Munich',
    'merchant.country' => 'DE',
    'merchant.mcc' => '5399',
    'shopperResultUrl' => 'https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status',
    'customer.ip' => '192.168.0.1',
    'customer.browser.acceptHeader' => 'text/html',
    'customer.browser.screenColorDepth' => '48',
    'customer.browser.javaEnabled' => 'false',
    'customer.browser.language' => 'de',
    'customer.browser.screenHeight' => '1200',
    'customer.browser.screenWidth' => '1600',
    'customer.browser.timezone' => '60',
    'customer.browser.challengeWindow' => '4',
    'customer.browser.userAgent' => 'Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)',
    'testMode' => 'EXTERNAL'
  })
  res = http.request(req)
  return JSON.parse(res.body)
end

puts request()
def initialPayment: String = {
  val url = "https://sandbox-card.peachpayments.com/v1/threeDSecure"
  val data = ("" +
    "entityId=8a8294174e735d0c014e78cf26461790" +
    "&amount=12.50" +
    "&currency=EUR" +
    "&paymentBrand=VISA" +
    "&merchantTransactionId=order99234" +
    "&transactionCategory=EC" +
    "&card.holder=John Smith" +
    "&card.number=4200000000000042" +
    "&card.expiryMonth=12" +
    "&card.expiryYear=2026" +
    "&card.cvv=123" +
    "&merchant.name=MerchantCo" +
    "&merchant.city=Munich" +
    "&merchant.country=DE" +
    "&merchant.mcc=5399" +
    "&shopperResultUrl=https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status" +
    "&customer.ip=192.168.0.1" +
    "&customer.browser.acceptHeader=text/html" +
    "&customer.browser.screenColorDepth=48" +
    "&customer.browser.javaEnabled=false" +
    "&customer.browser.language=de" +
    "&customer.browser.screenHeight=1200" +
    "&customer.browser.screenWidth=1600" +
    "&customer.browser.timezone=60" +
    "&customer.browser.challengeWindow=4" +
    "&customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" +
    "&testMode=EXTERNAL"
  )
  
  val conn = new URL(url).openConnection()

  conn match {
    case secureConn: HttpsURLConnection => secureConn.setRequestMethod("POST")
    case _ => throw new ClassCastException
  }

  conn.setDoInput(true)
  conn.setDoOutput(true)
  IOUtils.write(data, conn.getOutputStream())
  conn.setRequestProperty("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=")
  conn.connect()

  if (conn.getResponseCode() >= 400) {
    IOUtils.toString(conn.getErrorStream())
  } else {
    IOUtils.toString(conn.getInputStream())
  }
}
Public Function Request() As Dictionary(Of String, Object)
    Dim url As String = "https://sandbox-card.peachpayments.com/v1/threeDSecure"
    Dim data As String = "" +
        "entityId=8a8294174e735d0c014e78cf26461790" +
        "&amount=12.50" +
        "&currency=EUR" +
        "&paymentBrand=VISA" +
        "&merchantTransactionId=order99234" +
        "&transactionCategory=EC" +
        "&card.holder=John Smith" +
        "&card.number=4200000000000042" +
        "&card.expiryMonth=12" +
        "&card.expiryYear=2026" +
        "&card.cvv=123" +
        "&merchant.name=MerchantCo" +
        "&merchant.city=Munich" +
        "&merchant.country=DE" +
        "&merchant.mcc=5399" +
        "&shopperResultUrl=https://developer.peachpayments.com/docs/oppwa-integrations-server-to-server-standalone-3-d-secure#3-get-the-3-d-secure-status" +
        "&customer.ip=192.168.0.1" +
        "&customer.browser.acceptHeader=text/html" +
        "&customer.browser.screenColorDepth=48" +
        "&customer.browser.javaEnabled=false" +
        "&customer.browser.language=de" +
        "&customer.browser.screenHeight=1200" +
        "&customer.browser.screenWidth=1600" +
        "&customer.browser.timezone=60" +
        "&customer.browser.challengeWindow=4" +
        "&customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" +
        "&testMode=EXTERNAL"

    Dim req As WebRequest = WebRequest.Create(url)
    req.Method = "POST"
    req.Headers.Add("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=")
    req.ContentType = "application/x-www-form-urlencoded"
    Dim byteArray As Byte() = Encoding.UTF8.GetBytes(data)
    req.ContentLength = byteArray.Length
    Dim dataStream As Stream = req.GetRequestStream()
    dataStream.Write(byteArray, 0, byteArray.Length)
    dataStream.Close()
    Dim res As WebResponse = req.GetResponse()
    Dim resStream = res.GetResponseStream()
    Dim reader As New StreamReader(resStream)
    Dim response As String = reader.ReadToEnd()
    reader.Close()
    resStream.Close()
    res.Close()
    Dim jss As New System.Web.Script.Serialization.JavaScriptSerializer()
    Dim dict As Dictionary(Of String, Object) = jss.Deserialize(Of Dictionary(Of String, Object))(response)

    Return dict
End Function

responseData = Request()("result")("description")
{
  "id":"8ac7a4a19d29b03d019d29c30e3127a8",
  "paymentBrand":"VISA",
  "amount":"12.50",
  "currency":"EUR",
  "merchantTransactionId":"order99234",
  "result":{
    "code":"000.200.000",
    "description":"transaction pending"
  },
  "card":{
    "bin":"420000",
    "last4Digits":"0042",
    "holder":"John Smith",
    "expiryMonth":"12",
    "expiryYear":"2027"
  },
  "customer":{
    "ip":"192.168.0.1",
    "browser":{
      "acceptHeader":"text/html",
      "language":"de",
      "screenHeight":"1200",
      "screenWidth":"1600",
      "timezone":"60",
      "userAgent":"Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)",
      "javaEnabled":"false",
      "screenColorDepth":"48",
      "challengeWindow":"4"
    }
  },
  "threeDSecure":{
    "eci":"06"
  },
  "customParameters":{
    "PAYMENT_INHOUSE_FACADE":"true"
  },
  "redirect":{
    "url":"https://test.oppwa.com/connectors/asyncresponse_simulator;jsessionid=ABDFE84144FDCF5B72D66A59E5A1A36F.uat01-vm-con03?asyncsource=ACI_3DS_2&type=methodRedirect&cdkForward=true&ndcid=8a8294174e735d0c014e78cf26461790_12b03a1e230b407886eb6ab14d7f0cbe",
    "parameters":[
      
    ],
    "preconditions":[
      {
        "origin":"iframe#hidden",
        "waitUntil":"iframe#load",
        "description":"Hidden iframe post for 3D Secure 2.0",
        "url":"https://test.ppipe.net/connectors/demo/submit?action=ACI3DS2AccessControlServer&acsRequest=METHOD",
        "method":"POST",
        "parameters":[
          {
            "name":"threeDSMethodData",
            "value":"eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN0Lm9wcHdhLmNvbS9jb25uZWN0b3JzL2FyX3NpbXVsYXRvci8zZHMyO2pzZXNzaW9uaWQ9QUJERkU4NDE0NEZEQ0Y1QjcyRDY2QTU5RTVBMUEzNkYudWF0MDEtdm0tY29uMDM_YXN5bmNzb3VyY2U9QUNJXzNEU18yJnR5cGU9bWV0aG9kTm90aWZpY2F0aW9uJm5kY2lkPThhODI5NDE3NGU3MzVkMGMwMTRlNzhjZjI2NDYxNzkwXzEyYjAzYTFlMjMwYjQwNzg4NmViNmFiMTRkN2YwY2JlIiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiIxMTBlODA2ZS04MzljLTQ5OTktODg1Zi01NTg0OGVhYzIyMDYifQ"
          }
        ]
      }
    ]
  },
  "buildNumber":"9092e7a6af8301accda2f9a3a38f743f907dadd5@2026-03-23 16:50:06 +0000",
  "timestamp":"2026-03-26 10:49:02+0000",
  "ndc":"8a8294174e735d0c014e78cf26461790_12b03a1e230b407886eb6ab14d7f0cbe"
}

2. How to handle the responses

Issuers do not always return Method Data and Method URL. This step is optional, but if returned, handle it. Follow these steps after receiving the gateway response to the initial request.

  1. Collect the necessary data

    Extract the required data from the response received in the previous step. All necessary data exists in the redirect object.

    Example:

    {
        "redirect": {
            "url": "https://sandbox-card.peachpayments.com/v1/threeDSecure/execute",
            "parameters": [{
                "name": "name",
                "value": "value"
            }],
            "preconditions": [{
                "origin": "iframe#hidden",
                "waitUntil": "iframe#onload",
                "description": "Hidden iframe post for 3-D Secure 2.0",
                "method": "POST",
                "url": "methodURL",
                "parameters": [{
                    "name": "threeDSMethodData",
                    "value": "methodData"
                }]
            }]
        }
    }

    From the redirect object, extract the following fields:

    • preconditions.url
    • preconditions.parameters[].name and preconditions.parameters[].value (where parameters is an array and may contain multiple key-value pairs)
  2. Open a hidden iframe and post the data

    Use a hidden iframe to post the data to the preconditions.url, as shown below:

    <form name="hiddenForm" action="preconditions.url" method="POST">
        <input type="hidden" name="preconditions.parameters[].name" value="preconditions.parameters[].value">
    </form>
    <script>
        window.onload = function submitForm() {
            document.forms["hiddenForm"].submit();
        };
    </script>
  3. Request the authentication HTML

    Extract redirect.url and redirect.parameters[] fields from the response. Use these fields to request authentication from the cardholder's bank.

  4. Create an Iframe for authentication

    Create another iframe where the cardholder sees the authentication request from their bank. Wait for the onLoad() event from the previous step, then redirect the customer in this iframe to redirect.url. Include the key-value pairs from redirect.parameters[].

    <form name="authForm" action="redirect.url" method="POST">
        <input type="hidden" name="redirect.parameters[].name" value="redirect.parameters[].value">
    </form>
    <script>
        window.onload = function submitForm() {
            document.forms["authForm"].submit();
        };
    </script>

3. Get the 3-D Secure status

Use the /v1/threeDSecure/{id} endpoint to retrieve detailed information about the 3-D Secure request.

https://sandbox-card.peachpayments.com/v1/threeDSecure/8ac7a4a19d29b03d019d29c30e3127a8

curl -G "https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}" \
 -d "entityId=8a8294174e735d0c014e78cf26461790" \
 -H "Authorization: Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ="
public Dictionary<string, dynamic> Request() {
    Dictionary<string, dynamic> responseData;
    string data = "entityId=8a8294174e735d0c014e78cf26461790";
    string url = "https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}?" + data;
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
    request.Method = "GET";
    request.Headers["Authorization"] = "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=";
    
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
        Stream dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);
        var s = new JavaScriptSerializer();
        responseData = s.Deserialize<Dictionary<string, dynamic>>(reader.ReadToEnd());
        reader.Close();
        dataStream.Close();
    }
    
    return responseData;
}

responseData = Request()["result"]["description"];
import groovy.json.JsonSlurper

public static String request() {
    def data = "entityId=8a8294174e735d0c014e78cf26461790"
    def url = ("https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}?" + data).toURL()
    def connection = url.openConnection()
    connection.setRequestMethod("GET")
    connection.setRequestProperty("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=")
    def json = new JsonSlurper().parseText(connection.inputStream.text)
    json
}

println request()
private String request() throws IOException {
    URL url = new URL("https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}?entityId=8a8294174e735d0c014e78cf26461790");

    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=");
    
    int responseCode = conn.getResponseCode();
    InputStream is;

    if (responseCode >= 400) 
        is = conn.getErrorStream();
    else 
        is = conn.getInputStream();

    return IOUtils.toString(is);
}
const https = require('https');
const querystring = require('querystring');

const request = async () => {
    var path = '/v1/threeDSecure/{id}';
    path += '?entityId=8a8294174e735d0c014e78cf26461790';
    
    const options = {
        port: 443,
        host: 'sandbox-card.peachpayments.com',
        path: path,
        method: 'GET',
        headers: {
            'Authorization': 'Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ='
        }
    };

    return new Promise((resolve, reject) => {
        const postRequest = https.request(options, function(res) {
            const buf = [];
            res.on('data', chunk => {
                buf.push(Buffer.from(chunk));
            });
            res.on('end', () => {
                const jsonString = Buffer.concat(buf).toString('utf8');
                try {
                    resolve(JSON.parse(jsonString));
                } catch (error) {
                    reject(error);
                }
            });
        });

        postRequest.on('error', reject);
        postRequest.end();
    });
};

request().then(console.log).catch(console.error);
function request() {
    $url = "https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}";
    $url .= "?entityId=8a8294174e735d0c014e78cf26461790";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Authorization:Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ='
    ));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // this should be set to true in production
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $responseData = curl_exec($ch);
    
    if (curl_errno($ch)) {
        return curl_error($ch);
    }
    
    curl_close($ch);
    return $responseData;
}

$responseData = request();
try:
    from urllib.parse import urlencode
    from urllib.request import build_opener, Request, HTTPHandler
    from urllib.error import HTTPError, URLError
except ImportError:
    from urllib import urlencode
    from urllib2 import build_opener, Request, HTTPHandler, HTTPError, URLError
import json

def request():
    url = "https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}"
    url += '?entityId=8a8294174e735d0c014e78cf26461790'
    try:
        opener = build_opener(HTTPHandler)
        request = Request(url, data=b'')
        request.add_header('Authorization', 'Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=')
        request.get_method = lambda: 'GET'
        response = opener.open(request)
        return json.loads(response.read())
    except HTTPError as e:
        return json.loads(e.read())
    except URLError as e:
        return e.reason

responseData = request()
print(responseData)
require 'net/https'
require 'uri'
require 'json'

def request()
  path = "?entityId=8a8294174e735d0c014e78cf26461790"
  uri = URI.parse('https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}' + path)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  req = Net::HTTP::Get.new(uri)
  req['Authorization'] = 'Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ='
  res = http.request(req)
  return JSON.parse(res.body)
end

puts request()
def initialPayment: String = {
  val url = "https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}"
  val fullUrl = url + "?entityId=8a8294174e735d0c014e78cf26461790"
  val conn = new URL(fullUrl).openConnection()

  conn match {
    case secureConn: HttpsURLConnection => secureConn.setRequestMethod("GET")
    case _ => throw new ClassCastException
  }
  
  conn.setRequestProperty("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=")
  conn.connect()

  if (conn.getResponseCode >= 400) {
    IOUtils.toString(conn.getErrorStream())
  } else {
    IOUtils.toString(conn.getInputStream())
  }
}
Public Function Request() As Dictionary(Of String, Object)
    Dim url As String = "https://sandbox-card.peachpayments.com/v1/threeDSecure/{id}" +
        "?entityId=8a8294174e735d0c014e78cf26461790"

    Dim req As WebRequest = WebRequest.Create(url)
    req.Method = "GET"
    req.Headers.Add("Authorization", "Bearer OGE4Mjk0MTc0ZTczNWQwYzAxNGU3OGNmMjY2YjE3OTR8SFV3I3JGQTQ9bWpxaWYrPz9OWVQ=")
    req.ContentType = "application/x-www-form-urlencoded"

    Dim res As WebResponse = req.GetResponse()
    Dim resStream = res.GetResponseStream()
    Dim reader As New StreamReader(resStream)
    Dim response As String = reader.ReadToEnd()
    reader.Close()
    resStream.Close()
    res.Close()

    Dim jss As New System.Web.Script.Serialization.JavaScriptSerializer()
    Dim dict As Dictionary(Of String, Object) = jss.Deserialize(Of Dictionary(Of String, Object))(response)

    Return dict
End Function

responseData = Request()("result")("description")
{
  "id":"8ac7a4a19d29b03d019d29c30e3127a8",
  "paymentBrand":"VISA",
  "amount":"12.50",
  "currency":"EUR",
  "descriptor":"5959.7598.9284 OPP_Channel",
  "merchantTransactionId":"order99234",
  "result":{
    "code":"000.300.000",
    "description":"Two-step transaction succeeded"
  },
  "card":{
    "bin":"420000",
    "binCountry":"US",
    "last4Digits":"0042",
    "holder":"John Smith",
    "expiryMonth":"12",
    "expiryYear":"2027"
  },
  "customer":{
    "ip":"192.168.0.1"
  },
  "threeDSecure":{
    "eci":"05",
    "verificationId":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=",
    "version":"2.2.0",
    "dsTransactionId":"3063e429-4f4f-4f9a-a0c1-e4c966f109cc",
    "challengeMandatedIndicator":"N",
    "transactionStatusReason":"",
    "acsTransactionId":"dc281ea1-bf50-426a-80b7-7b4677f121e8",
    "cardHolderInfo":"",
    "authType":"01",
    "flow":"challenge",
    "authenticationStatus":"Y",
    "acsReferenceNumber":"b04ea28d11294692a29f63d2f5c84bfc",
    "dsReferenceNumber":"13db2d60d08c4f6b83de194ca5245e57",
    "purchaseDate":"20260326104902"
  },
  "customParameters":{
    "PAYMENT_INHOUSE_FACADE":"true"
  },
  "buildNumber":"9092e7a6af8301accda2f9a3a38f743f907dadd5@2026-03-23 16:50:06 +0000",
  "timestamp":"2026-03-26 10:56:41+0000",
  "ndc":"8a8294174e735d0c014e78cf26461790_0e764bbde8a941da84050648f3a0bcf5"
}