Hosted payment page
Take a card payment on Datman's hosted form by redirecting the shopper with an encrypted payload.
The Hosted Payment page redirects the shopper to a Datman-hosted form that handles the complete card payment. You don't send an API request yourself, and there's no API key in it. Instead, your server encrypts the payment details and sends the shopper's browser to a Datman URL. Datman takes the payment, sends the shopper back to you, and tells your server the result with a webhook.
This is one of two ways to take online payments. The endpoint reference is Open the hosted payment form (Sale).
Requirements
Before you begin, take into account the following requirements, limitations, and preparations.
| Requirement | Description |
|---|---|
| Integration type | Use this information to build an online payments integration for your merchants. |
| API credentials | Make sure that you have the following values from Datman: - Secret key: encrypts the payment details. Keep it on your server only. Never put it in a browser, app or page source. - Public key ( pub_key): tells Datman which secret to decrypt with. It goes in the URL and isn't secret. |
| Webhooks | Make sure that your server can receive the payment status webhook at your webhook_url, and that you have your webhook secret to verify the signature. Keep the webhook secret on your server only. |
| Limitations | Use HTTPS for redirect_url, cancel_url, webhook_url and back_url. |
| Setup steps | Make sure that the merchant you take the payment for has a Datman merchant ID (merchant_id) and that online payments are enabled for it. |
How it works
For a Hosted Payment page integration, you must integrate the following parts:
- Your payment server: builds and encrypts the payment details, and builds the URL to the hosted form.
- Your webhook server: listens for the webhook that includes the outcome of each payment.
Integration steps
To integrate the Hosted Payment page:
- Build the payload.
- Encrypt it.
- Redirect the shopper to the hosted payment page.
- Get the payment outcome.
Shopper checkout experience
When the shopper goes to check out:
- You redirect the shopper to the Datman-hosted payment form.
- The shopper completes the payment on the form.
- The shopper is redirected to your
redirect_url, or to yourcancel_urlif they cancel.
Payments integration flow
Your website, your server and the hosted payment page work together to complete the payment flow:
- The shopper chooses to check out on your website.
- Your server builds the payment details and encrypts them with your secret key.
- Your server builds the URL to the hosted form with the encrypted payload as
dataand yourpub_key. - Your website redirects the shopper's browser to that URL.
- The shopper completes the payment on the hosted form.
- The shopper is redirected to your
redirect_urlorcancel_url. - Your webhook server receives the payment status webhook with the payment outcome at your
webhook_url.
1. Build the payload
Create a JSON object with the payment details. Keys are case-sensitive. Note that amount is in major units, as a string, for example 24.50.
hoststringrequired
Your website's host, without http:// or https://.
merchant_idintegerrequired
The Datman merchant the payment is for.
order_idstring | integerrequired
Your unique order identifier.
customer_idstring | integerrequired
Your identifier for the shopper. Saved cards are linked to it and can be reused for the same shopper later.
emailstringrequired
The shopper's email address.
Format: email
providerstringrequired
The provider value Datman gave you.
phone_numberstringrequired
The shopper's phone number, in international format.
namestring
The merchant's business name.
amountstringrequired
The amount to charge, in major units, as a string.
avs_house_numberstring
House number, for address verification.
avs_postcodestring
Postcode, for address verification.
merchant_referencestring
Your own reference for the payment.
redirect_urlstringrequired
Where the shopper goes after a successful payment. Use HTTPS.
Format: uri
cancel_urlstringrequired
Where the shopper goes if they cancel. Use HTTPS.
Format: uri
webhook_urlstringrequired
Where Datman sends the payment status webhook. Use HTTPS. Treat the webhook, not the redirect, as the final status.
Format: uri
back_urlstringrequired
Where the shopper goes if they choose to go back to your site.
Format: uri
first_namestringrequired
The shopper's first name.
last_namestringrequired
The shopper's last name.
flatstring
Flat or apartment number.
address1string
Address line 1.
address2string
Address line 2.
statement_descriptorstring
Text on the shopper's card statement. Unsupported characters are removed and it's cut to 22 characters.
Max 22 characters
statement_descriptor_addressstring
Second statement line, such as a town. Unsupported characters are removed and it's cut to 20 characters.
Max 20 characters
split_feearray<HostedSplitFee>
Pay part of the amount to other Datman merchants, for example a delivery fee to the delivery partner.
split_fee[].partner_merchant_idstring | integerrequired
The merchant_id that receives this part of the payment.
split_fee[].type_idstring | integerrequired
Commission type: 1 Food/Goods, 2 Marketplace Fee, 3 Delivery Fee, 4 Delivery Tip, 5 Restaurant Tip, 6 Service Charge.
split_fee[].valuestring | numberrequired
The amount, or the percentage when value_type is percentage.
split_fee[].value_typestringrequired
One of: amount, percentage
{
"host": "sandbox.example.com",
"merchant_id": 63155480,
"order_id": "987654321",
"customer_id": "CUST98765",
"email": "john.doe@example.com",
"provider": "provider_value",
"phone_number": "+447911123456",
"amount": "150.75",
"redirect_url": "https://example.com/success",
"cancel_url": "https://example.com/cancel",
"webhook_url": "https://example.com/webhook",
"back_url": "https://example.com/back",
"first_name": "John",
"last_name": "Doe"
}2. Encrypt it
Encrypt the payload on your server, because the secret key must never reach the browser. Use AES-256-CBC:
- Key: your secret key, padded with zero bytes (or cut) to 32 bytes.
- IV: the first 16 characters of your secret key.
- Encoding: base64-encode the encrypted bytes, then base64-encode the result again.
import crypto from 'node:crypto';
export function encryptPayload(payload, secret) {
const key = Buffer.concat([Buffer.from(secret), Buffer.alloc(32)], 32); // 32-byte key
const iv = Buffer.from(secret).subarray(0, 16); // first 16 bytes of the secret
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const encrypted = cipher.update(JSON.stringify(payload), 'utf8', 'base64') + cipher.final('base64');
return Buffer.from(encrypted).toString('base64'); // base64 a second time
}function encryptPayload(array $payload, string $secret): string {
$iv = substr($secret, 0, 16); // first 16 characters of the secret
// openssl_encrypt pads or cuts the key to 32 bytes, as Datman does
$encrypted = openssl_encrypt(json_encode($payload), 'AES-256-CBC', $secret, OPENSSL_RAW_DATA, $iv);
return base64_encode(base64_encode($encrypted)); // base64 twice
}3. Redirect the shopper to the hosted payment page
Build the URL with the encrypted payload as data and your public key as pub_key, URL-encoding both. Then redirect the shopper's browser to it. The shopper pays on the hosted form.
The Open the hosted payment form (Sale) page in the API Explorer shows the sandbox and production endpoint URLs. Keep the endpoint URL in your configuration.
app.post('/checkout', (req, res) => {
const data = encryptPayload(buildPayload(req), process.env.DATMAN_SECRET_KEY);
const url = new URL(process.env.DATMAN_HOSTED_FORM_URL); // endpoint URL from the API Explorer
url.searchParams.set('data', data);
url.searchParams.set('pub_key', process.env.DATMAN_PUBLIC_KEY);
res.redirect(303, url.toString());
});4. Get the payment outcome
After the hosted form finishes the payment flow, you can show the shopper the current payment status. Datman sends a webhook with the outcome of the payment.
Show the result of the payment
- After a successful payment, the shopper is sent to your
redirect_url. - If they cancel, they're sent to your
cancel_url.
Don't treat the redirect as the final status, because redirects can be skipped or faked.
Update your order management system
Update your order management system when you get the payment status webhook at your webhook_url. Verify the webhook's signature, then use order_id to match it to your order. Only fulfil the order once the webhook says it's paid.
For a successful payment, the webhook contains status authorisation and success true. For an unsuccessful payment, it contains success false and a reason.
Example webhook for a successful payment
{
"order_id": "987654321",
"amount": "150.75",
"currency": "GBP",
"customer_id": "CUST98765",
"xref": "O88213045M63155480T4821937",
"status": "authorisation",
"success": "true",
"date": "2026-10-15 12:34:56+01:00"
}Test and go live
Build and test against the sandbox endpoint URL. When you are ready to go live:
- Switch to the production endpoint URL shown in the API Explorer.
- Use your live secret key, public key and webhook secret.
- Make sure that
redirect_url,cancel_url,webhook_urlandback_urluse HTTPS.
Troubleshooting
Payment errors
If the request can't be processed, the page shows a message instead of the payment form:
| Message | Usual cause | What to check |
|---|---|---|
| Unable to process this request! | A required key is missing, or data doesn't decrypt | That every required field is present; that you used the right secret for your pub_key, the right IV and both base64 steps; that data is URL-encoded |
| Online payment not available for this merchant account! | Online payments aren't enabled for that merchant | Contact Datman support |

