Terminal & eCommerce Integration

eCommerce (HPP) and terminal (virtual/hardware) integrations share the same API set.
You can choose between PUSH (webhook) and PULL (polling) integration modes.


Integration Approach: Window, Popup, or Tab Required

IMPORTANT:
The integrating application must launch the payment or tokenization flow in a new browser window, popup, or tab.

  • Embedding the payment flow in an iframe is not supported due to PCI DSS 4.0 restrictions and compliance requirements.
  • Integration via HTTP redirect (server-side or client-side) is not supported yet but will be available in a future release.

We recommend using window.open() or similar techniques to launch the viewUrl provided by the PAYENGINE API.
The payment flow must always remain isolated from your main application window.


Why is customerInfo required (for HPP/eCommerce)?

The customerInfo block is included in eCommerce Hosted Payment Page (HPP) requests because some payment service providers (PSPs)—as well as special requirements from networks such as VISA and Mastercard—require additional end-customer data for security, fraud prevention, or compliance reasons. Whether this block is required depends on the selected PSP and project configuration.

Best Practice: We recommend always supplying as much customer information as is available (especially mobile phone number and email address), even if not currently enforced by your PSP. This proactive approach helps avoid major integration changes later, should your PSP requirements change, or if you switch to another provider that mandates this data.

Note: customerInfo is ignored for terminal integrations.

Please note that certain data points, specifically the mobile phone number and email address, are often used by payment networks or providers for enhanced security checks (such as Strong Customer Authentication or fraud scoring).

In summary:

  • Check with your payment provider for exact requirements.
  • Providing customerInfo is strongly recommended to ensure future-proof integration and maximize transaction acceptance.

Flow Overview

PUSH Mode

Pullmode

If you are implementing a web application consider the following message flow between the components.

Push

PULL Mode

Pullmode

If you are implementing a web application consider the following message flow between the components.

Pull

Still doubts? An more detailed sequence to explain the principle can be here!


API Calls Used

  • POST /{customerID}/initpayNoIframe
  • POST /{customerID}/initCreateTokenNoIframe
  • POST /{customerID}/initauthNoIframe
  • GET /{customerID}/paystatus?requestid&serviceProvider
  • GET /{customerID}/transaction?requestid&serviceProvider
    see (see Webservices)
  • Webhook (PUSH): /paymentCommit, /authorizationCommit, /createTokenCommit etc. (see Callbacks)

Node.js Example

Initialize Payment

const baseUrl = "{baseUrl}";
const username= "[your-user}"
const password= "{your password}"


async function postData(url = '', data = {}, jwt) {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 
        'Content-Type': 'application/json', 
        'Authorization': 'Bearer ' + jwt 
  
      },
  
      body: JSON.stringify(data)
    });
      console.log(response)
  return response.json();
  }

  
const loginUrl = `https://${baseUrl}/login` ;
let loginmsg = {
  "username": `${username}`,
  "password": `${password}`
}

console.log(loginUrl)
const {access_token} = await postData(loginUrl, loginmsg, null)

const url = `https://${baseUrl}/V2/0000/initpayNoIframe`;
let msg = {
  "hotelID": "1",
  "hotelIDType": "SIHOT.PMS",
  "user": "WEBUSER",
  "datetime": "2025-06-01T11:00:00",
  "serviceProvider": "spayengine",
  "amount": "2000",
  "currency": "EUR",
  "cardInfoRefID": "2270",
  "resNo": "20008505/1",
  "callbackSuccessUrl": "https://yourapp/success",
  "callbackAbortUrl": "https://yourapp/failure",
  "supportedFeatures": "",
  "description": "Online payment",
      "customerInfo": {
        "mobilePhone": "",
        "landPhone": "",
        "email": "",
        "firstName": "",
        "lastName": "",
        "companyName": "",
        "address": {
            "street1": "",
            "street2": null,
            "street3": null,
            "city": "",
            "country": "DE",
            "postalCode": "",
            "state": ""
        }
    }

};
postData(url, msg, access_token).then(e => console.log(e));

Get Payment Status (PULL)

const url = initResponse.stateRetrivalUrl;
fetch(url)
  .then(response => response.json())
  .then(data => console.log(data));

See Helper Functions for postData.