1.1. Server-to-Server Sale

Introduction

Sale is a type of transaction, in which Payer receives goods or services from Connecting Party in exchange for money or other assets. In this use case Server-to-server Sale, card data is transferred directly in initiating request.

See terms definitions (Connecting Party, 3DS Method, etc) in Glossary.

Sale Flow

skinparam roundcorner 20
skinparam sequenceArrowThickness 1
skinparam maxmessagesize 1200
skinparam sequenceParticipant underline
actor Payer
participant "Connecting Party" as A
participant "ConnPay" as B
autonumber
Payer -> A: Checkout
activate A
A -> B: /api/v2/sale/
activate B
B --> A: Order ID
B -> B: Process\nSale
hnote over Payer,B : See 3DS Decision Making Schema
group Get Final Status
== Receive Connecting Party Callback ==
A <- B: Callback with Final Status
A --> B: HTTP 200
deactivate B
== Order Status Request ==
A -> B: Get Status by Order ID
activate B
B --> A: Final Status
deactivate B
end
A --> Payer: Show result
deactivate Payer
deactivate A

(2) To implement sale request see /api/v2/sale/. See 3DS Overview to get more information about 3DS flow. See 3DS Decision Making Schema and 3DS Implementation Scenarios to correctly implement 3DS flow for this Use-Case.
(5) To implement callback with final status handling see Connecting Party Callback.
(7) To implement order status request see /api/v2/status/. Status should be requested multiple times with 3-5 seconds interval until final status will be received in response.

3DS Decision Making Schema

<style>
activityDiagram {
BackgroundColor #Turquoise
  diamond {
    BackgroundColor #Turquoise
  }
}
document {
   BackgroundColor #fcfcfc
}
</style>
title 3DS Decision Making Schema
start
: (1) Send **/api/v2/status** request\nwith orderid=**paynet-order-id**\nProcess **/api/v2/status** response;
while ((2) Check If **status** response field equals\nto finished status values\n**status** == approved\nOR **status** == declined\nOR **status** == error\nOR **status** == unknown\nOR **status** == filtered) is (NO);
if ((3) **tds_status** field is present) then (YES)
if ((4) **tds_status** == MethodUrlFrame?) then (YES)
#Plum :(5) Create iframe\nto pass 3DS Method\n3DS 2.x Frictionless flow\nto be applied.\n\nSee 3DS 2.x Frictionless Flow;
(NO      ) elseif ((6) **tds_status** == CReqForm?) then (YES)
#Plum :(7) Create CReq HTML Page\nwhich redirects to ACS\n3DS 2.x Challenge Flow\nto be applied\n\nSee 3DS 2.X Challenge Flow;
(NO      ) elseif ((8) **tds_status** == PaReqForm?) then (YES)
#Plum :(9) Create PaReq HTML Page\nwhich redirects to ACS\n3DS 1.0.2 Authentication Flow\nto be applied\n\nSee 3DS 1.0.2 Authentication Flow;
endif
(NO      )elseif ((10) **html** and **redirect-to** field is present) then (YES)
#Plum :(11) Create Wait HTML Page\nwhich redirects to result page\n(3DS 2.x or 1.0.2 to be applied)\n\nSee Simplified authentication flow;
else (NO)
endif
backward:(12) Send new\n**/api/v2/status** request\nProcess\n**/api/v2/status** response;
endwhile (YES)
:(13) Show result page to the Payer;
stop
legend left
=Legend
| Color | Implementation responsibility |
|<#Turquoise>| Connecting party |
|<#Plum>| Connecting and other party |
| | Other Party |
endlegend

Connecting party has to implement all steps marked in green and purple. Below are the description for steps which reference specific API commands according to the step ID:

(1) To implement order status request see /api/v2/status/. Status should be requested multiple times with 3-5 seconds interval until final status will be received in response.
(5) If tds_status is MethodUrlFrame see 3DS 2.x Frictionless Flow.
(7) If tds_status is CReqForm see 3DS 2.X Challenge Flow.
(9) If tds_status is PaReqForm see 3DS 1.0.2 Authentication Flow.
(11) If tds status is not present, but html and redirect-to fields are present, see Simplified authentication flow with html page.
(12) The same as point (1).

Non3D Flow

Sale transaction should be considered as non3D (no 3DS authentication) if all conditions are met:

1. steps 1-2-(12)-13 of 3DS decision making schema were followed.
2. tds_status, html and redirect-to parameters were not present.
3. transaction received final status (approved, declined, error, filtered).

Note

Please note that transaction status “unknown” might appear for both 3DS and non3D transactions. See details in Statuses.

3DS 2.x.0 Frictionless Flow

<style>
activityDiagram {
  diamond {
    BackgroundColor #Turquoise
  }
}
document {
   BackgroundColor #fcfcfc
}
</style>
title 3DS 2.x.0 Frictionless Flow
start
#Turquoise:(1) Send **/api/v2/status/** API request;
#Turquoise:(2) Process **/api/v2/status/** response.
Gather:
**tds-method-url-frame-3ds-server-trans-id**
**tds-method-url-frame-3ds-method-url**;
if ((3) **tds-method-url-frame-3ds-method-url** is present) then (yes)
    #Turquoise:(4) The Connecting Party constructs **3DS Method HTML Page**\ncontaining hidden iframe and upload **3DS Method Result HTML Form**\nusing the parameters received on the previous steps\nand providing **threeDSMethodNotificationURL**;
    #Turquoise:(5) HTML Page, once rendered, is automatically submitted
    into iframe (using HTML Page target attribute);
    fork
        note left
        **iframe** lifecycle
        end note
        :(6) Payer's iframe gets redirected to
        **tds-method-url-frame-3ds-method-url**
        URL (Issuer ACS);
        :(7) Issuer ACS collects Payer Identity Data from browser;
        :(8) Issuer ACS notifies (using HTTP POST)
        **threeDSMethodNotificationURL** on completion;
        #Turquoise:(9) When notification is received gather **threeDSMethodData**.
        Base64Decode it and check **threeDSServerTransID**;
        #Turquoise:(10) Save **threeDSCompInd=Y** for the current Transaction;
        #Turquoise:(11) Return **3DS Method Done HTML Page**;
    fork again
        note left
        **3DS Method HTML Page** lifecycle
        end note
        repeat
            #Turquoise:(12) Check if Issuer ACS notification
            is received from iframe internal JavaScript;
        repeat while ((13) notification is recieved OR timeout exceeded?) is (no)
        -> (yes);
        if ((14) timeout exceeded?) then (yes)
            #Turquoise:(15) Save **threeDSCompInd=N**
            for the current Transaction;
        else (no)
        endif
        :(16) After executing 3ds method\nsend data to connecting party's server;
   end fork
    else (no)
        #Turquoise:(17) Save **threeDSCompInd=U**
        for the current Transaction;
endif
#Turquoise:(18) Send **api/3ds/v1/upload-method-url-result/** request
with the collected Payer's data and **threeDSCompInd**,
Payer's browser info and **notificationURL**
which is to be used further in the Challenge Flow
(see 3DS Decision Making Schema and 3DS 2.X Challenge Flow).;
#Turquoise:(19) Send **/api/v2/status/** API request
Process **/api/v2/status/** response and follow **3DS Decision Making Schema**.;
stop
legend left
=Legend
| Color | Implementation responsibility |
|<#Turquoise>| Connecting party |
| | Other Party |
endlegend

Connecting party has to implement all steps marked in green. Below are the description for steps which reference specific API commands according to the step ID:

(1) To implement order status request see /api/v2/status/. Status should be requested multiple times with 3-5 seconds interval until final status will be received in response.
(2) The same as point (1).
(4) To construct 3DS Method HTML page see example below.
(9) To process 3DS Method Notification see Process 3DS Method Notification.
(11) To construct 3DS Method Done HTML page see example.
(18) To upload method url result see /api/3ds/v1/upload-method-url-result/.
(19) The same as point (1).

3DS Method HTML Page Example

3DS Method HTML Page example below performs 3DS Method initiation through iframe technique and holding of the Payer’s browser until the 3DS Method is not finished on the Connecting Party server. Once it is finished or timeout is reached Connecting Party has to follow the next steps following 3DS Decision Making Schema and redirect Payer’s browser to the corresponding URL (either Challenge Flow or payment result page). Normal timeout value is 30 sec.

3DS Method HTML Page consists of the following parameters:

Parameter

Description

tds-method-url-frame-3ds-method-url

ACS 3DS Method URL is received by the Connecting Party in the /api/v2/status/ response.

tdsMethodUploadUrl

Connecting Party’s URL, where the result comes after the completion of the flow.

threeDSMethodData

JSON value containing threeDSServerTransID and threeDSMethodNotificationURL. See below how to construct threeDSMethodData.

Construct threeDSMethodData

In order to construct threeDSMethodData the Connecting Party has to use the following parameters.

Parameter

Description

threeDSServerTransID

Universally unique transaction identifier assigned by the 3DS Server to identify a single transaction.
Received in the /api/v2/status/ response as tds-method-url-frame-3ds-server-trans-id parameter.

threeDSMethodNotificationURL

The URL that will receive the notification of 3DS Method completion from the ACS. The Connecting Party is responsible for providing valid threeDSMethodNotificationURL. Normally when the Connecting Party receives any request on this URL is has to return 3DS Method Done HTML Page (see example below).

threeDSMethodData construction example

  1. Construct threeDSMethodData JSON.

{"threeDSServerTransID":"3d671629-a410-4a5d-9288-b38ceadd41f2","threeDSMethodNotificationURL":"https://merchant.com/3ds-method-complete/"}
  1. Apply base64 url encoding to resultant JSON.

eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjNkNjcxNjI5LWE0MTAtNGE1ZC05Mjg4LWIzOGNlYWRkNDFmMiIsInRocmVlRFNNZXRob2ROb3RpZmljYXRpb25VUkwiOiJodHRwczovL21lcmNoYW50LmNvbS8zZHMtbWV0aG9kLWNvbXBsZXRlLyJ9

Generating Fingerprint.

The 3DS Method can be optionally used by issuers to gather browser fingerprints using JavaScript. This is done by loading a URL in a hidden iframe, before the authentication. This iframe will then execute some fingerprinting JavaScript, before POST’ing to the prespecified URL belonging to the requestor. The 3DS Method fingerprint result is tied to the authentication by the threeDSServerTransID.

function gatherBrowserData() {
  var colorDepth = screen.colorDepth; // 24
  var javaEnabled = navigator.javaEnabled(); // true
  var browserLanguage = navigator.language; // en_US
  var screenHeight = screen.height; // 1080
  var screenWidth = screen.width; // 1920
  var userAgent = navigator.userAgent; // Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
  var browserTimezoneZoneOffset = new Date().getTimezoneOffset(); // 0
}

Construct 3DS Method HTML page example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>ACS v2 3DS Method ...</title>
    <style>
.progress{
    position: absolute;
    height: 10px;
    width: 100%;
}
.progress .color{
    position: absolute;
    background-color: #444;
    width: 100%;
    height: 10px;
    animation: progres 11s linear;
}
@keyframes progres{
    0%{
      width: 0%;
     background-color: #ddd;
   }
    25%{
        width: 50%;
        background-color: #ccc;
    }
    50%{
        width: 75%;
        background-color: #bbb;
    }
    75%{
        width: 85%;
        background-color: #aaa;
    }
    100%{
        width: 100%;
        background-color: #777;
    }
};
    </style>
    <script>
var fallbackTimeout = null;
function processForm() {
    document.title = "ACS v2 AReq ...";
    document.getElementById( "browserJavaEnabled"       ).value = navigator.javaEnabled();
    document.getElementById( "browserJavascriptEnabled" ).value = true;
    document.getElementById( "browserLanguage"          ).value = navigator.language;
    document.getElementById( "browserColorDepth"        ).value = screen.colorDepth;
    document.getElementById( "browserScreenHeight"      ).value = screen.height;
    document.getElementById( "browserScreenWidth"       ).value = screen.width;
    document.getElementById( "browserTZ"                ).value = new Date().getTimezoneOffset();
    document.autoForm.submit();
}
function onPostMessage(event) {
    if(!event.data.hasOwnProperty('methodNotification')) {
       return;
    }
    if(fallbackTimeout != null) {
         clearTimeout(fallbackTimeout);
         fallbackTimeout = null;
    }
    document.getElementById( "threeDSCompInd" ).value = 'Y';
    processForm();
}
function onPageLoaded() {
    fallbackTimeout = setTimeout(processForm, 10 * 1000);
    document.methodForm.submit();
    window.addEventListener('message', onPostMessage);
}
    </script>
</head>
<body onload="onPageLoaded()">
<div class="progress">
    <div class="color"></div>
</div>
<iframe style="width:0; height:0; border:0;" name="methodFrame"></iframe>
<form name="methodForm" target="methodFrame" action="[=tds-method-url-frame-3ds-method-url]" method="POST">
    <input type="hidden" name="threeDSMethodData" value="[=threeDSMethodData]">
</form>
<form name="autoForm" action="[=tdsMethodUploadUrl]" method="post">
    <input type="hidden" name="threeDSServerTransID" value="[=threeDSServerTransID]"/>
    <input type="hidden" name="threeDSCompInd" id="threeDSCompInd" value="N"/>
    <input type="hidden" name="browserJavaEnabled"       id="browserJavaEnabled"        value="" />
    <input type="hidden" name="browserJavascriptEnabled" id="browserJavascriptEnabled"  value="" />
    <input type="hidden" name="browserLanguage"          id="browserLanguage"           value="" />
    <input type="hidden" name="browserColorDepth"        id="browserColorDepth"         value="" />
    <input type="hidden" name="browserScreenHeight"      id="browserScreenHeight"       value="" />
    <input type="hidden" name="browserScreenWidth"       id="browserScreenWidth"        value="" />
    <input type="hidden" name="browserTZ"                id="browserTZ"                 value="" />
    <noscript>
        <input type="submit" name="submit" value="Upload 3DS Method Result"/>
    </noscript>
</form>
</body>
</html>

Process 3DS Method Notification

When 3DS Method is completed, the Connecting Party receives HTTP POST request at threeDSMethodNotificationURL with threeDSMethodData, which contains threeDSServerTransID (in base64 encoded JSON).

  1. Get threeDSMethodData

threeDSMethodData=eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjNkNjcxNjI5LWE0MTAtNGE1ZC05Mjg4LWIzOGNlYWRkNDFmMiJ9Cg
  1. Apply base64 url decoding to get JSON, which contains threeDSServerTransID.

{"threeDSServerTransID":"3d671629-a410-4a5d-9288-b38ceadd41f2"}

3DS Method Done HTML Page Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>ACS v2 3DS Method Notification Handler...</title>
    <script>
        window.parent.postMessage({ methodNotification: "COMPLETE" }, "*");
    </script>
</head>
<body>
<p>This should not be displayed</p>
</body>
</html>

3DS 2.x.0 Challenge Flow

<style>
document {
   BackgroundColor #fcfcfc
}
</style>
title 3DS 2.x.0 Challenge Flow
start
#Turquoise:(1) Send **/api/v2/status/** API request;
#Turquoise:(2) Process **/api/v2/status/** response.
Gather:
**tds-creq-form-creq**
**tds-creq-form-acs-url**;
#Turquoise:(3) Construct CReq HTML Page based on the gathered parameters.
Add **threeDSSessionData** with the custom data
in the format: Max length: 1024 bytes, format: Alphanumeric,
base64url encoded without padding.;
#Turquoise:(4) Return CReq HTML Page to Payer's browser;
:(5) CReq Page gets redirected to ACS URL **tds-creq-form-acs-url**.
Payer passes 3DS Challenge Verification.
ACS return CRes Page.
CRes Page gets submitted to **notificationURL**;
#Turquoise:(6) Process CRes Page parameters.
Gather parameters:
**cres**
**threeDSSessionData**;
#Turquoise:(7) Send HTTP POST **/api/3ds/v1/upload-cres-result/** API Request
providing **cres**, **orderid=paynet-order-id**;
#Turquoise:(8) Send **/api/v2/status/** API request
Process **/api/v2/status/** response and follow **3DS Decision Making Schema**.;
stop
legend left
=Legend
| Color | Implementation responsibility |
|<#Turquoise>| Connecting party |
| | Other Party |
endlegend

(1) To implement order status request see /api/v2/status/.
(2) The same as point (1).
(3) To create CReq HTML Page see example.
(5) To implement CRes redirect see CRes redirect.
(7) To upload CRes result see /api/3ds/v1/upload-cres-result/.
(8) The same as point (1).

CReq HTML Page Example

CReq HTML Page redirects the Payer’s browser to ACS Server URL, provided in tds-creq-form-acs-url parameter. The result CRes value will be returned from ACS to notificationURL provided by Connecting Party on the previous step.

Field

Description

Necessity

creq

ACS 3DS CReq data, which received by the Connecting Party in the /api/v2/status/ response. The same as tds-creq-form-creq.

Required

threeDSSessionData

Value which will be posted back within CRes to notificationURL at the end of the process. Max length: 1024 bytes, format: Alphanumeric, Base64url encoded without padding.

Optional

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Redirecting ...</title>
  <script type="text/javascript" language="javascript">
    function makeSubmit() {
              document.returnform.submit();
        }
  </script>
</head>
<body onLoad="makeSubmit()">
<form name="returnform" action="https://acs.bank-domain.com/mdpayacs/creq" method="POST">
  <input type="hidden" name="creq" value="eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6ImM1NDA5N2VhLTc0ZTctNDE2My05MTQ4LTNjMTY1NTg3NGIwMCIsImFjc1RyYW5zSUQiOiIxMjU1NTkyMi1lZmYzLTRjOTQtOTk4Mi0yMDM3NjJhMzdmMjkiLCJjaGFsbGVuZ2VXaW5kb3dTaXplIjoiMDIiLCJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIn0=">
  <input type="hidden" name="threeDSSessionData" value="NjY4MDU3NQ">
  <noscript>
    <input type="submit" name="submit" value="Press this button to continue"/>
  </noscript>
</form>
</body>
</html>

3DS 1.0.2 Authentication Flow

<style>
document {
   BackgroundColor #fcfcfc
}
</style>
title 3DS 1.0.2 Authentication Flow
start
#Turquoise:(1) Send **/api/v2/status/** API request;
#Turquoise:(2) Process **/api/v2/status/** response.
Gather:
**tds-pareq-form-pareq**
**tds-pareq-form-acs-url**;
#Turquoise:(3) Construct PAReq HTML Page based on the gathered parameters.
Add **TermUrl** where the Payer gets redirected back with PARes data submitted.
Add **MD** with the custom data which is be posted back.;
#Turquoise:(4) Return PAReq HTML Page to Payer's browser;
:(5) PaReq Page gets redirected to ACS URL **tds-pareq-form-acs-url**;
:(6) Payer passes 3DS Challenge Verification;
:(7) ACS returns PARes Page;
:(8) PaRes Page gets submitted to the **TermUrl**;
#Turquoise:(9) Process PARes Page parameters.
Gather parameters:
**PaRes**
**MD**;
#Turquoise:(10) Send HTTP POST **/api/3ds/v1/upload-pares-result/** API Request
providing **paRes**, **orderid=paynet-order-id**;
#Turquoise:(11) Send **/api/v2/status/** API request
Process **/api/v2/status/** response and follow **3DS Decision Making Schema**.;
stop
legend left
=Legend
| Color | Implementation responsibility |
|<#Turquoise>| Connecting party |
| | Other Party |
endlegend

(1) To implement order status request see /api/v2/status/.
(2) The same as point (1).
(3) To construct PaReq HTML Page see example.
(5) To implement PaRes redirect see PaRes redirect.
(10) To upload PaRes result see /api/3ds/v1/upload-pares-result/.
(11) The same as point (10).

PaReq HTML Page Example

PaReq HTML Page redirects the Payer’s browser to ACS Server URL, provided in tds-pareq-form-acs-url parameter.

PaReq HTML Page consists of the following parameters:

Field

Description

Necessity

tds-pareq-form-acs-url

ACS 3DS PaReq URL is received by the Connecting Party in the /api/v2/status/ response.

Required

MD

Merchant Data, which comes back to your termination page.

Optional

PaReq

ACS 3DS PaReq data, which received by the Connecting Party in the /api/v2/status/ response. The same as tds-pareq-form-pareq.

Required

TermURL

URL of termination page, where the Payer gets redirected back with PaRes data submitted.

Required

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Loading acs..</title>
  <script type="text/javascript" language="javascript">
    function makeSubmit() {
      document.returnform.submit();
    }
  </script>
</head>
<body onLoad="makeSubmit()">
<form name="returnform" action="$tds-pareq-form-acs-url" method="POST">
  <input type="hidden" name="MD" value="some_merchant_data"/>
  <input type="hidden" name="PaReq" value="$tds-pareq-form-pareq"/>
  <input type="hidden" name="TermUrl" value="https://termination.page"/>
  <noscript>
    <input type="submit" name="submit" value="Submit"/>
  </noscript>
</form>
</body>
</html>

Simplified Authentication Flow

<style>
document {
   BackgroundColor #fcfcfc
}
activitydiagram {
diamond {
  BackgroundColor #Turquoise
  }
}
</style>
title Simplified Authentication Flow
start
#Turquoise:(1) Send **/api/v2/status/** API request;
#Turquoise:(2) Process **/api/v2/status/** response.
Gather:
**html** parameter;
fork
#Turquoise:(3)Gather **html** parameter;
#Turquoise:(4) Return content from **html** parameter to the Payer's browser as is;
forkagain
#Turquoise:(5)Gather **redirect-to** parameter;
#Turquoise:(6)Redirect Payer to redirect URL;
endfork
:(7) Payer's browser gets redirected to ACS and Payer passes either 3DS 1.0.2 or 3DS 2.X flow.;
:(8) Payer's browser gets redirected back to **redirect_url** provided in the initial **api/v2/sale/** request.;
#Turquoise:(9) Process Payer's Browser final redirect to **redirect_url**.;
#Turquoise:(10) Return Wait HTML Page to the Payer's browser;
fork
note left
        **Wait HTML Page** lifecycle
end note
repeat
#Turquoise: (11) Request Connecting Party Server on the status of the transaction;
#Turquoise: (12) Process transaction status;
repeat while ((13) Received finished status\n(approved, declined, error, filtered or uknown)?) is (no)
-> (yes);
#Turquoise:(14) Redirect Payer's browser to the result page;
fork again
note left
        **Connecting Party Server** lifecycle
end note
#Turquoise:(15) Send **/api/v2/status/** API request;
#Turquoise:(16) Process **/api/v2/status/** response \nand follow **3DS Decision Making Schema** to analyze status response;
end fork
stop
legend left
=Legend
| Color | Implementation responsibility |
|<#Turquoise>| Connecting party |
| | Other Party |
endlegend

(1) and (2) To implement order status request see /api/v2/status/.
(9) To implement final redirect see Final redirect.
(10) The HTML wait page on Connecting Party side can have custom design and should communicate with Connecting Party server as described on the diagram.
(15) and (16) The same as point (1) and (2).