Verifone sends uppercase form fields, not JSON.
Most IPN handlers get this wrong.
2Checkout (now Verifone) is built for SaaS subscriptions and digital goods. It sends IPNs as form-encoded POST data with HMAC-SHA256 — not JSON webhooks. Start testing your IPN handler here without an account.
Your App
POST /checkout/init
2Checkout
Hosted checkout
IPN Notification
POST to your ipn_url
IPN_TYPE=PAYMENT_APPROVED 2Checkout was acquired by Verifone in 2021 and rebranded as Verifone Digital Commerce. The IPN format stayed the same — form-encoded fields with uppercase names like IPN_TYPE, HASH, and MERCHANT — but the sandbox URL and the newer LCN notification format changed. If you are building or updating a 2Checkout integration, this mock covers both formats.
Getting a merchant account takes time, and the Verifone sandbox requires a verified account before you can test anything. This mock lets you start immediately: init a payment, receive an IPN at your listener, verify the HMAC-SHA256 signature, and branch on IPN_TYPE — all without creating a Verifone account.
Four IPN types are available on demand: PAYMENT_APPROVED, PAYMENT_PENDING, PAYMENT_DECLINED, and REFUND_ISSUED. Test your subscription provisioning logic, access revocation on REFUND_ISSUED, and your HMAC verification code before you write a single line against the real API.
4
IPN event types
HMAC
SHA-256 signature
Form
encoded, not JSON
SaaS
subscription focus
2Checkout became Verifone — what actually changed
In 2021, 2Checkout was acquired by Verifone. The IPN format and HMAC algorithm stayed the same, but the API endpoints, sandbox URL, and new notification format changed. If you are migrating an old integration:
Existing IPN verification code works without changes. Only the sandbox URL and the new LCN format (JSON) differ. If you are building new, use LCN.
IPN types to handle
Branch your listener on IPN_TYPE. There are four values.
PAYMENT_APPROVED→ Grant accessThe IPN arrives with IPN_TYPE = PAYMENT_APPROVED. Verify the HMAC hash first, then grant product access or activate the subscription. This is the only IPN type where you should fulfill the order.
PAYMENT_PENDING→ Hold & waitPayment is under review or waiting for bank confirmation. Hold fulfillment and do not grant access yet. Wait for either PAYMENT_APPROVED or PAYMENT_DECLINED before acting.
PAYMENT_DECLINED→ Notify customerCard was declined or the fraud check failed. Let the customer know and give them a chance to try a different payment method. Do not suspend existing access for renewals.
REFUND_ISSUED→ Revoke accessA refund has been issued. Revoke product access, mark the subscription as cancelled in your system, and send the customer a confirmation email.
Integration code
Init request, response, verify endpoint, and the exact IPN payload your listener receives.
curl -X POST https://mockgateway.com/api/base/2checkout/init \
-H "Authorization: Bearer YOUR_MOCK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"merchant_code": "MOCK_MERCHANT",
"dynamic_product": "Pro Plan Monthly",
"price": "39.00",
"currency": "USD",
"return_url": "https://yourapp.com/checkout/return",
"ipn_url": "https://yourapp.com/webhooks/2checkout"
}'Request parameters
Fields accepted by POST /api/base/2checkout/init
| Parameter | Type | Required | Description |
|---|---|---|---|
Currency | string | required | Three-letter ISO currency code. e.g. USD |
Items | array | required | The products being ordered, each with a price. e.g. [{"Price": {"UnitNetPrice": 99.99}}] |
ExternalReference | string | optional | Your own order reference. e.g. my-order-001 |
BillingDetails.FirstName | string | required | Buyer first name. e.g. John |
BillingDetails.Email | string | required | Buyer email address. e.g. john@example.com |
BillingDetails.CountryCode | string | required | Two-letter ISO country code. e.g. US |
PaymentDetails.Type | string | required | How the order is paid. e.g. CC |
Response fields
Fields returned in every 2Checkout mock payment response.
| Field | Type | Description |
|---|---|---|
order_number | string | 2Checkout order reference number |
invoice_id | string | Invoice identifier |
status | enum | Current status of the order |
sale_id | string | 2Checkout sale identifier |
vendor_id | string | 2Checkout vendor account ID |
created_at | timestamp | Order creation timestamp |
Frequently asked questions
What is the 2Checkout IPN?
IPN stands for Instant Payment Notification. 2Checkout sends form-encoded POST data to your ipn_url after each transaction event. You must check the HMAC-SHA256 HASH field before processing any IPN — never trust an unverified notification.
What is the difference between IPN and LCN?
IPN is the legacy format — form-encoded, uppercase field names like IPN_TYPE and HASH. LCN (Lifecycle Notifications) is Verifone's newer format — JSON, lowercase, modern webhook style. If you are building a new integration today, use LCN. If you are maintaining an old 2Checkout integration, you are using IPN.
What is the refno?
The refno is 2Checkout's unique ID for a transaction. It appears in the checkout response and in every IPN as REFNOEXT. Store it on your order so you can match incoming notifications to the right customer.
When should I move to the real Verifone sandbox?
Once your IPN handler, HMAC verification, and IPN_TYPE branching work here. The Verifone sandbox requires an account but gives you access to the real hosted checkout and actual subscription lifecycle events.
Other gateway templates
Looking for a different provider?