GOV.UK Pay Telephone Payments reporting
Document status
Date | Author | Comment |
---|---|---|
12/6/19 | David Heath | Add optional telephone number to notification payload |
12/6/19 | David Heath | Add notes of decisions made 27/3 (reference, description and date semantics) |
5/6/19 | David Heath | return GOV.UK Pay status from notification endpoint, changes to payment_outcome structure. Idempotency based on provider_id . Add 422 HTTP response code. |
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 ECKOH -
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
-
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. NHS BSA will set a reference for each payment which will be passed to ECKOH and on to GOV.UK Pay -
The
description
field is intended as a human-readable description of the payment. NHS BSA will set a description for each payment which is passed to ECKOH and on to GOV.UK Pay. -
Transaction date - GOV.UK Pay will accept two optional fields with the notification payload:
created_date
- date/time when the payment was initiated by NHS BSAauthorised_date
- date/time when the payment was authorised by Worldpay
Points still awaiting confirmation
- NHS BSA gateway configuration - we recommend Option 1 (Separate accounts)
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, indicated in the payment_outcome
:
-
status
success
- payment has been authorised successfully and sent for capture -
status
failed
, codeP0050
- error processing payment, further details insupplemental
-
status
failed
, codeP0010
- authorisation declined
Retries will be processed idempotently, keyed by provider_id
.
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
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. Details are in the response body json. |
422 | Unprocessable entity - unparsable, missing required fields, or invalid fields. Details are in the response body json. |
5xx | Technical error. Request should be retried |
Example URI
Headers
Content-Type: application/json
Body
{
"amount": 12000,
"reference": "MRPC12345",
"description": "New passport application",
"created_date": "2018-02-21T16:04:25Z",
"authorised_date": "2018-02-21T16:05:33Z",
"processor_id": "183f2j8923j8",
"provider_id": "17498-8412u9-1273891239",
"auth_code": "666",
"payment_outcome": {
"status": "success",
"code": "P0010",
"supplemental": {
"error_code": "ECKOH01234",
"error_message": "textual message describing error code"
}
},
"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",
"telephone_number": "+447700900796"
}
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"
},
"created_date": {
"type": "string",
"description": "date/time when the payment was initiated by NHS BSA - ISO8601 including timezone"
},
"authorised_date": {
"type": "string",
"description": "date/time when the payment was authorised by Worldpay - ISO8601 including timezone"
},
"processor_id": {
"type": "string",
"description": "Unique Eckoh Reference generated by Eckoh"
},
"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": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"failed"
]
},
"code": {
"type": "string",
"enum": [
"P0010",
"P0030",
"P0050"
],
"description": "explanatory error code. For status `failed` a code is required"
},
"supplemental": {
"type": "object",
"properties": {
"error_code": {
"type": "string",
"description": "a code indicating the error reason. This will be persisted in a GOV.UK Pay custom metadata field named `notification_error_code`."
},
"error_message": {
"type": "string",
"description": "human readable message describing the error. This will be persisted in a GOV.UK Pay custom metadata field named `notification_error_message`"
}
},
"description": "optional additional details about the error or failure. These fields are stored as [custom metadata](https://docs.payments.service.gov.uk/optional_features/custom_metadata/#adding-custom-metadata) in GOV.UK Pay, so they would be visible in the selfservice interface and reporting"
}
},
"required": [
"status"
]
},
"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"
},
"telephone_number": {
"type": "string",
"description": "caller's phone number (stored as metadata field in GOV.UK Pay)"
}
},
"required": [
"amount",
"reference",
"description",
"processor_id",
"provider_id",
"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",
"created_date": "2018-02-21T16:04:25Z",
"authorised_date": "2018-02-21T16:05:33Z",
"processor_id": "183f2j8923j8",
"provider_id": "17498-8412u9-1273891239",
"auth_code": "666",
"payment_outcome": {
"status": "success",
"code": "P0010",
"supplemental": {
"error_code": "ECKOH01234",
"error_message": "textual message describing error code"
}
},
"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",
"telephone_number": "+447700900796",
"payment_id": "hu20sqlact5260q2nanm0q8u93",
"state": {
"status": "success",
"finished": true,
"message": "Hello, world!",
"code": "P0010"
}
}
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"
},
"created_date": {
"type": "string",
"description": "date/time when the payment was initiated by NHS BSA - ISO8601 including timezone"
},
"authorised_date": {
"type": "string",
"description": "date/time when the payment was authorised by Worldpay - ISO8601 including timezone"
},
"processor_id": {
"type": "string",
"description": "Unique Eckoh Reference generated by Eckoh"
},
"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": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"failed"
]
},
"code": {
"type": "string",
"enum": [
"P0010",
"P0030",
"P0050"
],
"description": "explanatory error code. For status `failed` a code is required"
},
"supplemental": {
"type": "object",
"properties": {
"error_code": {
"type": "string",
"description": "a code indicating the error reason. This will be persisted in a GOV.UK Pay custom metadata field named `notification_error_code`."
},
"error_message": {
"type": "string",
"description": "human readable message describing the error. This will be persisted in a GOV.UK Pay custom metadata field named `notification_error_message`"
}
},
"description": "optional additional details about the error or failure. These fields are stored as [custom metadata](https://docs.payments.service.gov.uk/optional_features/custom_metadata/#adding-custom-metadata) in GOV.UK Pay, so they would be visible in the selfservice interface and reporting"
}
},
"required": [
"status"
]
},
"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"
},
"telephone_number": {
"type": "string",
"description": "caller's phone number (stored as metadata field in GOV.UK Pay)"
},
"payment_id": {
"type": "string"
},
"state": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "the [GOV.UK Pay state](https://docs.payments.service.gov.uk/api_reference/#payment-status-lifecycle) that has been recorded,"
},
"finished": {
"type": "boolean",
"description": "indicating whether this is a terminal state"
},
"message": {
"type": "string",
"description": "human readable description of the error condition based on [GOV.UK Pay's status codes `P00xx`](https://docs.payments.service.gov.uk/api_reference/#errors-caused-by-payment-statuses)"
},
"code": {
"type": "string",
"description": "[GOV.UK Pay error code](https://docs.payments.service.gov.uk/api_reference/#errors-caused-by-payment-statuses) indicating the error condition."
}
},
"required": [
"status",
"finished"
],
"description": "https://govukpay-api-browser.cloudapps.digital/#tocspaymentstate"
}
},
"required": [
"amount",
"reference",
"description",
"processor_id",
"provider_id",
"card_type",
"name_on_card",
"card_expiry",
"last_four_digits",
"first_six_digits",
"payment_id",
"state"
]
}
201
Headers
Content-Type: application/json
Body
{
"amount": 12000,
"reference": "MRPC12345",
"description": "New passport application",
"created_date": "2018-02-21T16:04:25Z",
"authorised_date": "2018-02-21T16:05:33Z",
"processor_id": "183f2j8923j8",
"provider_id": "17498-8412u9-1273891239",
"auth_code": "666",
"payment_outcome": {
"status": "success",
"code": "P0010",
"supplemental": {
"error_code": "ECKOH01234",
"error_message": "textual message describing error code"
}
},
"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",
"telephone_number": "+447700900796",
"payment_id": "hu20sqlact5260q2nanm0q8u93",
"state": {
"status": "success",
"finished": true,
"message": "Hello, world!",
"code": "P0010"
}
}
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"
},
"created_date": {
"type": "string",
"description": "date/time when the payment was initiated by NHS BSA - ISO8601 including timezone"
},
"authorised_date": {
"type": "string",
"description": "date/time when the payment was authorised by Worldpay - ISO8601 including timezone"
},
"processor_id": {
"type": "string",
"description": "Unique Eckoh Reference generated by Eckoh"
},
"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": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"failed"
]
},
"code": {
"type": "string",
"enum": [
"P0010",
"P0030",
"P0050"
],
"description": "explanatory error code. For status `failed` a code is required"
},
"supplemental": {
"type": "object",
"properties": {
"error_code": {
"type": "string",
"description": "a code indicating the error reason. This will be persisted in a GOV.UK Pay custom metadata field named `notification_error_code`."
},
"error_message": {
"type": "string",
"description": "human readable message describing the error. This will be persisted in a GOV.UK Pay custom metadata field named `notification_error_message`"
}
},
"description": "optional additional details about the error or failure. These fields are stored as [custom metadata](https://docs.payments.service.gov.uk/optional_features/custom_metadata/#adding-custom-metadata) in GOV.UK Pay, so they would be visible in the selfservice interface and reporting"
}
},
"required": [
"status"
]
},
"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"
},
"telephone_number": {
"type": "string",
"description": "caller's phone number (stored as metadata field in GOV.UK Pay)"
},
"payment_id": {
"type": "string"
},
"state": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "the [GOV.UK Pay state](https://docs.payments.service.gov.uk/api_reference/#payment-status-lifecycle) that has been recorded,"
},
"finished": {
"type": "boolean",
"description": "indicating whether this is a terminal state"
},
"message": {
"type": "string",
"description": "human readable description of the error condition based on [GOV.UK Pay's status codes `P00xx`](https://docs.payments.service.gov.uk/api_reference/#errors-caused-by-payment-statuses)"
},
"code": {
"type": "string",
"description": "[GOV.UK Pay error code](https://docs.payments.service.gov.uk/api_reference/#errors-caused-by-payment-statuses) indicating the error condition."
}
},
"required": [
"status",
"finished"
],
"description": "https://govukpay-api-browser.cloudapps.digital/#tocspaymentstate"
}
},
"required": [
"amount",
"reference",
"description",
"processor_id",
"provider_id",
"card_type",
"name_on_card",
"card_expiry",
"last_four_digits",
"first_six_digits",
"payment_id",
"state"
]
}
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"
]
}
422
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"
]
}