Crypto payment integrations are notoriously hard to test. Unlike traditional payment providers where you can trigger test events with a curl command, on-chain payment flows involve external wallets, ledger confirmations, and events that happen asynchronously after a transaction is broadcast.
In 2026, as more applications accept XRPL payments, RLUSD, and crypto-native invoicing, developers need better tooling for webhook testing. This guide covers the three main scenarios you'll encounter and how to handle each one.
Scenario 1: Stripe Crypto Payouts Webhooks
Stripe has expanded its crypto capabilities in 2026. If your platform uses Stripe for any crypto-adjacent features (payouts, crypto-collateral products, or currency conversion), you'll deal with these event types:
payment_intent.succeeded— standard, but may precede a crypto conversion steppayout.paid— fires when crypto proceeds are settled to your accountcrypto.onramp.session.completed— fires when a user completes a crypto purchase via Stripe's onramp
The challenge: Stripe's test mode doesn't always replicate the exact payload structure of crypto events. And if you're building a webhook handler for a new event type, you need to see a real payload before you can write reliable parsing code.
Solution: Catch the real payload first
# 1. Create a HubHook catch endpoint
curl -X POST https://api.hubhook.io/api/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"dev@yourapp.com"}'
# → returns: {"apiKey": "hh_abc123..."}
# 2. Create a hook
curl -X POST https://api.hubhook.io/api/hooks \
-H "X-Api-Key: hh_abc123..." \
-H "Content-Type: application/json" \
-d '{"name":"stripe-crypto-test"}'
# → returns: {"catchUrl": "https://api.hubhook.io/catch/abc123..."}
# 3. Set your Stripe webhook to the catch URL
# In Stripe Dashboard → Developers → Webhooks → Add endpoint
# URL: https://api.hubhook.io/catch/abc123...
Now trigger a Stripe test event. The payload lands in HubHook. You can inspect the full structure — headers, body, event type — before you write a single line of handler code.
Scenario 2: XRPL On-Chain Payment Verification
If you're accepting XRP or RLUSD payments directly on the XRP Ledger, there's no Stripe between you and the user. The payment flow looks like this:
- You generate a destination address + optional destination tag
- User sends payment from their wallet (Xaman, XUMM, exchange)
- Transaction appears on XRPL within 3–5 seconds
- You poll XRPL or subscribe to account notifications to verify payment
- You update your application state accordingly
The "step 4" is where it gets messy. Most apps use one of three approaches:
- XRPL WebSocket subscription: Connect to an XRPL node via WebSocket, subscribe to account transactions, handle payment events in real-time.
- Polling: Check the destination wallet's transaction history every N seconds. Simple but inefficient.
- Third-party webhook services: Services that watch XRPL and POST to your webhook URL when specific events happen.
Testing XRPL payment events with HubHook
For the WebSocket approach, you can simulate incoming events by POSTing directly to your catch URL with a realistic XRPL payment payload:
# Simulate an XRPL payment received event
curl -X POST https://api.hubhook.io/catch/YOUR_HOOK_ID \
-H "Content-Type: application/json" \
-d '{
"type": "transaction",
"transaction": {
"TransactionType": "Payment",
"Account": "rSenderAddress...",
"Destination": "rYourDestAddress...",
"DestinationTag": 12345678,
"Amount": {
"currency": "USD",
"issuer": "rMwjYedjc7qqtKGkQjDe...",
"value": "500"
},
"Fee": "12",
"hash": "A1B2C3D4E5F6..."
},
"validated": true,
"ledger_index": 102407244
}'
Once you've captured this synthetic event, you can inspect it, copy the exact structure, and build your handler to parse real XRPL transaction payloads.
XRPL destination tags: the gotcha
One thing that trips up developers new to XRPL: the destination tag. Unlike a unique deposit address per user (like Bitcoin/Ethereum style), XRPL commonly uses a single address with a numeric destination tag to route payments to specific users or invoices.
Your webhook handler needs to:
- Check that the
DestinationTagmatches a pending invoice in your system - Verify the
Amountmatches the expected amount (for XRP) or that the token issuer is correct (for RLUSD/USDC) - Confirm
validated: truebefore marking the payment as complete
HubHook makes it easy to test all of these edge cases: send 10 different synthetic payloads — some with wrong tags, some with wrong amounts, some unvalidated — and verify your handler correctly accepts only the right one.
Scenario 3: Multi-Chain Payment Events
Some apps in 2026 accept payments on multiple chains: XRPL for XRP/RLUSD, Ethereum for USDC/USDT, Solana for SOL. Each chain has its own event structure. Your webhook handler needs to route and parse them correctly.
A multi-chain payment event router might look like:
# Test your multi-chain handler with different event types
# XRPL payment
curl -X POST https://api.hubhook.io/catch/YOUR_HOOK_ID \
-H "X-Chain: xrpl" \
-H "Content-Type: application/json" \
-d '{"type":"payment","chain":"xrpl","txHash":"A1B2..."}'
# ETH ERC-20 transfer
curl -X POST https://api.hubhook.io/catch/YOUR_HOOK_ID \
-H "X-Chain: ethereum" \
-H "Content-Type: application/json" \
-d '{"type":"transfer","chain":"ethereum","token":"USDC","txHash":"0x1234..."}'
# Solana transfer
curl -X POST https://api.hubhook.io/catch/YOUR_HOOK_ID \
-H "X-Chain: solana" \
-H "Content-Type: application/json" \
-d '{"type":"transfer","chain":"solana","signature":"5K3F..."}'
After sending these, check your HubHook inspector to see each request with its headers and body. If your handler is running locally, use HubHook Pro's relay feature to forward captured events to localhost:3000 for live testing.
The Relay Pattern: Testing Your Local Handler with Production-Structure Events
This is where HubHook Pro becomes valuable for crypto payment testing. The workflow:
- Set your Stripe/XRPL webhook endpoint to your HubHook catch URL
- Trigger a real test payment (Stripe test mode, or XRPL testnet)
- The real event lands in HubHook
- Use the relay feature to forward that exact event to your local handler:
POST /api/hooks/:id/relay/:reqIdwith yourrelayUrl: "http://localhost:3000/webhook" - Your local handler processes a real-structure event — no mocking required
# Relay a captured event to your local server
curl -X POST https://api.hubhook.io/api/hooks/HOOK_ID/relay/REQUEST_ID \
-H "X-Api-Key: hh_pro_key..." \
-H "Content-Type: application/json" \
-d '{"relayUrl": "http://localhost:3000/webhook/payment"}'
# → Returns: {"relayed":true,"status":200,"responseBody":"..."}
This beats ngrok tunnels for this use case because you don't need a public URL during development. You capture events in HubHook, replay them on demand to localhost, and iterate on your handler code.
Webhook Security for Crypto Payments
A few security points specific to crypto payment webhooks:
- Never trust the webhook alone. For XRPL payments, always verify the transaction hash against the actual XRPL ledger before marking a payment complete. HubHook captures what was sent to your endpoint — the source of truth is the blockchain.
- Signature verification is mandatory for Stripe. Stripe signs every webhook with HMAC-SHA256. Your handler should verify this signature. HubHook shows you the
Stripe-Signatureheader in the inspector so you can test your verification logic. - Idempotency for XRPL. XRPL transactions can sometimes be delivered more than once by watch services. Use the transaction hash as an idempotency key — if you've already processed that hash, skip it.
- Amount precision matters. XRP amounts are in drops (1 XRP = 1,000,000 drops). RLUSD amounts are decimal strings. Parse carefully — off-by-one on the decimal can be expensive.
A Quick Reference: Event Types by Source
| Source | Event Type | Key Fields to Verify |
|---|---|---|
| Stripe | payment_intent.succeeded | amount, currency, status, stripe-signature header |
| XRPL | Payment (XRP) | DestinationTag, Amount (drops), validated, hash |
| XRPL | Payment (RLUSD) | Amount.currency, Amount.issuer, Amount.value, validated |
| Ethereum | Transfer (ERC-20) | to, value, contractAddress (must match USDC), confirmations |
| Solana | transfer | destination, amount, mint (for SPL tokens), signature |
Getting Started
The free HubHook tier gives you 3 active hooks with 25 captured requests each — enough to test your Stripe and XRPL integrations thoroughly. Pro ($9/month) adds 50 hooks, 30-day history, and the relay feature for local development forwarding.
Start by creating a hook, pointing your payment provider at the catch URL, and triggering a test transaction. Ten minutes of setup saves hours of debugging "what payload did I actually receive?"