Skip to content
TilloTech Docs

ePay Processor and API

This page describes the ePay integration for operations and customer-service teams. It covers synchronous voucher issuance, manual and automatic cancellation, host and SKU selection, response validation, and the audit fields needed to investigate an order.

What ePay does

ePay is a synchronous digital voucher processor. The application sends one JSON request to a configured ePay host, maps the response into a card, and then creates the application delivery URL. The provider response calls the voucher code PINCREDENTIALS.PIN; this value is stored as the card code, while the application card PIN is empty.

PropertyBehaviour
Processor typeSKU per denomination or SKU per product, depending on brand configuration
ProcessingSynchronous request and response
DeliveryDigital voucher code with an application-generated delivery URL
Balance lookupUnsupported by the ePay processor; the shared synchronous default rejects it
CancellationSupported through manual CANCEL requests and automatic cancellation after a create-call failure
Issue success ruleResponse has a successful RESULT value and PINCREDENTIALS
Provider referenceHOSTTXID

Order lifecycle

  1. A partner requests an ePay brand, face value, currency, and digital delivery.
  2. The processor reads the brand host attribute and selects the matching host credentials and endpoint from config/epay.php.
  3. It resolves the product identifier. Fixed-denomination brands use epay-sku-<amount with two decimals>; open-value brands use epay-sku.
  4. It reads the partner attribute epaystoreid-<partner slug> for SHOPID.
  5. It sends a SALE request. Amounts are converted to minor units, currency is uppercased, and the partner client request ID is sent as TXID.
  6. A successful response must contain PINCREDENTIALS. HOSTTXID becomes the processor reference, PINCREDENTIALS.PIN becomes the voucher code, and the expiry is mapped from the configured brand expiry or provider VALIDTO.
  7. The application creates the delivery URL and records the successful ePay audit. A Wrappr failure after provider success is an error and must be investigated as a potentially issued voucher.
  8. A manual cancellation uses CANCEL with the original client request ID in TXREF. If the initial create call fails before a response is received, the processor attempts an automatic cancellation using a transaction ID suffixed with AC.

Example API order flow

The ePay client posts JSON to the selected host endpoint. Credentials are part of the JSON authorization object in this integration; the examples redact them. Values, product IDs, transaction IDs, and voucher data are illustrative.

Create a voucher

For a non-central host such as gb or rest_of_europe, the request includes MODE and PRODUCTID:

http
POST ${EPAY_ENDPOINTURI}
Accept: application/json
Content-Type: application/json;charset=utf-8

{
  "TYPE": "SALE",
  "AUTHORIZATION": {
    "USERNAME": "[REDACTED]",
    "PASSWORD": "[REDACTED]"
  },
  "TERMINALID": "[REDACTED]",
  "LOCALDATETIME": "2026-08-21 17:17:00",
  "TXID": "client-request-id-example",
  "AMOUNT": 10000,
  "CURRENCY": "GBP",
  "SHOPID": "[PARTNER SHOP ID]",
  "RECEIPT": {
    "LANGUAGE": "ENG"
  },
  "MODE": "DIRECT",
  "PRODUCTID": "product-sku-example"
}

For a central.* host, the processor sends the product identifier as CARD.EAN and does not add MODE or PRODUCTID:

json
{
  "TYPE": "SALE",
  "AUTHORIZATION": {
    "USERNAME": "[REDACTED]",
    "PASSWORD": "[REDACTED]"
  },
  "TERMINALID": "[REDACTED]",
  "LOCALDATETIME": "2026-08-21 17:17:00",
  "TXID": "client-request-id-example",
  "AMOUNT": 10000,
  "CURRENCY": "EUR",
  "SHOPID": "[PARTNER SHOP ID]",
  "RECEIPT": {
    "LANGUAGE": "ENG"
  },
  "CARD": {
    "EAN": "product-sku-example"
  }
}

A redacted successful response has this relevant shape:

json
{
  "AMOUNT": 10000,
  "CURRENCY": "GBP",
  "HOSTTXID": "epay-reference-example",
  "MODE": "DIRECT",
  "PINCREDENTIALS": {
    "PIN": "[REDACTED VOUCHER CODE]",
    "SERIAL": "[REDACTED SERIAL]",
    "VALIDTO": "2027-08-21T00:00:00.000Z"
  },
  "RESULT": 0,
  "RESULTTEXT": "OK",
  "SERVERDATETIME": "2026-08-21 17:17:01",
  "TERMINALID": "[REDACTED]",
  "TXID": "provider-transaction-example",
  "TXNERROR": 0,
  "TYPE": "SALE"
}

Cancel a voucher

Manual cancellation uses TYPE: CANCEL, MODE: MANUAL, and a TXREF containing the original client transaction ID. The serial number from the saved issue response is compared with the cancellation response when PINCREDENTIALS is present.

json
{
  "TYPE": "CANCEL",
  "AUTHORIZATION": {
    "USERNAME": "[REDACTED]",
    "PASSWORD": "[REDACTED]"
  },
  "TERMINALID": "[REDACTED]",
  "LOCALDATETIME": "2026-08-21 17:18:00",
  "TXID": "cancellation-request-id-example",
  "AMOUNT": 10000,
  "CURRENCY": "GBP",
  "SHOPID": "[PARTNER SHOP ID]",
  "RECEIPT": {
    "LANGUAGE": "ENG"
  },
  "MODE": "MANUAL",
  "PRODUCTID": "product-sku-example",
  "TXREF": {
    "TYPE": "CLIENT",
    "Value": "original-client-request-id-example"
  }
}

Automatic cancellation uses the same TXREF type, sets MODE: AUTOMATIC, and appends AC to the original transaction ID. It is an internal recovery request, not a second customer order.

Response mapping and validation

The processor treats a response as unsuccessful when RESULT is present and is not 0. Empty responses and transport errors are also failures. For an issue response, PINCREDENTIALS must exist; otherwise the sale is not completed.

Provider dataApplication result
RESULT: 0Successful provider result check
Non-zero RESULTePay error containing RESULT and RESULTTEXT; no card is completed
Missing or empty responseePay error; no card is completed
Missing PINCREDENTIALS on SALEePay error even when another response field is present
HOSTTXIDprocessor_reference
PINCREDENTIALS.PINCard code; it is not copied into the application PIN field
PINCREDENTIALS.SERIALReturned only when the brand returnSerialNumber attribute is truthy; used for cancellation comparison when available
Provider VALIDTOExpiration fallback unless it is the sentinel 3000-01-01... value
Brand expiry_monthsPreferred application expiry when configured
Cancellation PINCREDENTIALS.SERIALMust match the saved issue serial when the response includes it
Cancellation AMOUNTDivided by 100 for the returned cancellation card face value

Receipt arrays, server timestamps, and other response fields are retained in the raw audit response but do not by themselves establish voucher completion. The application-generated URL is created after the ePay card has been mapped; a failure in that later URL step leaves a provider-issued voucher requiring manual cancellation review.

Provider states and retry behaviour

ePay does not expose a status-polling flow in this processor. The outcome is determined by the one synchronous response or by a cancellation response.

ConditionProcessor resultOperational consequence
HTTP response 200 with successful provider result and issue credentialsSuccessVoucher code and processor reference are available
Non-zero RESULT or missing issue credentialsProcessor errorDo not issue a replacement until the original transaction and audit are checked
Transport/connection failure before a response is received for SALEAutomatic cancellation is attemptedCheck both the failed sale audit and automatic cancellation evidence
Response received but parsing or URL generation failsError; automatic cancellation is not triggered by the create-response guardTreat the voucher as potentially issued and arrange cancellation review
Cancellation response has a mismatched serialErrorDo not regard the cancellation as confirmed
Cancellation message contains PRODUCT ALREADY USEDWarning-level cancellation errorEscalate with the original serial and redacted audits; the code treats this as a warning, not success
Request timeoutExternal service-unavailable errorCheck ePay outcome before retrying because the provider may have processed the sale

There is no general idempotency key separate from the ePay TXID in the processor. The sale client request ID is used as the issue transaction ID, while an automatic cancellation uses the original ID plus AC. A manual re-order after an uncertain network result can create a duplicate voucher; compare the original transaction first.

Audit comparison fields

ePay stores the legacy AuditEpay record and also writes processor interaction request/response entries keyed by the sale record UUID. Compare:

  1. AuditEpay.clientRequestID, partnerID, transactionTime, status, and errorMessage.
  2. The request fields TYPE, MODE, TXID, TXREF, AMOUNT, CURRENCY, SHOPID, the selected product field, and host endpoint. Never expose AUTHORIZATION values.
  3. The response fields RESULT, RESULTTEXT, TYPE, HOSTTXID, TXID, AMOUNT, CURRENCY, and provider date/time fields.
  4. For issue, compare HOSTTXID with the card processor reference and compare the saved serial with any later cancellation serial without copying either credential into a ticket.
  5. For manual cancellation, confirm the cancellation TXREF.Value points to the original client request ID and that MODE is MANUAL.
  6. For automatic cancellation, look for the AC transaction ID, MODE: AUTOMATIC, and the original issue transaction in TXREF.
  7. Confirm the audit sequence: issue request, issue response, any automatic cancellation request/response, and any later manual cancellation request/response. A successful provider issue followed by a failed application URL generation is not the same as a provider rejection.

The AuditEpay table contains requestParams, responseParams, raw request and response, requestID, gcClaimCodeHash, and the status values REQUESTED, SUCCESS, or ERROR. Interaction audit content is encrypted at rest and supports redaction when read through the audit model.

Settings

Processor settings

The host configuration is read from config/epay.php. Each host entry supplies credentials and an endpoint:

Host valueConfiguration pathEnvironment variables
gbepay.hosts.gbEPAY_USERNAME, EPAY_PASSWORD, EPAY_TERMINALID, EPAY_ENDPOINTURI
rest_of_europeepay.hosts.rest_of_europeEPAY_USERNAME_ROE, EPAY_PASSWORD_ROE, EPAY_TERMINALID_ROE, EPAY_ENDPOINTURI_ROE
central.france, central.italy, central.spain, central.germany, central.denmark, central.sweden, central.norway, central.finland, central.belgium, central.netherlands, central.austria, central.luxembourg, central.switzerland, central.portugalepay.hosts.central.<country>Country-specific EPAY_USERNAME_CENTRAL_* and EPAY_TERMINALID_CENTRAL_* values, with EPAY_ENDPOINTURI_CENTRAL for the endpoint

The request timeout is fixed in EpayProcessor at 20.0 seconds. The provider credentials are sent in the JSON AUTHORIZATION object. No live endpoint, credential, terminal ID, or shop ID should be copied into operational documentation or tickets.

Brand settings

The host brand attribute is required and selects the host configuration. Supported values are gb, rest_of_europe, and the listed central.<country> values. A missing host produces a configuration error.

Product mappings follow the brand's denomination model:

Brand modelAttribute used by the processorRequest field
Fixed denominationsepay-sku-<face value with two decimals>, for example epay-sku-123.00PRODUCTID for non-central hosts or CARD.EAN for central hosts
Open valueepay-skuPRODUCTID for non-central hosts or CARD.EAN for central hosts

The partner must have epaystoreid-<partner slug> as a partner attribute for SHOPID. Missing product or shop mappings stop request construction. The optional returnSerialNumber brand attribute controls whether the serial is included in the returned application card; its default behavior is false.

The checked-in onboarding migration includes host assignments for brands such as itunes-de, itunes-fr, just-eat-ie, Nintendo country variants, share-now-de, share-now-it, and Xbox country variants. It also records product identifiers for brands including itunes, google-play, just-eat, digiigifts, and YouChoose variants. These migration values are onboarding history, not a substitute for checking the current brand attributes.

API operations

OperationInternal serviceProvider requestUse
IssueePayCreateGCTYPE: SALESynchronously issue a voucher
Manual cancellationePayCancelGCTYPE: CANCEL, MODE: MANUALCancel an existing issue using TXREF
Automatic cancellationePayCancelAutomaticTYPE: CANCEL, MODE: AUTOMATICRecovery attempt after a create-call failure

No ePay catalogue, balance, or status-retrieval operation is defined in the inspected processor/client code. ePay uses the issue response itself rather than a separate retrieval call.

Customer-service investigation

For a failed, uncertain, or cancellation-related order:

  1. Confirm the sale UUID, client request ID, partner slug, brand slug, denomination, currency, and the requested transaction type.
  2. Confirm the current brand host, fixed/open denomination flag, matching epay-sku-* or epay-sku, and partner epaystoreid-<partner slug> attribute.
  3. Locate the AuditEpay record by clientRequestID and partner ID. Compare its status, error message, request/response, and transaction time.
  4. In the redacted interaction audit, verify the endpoint family and compare TYPE, MODE, TXID, TXREF, AMOUNT, CURRENCY, and product field. Never include the authorization object in an escalation.
  5. If ePay returned HOSTTXID or issue credentials, treat the voucher as potentially issued even if the application URL failed. Check for an automatic cancellation attempt before considering a manual cancellation.
  6. For cancellation, compare the original response serial with the cancellation response serial, and verify RESULT: 0, TYPE: CANCEL, and the expected TXREF.
  7. Do not manually re-order after a timeout, connection failure, or malformed response until the original TXID and any automatic cancellation audit have been reviewed.

Limitations and support contacts

The ePay integration supports issue and cancellation only. Balance lookup, provider catalogue retrieval, and a separate order-status retrieval operation are not implemented here. The codebase does not define an ePay-specific technical or support contact in the inspected config, migrations, or tests; use the established internal escalation route when the redacted audit comparison is inconclusive.

Escalations should include the internal sale UUID, client request ID, partner ID/slug, brand and host value, processor reference if present, transaction times, sanitized result code/text, and the ordered audit sequence. Do not include passwords, authorization headers, voucher codes, serial numbers, full shop IDs, or live card data.

  • app/Processors/EpayProcessor.php — synchronous issue, cancellation, request construction, response mapping, timeout handling, and automatic cancellation.
  • app/AuditEpay.php — legacy ePay audit model and stored fields.
  • app/ProcessorInteractionAuditLog.php — encrypted processor request/response interaction records.
  • config/epay.php — host, endpoint, credential, and terminal configuration.
  • app/DataIssuer.php — ePay additional brand attributes and SKU format.
  • database/migrations/2017_05_22_091328_create_audit_epay.php — ePay audit schema and issuer creation.
  • database/migrations/2019_08_13_145053_RCC-5187_move_epay_store_id_to_partner_attribute.php — partner shop-ID migration.
  • database/migrations/2024_06_26_074902_rcc-11795_epay-sku-configuration.php — host, serial-return, and product-ID onboarding mappings.
  • database/migrations/2024_10_07_134754_r_c_c-15073-correct-bad-epay-skus-and-convert-to-new-format-fixed-denom.php — fixed-denomination SKU attribute format.
  • database/migrations/2024_10_08_153937_r_c_c-15073-convert-open-value-epay-sku-attribute-names-to-new-format.php — open-value epay-sku attribute format.
  • tests/Unit/Processors/EpayProcessorTest.php — issue, cancellation, host selection, SKU mapping, expiry, serial-return, audit, and transport scenarios.