API v2

Simple Crypto Payments

Integrate EpPay with just a network slug and token type — no RPC URLs or contract addresses needed.

How It Works

EpPay uses a secure server-to-server callback architecture. The callback URL is set by the merchant at payment creation and cannot be tampered with by the mobile app.

Payment Flow

1
Merchant creates payment

Your app/website sends POST /api/v2/create-payment with amount, wallet, network, token, and callback URL. EpPay returns a payment_id and qr_data.

2
QR code displayed

Your app displays the QR code (from qr_data) to the customer. The QR encodes the payment ID for the EpPay mobile app.

3
Customer scans & pays

Customer scans the QR with the EpPay mobile app, reviews the payment details, and approves the blockchain transaction.

4
Mobile app confirms to EpPay

After the blockchain transaction is confirmed, the mobile app sends the transaction proof (tx hash, sender address) to POST /api/v2/payments/{id}/verify.

5
EpPay notifies merchant

EpPay saves the payment as completed and sends a server-to-server POST to your callback URL with the payment details (payment_id, amount, tx_hash, from, network).

6
Mobile app shows success

EpPay returns a success response to the mobile app, which displays a confirmation screen to the customer.

7
Merchant frontend updates

Your frontend polls GET /api/v2/payments/{id}/status every 3-5 seconds. When confirmed is true, show the success screen to the customer.

Why this architecture? The callback URL is stored server-side at payment creation by the merchant — the mobile app never sees or touches it. This prevents callback URL tampering and ensures server-to-server delivery even if the customer's browser disconnects.

Merchant App                    EpPay Server                  EpPay Mobile App          Blockchain
     |                               |                              |                      |
     |  POST /api/v2/create-payment  |                              |                      |
     |  (amount, to, network,        |                              |                      |
     |   token_type, callback_url)   |                              |                      |
     |------------------------------>|                              |                      |
     |                               | Stores payment + callback    |                      |
     |  { payment_id, qr_data, ... } |                              |                      |
     |<------------------------------|                              |                      |
     |                               |                              |                      |
     | Display QR code               |                              |                      |
     |                               |       Scan QR code           |                      |
     |                               |<-----------------------------|                      |
     |                               |       Payment info           |                      |
     |                               |----------------------------->|                      |
     |                               |                              |                      |
     |                               |                              |  Send transaction    |
     |                               |                              |--------------------->|
     |                               |                              |  TX confirmed        |
     |                               |                              |<---------------------|
     |                               |                              |                      |
     |                               | POST /verify (txHash, from)  |                      |
     |                               |<-----------------------------|                      |
     |                               |                              |                      |
     |  POST callback_url            | Saves payment, fires callback|                      |
     |  (payment_id, tx_hash, ...)   |                              |                      |
     |<------------------------------|                              |                      |
     |                               |  { success, payment_id }     |                      |
     |                               |----------------------------->|                      |
     |                               |                              | Show success         |
     |                               |                              |                      |
     | Poll GET /status              |                              |                      |
     |------------------------------>|                              |                      |
     | { confirmed: true }           |                              |                      |
     |<------------------------------|                              |                      |
     | Show success page             |                              |                      |
     |                               |                              |                      |

Quick Start

Accept crypto payments in 3 steps:

1

Get your API key and phone code

Create an account, link your phone with the EpPay app, then copy your API key and phone code from the Developers page. See API Keys & Phone Code.

2

Create a payment

Send a POST request to POST /api/v2/create-payment:

curl -X POST https://eppay.io/api/v2/create-payment \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "YOUR_API_KEY",
    "phone_code": "YOUR_PHONE_CODE",
    "amount": "25.00",
    "to": "0xYourWalletAddress",
    "network": "bsc",
    "token_type": "USDT",
    "success": "https://your-site.com/eppay-callback"
  }'
3

Poll for payment status

Use the returned payment_id to poll GET /api/v2/payments/{payment_id}/status every 3-5 seconds. When confirmed is true, the payment is done. Your callback URL also receives a server-to-server POST automatically.

Ready-made code: see the Code Examples for JavaScript, PHP and Python.

API Keys & Phone Code

Every payment request needs two things: an API key and your phone code. Both are on the Developers page and in the EpPay app, under the eppay.io tab. Keep them on your server: never put them in a web page or a mobile app.

API keys

  • An account can hold up to 5 active keys, one for each website, shop or app. Give each one a name when you add it.
  • Regenerate gives one key a new value. Revoke stops it and frees its place. Either takes effect at once and leaves your other keys alone.

Phone code

  • The code of the phone linked to your account, such as EP-7K3Q-9XMD. To link a phone, install the EpPay app, then scan the code on the sign-in page or follow Link your EpPay app.
  • A phone links to one account, so all your keys use the same code.
  • Required on every request that creates a payment since 1 November 2026. Send it as phone_code in the body or in the X-EpPay-Phone-Code header. Checking a payment's status needs neither the key nor the code.

When a request is refused

The response explains the problem in error and, for the phone code, gives a code:

Status Code What to do
403 phone_code_required The request has no phone code. Add phone_code.
403 phone_code_mismatch The code is not the one for the phone linked to this key's account. Each key works only with its own account's code.
403 phone_not_linked The key's account has no linked phone. Link one.
401 none The API key is wrong, revoked or belongs to a suspended account.

Create Payment

POST https://eppay.io/api/v2/create-payment

Creates a new payment and returns a rich response with QR data and payment URL.

Request Parameters

Parameter Type Required Description
apiKey String Yes Your EpPay API key
phone_code String Yes The code of the phone linked to the key's account, such as EP-7K3Q-9XMD. It can also be sent as the X-EpPay-Phone-Code header. See API Keys & Phone Code.
amount String Yes Payment amount (e.g. "25.00")
to String Yes Your wallet address to receive the payment
network String Yes Network slug: "bsc", "eth", "polygon", etc. See Supported Networks
token_type String Yes "USDT" or "USDC"
success String No Your server callback URL — receives a POST when payment is confirmed
platform_fee_bps Integer No Ignored. The fee comes from your API key and is returned in the response; requests that still send this field are logged. See Platform Fees.
platform_fee_recipient String No Ignored. The platform fee always goes to EpPay's fee address, returned in the response.
referrer_address String No Optional address of a referral partner, who receives a share of EpPay's platform fee (not of your amount). Ignored when it is your own wallet: the invoice's to address, a wallet on your account or an address you have been paid at. Dropped at settlement if it turns out to be the payer.
referrer_fee_share_bps Integer No Ignored. The referrer's share is set by EpPay: 2500 (25% of the platform fee) when referrer_address is accepted, returned in the response.

Response

{
    "payment_id": "8a020135-19b7-42df-be4b-1a8722ad0570",
    "amount": "25.00",
    "network": "bsc",
    "token_type": "USDT",
    "to": "0xYourWalletAddress",
    "status": "pending",
    "qr_data": "product=uuideppay&id=8a020135-19b7-42df-be4b-1a8722ad0570",
    "payment_url": "https://eppay.io/payment/8a020135-19b7-42df-be4b-1a8722ad0570",
    "created_at": "2026-02-28T12:00:00+00:00",
    "is_existing": false,
    "platform_fee_bps": 50,
    "platform_fee_recipient": "0x4Bd14042002BE327751D00fFa4849C28b7c1381F",
    "referrer_address": null,
    "referrer_fee_share_bps": null
}

Note: platform_fee_bps and platform_fee_recipient are set on every invoice whose API key carries a fee: keys issued since 1 September 2026 and invoices created without a key carry 50 bps. They are null on keys without a fee (some keys issued earlier), and referrer_address and referrer_fee_share_bps are null unless the invoice names a referrer. Your integration code should treat all four as optional.

QR Code

Use the qr_data field to generate a QR code. The customer scans it with the EpPay mobile app to approve the payment.

product=uuideppay&id=PAYMENT_ID

Check Payment Status

GET https://eppay.io/api/v2/payments/{payment_id}/status

Rich status including network, transaction hash, sender address, and timestamps.

Response (Pending)

{
    "payment_id": "8a020135-...",
    "status": "pending",
    "confirmed": false,
    "amount": "25.00",
    "network": "bsc",
    "token_type": "USDT",
    "tx_hash": null,
    "from": null,
    "completed_at": null,
    "platform_fee_bps": 50,
    "platform_fee_recipient": "0x4Bd14042002BE327751D00fFa4849C28b7c1381F",
    "referrer_address": null,
    "referrer_fee_share_bps": null
}

Response (Completed)

{
    "payment_id": "8a020135-...",
    "status": "completed",
    "confirmed": true,
    "amount": "25.00",
    "network": "bsc",
    "token_type": "USDT",
    "tx_hash": "0xabc123...",
    "from": "0xSenderAddress",
    "completed_at": "2026-02-28T12:05:30+00:00",
    "platform_fee_bps": 50,
    "platform_fee_recipient": "0x4Bd14042002BE327751D00fFa4849C28b7c1381F",
    "referrer_address": null,
    "referrer_fee_share_bps": null
}

Tip: Poll every 3-5 seconds until confirmed is true. Set a timeout (e.g. 30 minutes) to stop polling. Your callback URL is also notified server-to-server.

Payment Details

GET https://eppay.io/api/v2/payments/{payment_id}

Full payment object with nested network details.

{
    "payment_id": "8a020135-...",
    "amount": "25.00",
    "to": "0xYourWalletAddress",
    "from": "0xSenderAddress",
    "network": {
        "slug": "bsc",
        "name": "binance",
        "coin": "BNB"
    },
    "token_type": "USDT",
    "status": "completed",
    "tx_hash": "0xabc123...",
    "created_at": "2026-02-28T12:00:00+00:00",
    "completed_at": "2026-02-28T12:05:30+00:00",
    "platform_fee_bps": 50,
    "platform_fee_recipient": "0x4Bd14042002BE327751D00fFa4849C28b7c1381F",
    "referrer_address": null,
    "referrer_fee_share_bps": null
}

Verify Payment

POST https://eppay.io/api/v2/payments/{payment_id}/verify

Called by the EpPay mobile app after the blockchain transaction is confirmed. Triggers the merchant callback.

Request Parameters

Parameter Type Description
status String Must be "success"
txHash String On-chain transaction hash
from String Sender wallet address

Response

{
    "success": true,
    "message": "Payment verified successfully",
    "payment_id": "8a020135-...",
    "status": "completed",
    "tx_hash": "0xabc123...",
    "amount": "25.00",
    "completed_at": "2026-02-28T12:05:30+00:00"
}

Merchant Callback (server-to-server)

EpPay POSTs to your success callback URL:

{
    "success": "success",
    "message": "Payment verified successfully",
    "payment_id": "8a020135-...",
    "amount": "25.00",
    "tx_hash": "0xabc123...",
    "from": "0xSenderAddress",
    "token_type": "USDT",
    "network": "bsc",
    "platform_fee_bps": 50,
    "platform_fee_recipient": "0x4Bd14042002BE327751D00fFa4849C28b7c1381F",
    "referrer_address": null,
    "referrer_fee_share_bps": null
}

Reconciliation tip: when platform_fee_bps > 0, the on-chain transfer to your wallet is amount × (1 − platform_fee_bps / 10000). The platform fee is transferred separately in the same batch to platform_fee_recipient. Your accounting should record the gross amount as revenue and the fee as an expense — your wallet will show the net.

Networks API

GET https://eppay.io/api/v2/networks

Returns all supported blockchain networks with available tokens.

[
    {
        "slug": "bsc",
        "name": "binance",
        "coin": "BNB",
        "chain_id": 56,
        "explorer": "https://bscscan.com",
        "tokens": [
            { "type": "USDT", "available": true },
            { "type": "USDC", "available": true }
        ]
    }
]

Platform Fees

EpPay can charge a transparent stablecoin fee on each payment, expressed in basis points (bps). 1 bps = 0.01%. 50 bps = 0.50%. The fee is deducted on-chain in the same token as the payment (USDT, USDC, etc.), so it's predictable, chain-agnostic, and doesn't depend on native-coin prices.

How the split works

When a buyer pays an invoice of amount tokens, the mobile app sends two on-chain transfers in the same batch:

  • Merchant receives amount × (1 − platform_fee_bps / 10000)
  • EpPay treasury (platform_fee_recipient) receives the whole fee, amount × platform_fee_bps / 10000
  • Referrer (if the invoice names one): EpPay owes them fee × referrer_fee_share_bps / 10000 out of its own fee and settles it separately; it never comes out of the merchant's amount, and a merchant cannot be their own referrer

Example: 25 USDT payment with platform_fee_bps=50 (0.5%), no referrer → merchant gets 24.875 USDT, treasury gets 0.125 USDT.

Who sets the fee?

The fee is set per API key by EpPay. Keys issued since 1 September 2026, and invoices created without a key, carry 50 bps (0.5%); some keys issued earlier carry no fee. We may change fees, including the fee on an existing key: we tell you by e-mail at least 30 days before a change applies to your keys, and if you do not agree you can stop using the key before it takes effect (see the Terms of Service).

The fee cannot be set per invoice: platform_fee_bps and platform_fee_recipient in a request are ignored and logged. Fees already paid on the blockchain are not refunded when you refund a buyer.

Fee fields on every response

These fields appear on create-payment, payments/{id}, payments/{id}/status, and the merchant callback:

Field Type Description
platform_fee_bps Integer or null Fee rate in basis points. null or 0 means no fee was charged.
platform_fee_recipient String or null On-chain address that received the fee. Usually EpPay's treasury.
referrer_address String or null Referrer's on-chain address, if any.
referrer_fee_share_bps Integer or null Referrer's share of the fee in bps, set by EpPay: 2500 (25%) when the invoice has an accepted referrer, otherwise null.

Reconciling your accounts

When platform_fee_bps > 0, your wallet receives the net amount, not the gross. To keep clean books:

  • Record amount as gross revenue against the customer.
  • Record amount × platform_fee_bps / 10000 as a "payment processing" expense.
  • Confirm the on-chain transfer to your wallet matches the net amount (look up tx_hash on the block explorer).

Backward compatibility: the four fee fields are always present in responses but are null unless fees are active for your API key. Your existing integration will keep working without code changes — you only need to handle these fields if you want to display the fee to end users or use them for accounting.

Laravel Package

The eppay/laravel-eppay package provides a clean Facade, Blade components, and automatic status polling for Laravel applications.

Update pending. The published packages (eppay/laravel-eppay 2.0.1 and eppay 2.0.0 on npm) do not send the phone code yet, so eppay.io refuses their payment requests. Until updated versions are out, call Create Payment from your server directly.

Installation

composer require eppay/laravel-eppay

Publish Config

php artisan vendor:publish --tag=eppay-config

Environment Variables

EPPAY_API_KEY=your_api_key_here
EPPAY_PHONE_CODE=your_phone_code_here
EPPAY_DEFAULT_BENEFICIARY=0xYourWalletAddress
EPPAY_DEFAULT_NETWORK=bsc
EPPAY_DEFAULT_TOKEN_TYPE=USDT
EPPAY_SUCCESS_URL=https://yoursite.com/eppay/callback

Usage

Create a Payment

use EpPay\LaravelEpPay\Facades\EpPay;

// Create payment with defaults from .env
$payment = EpPay::createPayment(amount: 25.00);

// Or specify everything
$payment = EpPay::createPayment(
    amount: 25.00,
    to: '0xWalletAddress',
    network: 'bsc',
    tokenType: 'USDT',
    successUrl: route('payment.callback'),
);

// Response:
// $payment['payment_id']   → "8a020135-..."
// $payment['qr_data']      → "product=uuideppay&id=..."
// $payment['payment_url']  → "https://eppay.io/payment/..."
// $payment['network']      → "bsc"
// $payment['token_type']   → "USDT"

Check Payment Status

// Rich status response
$status = EpPay::checkStatus($paymentId);
// $status['confirmed']    → true/false
// $status['status']       → "pending" or "completed"
// $status['tx_hash']      → "0x..." (when completed)
// $status['from']         → "0x..." (sender address)
// $status['completed_at'] → "2026-02-28T..."

// Simple boolean check
if (EpPay::isPaymentCompleted($paymentId)) {
    // Payment is done!
}

// Full payment details (with nested network object)
$details = EpPay::getPaymentDetails($paymentId);

QR Code Generation

// Get QR data string
$qrData = EpPay::getQrCodeData($paymentId);
// → "product=uuideppay&id=8a020135-..."

// Get QR as base64 SVG (for img src)
$qrUrl = EpPay::getQrCodeUrl($paymentId, 300);
// → "data:image/svg+xml;base64,..."

// Get payment page URL
$url = EpPay::getPaymentUrl($paymentId);
// → "https://eppay.io/payment/8a020135-..."

Blade Component

<!-- Auto-polling QR code component -->
<x-eppay-payment-qr
    :payment-id="$paymentId"
    :auto-refresh="true"
    success-url="/payment/success"
    cancel-url="/payment/cancel"
/>

Handle Callback

// routes/web.php
Route::post('/eppay/callback', [PaymentController::class, 'handleCallback']);

// In your controller:
public function handleCallback(Request $request)
{
    $paymentId = $request->input('payment_id');
    $txHash    = $request->input('tx_hash');
    $amount    = $request->input('amount');
    $network   = $request->input('network');

    // Verify payment is actually complete (double-check)
    if (!EpPay::isPaymentCompleted($paymentId)) {
        return response()->json(['error' => 'Not confirmed'], 400);
    }

    // Update your order
    Order::where('payment_id', $paymentId)
         ->update(['status' => 'paid', 'tx_hash' => $txHash]);

    return response()->json(['received' => true]);
}

Available Networks

$networks = EpPay::getNetworks();
// Returns array of networks with slug, name, coin, tokens

JavaScript Checkout Widget

Drop-in payment widget that handles network/token selection, QR code display, and automatic payment status polling. No build tools or dependencies required.

Not available at the moment. This runs in your customer's browser, so it cannot keep your phone code private, and it does not send it. Since 1 November 2026 eppay.io refuses its requests. Create the payment on your server instead (Create Payment), then show your customer the payment_url or QR code from the response.

Installation

Add the script tag to your page:

<script src="https://eppay.io/js/eppay-checkout.js"></script>

Usage

<div id="eppay-checkout"></div>
<script src="https://eppay.io/js/eppay-checkout.js"></script>
<script>
  EpPayCheckout.init({
    container: '#eppay-checkout',
    apiKey: 'YOUR_API_KEY',
    to: '0xYourWalletAddress',
    amount: 25.00,                              // Fixed amount (omit for variable)
    successUrl: 'https://yoursite.com/callback', // Server callback URL
    onComplete: function(paymentId) {
      console.log('Payment completed:', paymentId);
      window.location.href = '/thank-you?payment=' + paymentId;
    }
  });
</script>

Configuration Options

Option Type Required Description
container String Yes CSS selector for the container element
apiKey String Yes Your EpPay API key
to String Yes Your wallet address to receive payments
amount Number No Fixed amount. Omit for customer-editable input.
successUrl String No Server callback URL — receives POST on payment confirmation
onComplete Function No Client-side callback when payment is confirmed. Receives paymentId.
baseUrl String No Override API base URL (default: https://eppay.io)

Widget Flow

  1. Widget loads and fetches available networks from GET /api/v2/networks
  2. Customer selects a blockchain network and token type (USDT or USDC)
  3. If amount is variable, customer enters the payment amount
  4. Widget creates payment via POST /api/v2/create-payment
  5. QR code is displayed for the customer to scan with EpPay mobile app
  6. Widget auto-polls GET /api/v2/payments/{id}/status every 3 seconds
  7. On confirmation, success screen is shown and onComplete callback fires

Hosted Checkout Page

Not available at the moment. This runs in your customer's browser, so it cannot keep your phone code private, and it does not send it. Since 1 November 2026 eppay.io refuses its requests. Create the payment on your server instead (Create Payment), then show your customer the payment_url or QR code from the response.

Redirect customers to the hosted checkout instead of embedding:

https://eppay.io/checkout?apiKey=YOUR_API_KEY&to=0xYourWallet&amount=25.00&success=https://your-site.com/eppay-callback

CORS Enabled: The widget JS and all /api/* endpoints support cross-origin requests from any domain.

Supported Networks

Use the slug value as the network parameter in your API requests.

binance

Binance

bsc
USDT USDC
ethereum

Ethereum

eth
USDT USDC
scimatic

Scimatic

scimatic
USDT
avalanche

Avalanche

avalanche
USDT USDC
polygon

Polygon

polygon
USDT USDC
fantom

Fantom

fantom
USDT USDC
cronos

Cronos

cronos
USDT USDC
arbitrum

Arbitrum

arbitrum
USDT USDC
cosmos

Cosmos

cosmos
USDT
celo

Celo

celo
USDT USDC
tron

Tron

tron
USDT

Network Reference Table

Network Slug Coin USDT USDC
Binance bsc BNB ✓ ✓
Ethereum eth ETH ✓ ✓
Scimatic scimatic SCI ✓ ✗
Avalanche avalanche AVAX ✓ ✓
Polygon polygon MATIC ✓ ✓
Fantom fantom FTM ✓ ✓
Cronos cronos CRO ✓ ✓
Arbitrum arbitrum ARB ✓ ✓
Cosmos cosmos ATOM ✓ ✗
Celo celo CELO ✓ ✓
Tron tron TRX ✓ ✗

Code Examples

JavaScript (Vanilla)

// 1. Create a payment
const response = await fetch('https://eppay.io/api/v2/create-payment', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        apiKey: 'YOUR_API_KEY',
        phone_code: 'YOUR_PHONE_CODE',
        amount: '25.00',
        to: '0xYourWalletAddress',
        network: 'bsc',
        token_type: 'USDT',
        success: 'https://your-site.com/eppay-callback'
    })
});

const data = await response.json();
console.log('Payment ID:', data.payment_id);
console.log('QR data:', data.qr_data);
console.log('Payment URL:', data.payment_url);

// 2. Display QR code (using any QR library)
generateQR(data.qr_data);

// 3. Poll for status
const poll = setInterval(async () => {
    const res = await fetch(
        `https://eppay.io/api/v2/payments/${data.payment_id}/status`
    );
    const status = await res.json();

    if (status.confirmed) {
        clearInterval(poll);
        console.log('Payment confirmed!');
        console.log('TX Hash:', status.tx_hash);
        console.log('From:', status.from);
        window.location.href = '/success?id=' + data.payment_id;
    }
}, 3000);

PHP (cURL)

<?php
// 1. Create a payment
$ch = curl_init('https://eppay.io/api/v2/create-payment');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'apiKey'     => 'YOUR_API_KEY',
        'phone_code' => 'YOUR_PHONE_CODE',
        'amount'     => '25.00',
        'to'         => '0xYourWalletAddress',
        'network'    => 'bsc',
        'token_type' => 'USDT',
        'success'    => 'https://your-site.com/eppay-callback',
    ]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

$paymentId = $result['payment_id'];
echo "QR Data: " . $result['qr_data'];
echo "Payment URL: " . $result['payment_url'];

// 2. Check status
$status = json_decode(
    file_get_contents("https://eppay.io/api/v2/payments/{$paymentId}/status"),
    true
);

if ($status['confirmed']) {
    echo "Paid! TX: " . $status['tx_hash'];
}

Python

import requests, time

# 1. Create payment
resp = requests.post('https://eppay.io/api/v2/create-payment', json={
    'apiKey': 'YOUR_API_KEY',
    'phone_code': 'YOUR_PHONE_CODE',
    'amount': '25.00',
    'to': '0xYourWalletAddress',
    'network': 'bsc',
    'token_type': 'USDT',
    'success': 'https://yoursite.com/callback'
})
data = resp.json()
print(f"Payment: {data['payment_id']}")
print(f"QR: {data['qr_data']}")

# 2. Poll for confirmation
while True:
    status = requests.get(
        f"https://eppay.io/api/v2/payments/{data['payment_id']}/status"
    ).json()
    if status['confirmed']:
        print(f"Confirmed! TX: {status['tx_hash']}")
        break
    time.sleep(3)

Laravel (using eppay/laravel-eppay)

<?php
use EpPay\LaravelEpPay\Facades\EpPay;

// Create payment (uses .env defaults)
$payment = EpPay::createPayment(
    amount: 25.00,
    successUrl: route('payment.callback'),
);

// Redirect to payment page or show QR
return view('payment', [
    'paymentId' => $payment['payment_id'],
    'qrData'    => $payment['qr_data'],
]);

Handling Platform Fees in Your Callback

When EpPay POSTs to your callback URL, the payload includes the fee fields. Record the gross amount against the customer and the fee as an expense, so your books match the on-chain reality.

<?php
// POST handler for your "success" callback URL

$payload = json_decode(file_get_contents('php://input'), true);

// Core fields
$paymentId = $payload['payment_id'];
$grossAmount = (float) $payload['amount'];
$txHash = $payload['tx_hash'];
$buyer = $payload['from'];

// Fee fields (null when fees disabled for this API key)
$feeBps = (int) ($payload['platform_fee_bps'] ?? 0);
$feeAmount = $feeBps > 0 ? $grossAmount * $feeBps / 10000 : 0;
$netAmount = $grossAmount - $feeAmount;

// Record in your ledger
Order::where('payment_id', $paymentId)->update([
    'status'      => 'paid',
    'tx_hash'     => $txHash,
    'buyer'       => $buyer,
    'gross'       => $grossAmount,
    'platform_fee'=> $feeAmount,  // what EpPay kept
    'net_received'=> $netAmount,  // what hit your wallet
]);

http_response_code(200);