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:
-
Encryption - Transmitted via HTTPS protocol with TLS1.2+ encryption
-
Timeliness - Transmitted as soon as possible after the event occurs. Ideally in a few seconds or less.
-
Authenticity - using OAuth 2 bearer token
-
Retries - If the notification is not acknowledged via a successful 200 response then you must retry notification delivery for up to 72 hours.
-
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
-
GOV.UK Pay does not require an HMAC signature for authentication. OAuth bearer token is sufficient
-
Retries will be done individually on a per-payment basis
-
processor_id
will be populated with the 23 digitunique_reference_number
generated by KCOM -
Worldpay Notifications - Eckoh do not expect to receive notifications from Worldpay; therefore worldpay notifications will be directed to GOV.UK Pay’s endpoint.
-
auth_code
corresponds to theAuthorisationId
in the Worldpay auth response -
Payloads will be in JSON format with UTF8 character encoding
Points still awaiting confirmation
-
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. -
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. -
NHS BSA gateway configuration - we recommend Option 1 (Separate accounts)
-
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
- 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:
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
-
End user calls call centre operated by KCOM, and requests a service which requires payment
-
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.
-
ECKOH will make a [Payment Notification] call to GOV.UK Pay, containing transaction details and the status of the payment.
-
GOV.UK Pay records the transaction details
-
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 notificationPOST/v1/payment_notification
When we receive this call we expect the payment to be in one of three statuses:
-
success
- payment has been authorised successfully and sent for capture -
failed
- error processing payment, further details inerror_details
-
declined
- authorisation declined, further details inerror_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
orprocessor_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
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"
]
}
200
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"
]
}
201
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"
]
}
401
Headers
Content-Type: application/json
Body
+ Body - empty body
400
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"
]
}