Hosted Payment Pages Integration
A clear, step-by-step guide to integrating the Gateway's Hosted Integration. It is a condensed, developer-friendly companion to the official guide at https://guides.gitbook.io/integrationguide (V4.21). Where this document simplifies something, the official guide remains the source of truth.
In one sentence: you build a set of fields, sign them, and POST them from the customer's browser to the Gateway; the Gateway shows its payment page, takes the payment (card, Apple Pay, Google Pay, etc.), then sends the customer's browser back to your site with the result — and your server never touches card data.
1. Choosing the right integration method
The Gateway offers three integration methods. Choose Hosted unless you have a specific reason not to.
| Method | Who collects card data | PCI scope | Use when |
|---|---|---|---|
| Hosted | The Gateway (on its Hosted Payment Page) | Lowest — your server needs no SSL certificate and the lowest level of PCI DSS | You want the fastest, safest integration and don't want to handle card data. |
| Direct | You, on your own secure server | Higher — needs SSL + higher PCI DSS, validated annually | You need the customer to stay entirely on your own pages. |
| Batch | You (queued; no customer interaction) | Higher | Bulk/recurring charges. Cannot do 3-D Secure or interactive wallet/checkout pages. |
A middle option, Hosted Payment Fields, lets you build your own form while the sensitive inputs stay hosted by the Gateway — same low PCI scope as Hosted, full control of layout. See §14.3.
PCI note (verified): with Hosted Payment Pages, because the card data is entered on the Gateway's page and never reaches your server, your web server does not need an SSL certificate and you qualify for the lowest level of PCI DSS compliance. (You will still serve your own site over HTTPS in practice, and the Gateway endpoint itself is always HTTPS — see §7.) Transaction and card data are retained for approximately 13 months; your acquirer may differ.
2. How much work is this?
For a basic card sale with a developer who already has the credentials: roughly half a day to two days. Most of that time goes on getting the signature right and handling the callback correctly. Using the official server-side SDK (§14.1) removes most of the manual work because it signs requests and verifies responses for you.
Wallets (Apple Pay / Google Pay) add no extra build time if they're boarded on your merchant account — see §12.
3. Prerequisites
You'll be given these during onboarding (production and test sets):
| Item | Notes |
|---|---|
Merchant Account ID (merchantID) | Identifies the merchant account each request is for. Samples in the docs use 100001. |
| Hosted Integration URL | The endpoint your form POSTs to. Use the exact URL provided — it may be customised to your account. Docs use the dummy form https://gateway.example.com/<integration>. Always HTTPS. |
| Signing secret | Set per merchant account in the Merchant Management System (MMS). Used to sign requests (strongly recommended; may be mandatory). |
Replace all dummy values (100001, gateway.example.com) with the real values you were
given. Test accounts connect to the Gateway's Simulator, not a real acquirer — see
§15.
4. The payment flow
Your site (browser) Gateway (HPP) Your server
──────────────────────────────────────────────────────────────────────────
1. Build + sign fields
2. POST form ────────────────▶ 3. Show Hosted Payment Page
(card / Apple Pay / Google Pay / APMs)
4. Customer pays; 3-D Secure if needed
5. Gateway processes the payment
7. Browser returns ◀─── 6a. Redirect (HTTP POST) to redirectURL
to redirectURL with
the response fields
6b. (optional) POST a copy to callbackURL ─▶ 8. Verify + fulfil order
9. Show confirmation page
Two separate things come back after payment:
redirectURL— the customer's browser is sent here (HTTP POST). Use it to show a result page.callbackURL— an independent server-to-server copy of the result. Use it to update your systems / fulfil the order.
Why both? The customer can close their browser before the redirect fires, so you may never receive the
redirectURLPOST. The Gateway explicitly recommends usingredirectURLfor a confirmation page only, andcallbackURLto update your backend. Fulfil from the callback, not the redirect. This is the single most common integration mistake.
5. Step 1 — Build the request
Requests are name/value pairs, URL-encoded as application/x-www-form-urlencoded. For the
Hosted Integration the request is sent from the browser (see §7),
so it's normally a set of hidden form fields.
5.1 Actions supported by the Hosted Integration
The Hosted Integration only supports the basic payment actions. This is a common point of confusion:
action | Supported on Hosted? | What it does |
|---|---|---|
SALE | Yes | Authorises and (unless delayed) captures a payment. |
VERIFY | Yes | Checks the card account exists; no funds moved/held; amount must be 0. |
PREAUTH | Yes | Seeks authorisation then immediately voids it to check validity/funds. The docs recommend VERIFY instead where the acquirer supports it. |
REFUND, REFUND_SALE, CAPTURE, CANCEL, QUERY | No | These are not supported on Hosted — use the Direct/Batch Integration or the MMS for refunds, captures, cancellations and lookups. |
So a normal checkout uses SALE.
5.2 Core fields for a card SALE
| Field | Required | Example | Description |
|---|---|---|---|
merchantID | Yes | 100001 | Your Merchant Account ID. |
action | Yes | SALE | See §5.1. |
amount | Yes | 1099 | Minor units (1099 = £10.99) or major units with a decimal (10.99). For VERIFY it must be 0. |
type | Yes | 1 | 1 = E-commerce (ECOM), 2 = MOTO / Card-Not-Present, 9 = Continuous Authority. Online checkout = 1. |
currencyCode | Yes | 826 | ISO-4217 — 3-letter (GBP) or 3-digit (826). |
countryCode | Yes | 826 | ISO-3166-1 — 2/3-letter (GB/GBR) or 3-digit (826). |
redirectURL | Yes | https://yoursite.com/payment/return | Fully-qualified URL the browser returns to. Mandatory for Hosted. |
signature | Yes¹ | (computed) | Hash of the request + your secret — see §6. |
transactionUnique | Recommended | (unique id) | Your own unique ID for this attempt; aids duplicate detection and anti-spoofing. |
orderRef | Optional | Order 1234 | Free-text reference stored with the transaction. |
callbackURL | Recommended | https://yoursite.com/api/payment/callback | Server endpoint that receives a copy of the result. |
¹ A signature may be mandatory on your account; if so, MMS lets you change the secret but
not remove it. A merchantPwd field exists but is discouraged on Hosted (it would be
visible in the browser) — use signing instead.
Hosted-specific behaviour (verified):
- You don't send card fields.
cardNumber,cardExpiryMonth/Year,cardCVVare collected on the HPP. If you do send a card value it is only used to pre-fill the corresponding HPP input (and you should only do that if you're PCI-compliant to handle it). - Don't send
deviceIpAddress— the Hosted Integration uses the customer's IP automatically. - The Gateway may add new request/response fields at any time. Don't send fields that might clash with future Gateway fields, and ignore any response fields you don't recognise.
5.3 Field formats
| Type | Format |
|---|---|
| Monetary amounts | Minor units (1099) or major units with one decimal (10.99). |
| Currency codes | ISO-4217 — GBP or 826. |
| Country codes | ISO-3166-1 — GB, GBR, or 826. |
| Dates / timestamps | YYYY-MM-DD / YYYY-MM-DD HH:MM:SS. |
| Records / arrays | field[sub] notation; arrays use numeric sub-keys from 0 (e.g. items[0][amount]). Booleans as the words true/false. |
Field names are case-sensitive and alphanumeric; root names can't start with a digit. There's a practical limit of ~200 request parameters (255 hard limit, leaving room for response fields).
6. Step 2 — Sign the request
When a signing secret is configured, every request must include a signature. The Gateway
recomputes the hash and rejects the request if it doesn't match — proving the data wasn't
altered in the browser. The Gateway also signs its response, so you can verify what comes
back. If signing is enabled, callback data is signed too.
Algorithm (exactly as the Gateway does it):
- Take all request fields except
signature. - Sort them by field name (
ksort— top-level keys only; record sub-fields keep their order). - URL-encode into a query string (PHP
http_build_query,&separator). - Normalise all line endings in that string to
%0A(replace%0D%0A,%0A%0D,%0A,%0D→%0A). - Append your secret and hash with SHA-512.
- If you use a non-default algorithm, prefix the hex digest with
{ALGO}(e.g.{SHA256}…). For SHA-512, no prefix.
Reference implementation (PHP — canonical, from the guide):
<?php
function createSignature(array $data, string $key, ?string $algo = null): string {
if ($algo === null) {
$algo = 'SHA512';
}
ksort($data);
// URL-encode the sorted fields
$ret = http_build_query($data, '', '&');
// Normalise all line endings (CRNL|NLCR|NL|CR) to just NL (%0A)
$ret = preg_replace('/%0D%0A|%0A%0D|%0A|%0D/i', '%0A', $ret);
// Hash the signature string and the key together
$ret = hash($algo, $ret . $key);
// Prefix the algorithm if not the default
if ($algo !== 'SHA512') {
$ret = '{' . $algo . '}' . $ret;
}
return $ret;
}
Node.js / TypeScript version (for a Next.js backend). The critical requirement is that
your query string is byte-for-byte identical to PHP's http_build_query, or the hash
won't match:
import crypto from "crypto";
// Mirror PHP http_build_query (RFC 1738): spaces -> '+', and encode the
// reserved characters PHP encodes that encodeURIComponent leaves alone.
function phpRawEncode(s: string): string {
return encodeURIComponent(s)
.replace(/%20/g, "+")
.replace(/[!'()*~]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
}
function httpBuildQuery(params: Record<string, unknown>): string {
const parts: string[] = [];
const add = (key: string, val: unknown) => {
if (val === null || val === undefined) return;
if (typeof val === "object") {
// Records: PHP does NOT sort sub-fields — keep insertion order.
for (const k of Object.keys(val as object)) {
add(`${key}[${k}]`, (val as Record<string, unknown>)[k]);
}
} else {
parts.push(`${phpRawEncode(key)}=${phpRawEncode(String(val))}`);
}
};
for (const k of Object.keys(params).sort()) add(k, params[k]); // ksort: top level only
return parts.join("&");
}
export function createSignature(
data: Record<string, unknown>,
key: string,
algo: "SHA512" | "SHA256" = "SHA512"
): string {
let str = httpBuildQuery(data).replace(/%0D%0A|%0A%0D|%0A|%0D/gi, "%0A");
const hash = crypto.createHash(algo.toLowerCase()).update(str + key).digest("hex");
return algo === "SHA512" ? hash : `{${algo}}${hash}`;
}
Verify the Node version once against a known-good PHP output or the official SDK before trusting it. Subtle differences in
+,~,*,(,)encoding are the usual cause of "signature mismatch" (Gateway code 65539). For nested fields (e.g. anitems[]basket), prefer the official SDK (§14.1), whose encoding is guaranteed to match.
7. Step 3 — Send the customer to the HPP
The request must be sent from the customer's browser, because the response is the HTML payment page. The simplest method is an auto-submitting form of hidden fields — the browser handles the encoding.
<?php
$gatewayUrl = 'https://YOUR-GATEWAY-HOST/hosted/'; // exact URL from onboarding (HTTPS)
$signatureKey = 'YOUR_SIGNATURE_SECRET'; // from MMS
$fields = [
'merchantID' => '100001',
'action' => 'SALE',
'type' => 1,
'amount' => 1099,
'currencyCode' => 'GBP',
'countryCode' => 'GB',
'transactionUnique' => bin2hex(random_bytes(16)),
'orderRef' => 'Order 1234',
'redirectURL' => 'https://yoursite.com/payment/return',
'callbackURL' => 'https://yoursite.com/api/payment/callback',
];
$fields['signature'] = createSignature($fields, $signatureKey);
?>
<form id="pay" action="<?= htmlspecialchars($gatewayUrl) ?>" method="post">
<?php foreach ($fields as $name => $value): ?>
<input type="hidden" name="<?= htmlspecialchars($name) ?>"
value="<?= htmlspecialchars($value) ?>">
<?php endforeach; ?>
<noscript><button type="submit">Pay now</button></noscript>
</form>
<script>document.getElementById('pay').submit();</script>
Next.js note: build and sign the fields on the server (Route Handler / Server Action) so the signing secret never reaches the client, then return the hidden-field form to the page and auto-submit it. Don't fetch the Gateway URL server-side and proxy the HTML — the customer's browser must load the HPP.
Full page vs lightbox (verified): the plain redirect form above opens the HPP as a new
browser page. To show it as a lightbox/modal overlay on top of your site, use the
Hosted Payment Page Library
(§14.2) or point the form
action at a modal URL. The page is styled with your logo and colours in MMS; fully
customised full-page or iframe pages can be arranged separately.
HTTPS: the Gateway endpoint is HTTPS only — HTTP is not supported and is not redirected.
8. Step 4 — Read the result (redirectURL)
After payment the Gateway redirects the browser to your redirectURL via HTTP POST,
containing the original request fields plus response fields. Use this page only to show the
customer a result, and verify the signature first.
<?php
// https://yoursite.com/payment/return
$response = $_POST;
// 1. Verify the signature the Gateway returned (it signs the response too).
$theirSig = $response['signature'] ?? '';
unset($response['signature']);
if (!hash_equals(createSignature($response, $signatureKey), $theirSig)) {
http_response_code(400);
exit('Invalid signature — do not trust this response.');
}
// 2. Show the outcome (responseCode 0 == success).
if (($response['responseCode'] ?? null) === '0') {
echo 'Payment successful. Thank you!';
} else {
echo 'Payment was not completed: '
. htmlspecialchars($response['responseMessage'] ?? 'Unknown error');
}
9. Step 5 — Fulfil the order (callbackURL)
If you set callbackURL, the Gateway POSTs a copy of the result directly to it, independent
of the browser. This is where you update your database and fulfil the order.
<?php
// https://yoursite.com/api/payment/callback (no UI; just return 200)
$response = $_POST;
$theirSig = $response['signature'] ?? '';
unset($response['signature']);
if (!hash_equals(createSignature($response, $signatureKey), $theirSig)) {
http_response_code(400);
exit;
}
if (($response['responseCode'] ?? null) === '0') {
// Mark the order paid using $response['transactionUnique'] / $response['orderRef'].
// IMPORTANT: make this idempotent — a callback may arrive more than once.
}
http_response_code(200);
Both redirectURL and callbackURL must be fully-qualified (scheme + host). Neither is
supported by the Batch Integration.
10. Understanding the response & response codes
The response echoes your request fields and adds response fields. The important ones:
| Field | Meaning |
|---|---|
responseCode | Numeric outcome — use this, not the message, to decide success. 0 = success. |
responseStatus | Overall processing status of the request. |
responseMessage | Human-readable message (e.g. an auth code on success). |
state | Transaction state, e.g. received, approved, captured, etc. |
xref | The Gateway's reference for this transaction (used by Direct/Batch follow-ups). |
transactionUnique, orderRef | Echoed back so you can match to your order. |
acquirerResponseCode / acquirerResponseMessage | The raw response from the acquirer (may be non-numeric; ask your acquirer for meanings). |
Rule (verified): a zero responseCode always indicates success. Always branch on
responseCode, never on the text of responseMessage.
Response code families
0— success.- Authorisation codes (ISO-8583 based, 0–9999) — the acquirer's decision. Examples:
1Refer to card issuer ·4/5Decline (keep card / do not honor) ·14Invalid card number ·51Insufficient funds ·54Expired card ·65SCA required ·82/935 (N7)CVV failure. - Gateway codes (65536+) — problems before/around authorisation. Examples:
65539Invalid credentials (unknownmerchantIDor signature mismatch) ·65540Permission denied (IP not allowed) ·65541Action not allowed ·65542Request mismatch (changed card details when completing/refunding) ·65546Currency not supported ·65554Duplicate request ·65576Request cancelled (customer hit Cancel on the HPP — seeformCancelRequiredin §11). - Missing / invalid field codes (66048–67071) — a field is missing or invalid. By design,
the invalid code is exactly 256 greater than the matching missing code (e.g. missing
action=66055, invalidaction=66311).
For the complete lists, see the official Response and Advice Codes section.
11. Customising the Hosted Payment Page
You can change what the HPP shows and requires by adding optional fields to the same request. All are optional.
Prefill fields (initial values, still editable by the customer): customerName,
customerAddress, customerTown, customerCounty, customerPostcode,
customerCountryCode, customerEmail, customerPhone, receiverDateOfBirth. You can also
prefill card fields, but only send cardNumber if you're PCI-compliant for card storage, and
cardCVV only for testing (CVVs must never be stored).
Show / require fields with the matching *Mandatory fields (Y/N): cardCVVMandatory,
customerNameMandatory, customerFullNameMandatory (name must be ≥ two words of ≥ two
characters), customerAddressMandatory, customerTownMandatory, customerCountyMandatory,
customerPostcodeMandatory, customerCountryCodeMandatory, customerEmailMandatory,
customerPhoneMandatory, receiverDateOfBirthMandatory. On the standard modal HPP: Y =
shown and required; N = shown but optional; omitting it means the field need not be shown.
The Gateway may force some fields mandatory if your acquirer requires them.
Page behaviour:
| Field | Description |
|---|---|
allowedPaymentMethods | Comma-separated list of payment methods to show on the HPP (where supported). |
paymentMethod | Open the HPP straight into a specific alternative method without the customer selecting it. |
formResponsive | Y/N — let the HPP adapt its layout to the display size. |
formCancelRequired | Show a Cancel button. Cancelling returns responseCode 65576 (REQUEST CANCELLED). |
formRedirectDelay | Seconds before redirecting back after completion. -1 to 300; default 5; 0 = immediate; -1 = no automatic redirect. |
formAmountEditable | Let the customer choose the amount they pay. |
Gateway Wallet (stored cards): walletID, cardID, cardToken, customerAddressID,
formWalletRequired, formSaveCardRequired (defaults to Y). These let the customer select
a previously stored card/address or save a new one. (WalletRequired is a deprecated alias
for formSaveCardRequired.)
Not all option fields/features are supported on a fully customised HPP.
12. Apple Pay, Google Pay & other wallets/APMs
What the guide says (verified). The Gateway supports the Apple Pay, Android Pay and Google Pay digital wallets. A wallet produces a secure payment token, which is sent to the Gateway instead of the cardholder's actual card details. Wallets work on any merchant account configured to accept them.
Account-level prerequisites (verified):
- Digital wallet support is not available with all acquirers and must be enabled on your merchant account before use (your "mass boarding" wallet setup).
- Contact customer support to confirm acquirer support, enable a wallet, and for details on accepting payment tokens.
There are two ways a wallet payment reaches the Gateway:
12.1 Via the Hosted Payment Page (your setup)
Because the wallets are enabled on your merchant account, the Hosted Payment Page can present
the enabled wallet options; you can influence which methods are shown with
allowedPaymentMethods, or open a specific one with paymentMethod
(see §11). The HPP handles the wallet interaction
and the token, and the result returns through your redirectURL / callbackURL exactly like
a card payment — so your result handling (§8–§9) is
unchanged. This is why wallets are "easier" on Hosted: the token capture and card-data
handling stay on the Gateway side.
The precise HPP presentation/handling for each wallet is a "contact support" item in the guide, and a dedicated Hosted Implementation / Digital Wallet Tokens sub-page may cover specifics I haven't been able to read. The flow is verified; confirm any wallet-specific HPP options with support before relying on them.
12.2 Via the Direct Integration with a token (verified mechanics)
If instead you collect the wallet token yourself (e.g. from an Apple Pay / Google Pay
button in your own app or page) and process it server-side, you send it through the Direct
Integration. In place of the standard card details, send these two fields alongside the
basic request fields (merchantID, action, amount, type, currencyCode,
countryCode, signature, etc.):
| Field | Mandatory | Value |
|---|---|---|
paymentMethod | Yes | The token type: applepay, androidpay, or googlepay. |
paymentToken | Yes | The secure payment token produced by the wallet-enabled application. |
There are no additional response fields — you read the outcome exactly as for any other transaction (§10).
Note: §12.2 is the Direct Integration path (it requires the higher PCI/SSL setup that Direct implies, though you handle a token rather than raw card data). For the Hosted route (§12.1) you don't send these fields yourself — the HPP does.
For test wallets, Apple Pay / Amazon Pay / PayPal sandbox accounts are arranged via customer support (see §15).
13. 3-D Secure / SCA
For the Hosted Integration, 3-D Secure is handled on the Hosted Payment Page — if a
transaction needs Strong Customer Authentication (SCA), the HPP runs the 3-D Secure challenge
before returning the customer to your redirectURL. You don't implement the 3DS flow yourself
(that complexity is the Direct Integration's concern).
What you should know:
- An SCA-required outcome surfaces as authorisation
responseCode65 (SCA REQUIRED) in the simulator; a fully authenticated card returns0. - You can test specific 3-D Secure authentication outcomes by varying the card expiry month on test cards — see §15.
- Batch cannot do 3-D Secure at all; that's one reason checkout flows use Hosted (or Direct).
14. The official libraries
Three official libraries remove most of the manual work. Use the server-side SDK for signing/verification; add a client-side library only if you want the lightbox overlay or your own styled form.
14.1 Gateway Integration Library (server-side SDK)
A server-side library (the Gateway class, P3/SDK namespace) available in many languages.
It signs requests, builds the form, and verifies responses. Supports Hosted and Direct (not
Batch).
Configure once: hostedURL, directURL, merchantID, merchantSecret (enables auto
signing + verification), optional merchantPwd, proxyUrl, debug.
Key methods:
hostedRequest(request, options)→ returns a ready-to-embed HTML<form>fragment that POSTs to the HPP; adds the correctsignatureautomatically ifmerchantSecretis set.optionscan set the submit button (text/image/HTML) and extra form attributes (defaults to a "Pay Now" button).verifyResponse(response, secret)→ validates and decodes the data POSTed back to yourredirectURL/callbackURL; throws if the signature is wrong orresponseCodeis missing.sign(request, secret)→ returns the signature for a request, to sign manually.
Using hostedRequest() + verifyResponse() is the most reliable route because the signature
encoding (including nested fields) is guaranteed correct.
14.2 Hosted Payment Page Library (client-side — the lightbox)
A client-side script that shows the HPP in a lightbox/modal overlay over your site instead of a new page, with no other changes to your site. Load it from your Gateway host:
<script src="https://YOUR-GATEWAY-HOST/sdk/web/v1/js/hostedforms.min.js"></script>
- Works with or without jQuery (adds a
$(el).hostedForm(data)plugin if jQuery is present). Exposeswindow.hostedFormsand aFormclass. new window.hostedForms.classes.form.Form(element, data)builds or adapts a<form>. The overlay triggers whendata.modalis true, the form hasdata-hostedform-modal, or itsactioncontains/ends withmodal.- Auto-submit with
data.submit.type: 'auto'or adata-hostedform-autosubmitattribute; otherwise it disables the submit button on click to prevent double-submits. - The overlay is a semi-opaque full-screen iframe; your cart stays visible but greyed out. On
completion the browser is redirected to your
redirectURLas normal.
You still build and sign the same fields server-side (§6) and handle the result the same way.
14.3 Hosted Payment Fields Library (client-side — your own form, hosted inputs)
Use this to design your own payment form while the sensitive inputs stay hosted by the Gateway (the PCI benefit of Hosted with full layout control). Load it from your Gateway host; jQuery is required and must load first:
<script src="https://YOUR-GATEWAY-HOST/sdk/web/v1/js/hostedfields.min.js"></script>
- Provides 6 components:
cardNumber,cardCVV,cardExpiryDate,cardStartDate,cardIssueNumber, andcardDetails(number + expiry + CVV in one line). They validate, format, and show the card-type icon. - Declare a field three ways (pick one, don't mix):
<input type="hostedfield:cardNumber" name="card-number"> <div class="hostedfield" data-hostedfield-type="cardExpiryDate"></div> <input data-hostedfield='{"type":"cardCVV"}'> - With the default
autoSetup/autoSubmit, the library validates on submit, produces apaymentTokenrepresenting the collected card data, and adds it to your form as a hiddenpaymentTokeninput. - You then submit that
paymentTokento your server and process the payment via the Direct Integration — your server handles the token, never the raw card data. - Style fields with your own CSS via a designated stylesheet (selectors must include the
hostedfieldclass /-hostedfieldid suffix); richhostedfield:*events andhf-*state classes are available.
This is a hybrid (hosted fields + Direct Integration), not the standard Hosted redirect. Use it when you need a fully custom-built form but want to stay out of PCI scope.
15. Testing
Test Merchant Accounts connect to the Gateway's Simulator (not a real acquirer), which emulates authorisation and settlement. (All values below are from the guide's Integration Testing page.)
15.1 Test amounts — drive the outcome with the amount
The transaction amount selects the simulated result:
| Amount (minor units) | Amount (£) | Authorisation | Settlement |
|---|---|---|---|
| 100 – 2499 | 1.00 – 24.99 | (0) AUTH CODE | ACCEPTED |
| 2500 – 4999 | 25.00 – 49.99 | (0) AUTH CODE | REJECTED |
| 5000 – 7499 | 50.00 – 74.99 | (1) CARD REFERRED → (0) if authorisationCode supplied | ACCEPTED |
| 7500 – 9999 | 75.00 – 99.99 | (1) CARD REFERRED → (0) if authorisationCode supplied | REJECTED |
| 10000 – 14999 | 100.00 – 149.99 | (5) CARD DECLINED | N/A |
| 15000 – 19999 | 150.00 – 199.99 | (4) CARD DECLINED – KEEP CARD | N/A |
| 20000 – 24999 | 200.00 – 249.99 | (65) SCA REQUIRED → (0) if not SCA-eligible | ACCEPTED |
| 25000 – 29999 | 250.00 – 299.99 | (65) SCA REQUIRED → (5) if not SCA-eligible | N/A |
Any other amount returns responseCode 66311 (Invalid Test Amount). Settlement outcome
applies only to transactions that are authorised and captured (not cancelled), and uses the
captured amount.
Override trick: set the Cardholder Name to Test [N] where N is a pounds value, to force
the simulated outcome regardless of the real amount (e.g. name Test [20] with a £10,000
amount → ACCEPTED, because £20 falls in the accepted band).
15.2 Test cards
Test accounts only accept designated test cards (these won't work on production). Use expiry December of the current year (unless simulating 3DS states — see below). A few examples:
| Scheme | Card number | CVV |
|---|---|---|
| Visa Credit | 4929 4212 3460 0821 | 356 |
| Visa Debit | 4539 7910 0173 0106 | 289 |
| Mastercard Credit | 5301 2500 7000 0191 | 419 |
| Mastercard Debit | 5573 4712 3456 7898 | 159 |
| American Express | 3742 4545 5400 001 | 4887 |
(The guide lists more, including Electron, JCB and Diners Club, plus the billing addresses needed to test AVS/CV2. Diners Club doesn't support AVS — test it on a MID with AVS off.)
15.3 3-D Secure (v2) testing
Test accounts use the 3-D Secure PIT system. For the frictionless flow, the card expiry month selects the returned authentication status:
| Expiry month | Status | Simulates |
|---|---|---|
| 01 | Y | Fully authenticated |
| 02 | N | Not authenticated |
| 03 | U | Unknown |
| 04 | A | Attempted |
| 06 | R | Rejected (don't send for auth) |
| 12 | C | Challenge (non-frictionless; choose the outcome on the challenge dialog) |
(If the chosen month has already passed this year, use next year's date or the card shows as expired.)
15.4 Wallet / PayPal / Amazon Pay sandboxes
PayPal, Amazon Pay and similar sandbox test accounts are arranged via customer support so you can watch transactions land in your own sandbox.
16. Going live
- Swap test
merchantID, signing key and Gateway URL for the production ones provided. - Confirm end-to-end: HPP loads (signature accepted) → a real small payment returns
responseCode 0toredirectURL→callbackURLfires and verifies → wallet buttons appear if boarded. - Always POST to HTTPS.
- On
5xx(network/maintenance) responses, retry a limited number of times with increasing delays; a503means scheduled maintenance — retry after the window.
17. Common mistakes
| Symptom | Likely cause |
|---|---|
"Signature mismatch" / 65539 | Query-string encoding doesn't match PHP http_build_query; the signature field was included in its own hash; fields not sorted; line endings not normalised to %0A; wrong secret. |
| Orders not fulfilled despite success | Fulfilling from redirectURL instead of callbackURL; customer closed the browser before redirect. |
| Duplicate orders | Callback handled non-idempotently (it can fire more than once) — dedupe on transactionUnique. |
| Refund/capture "not allowed" | Those actions aren't supported on Hosted (§5.1) — do them via Direct/Batch or MMS. |
| HPP never loads | POSTing from the server instead of the browser; using HTTP; wrong Gateway URL. |
| Wallets not showing | Apple/Google Pay not boarded on that account, or restricted by allowedPaymentMethods. |
66311 in testing | Test amount outside the valid bands (§15.1). |
18. Quick reference
Endpoint: https://YOUR-GATEWAY-HOST/hosted/ (HTTPS, exact URL from onboarding)
Encoding: application/x-www-form-urlencoded
Method: POST from the customer's browser
Actions: Hosted supports SALE, VERIFY, PREAUTH only
Auth: signature (recommended) | merchantPwd (discouraged for Hosted)
Success: responseCode == 0 (always; never branch on responseMessage text)
Result in: redirectURL (browser → show page) + callbackURL (server → fulfil order)
Wallets: Apple/Android/Google Pay = token model; enable per account (acquirer-dependent).
Hosted: HPP presents/handles the wallet, result via redirect/callback.
Direct: send paymentMethod=applepay|androidpay|googlepay + paymentToken
Lightbox: use the Hosted Payment Page Library (hostedforms.min.js)
19. Glossary
| Term | Meaning |
|---|---|
| Gateway | The payment gateway. |
| Merchant | You, the business using the Gateway. |
| Acquirer | The bank/financial institution that processes the merchant's card payments. |
| Issuer | The bank that issued the cardholder's card. |
| Cardholder / Customer | The person making the payment. |
| Merchant Account | A Gateway account mapped to an acquirer-provided account. |
| HPP — Hosted Payment Page | A page on the Gateway's secure server that collects payment details. |
| HPF — Hosted Payment Field | An individual Gateway-hosted input for sensitive card data. |
| APM | Alternative Payment Method (e.g. local payment schemes, wallets). |
| Checkout / Wallet | Third-party checkout/wallet solutions (e.g. PayPal, Amazon Pay, Masterpass). |
| xref | The Gateway's reference for a transaction. |
20. Sources & verification notes
Read and used directly (Gateway Integration Guide V4.21 — https://guides.gitbook.io/integrationguide): Introduction & Disclaimer; Terminology; Integration Methods; Integration Details; Authentication; Prerequisites; Supported Actions; Security and Compliance; New Transactions → Request Fields; Hosted Payment Page Options; Pay Buttons (signature code); Gateway Integration Library; Hosted Payment Page Library; Hosted Payment Fields Library; Response and Advice Codes (Response Codes, Gateway Response Codes, General Error Codes, Authorisation Response Codes); Integration Testing; Digital Wallet Transactions (parent + Direct Implementation sub-page).
Stated, not yet verified verbatim:
- Any Hosted Implementation / Digital Wallet Tokens sub-page for wallets — §12.2 (the
Direct token mechanics:
paymentMethod=applepay/androidpay/googlepay+paymentToken) is fully verified. What's not verified is the precise way each wallet is presented and its token handled on the Hosted Payment Page (§12.1); the guide defers some of this to customer support. Confirm HPP wallet specifics with support if needed. - Sample Signature Calculation page — the algorithm in §6 is the canonical implementation
taken from the Pay Buttons example and the SDK's
sign()method; the dedicated page would restate it. - The full Response/Advice code lists — §10 covers the families and the key codes; the complete tables live in the official Response and Advice Codes section.
This document summarises the Hosted Integration for day-to-day developer use; the official guide remains authoritative for exhaustive field lists, response codes and edge cases.
