Menu

Direct integration

IPS V3.1.2.0
Released August 2021

Introduction to STOMP

Overview

The section shows you how to integrate with the IPS payment service API from your Point of Sale application directly through IPS’s STOMP API.

Click below to jump straight to our Payment API guide:

Protocol

IPS’s payment service API uses JSON (JavaScript Object Notation) messages over STOMP (Simple, or Streaming, Text Orientated Messaging Protocol) WebSocket connections. These allow bi-directional messaging to complete payment operations.

Some of the advantages of using STOMP are:

  • Support real-time interaction with IPS during the payment flow
  • Build on web sockets, which are natively supported on many platforms and in many languages (e.g. JavaScript, Java, .NET)
  • Provide a standardised and formal structure to web socket messages, making the messages easier to work with
  • You can implement STOMP with many off-the-shelf STOMP client libraries available in many languages and platforms

If you're not familiar with the STOMP protocol, you should learn about it before you continue with this guide. For more information, see theSTOMP Specificationweb page.

Processes

SDK flow

The flow chart above shows the standard process for each operation. The operations are summarised below:

  1. Connect to IPS’s STOMP endpoint
    1. Open a web socket connection to the STOMP URL
    2. Send a STOMP CONNECT frame
    3. Wait for a STOMP CONNECTED frame
  2. Subscribe to each STOMP destination required for the operation
    1. Send a STOMP SUBSCRIBE frame
  3. Send and receive messages on the STOMP destinations relevant to the operation (operations may support many messages back-and-forth to complete)
    1. Send STOMP SEND frames
    2. Receive STOMP MESSAGE frames
  4. When all messages have been exchanged, disconnect from IPC’s STOMP endpoint
    1. Send a STOMP DISCONNECT frame
    2. Close the web socket connection

Each of these STOMP actions (CONNECT, CONNECTED, SEND, MESSAGE and DISCONNECT) should be supported by your chosen STOMP library. See theSTOMP Specificationweb page for details on these actions and available STOMP clients.

The payload and headers of each SEND frame sent to, and MESSAGE frame received from, IPS are described in theAPI Reference.

Errors

This API has three types of errors:

Business errors

The request was in progress but failed. The error is returned in the process's normal reply destination. If this occurs during a payment, you must still give a receipt to the customer and record the payment.

Technical errors

The request could not be processed and the error is returned in the /client/v1/error STOMP destination. An example is the request message was invalid, or part of the system is unavailable. In this scenario, you don't have to give a receipt and you can re-try the payment after you fix the error.

Some possible errors are in the table below:

ProblemError codeError message formatError message example
Invalid STOMP destination.10001The destination <destination> is not recognised.The destination /v1/payment/void is not recognised.
Unable to parse JSON payload.10002The message payload is not valid JSON.The message payload is not valid JSON.
Validation fails in the payload.10003The message payload field <field> is <problem>.The message payload field paymentinstrument.type is missing.
Validation fails in the headers.10004The message header <header> is <problem>.The message header x-wp-message-id is missing.
Unexpected internal error, see logs for details.11001Internal server error.Internal server error.
IPS is not authorised to register a Point of Sale.12001The requested operation is not allowed.The requested operation is not allowed.
The POS registration request could not be processed.13001<reason>Invalid activation code.

Protocol errors

The server sends a STOMP ERROR frame, and the web socket connection is terminated. This may occur if there is a fatal error in the connection between client and server which cannot be rectified. Another example is when IPS receives invalid STOMP frames from the client. You must re-establish a new web socket connection after you fix the error.

API Security

Before your POS (Point Of Sale) application can establish a connection to IPS, each application must have a unique point of sale license key.

To get a point of sale license key for a new POS device, first connect without a point of sale license key to create an unauthenticated web socket connection, then use the /v1/pos/registration endpoint to register the POS device and receive a point of sale license key.

Once registered, you must provide the point of sale license key in the x-wp-authorization header of each CONNECT message. This creates an authenticated web socket connection which you can then use to perform other operations such as making a payment.

Example

CONNECT
accept-version:1.2,1.1
heart-beat:0,0
x-wp-authorization: <Point of Sale License Key>

Any authorization error causes the server to send a STOMP ERROR and the web socket connection is terminated.

Process Flows

JavaScript example - Registering a POS

Note: The stomp.js library uses as the STOMP client in this example is availablehere

Define the STOMP endpoint

Copied!
// The location of IPS's STOMP endpoint
var stompClient = Stomp.client("wss://localhost:8080/ipc-app/payment/PAYPOINT1")

Define how to handle replies from IPS throughout the registration process

Copied!
// Function to handle the connection errors with IPS
var handle_connection_error = function(error) {
  // Correct the error and retry
  ...
}

// Function to handle a successful registration reply
var handle_registration_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Store the POS License Key in the paypload, to be used in the x-wp-authorisation header of future connections to IPS
  ...

  // Disconnect from IPS
  stompClient.disconnect(null, handle_connection_error)
}

// Function to handle errors from an unsuccessful registration
var handle_error_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Correct the error
  ...

  // Disconnect from IPS
  stompClient.disconnect(null, handle_connection_error)

  // Retry if necessary
  ...
}

Define how to start the registration process

Copied!
// Function to start the registration process once connected to IPS
var start_registration = function() {
  // Subscribe to destinations you expect to receive replies on, assigning functions to each reply
  stompClient.subscribe('/client/v1/pos/registration', handle_registration_reply)
  stompClient.subscribe('/client/v1/error', handle_error_reply)

  // Define the payload for registration
  var payload = JSON.stringify({
    pointOfSaleReference: 'POS_123',      // The Point of Sale Reference you entered into the IPS Control Center
    pointOfSaleId: 'uydVea',              // Point of Sale ID from the IPS Control Center
    pointOfSaleActivationCode: 'jYecVUTB' // Point of Sale Activation Code from the IPS Control Center
  })

  // Define the headers for registration
  var headers = {
    'x-wp-publisher-id': ...,   // Unique ID per POS instance
    'x-wp-correlation-id': ..., // UUID, unique per operation
    'x-wp-message-id': ...      // UUID, unique per message
  }

  // Start the registration
  stompClient.send('/v1/pos/registration', headers, payload)
}

Connect to IPS to start the registration process

Copied!
var headers = {
  // No headers required for connection
}

// Connect to IPS, and start the registration when connected
stompClient.connect(headers, start_registration, handle_connection_error)

JavaScript example - Making a sale

Note: The stomp.js library uses as the STOMP client in this example is availablehere

Define the STOMP endpoint

Copied!
// The location of IPS's STOMP endpoint
var stompClient = Stomp.client("wss://localhost:8080/ipc-app/payment/PAYPOINT1")

Define how to handle replies from IPS throughout the payment process

Copied!
// Function to handle the connection errors with IPS
var handle_connection_error = function(error) {
  // Correct the error and retry
}

// Function to handle payment notifications
var handle_notification_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Display the notification text to the POS operator
  ...
}

// Function to handle payment receipts
var handle_receipt_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Print the receipt
  ...
}

// Function to handle payment results
var handle_result_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Handle the result of the payment, e.g. display on screen, or store the payment data
  ...
}

// Function to handle payment actions
var handle_action_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Perform the action
  ...

  // Respond to the action by sending a message to /v1/payment/action
  ...
}

// Function to handle confirmation from IPS that the payment process is complete
var handle_complete_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // The payment flow has completed, ready to start the next payment

  // Disconnect from IPS
  stompClient.disconnect(null, handle_connection_error)
}

// Function to handle errors from the payment process
var handle_error_reply = function(stompMessage) {
  var payload = JSON.parse(stompMessage.body)
  var headers = stompMessage.headers

  // Correct the error
  ...

  // Disconnect from IPS
  stompClient.disconnect(null, handle_connection_error)

  // Retry if necessary
  ...
}

Define how to start the payment

Copied!
// Function to start the payment process once connected to IPS
var start_payment = function() {
  // Subscribe to destinations you expect to receive replies on, assigning functions to each reply
  stompClient.subscribe('/client/v1/payment/notification', handle_notification_reply)
  stompClient.subscribe('/client/v1/payment/receipt', handle_receipt_reply)
  stompClient.subscribe('/client/v1/payment/result', handle_result_reply)
  stompClient.subscribe('/client/v1/payment/action', handle_action_reply)
  stompClient.subscribe('/client/v1/payment/complete', handle_complete_reply)
  stompClient.subscribe('/client/v1/error', handle_error_reply)

  // Define the payload for starting a payment
  var payload = JSON.stringify({
    paymentType: 'sale',
    merchantTransactionReference: "12345678AB",
    instruction: {
      value: {
        amount: 1099
      },
      paymentInstrument: {
        type: "card/present"
      }
    }
  })

  // Define the headers for starting a payment
  var headers = {
    'x-wp-publisher-id': ...,   // Unique ID per POS instance
    'x-wp-correlation-id': ..., // UUID, unique per operation
    'x-wp-message-id': ...      // UUID, unique per message
  }

  // Start the payment
  stompClient.send('/v1/payment', headers, payload)
}

Connect to IPS to start the payment

Copied!
var headers = {
  // The POS License Key header
  'x-wp-authorization': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ4Z3CseLRkkmLxat9JI2RYWjHwFSulJQiy8dmiNvdCW4'
}

// Connect to IPS, and start the payment when connected
stompClient.connect(headers, start_payment, handle_connection_error)

API Reference

The API reference describes the payload and headers of each message that can be sent between your POS application and IPS's payment service API.

Recommendations

We recommend that you use a STOMP client library if one is available for your language. The library clients enable the efficient connection and disconnection from the STOMP API, and send and receive STOMP frames.

FAQs

See theFAQstopic for frequently asked questions.