Duplicate order_code means
silent rejection. Worldpay
won't tell you why.
Worldpay's enterprise integration requires a merchant account and weeks of onboarding. This mock gives you the full Hosted Payment Page flow — with merchant_code, order_code, IPN callbacks, and status verification — from day one.
merchant_code
account identifier
order_code
unique per transaction
IPN
async notification
{
"order_code": "ORD-WP-9001",
"merchant_code": "MERCHANT_ACME",
"payment_status": "AUTHORISED",
"last_event": "AUTHORISED"
}
// IPN arrives — respond 200 immediately
Worldpay is one of the largest payment processors globally, handling transactions across 120+ currencies. Its integration model is older than most — it uses a redirect-based hosted payment page, and payment results arrive via IPN (Instant Payment Notification) rather than modern REST webhooks. The integration requires two identifiers: a merchant_code that identifies your Worldpay account, and an order_code that is your unique reference for each transaction.
The order_code requirement is a common source of bugs. Each code must be unique per merchant — if you submit the same code twice, Worldpay silently rejects the second request without a clear error. Use timestamps or UUIDs — anything that guarantees uniqueness. You cannot reuse codes even across test runs. The IPN that arrives contains the order_code back so you can match it to your internal order.
Worldpay's paymentStatus in the IPN takes four values: AUTHORISED (approved), REFUSED (bank declined), CANCELLED (customer abandoned), or ERROR (technical failure — safe to retry). Your IPN handler must respond with 200 OK or Worldpay retries delivery.
Integration flow
Worldpay uses a redirect-based hosted payment page. Your server never handles card data. The flow is four steps connected by async notifications.
Initialize order
POST /api/base/worldpay/payments/authorizationsSend merchant_code, order_code, amount, and redirect URLs. Receive a redirect_url pointing to the Worldpay hosted payment page.
Customer redirect
redirect → Worldpay HPPSend the customer to redirect_url. Worldpay hosts the card entry form. Your server does not touch card data at any point.
Receive IPN
POST to your webhookWorldpay POSTs an Instant Payment Notification to your server with the payment_status. Respond 200 immediately or Worldpay retries.
Verify and fulfill
GET /verify/{order_code}Confirm the order status server-side via the verify endpoint. Only fulfill after both IPN and verify return AUTHORISED.
merchant_code vs order_code
Worldpay requires both identifiers on every request. They serve completely different purposes.
Your Worldpay account identifier. Assigned during onboarding. This is the same on every single request you make — it identifies your merchant account to Worldpay's systems. Think of it as your username.
In this mock, use any non-empty string. In production, Worldpay provides this after account approval.
Your unique reference for this specific payment. You generate it. Worldpay returns it in every IPN and status check so you can match the payment notification back to your internal order.
Must be unique per merchant. A good pattern: ORD-{timestamp}-{uuid_short}
Critical: order codes must be unique
Reusing an order_code causes silent failures. Worldpay will treat the duplicate as a reference to the original payment and return stale status data instead of processing a new charge. There is no error thrown — the failure is invisible until you notice the customer was never actually charged. Generate a fresh code for every payment attempt.
Integration code
curl -X POST https://mockgateway.dev/api/base/worldpay/payments/authorizations \
-H "Authorization: Bearer YOUR_MOCK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"merchant_code": "MERCHANT_ACME_UK",
"order_code": "ORD-WP-9001",
"amount": 7500,
"currency": "GBP",
"description": "Annual subscription",
"shopper_email": "buyer@example.com",
"success_url": "https://yourapp.com/checkout/success",
"cancel_url": "https://yourapp.com/checkout/cancel"
}'
// merchant_code: your Worldpay account identifier
// order_code: your unique reference — must not be reusedRequest parameters
Sent to POST /api/base/worldpay/payments/authorizations
| Parameter | Type | Required | Description |
|---|---|---|---|
transactionReference | string | required | Your own unique reference for the payment. e.g. order-12345 |
merchant.entity | string | required | The merchant account the payment is routed to. e.g. default |
instruction.narrative.line1 | string | required | What appears on the cardholder statement. 24 characters at most. e.g. MockGateway |
instruction.value.currency | string | required | Three-letter ISO currency code. e.g. GBP |
instruction.value.amount | integer | required | Amount in the smallest currency unit (1000 = £10.00). e.g. 1000 |
instruction.paymentInstrument.type | string | required | The kind of instrument being charged. e.g. card/plain |
Response fields
| Field | Type | Description |
|---|---|---|
orderCode | string | Worldpay order code |
paymentStatus | enum | Payment result |
lastEvent | string | Last payment event |
created_at | datetime | |
authorizationCode | string | The code the issuer returned for the authorization |
Questions about Worldpay
Other gateway templates
Looking for a different provider?