Back to top

GOV.UK Pay Telephone Payments reporting

Document status

Date Author Comment
24/1/19 David Heath first draft

Purpose and intended audience

this document describes requirements for the API integration between ECKOH and GOV.UK Pay.

Security requirements

The integration with GOV.UK Pay will be via a new endpoint on the existing GOV.UK Pay Public API, and so this document should be read in conjunction with our public API documentation.

In particular the Security section outlines overal security requirements including secure handling of API tokens and PCI DSS compliance.

Overview of architectural components

Component Description
Worldpay payment gateway used to process payments on behalf of NHS BSA
ECKOH Payments IVR and integration with Worldpay
KCOM Call centre IVR
GOV.UK Pay integrated payment processing
NHS BSA delivering the end-user service

For each completed telephone payment transaction ECKOH will send a payment notification to GOV.UK Pay satisfying the following requirements:

  1. Encryption - Transmitted via HTTPS protocol with TLS1.2+ encryption

  2. Timeliness - Transmitted as soon as possible after the event occurs. Ideally in a few seconds or less.

  3. Authenticity - using OAuth 2 bearer token

  4. Retries - If the notification is not acknowledged via a successful 200 response then you must retry notification delivery for up to 72 hours.

  5. Configuration - API tokens are issued via GOV.UK Pay’s selfservice interface, NHSBSA will have access to this interface, and may choose to grant access to ECKOH staff by issuing user accounts.

Technical decisions agreed

  1. GOV.UK Pay does not require an HMAC signature for authentication. OAuth bearer token is sufficient

  2. Retries will be done individually on a per-payment basis

  3. processor_id will be populated with the 23 digit unique_reference_number generated by KCOM

  4. Worldpay Notifications - Eckoh do not expect to receive notifications from Worldpay; therefore worldpay notifications will be directed to GOV.UK Pay’s endpoint.

  5. auth_code corresponds to the AuthorisationId in the Worldpay auth response

  6. Payloads will be in JSON format with UTF8 character encoding

Points still awaiting confirmation

  1. The reference field is intended as the primary way for end-users and NHS BSA support staff to identify a payment, and will be used for online NHS BSA payments. We recommend that NHS BSA sets a reference for each payment which is passed to ECKOH and on to GOV.UK Pay.

  2. The description field is intended as a human-readable description of the payment. We recommend that NHS BSA sets a description for each payment which is passed to ECKOH and on to GOV.UK Pay.

  3. NHS BSA gateway configuration - we recommend Option 1 (Separate accounts)

  4. Transaction date - we imagine that there are a number of possible transaction dates which could be provided. For example:

  • date/time when the payment was initiated by NHS BSA
  • date/time when the call started
  • date/time when the payment was sent for authorisation
  • date/time when the payment was authorised
  • date/time when the payment was sent for capture

parties are to agree on the semantics of this date.

Features of GOV.UK Pay not available for telephone payments

  1. Email notifications GOV.UK Pay offers a feature to send email notifications about payments and refunds to users. For telephone payments this will not be possible unless we are provided with an email address for the user. If the NHS BSA wishes to use this feature they would need to pass an email address to ECKOH who would then propagate it to GOV.UK Pay via the email_address field.

NHS BSA Gateway configuration

NHS BSA will process payments via two channels:

  1. online using GOV.UK Pay

  2. by telephone using ECKOH, with payment information reported to GOV.UK Pay

There are several options for structuring accounts.

Option 1 - separate pay services

Channel GOV.UK Pay Service Worldpay merchant code
Online A MC1
Telphone B MC2

Each channel uses a separate pay service and a separate worldpay merchant code.

The advantage of this approach is that it allows separate access control for online transaction data and telephone payment transaction data.

Separate GOV.UK Pay API tokens will be required for each Service.

Transactions would be stored in separate ‘ledgers’ in GOV.UK Pay.

Option 2 - single Pay service

Channel GOV.UK Pay Service Worldpay merchant code
Online A MC1
Telphone A MC1

GOV.UK Pay manages access controls on a per-service basis, so in this scenario users with access to Pay’s selfservice interface would have access to payments via both channels.

Furthermore, API tokens issued here provide read and write access to transactions from both channels.

Assumption

Our assumption is that NHS BSA will use Option 1.

In both scenarios, notifications from Worldpay for BOTH online and telephone payments MUST be directed to GOV.UK Pay as per the instructions.

ECKOH have indicated that they do not need to receive worldpay notifications.

Configuration of GOV.UK Pay gateway accounts

Full details of the configuration process are covered in our documentation:

https://docs.payments.service.gov.uk/switching_to_live/set_up_a_live_worldpay_account/

Example payment flow

  1. End user calls call centre operated by KCOM, and requests a service which requires payment

  2. Call is transferred to ECKOH who receive the payment details and process the payment with Worldpay. Payment will be AUTHORISED and if successful, CAPTURE requested.

  3. ECKOH will make a [Payment Notification] call to GOV.UK Pay, containing transaction details and the status of the payment.

  4. GOV.UK Pay records the transaction details

  5. GOV.UK Pay receives a CAPTURED notification from Worldpay

Refunds

NHS BSA will be able to issue refunds of telephone payments via the GOV.UK Pay selfservice interface or GOV.UK Pay API.

Resource Group

Notifications

Payment notification
POST/v1/payment_notification

When we receive this call we expect the payment to be in one of three statuses:

  1. success - payment has been authorised successfully and sent for capture

  2. failed - error processing payment, further details in error_details

  3. declined - authorisation declined, further details in error_details

Retries will be processed idempotently.

GOV.UK Pay will respond with either a 200 or 201 status code to indicate a successfully received transaction.

  • 201 indicates a transaction not seen before

  • 200 indicates a transaction already seen (provider_id or processor_id seen before)

On receipt of a response outside of the 200-299 range, the notification MUST be retried.

Retries must continue at a maximum frequency of once per hour for up to 72 hours.

Other response codes possible are:

Code Meaning
200 OK
201 Created
401 Unauthorised - invalid API token
400 Bad request - unparsable, missing required fields, or invalid fields. See error_details
5xx Technical error. Request should be retried

Example URI

POST http://publicapi.payments.service.gov.uk//v1/payment_notification
Request
HideShow
Headers
Content-Type: application/json
Body
{
  "amount": 12000,
  "reference": "MRPC12345",
  "description": "New passport application",
  "transaction_date": "2018-02-21T16:04:25Z",
  "processor_id": "183f2j8923j8",
  "provider_id": "17498-8412u9-1273891239",
  "auth_code": "666",
  "payment_outcome": "success",
  "error_details": {
    "message": "only present if something went wrong",
    "code": "123"
  },
  "card_type": "master-card",
  "name_on_card": "Jane Doe",
  "email_address": "jane_doe@example.com",
  "card_expiry": "02/19",
  "last_four_digits": "1234",
  "first_six_digits": "654321"
}
Schema
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "amount": {
      "type": "number",
      "description": "the amount in pence"
    },
    "reference": {
      "type": "string",
      "description": "a reference code determined by you, max 255 chars, this may have been provided by the NHS service when they initiated the telephone payment"
    },
    "description": {
      "type": "string",
      "description": "human readable description, this may have been provided by the NHS service when they initiated the telephone payment"
    },
    "transaction_date": {
      "type": "string",
      "description": "ISO8601 including timezone"
    },
    "processor_id": {
      "type": "string",
      "description": " 23 digit `unique_reference_number` generated by KCOM"
    },
    "provider_id": {
      "type": "string",
      "description": "WorldPay `orderCode`"
    },
    "auth_code": {
      "type": "string",
      "description": "[Worldpay `AuthorisationId`](http://support.worldpay.com/support/kb/gg/corporate-gateway-guide/content/directintegration/paymentrequests.htm#ExampleAuth)"
    },
    "payment_outcome": {
      "type": "string",
      "enum": [
        "success",
        "failed",
        "declined"
      ]
    },
    "error_details": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string",
          "description": "human readable description of the error condition"
        },
        "code": {
          "type": "string",
          "description": "machine readable alpha-numeric code indicating the error condition. All error codes must be documented by ECKOH."
        }
      },
      "required": [
        "message",
        "code"
      ]
    },
    "card_type": {
      "type": "string",
      "enum": [
        "master-card",
        "visa",
        "maestro",
        "diners-club",
        "american-express"
      ]
    },
    "name_on_card": {
      "type": "string"
    },
    "email_address": {
      "type": "string"
    },
    "card_expiry": {
      "type": "string",
      "description": "card expiry date as MM/YY"
    },
    "last_four_digits": {
      "type": "string"
    },
    "first_six_digits": {
      "type": "string"
    }
  },
  "required": [
    "amount",
    "reference",
    "description",
    "processor_id",
    "provider_id",
    "payment_outcome",
    "card_type",
    "name_on_card",
    "card_expiry",
    "last_four_digits",
    "first_six_digits"
  ]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "amount": 12000,
  "reference": "MRPC12345",
  "description": "New passport application",
  "transaction_date": "2018-02-21T16:04:25Z",
  "processor_id": "183f2j8923j8",
  "provider_id": "17498-8412u9-1273891239",
  "auth_code": "666",
  "payment_outcome": "success",
  "error_details": {
    "message": "only present if something went wrong",
    "code": "123"
  },
  "card_type": "master-card",
  "name_on_card": "Jane Doe",
  "email_address": "jane_doe@example.com",
  "card_expiry": "02/19",
  "last_four_digits": "1234",
  "first_six_digits": "654321",
  "payment_id": "hu20sqlact5260q2nanm0q8u93"
}
Schema
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "amount": {
      "type": "number",
      "description": "the amount in pence"
    },
    "reference": {
      "type": "string",
      "description": "a reference code determined by you, max 255 chars, this may have been provided by the NHS service when they initiated the telephone payment"
    },
    "description": {
      "type": "string",
      "description": "human readable description, this may have been provided by the NHS service when they initiated the telephone payment"
    },
    "transaction_date": {
      "type": "string",
      "description": "ISO8601 including timezone"
    },
    "processor_id": {
      "type": "string",
      "description": " 23 digit `unique_reference_number` generated by KCOM"
    },
    "provider_id": {
      "type": "string",
      "description": "WorldPay `orderCode`"
    },
    "auth_code": {
      "type": "string",
      "description": "[Worldpay `AuthorisationId`](http://support.worldpay.com/support/kb/gg/corporate-gateway-guide/content/directintegration/paymentrequests.htm#ExampleAuth)"
    },
    "payment_outcome": {
      "type": "string",
      "enum": [
        "success",
        "failed",
        "declined"
      ]
    },
    "error_details": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string",
          "description": "human readable description of the error condition"
        },
        "code": {
          "type": "string",
          "description": "machine readable alpha-numeric code indicating the error condition. All error codes must be documented by ECKOH."
        }
      },
      "required": [
        "message",
        "code"
      ]
    },
    "card_type": {
      "type": "string",
      "enum": [
        "master-card",
        "visa",
        "maestro",
        "diners-club",
        "american-express"
      ]
    },
    "name_on_card": {
      "type": "string"
    },
    "email_address": {
      "type": "string"
    },
    "card_expiry": {
      "type": "string",
      "description": "card expiry date as MM/YY"
    },
    "last_four_digits": {
      "type": "string"
    },
    "first_six_digits": {
      "type": "string"
    },
    "payment_id": {
      "type": "string"
    }
  },
  "required": [
    "amount",
    "reference",
    "description",
    "processor_id",
    "provider_id",
    "payment_outcome",
    "card_type",
    "name_on_card",
    "card_expiry",
    "last_four_digits",
    "first_six_digits"
  ]
}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
  "amount": 12000,
  "reference": "MRPC12345",
  "description": "New passport application",
  "transaction_date": "2018-02-21T16:04:25Z",
  "processor_id": "183f2j8923j8",
  "provider_id": "17498-8412u9-1273891239",
  "auth_code": "666",
  "payment_outcome": "success",
  "error_details": {
    "message": "only present if something went wrong",
    "code": "123"
  },
  "card_type": "master-card",
  "name_on_card": "Jane Doe",
  "email_address": "jane_doe@example.com",
  "card_expiry": "02/19",
  "last_four_digits": "1234",
  "first_six_digits": "654321",
  "payment_id": "hu20sqlact5260q2nanm0q8u93"
}
Schema
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "amount": {
      "type": "number",
      "description": "the amount in pence"
    },
    "reference": {
      "type": "string",
      "description": "a reference code determined by you, max 255 chars, this may have been provided by the NHS service when they initiated the telephone payment"
    },
    "description": {
      "type": "string",
      "description": "human readable description, this may have been provided by the NHS service when they initiated the telephone payment"
    },
    "transaction_date": {
      "type": "string",
      "description": "ISO8601 including timezone"
    },
    "processor_id": {
      "type": "string",
      "description": " 23 digit `unique_reference_number` generated by KCOM"
    },
    "provider_id": {
      "type": "string",
      "description": "WorldPay `orderCode`"
    },
    "auth_code": {
      "type": "string",
      "description": "[Worldpay `AuthorisationId`](http://support.worldpay.com/support/kb/gg/corporate-gateway-guide/content/directintegration/paymentrequests.htm#ExampleAuth)"
    },
    "payment_outcome": {
      "type": "string",
      "enum": [
        "success",
        "failed",
        "declined"
      ]
    },
    "error_details": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string",
          "description": "human readable description of the error condition"
        },
        "code": {
          "type": "string",
          "description": "machine readable alpha-numeric code indicating the error condition. All error codes must be documented by ECKOH."
        }
      },
      "required": [
        "message",
        "code"
      ]
    },
    "card_type": {
      "type": "string",
      "enum": [
        "master-card",
        "visa",
        "maestro",
        "diners-club",
        "american-express"
      ]
    },
    "name_on_card": {
      "type": "string"
    },
    "email_address": {
      "type": "string"
    },
    "card_expiry": {
      "type": "string",
      "description": "card expiry date as MM/YY"
    },
    "last_four_digits": {
      "type": "string"
    },
    "first_six_digits": {
      "type": "string"
    },
    "payment_id": {
      "type": "string"
    }
  },
  "required": [
    "amount",
    "reference",
    "description",
    "processor_id",
    "provider_id",
    "payment_outcome",
    "card_type",
    "name_on_card",
    "card_expiry",
    "last_four_digits",
    "first_six_digits"
  ]
}
Response  401
HideShow
Headers
Content-Type: application/json
Body
+ Body - empty body
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "field": "amount",
  "code": "P0102",
  "description": "Invalid attribute value: amount. Must be less than or equal to 10000000"
}
Schema
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "field": {
      "type": "string",
      "description": "may specifiy which field is invalid"
    },
    "code": {
      "type": "string",
      "description": "as per https://docs.payments.service.gov.uk/api_reference/#http-status-codes"
    },
    "description": {
      "type": "string",
      "description": "human readable description of the error"
    }
  },
  "required": [
    "code",
    "description"
  ]
}

Generated by aglio on 26 Feb 2019