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.
- Call
createIntent()— get a unique deposit address and expiry. - Show the deposit address + amount to your customer.
- Customer sends crypto to that address on-chain.
- Platform detects the transfer, fires
payment.partialorpayment.receivedwebhook. - Once confirmed, platform sweeps net funds to your wallet and fires
payment.settled.
/pay/* endpoints. The key's bound network determines which chain the deposit address is created on.Webhook Events
| Event | Fired when |
|---|---|
payment.partial | Transfer detected but total_received < amount |
payment.received | total_received >= amount — settlement begins |
payment.settled | Net funds swept to destination wallet |
payment.expired | Intent 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()
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
| Parameter | Type | Required | Description |
|---|---|---|---|
$amount | string | Yes | Exact amount expected, as decimal string. E.g. "10.50" |
$tokenAddress | string|null | No | ERC-20 contract address. Omit to use the network default (USDT). |
$description | string|null | No | Human-readable label stored with the intent. |
$metadata | array|null | No | Arbitrary key-value pairs (order ID, customer ID, etc.). |
$webhookUrl | string|null | No | URL to receive payment event webhooks. |
$confirmationsRequired | int|null | No | Override 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
| Field | Type | Description |
|---|---|---|
id | string | Intent ID (pi_…) |
amount | string | Required payment amount |
token_address | string | ERC-20 contract or "native" |
token_symbol | string | Human-readable symbol (USDT, MATIC, …) |
network | string | Chain the address lives on |
deposit_address | string | Customer sends funds here |
total_received | string | Sum of all transfers detected so far |
status | string | pending | partial | received | settled | expired |
expires_at | string | ISO 8601 expiry timestamp |
listIntents()
List payment intents for the authenticated client. Paginated, filterable by status.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
$status | string|null | null | Filter: pending | partial | received | settled | expired |
$page | int | 1 | Page number (1-indexed) |
$limit | int | 20 | Results 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()
Retrieve a single payment intent by its ID.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
$intentId | string | Yes | Intent ID (pi_…) |
Example
$intent = Web3Api::pay()->getIntent('pi_abc123def456gh');
// $intent['status'] => "received"
// $intent['total_received'] => "25.00"
listPayments()
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()
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
Get current auto-sweep configuration.
$settings = Web3Api::pay()->getSweepSettings();
// $settings['destination_address'] => "0xYourWallet..."
// $settings['auto_sweep'] => true
// $settings['sweep_threshold'] => "0.01"
Set the wallet address where settled funds are swept, and configure auto-sweep behaviour.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
$destinationAddress | string|null | null | Ethereum address to receive swept funds. Leave null to skip sweeping. |
$autoSweep | bool | true | Enable automatic sweeping after confirmation. |
$sweepThreshold | string | "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_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.
$accounts = Web3Api::pay()->listGasAccounts();
// $accounts['data'] => [
// { network: "polygon", gas_payer: "platform", deposit_address: "0x...", balance: "0.0" },
// ]
Provision a gas account on a network. Each client gets one gas account per network.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
$network | string | Yes | Network slug: polygon, ethereum, bsc, etc. |
$gasPayer | string | "platform" | "platform" or "client" |
Example
$account = Web3Api::pay()->createGasAccount(
network: 'polygon',
gasPayer: 'platform',
);
// $account['deposit_address'] => "0x..." (deposit MATIC here if gas_payer = "client")
Example
$account = Web3Api::pay()->updateGasAccount(
network: 'polygon',
gasPayer: 'client',
lowBalanceThreshold: '0.005',
);
listTokens()
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"