Module

Payment Gateway — FREE (withdrawal fee at settlement)

Accept crypto payments from your customers. Each payment intent generates a unique deposit address. The platform monitors incoming transfers on-chain, fires webhooks, and auto-sweeps confirmed funds to your wallet. No credits are deducted — the platform takes a percentage fee from the settled amount.

ℹ️
How it works:
  1. Call createIntent() — get a unique deposit address and expiry.
  2. Show the deposit address + amount to your customer.
  3. Customer sends crypto to that address on-chain.
  4. Platform detects the transfer, fires payment.partial or payment.received webhook.
  5. Once confirmed, platform sweeps net funds to your wallet and fires payment.settled.
⚠️
API Key required for all /pay/* endpoints. The key's bound network determines which chain the deposit address is created on.

Webhook Events

EventFired when
payment.partialTransfer detected but total_received < amount
payment.receivedtotal_received >= amount — settlement begins
payment.settledNet funds swept to destination wallet
payment.expiredIntent expired before full payment. Partial funds go to platform profit wallet.

Webhook payload is signed with HMAC-SHA256. The signature is in the X-Web3Api-Signature header.

createIntent()

createIntent()
POST FREE API Key

Create a payment intent. Returns a unique deposit address. The customer sends the exact amount of token to deposit_address. The intent expires after 30 minutes.

Parameters

ParameterTypeRequiredDescription
$amountstringYesExact amount expected, as decimal string. E.g. "10.50"
$tokenAddressstring|nullNoERC-20 contract address. Omit to use the network default (USDT).
$descriptionstring|nullNoHuman-readable label stored with the intent.
$metadataarray|nullNoArbitrary key-value pairs (order ID, customer ID, etc.).
$webhookUrlstring|nullNoURL to receive payment event webhooks.
$confirmationsRequiredint|nullNoOverride default confirmation count (default: 2).

Example

$intent = Web3Api::pay()->createIntent(
    amount:      '25.00',
    description: 'Order #1042',
    metadata:    ['order_id' => 1042, 'customer_id' => 'usr_abc'],
    webhookUrl:  'https://yourapp.com/webhooks/crypto',
);

// Show to customer:
// $intent['deposit_address']  => "0x9Fe46736679d2D9a65F0992F2272dE9f3c7fa6e0"
// $intent['amount']           => "25.00"
// $intent['token_symbol']     => "USDT"
// $intent['network']          => "polygon"
// $intent['expires_at']       => "2024-06-01T12:30:00+00:00"
// $intent['id']               => "pi_abc123def456gh"

Response

FieldTypeDescription
idstringIntent ID (pi_…)
amountstringRequired payment amount
token_addressstringERC-20 contract or "native"
token_symbolstringHuman-readable symbol (USDT, MATIC, …)
networkstringChain the address lives on
deposit_addressstringCustomer sends funds here
total_receivedstringSum of all transfers detected so far
statusstringpending | partial | received | settled | expired
expires_atstringISO 8601 expiry timestamp

listIntents()

listIntents()
GET FREE API Key

List payment intents for the authenticated client. Paginated, filterable by status.

Parameters

ParameterTypeDefaultDescription
$statusstring|nullnullFilter: pending | partial | received | settled | expired
$pageint1Page number (1-indexed)
$limitint20Results per page (1–100)

Example

// All intents
$result = Web3Api::pay()->listIntents();

// Only settled, page 2
$result = Web3Api::pay()->listIntents(status: 'settled', page: 2, limit: 50);

// $result['data']  => [ { id, amount, status, deposit_address, ... }, ... ]
// $result['total'] => 142
// $result['page']  => 2
// $result['limit'] => 50

getIntent()

getIntent()
GET FREE API Key

Retrieve a single payment intent by its ID.

Parameters

ParameterTypeRequiredDescription
$intentIdstringYesIntent ID (pi_…)

Example

$intent = Web3Api::pay()->getIntent('pi_abc123def456gh');
// $intent['status']         => "received"
// $intent['total_received'] => "25.00"

listPayments()

listPayments()
GET FREE API Key

List all on-chain transfers detected for an intent. One row per transaction. Useful if the customer sent multiple partial payments.

Example

$payments = Web3Api::pay()->listPayments('pi_abc123def456gh');
// $payments['data'] => [
//   { id: "pay_…", tx_hash: "0x…", amount_received: "15.00", status: "confirmed", … },
//   { id: "pay_…", tx_hash: "0x…", amount_received: "10.00", status: "confirmed", … },
// ]

getSettlement()

getSettlement()
GET FREE API Key

Get the settlement breakdown for a completed intent. Available after status is settled.

Example

$settlement = Web3Api::pay()->getSettlement('pi_abc123def456gh');
// $settlement['gross_amount']  => "30.00"   // total received
// $settlement['fee_amount']    => "0.90"    // platform fee (%)
// $settlement['net_amount']    => "25.00"   // swept to your wallet
// $settlement['excess_amount'] => "4.10"    // overpayment → platform profit wallet
// $settlement['sweep_tx_hash'] => "0x..."   // on-chain sweep tx
// $settlement['excess_tx_hash']=> "0x..."   // on-chain excess tx

Sweep Settings

getSweepSettings()
GET FREE API Key

Get current auto-sweep configuration.

$settings = Web3Api::pay()->getSweepSettings();
// $settings['destination_address'] => "0xYourWallet..."
// $settings['auto_sweep']          => true
// $settings['sweep_threshold']     => "0.01"
updateSweepSettings()
PUT FREE API Key

Set the wallet address where settled funds are swept, and configure auto-sweep behaviour.

Parameters

ParameterTypeDefaultDescription
$destinationAddressstring|nullnullEthereum address to receive swept funds. Leave null to skip sweeping.
$autoSweepbooltrueEnable automatic sweeping after confirmation.
$sweepThresholdstring"0.01"Minimum balance (in token) to trigger a sweep.

Example

$settings = Web3Api::pay()->updateSweepSettings(
    destinationAddress: '0xYourBusinessWallet...',
    autoSweep:          true,
    sweepThreshold:     '5.00',
);

Gas Accounts

ℹ️
Gas accounts are only needed when gas_payer = "client". By default the platform pays sweep gas and recoups it from the fee. Set gas_payer to "client" and deposit native coin (MATIC, ETH, BNB, …) into the gas account address to pay sweep gas yourself.
listGasAccounts()
GET FREE API Key
$accounts = Web3Api::pay()->listGasAccounts();
// $accounts['data'] => [
//   { network: "polygon", gas_payer: "platform", deposit_address: "0x...", balance: "0.0" },
// ]
createGasAccount()
POST FREE API Key

Provision a gas account on a network. Each client gets one gas account per network.

Parameters

ParameterTypeRequiredDescription
$networkstringYesNetwork slug: polygon, ethereum, bsc, etc.
$gasPayerstring"platform""platform" or "client"

Example

$account = Web3Api::pay()->createGasAccount(
    network:  'polygon',
    gasPayer: 'platform',
);
// $account['deposit_address'] => "0x..."   (deposit MATIC here if gas_payer = "client")
updateGasAccount()
PATCH FREE API Key

Example

$account = Web3Api::pay()->updateGasAccount(
    network:             'polygon',
    gasPayer:            'client',
    lowBalanceThreshold: '0.005',
);

listTokens()

listTokens()
GET FREE API Key

List ERC-20 tokens (and native) accepted by the payment gateway. Use token_address from this list when calling createIntent().

Example

$tokens = Web3Api::pay()->listTokens(network: 'polygon');
// $tokens['data'] => [
//   { network: "polygon", token_address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
//     symbol: "USDT", decimals: 6, is_default: true },
//   { network: "polygon", token_address: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
//     symbol: "USDC", decimals: 6, is_default: false },
// ]

Full Flow Example

<?php
use Web3Sdk\Laravel\Facades\Web3Api;

// 1. Create intent when customer clicks "Pay with Crypto"
$intent = Web3Api::pay()->createIntent(
    amount:      '49.99',
    description: 'Pro Plan — 1 month',
    metadata:    ['user_id' => auth()->id(), 'plan' => 'pro'],
    webhookUrl:  route('webhooks.crypto'),
);

// 2. Show to customer
return view('checkout.crypto', [
    'address'   => $intent['deposit_address'],
    'amount'    => $intent['amount'],
    'symbol'    => $intent['token_symbol'],
    'network'   => $intent['network'],
    'expiresAt' => $intent['expires_at'],
    'intentId'  => $intent['id'],
]);

// 3. Webhook handler — receives payment.partial / payment.received / payment.settled
Route::post('/webhooks/crypto', function (Request $request) {
    $event    = $request->input('event');
    $intentId = $request->input('intent_id');
    $status   = $request->input('status');

    if ($event === 'payment.settled') {
        // Funds confirmed and swept — activate the subscription
        Order::where('intent_id', $intentId)->update(['status' => 'paid']);
    }

    return response()->json(['ok' => true]);
})->name('webhooks.crypto');

// 4. Manual status poll (optional)
$intent = Web3Api::pay()->getIntent($intentId);
// $intent['status']         => "settled"
// $intent['total_received'] => "49.99"