Simulation mode FauxPay never moves real money. No card data, no bank accounts, no exceptions.
FauxPay
Menu

Multi-currency payment gateway sandbox

Ship the checkout.
Skip the contract.

FauxPay is a payment gateway simulator with a real API, a hosted checkout page, and signed webhooks that retry. Ten currencies, deterministic test scenarios, and zero real money — so your team can finish the integration today instead of waiting on legal, KYC, and a merchant agreement.

  • No contract
  • No KYC
  • No card data
  • No real money

FauxPay checkout

Nusantara Coffee Co.

Pending

Amount due

Rp1,500.00

IDR · order ORDER-1029

Payment method

Virtual
Account
E-Wallet Card
Pay Rp1,500.00

Test controls — success / fail / pending

Supported currencies: IDR, INR, MYR, VND, MMK, THB, JPY, USDT, PHP, PKR.

Why FauxPay exists

The integration isn't the hard part. The paperwork is.

Most teams can wire up a payment flow in an afternoon. What takes months is everything around it: the legal entity, the KYC review, the merchant agreement, the go-live checklist. FauxPay fills that gap with a gateway that behaves like the real one and costs less than a team lunch.

The usual path

Weeks before line one

  • Business documents and legal review
  • KYC and underwriting on the merchant account
  • A signed agreement before any sandbox access
  • Weeks of back-and-forth with an account manager
The FauxPay path

One POST, then build

  • Register and get an API key in under a minute
  • Create a payment intent and get a checkout URL back
  • Redirect your customer, pick an outcome, ship it
  • Swap in the real gateway later without touching your UI
What this is not

Honest limits

  • Not a licensed payment provider
  • Not connected to any bank, card, or e-wallet network
  • Not a way to accept money from real customers
  • Not something to fake a real transaction with

Everything a gateway has

A gateway-shaped hole, filled properly.

If your integration works against FauxPay, it works against the gateway you graduate to. That's the whole design goal.

X-Api-Key

HMAC-signed API

Every merchant request carries a public key plus an HMAC-SHA256 signature of the raw body. You build the same signing code you will use in production.

/checkout/{token}

Hosted checkout page

Redirect to a token-scoped checkout URL. No auth needed, no merchant secrets in the browser, and a simulation banner your testers cannot miss.

X-FauxPay-Signature

Webhooks that retry

Signed payloads POSTed to your endpoint, retried with exponential backoff — 1m, 5m, 30m, 2h — with every attempt logged and resendable.

10 seeded

Ten currencies, no floats

Amounts are integers in the smallest unit, with precision read from the currency itself. Add another currency with one database row.

5 scenarios

Deterministic scenarios

Force an outcome when you create the intent — always_fail, delayed_success, expired. Your QA suite stops depending on which button a human clicks.

Merchant dashboard

Backoffice with delivery logs

Inspect intents, transactions, and each webhook attempt down to the response body and latency. Resend a delivery while you debug your handler.

The whole flow

Four steps, then you're testing.

  1. 1

    Create an account

    Register and FauxPay issues your first key pair. The secret is shown once and stored encrypted on our side.

  2. 2

    Create an intent

    POST the amount, currency, and your order id. Sign the raw body with your secret. You get a checkout URL back.

  3. 3

    Send the customer

    Redirect to that checkout URL. Your tester picks an outcome, or a scenario forces one for automated runs.

  4. 4

    Fulfil from the webhook

    We POST a signed event to your endpoint. Verify the signature, then mark the order paid in your own system.

Integration

Copy it, sign it, ship it.

Two things to implement: signing your outbound requests, and verifying our inbound webhooks. Both are HMAC-SHA256 over the raw body — the same scheme in both directions.

Create an intent

Serialise the payload once and sign those exact bytes — re-encoding a parsed object will change key order and break the signature.

<?php

$payload = json_encode([
    'amount'       => 150000,
    'currency'     => 'IDR',
    'order_id'     => 'ORDER-1029',
    'callback_url' => 'https://merchant.test/webhooks/fauxpay',
    'return_url'   => 'https://merchant.test/orders/1029/thank-you',
], JSON_UNESCAPED_SLASHES);

$response = Http::withHeaders([
    'X-Api-Key'   => config('services.fauxpay.public_key'),
    'X-Signature' => hash_hmac('sha256', $payload, config('services.fauxpay.secret')),
])->withBody($payload, 'application/json')
  ->post(config('services.fauxpay.url').'/api/v1/payment-intents');

$intent = $response->json('data');

return redirect($intent['checkout_url']);

Verify the webhook

Compare in constant time, and only trust this — not the browser redirect — when deciding whether an order is paid.

<?php

$rawBody   = $request->getContent();
$signature = (string) $request->header('X-FauxPay-Signature');

$expected = hash_hmac('sha256', $rawBody, config('services.fauxpay.secret'));

if (! hash_equals($expected, $signature)) {
    abort(403, 'Invalid signature');
}

$event = json_decode($rawBody, true);

if ($event['status'] === 'success') {
    // Safe to fulfil: mark the order paid, keyed by $event['order_id'].
}

Endpoints

Method Path What it does
POST /api/v1/payment-intents Create an intent and receive its checkout URL
GET /api/v1/payment-intents/{id} Read a single intent
GET /api/v1/payment-intents List intents, filterable by status and order id
GET /api/v1/transactions List terminal transactions
GET /api/v1/currencies Supported currencies and their precision
GET /api/v1/health Public health check — no signature required

Deterministic testing

Stop clicking buttons in QA.

Pass a scenario key when you create the intent and the outcome is decided before your test even runs. Same request, same result, every time.

Scenario Forced outcome Delay Use it for
always_success success 0s Intent resolves as success immediately, no delay.
always_fail failed 0s Intent resolves as failed immediately — useful for QA of failure paths.
always_pending pending 0s Intent stays pending until it expires or is resolved manually.
delayed_success success 5s Success after a 5 second delay — useful for polling tests.
expired expired 0s Intent expires without producing a terminal transaction.

Create your own by inserting a row into the scenarios table — no code changes required.

Pricing

One plan. Priced like a snack.

No per-transaction fees, because there are no transactions. You are paying for a sandbox that behaves like the real thing.

Sandbox access

Rp10,000 / month

Monthly. Cancel whenever — your integration keeps working until the end of the period you already paid for.

Start free, upgrade later

No card details required to try it

What's included

  • Unlimited sandbox payment intents
  • Hosted checkout page for every intent
  • Up to 10 currencies
  • Signed webhooks with automatic retry
  • Full webhook delivery logs
  • Manual webhook resend
  • Unlimited API keys, revocable
  • Merchant backoffice access

How billing works

We collect payment outside FauxPay — by transfer or any channel you already use. A tool that exists to avoid handling real money should not be asking for your card number, so it doesn't.

Safety by construction

Built so it can never touch money.

These are not policy promises — they are properties of the codebase. There is no processor integration to misconfigure, because none exists.

No processor integration

No Stripe, Midtrans, Xendit, or bank API keys anywhere in the codebase. Ever.

No card fields

FauxPay never asks for a PAN, CVV, or expiry — not even in test fixtures.

Marked everywhere

Every API response carries mode: simulation. Every page carries a visible banner.

Billed outside

Subscriptions are invoiced separately, so money never enters the application.

Questions

The things you're about to ask.

Is this a real payment gateway? +

No. FauxPay is a simulator. It has the shape of a gateway — intents, a hosted checkout, signed webhooks, a backoffice — but it is not licensed to process payments and has no connection to any financial network.

Can I put real card numbers into it? +

Please don't. There is nowhere for them to go, and storing them would be both pointless and dangerous. Use obviously fake values in obviously fake formats.

Can I use this in a live product? +

As a stand-in, yes — that is the intended use. Your customers can walk the full checkout flow while you finalise a real provider. Just make sure the simulation banner stays visible so nobody mistakes it for a real charge.

What happens if my webhook endpoint is down? +

We retry with exponential backoff at 1m, 5m, 30m, and 2h, then mark the delivery as given up. Every attempt is logged with its response code and latency, and you can replay a delivery from the backoffice.

Do I need a queue worker to receive webhooks? +

On your side, no — just an HTTPS endpoint. FauxPay needs its own queue worker running to deliver them, which is already configured for the hosted service.

Can I add a currency you do not support? +

Yes, and it is a two-step change: insert a row into the currencies table with its symbol and decimal precision, then use it. No code path is currency-specific.

What happens when I am ready for a real gateway? +

You swap the base URL, the API keys, and the signature secret. Your checkout flow, order state machine, and webhook handler stay exactly as they are — that is the point of building against a gateway-shaped mock.

Your checkout could be done by the end of the day.

Create a sandbox account, grab your keys, and send your first payment intent. It takes about as long as reading this page did.