Overview
Transaction API provides WebSocket support for real-time payment updates. This allows you to receive instant notifications about payment status changes without polling the API.
Connection
WebSocket URL
wss://api.transaction.gg/ws
Authentication
Include your JWT token in the connection query parameter:
const ws = new WebSocket ( 'wss://api.transaction.gg/ws?token=your_jwt_token' );
Connection Management
Basic Connection
class TransactionWebSocket {
constructor ( token ) {
this . token = token ;
this . ws = null ;
this . reconnectAttempts = 0 ;
this . maxReconnectAttempts = 5 ;
}
connect () {
this . ws = new WebSocket ( `wss://api.transaction.gg/ws?token= ${ this . token } ` );
this . ws . onopen = () => {
console . log ( 'WebSocket connected' );
this . reconnectAttempts = 0 ;
};
this . ws . onmessage = ( event ) => {
const data = JSON . parse ( event . data );
this . handleMessage ( data );
};
this . ws . onclose = () => {
console . log ( 'WebSocket disconnected' );
this . handleReconnect ();
};
this . ws . onerror = ( error ) => {
console . error ( 'WebSocket error:' , error );
};
}
handleMessage ( data ) {
switch ( data . event ) {
case 'payment.status_update' :
this . handlePaymentUpdate ( data );
break ;
case 'payment.completed' :
this . handlePaymentCompleted ( data );
break ;
case 'payment.expired' :
this . handlePaymentExpired ( data );
break ;
default :
console . log ( 'Unknown event:' , data . event );
}
}
handleReconnect () {
if ( this . reconnectAttempts < this . maxReconnectAttempts ) {
this . reconnectAttempts ++ ;
const delay = Math . pow ( 2 , this . reconnectAttempts ) * 1000 ;
setTimeout (() => {
console . log ( `Reconnecting... (attempt ${ this . reconnectAttempts } )` );
this . connect ();
}, delay );
}
}
}
Advanced Connection with Heartbeat
class AdvancedTransactionWebSocket extends TransactionWebSocket {
constructor ( token ) {
super ( token );
this . heartbeatInterval = null ;
this . pingInterval = 30000 ; // 30 seconds
}
connect () {
super . connect ();
this . ws . onopen = () => {
console . log ( 'WebSocket connected' );
this . reconnectAttempts = 0 ;
this . startHeartbeat ();
};
this . ws . onclose = () => {
console . log ( 'WebSocket disconnected' );
this . stopHeartbeat ();
this . handleReconnect ();
};
}
startHeartbeat () {
this . heartbeatInterval = setInterval (() => {
if ( this . ws . readyState === WebSocket . OPEN ) {
this . ws . send ( JSON . stringify ({ type: 'ping' }));
}
}, this . pingInterval );
}
stopHeartbeat () {
if ( this . heartbeatInterval ) {
clearInterval ( this . heartbeatInterval );
this . heartbeatInterval = null ;
}
}
}
Supported Events
Payment Status Update
{
"event" : "payment.status_update" ,
"payment" : {
"id" : "pay_abc123def456" ,
"status" : "pending" ,
"amountCrypto" : "0.00012345" ,
"crypto" : "BTC" ,
"address" : "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" ,
"confirmations" : 2 ,
"requiredConfirmations" : 3
},
"timestamp" : "2024-01-01T00:15:00Z"
}
Payment Completed
{
"event" : "payment.completed" ,
"payment" : {
"id" : "pay_abc123def456" ,
"status" : "completed" ,
"amountCrypto" : "0.00012345" ,
"crypto" : "BTC" ,
"address" : "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" ,
"incomingTxHash" : "abc123..." ,
"completedAt" : "2024-01-01T00:30:00Z" ,
"customerId" : "cus_V6n6SN2KnsIFCuQU" ,
"orderId" : "order_123"
},
"timestamp" : "2024-01-01T00:30:00Z"
}
Payment Expired
{
"event" : "payment.expired" ,
"payment" : {
"id" : "pay_abc123def456" ,
"status" : "expired" ,
"expiresAt" : "2024-01-01T01:00:00Z"
},
"timestamp" : "2024-01-01T01:00:00Z"
}
Event Handling
Payment Status Updates
handlePaymentUpdate ( data ) {
const payment = data . payment ;
// Update UI with new status
this . updatePaymentStatus ( payment . id , payment . status );
// Show confirmation progress
if ( payment . confirmations && payment . requiredConfirmations ) {
const progress = ( payment . confirmations / payment . requiredConfirmations ) * 100 ;
this . updateConfirmationProgress ( payment . id , progress );
}
}
Payment Completion
handlePaymentCompleted ( data ) {
const payment = data . payment ;
// Update order status
this . updateOrderStatus ( payment . orderId , 'completed' );
// Send confirmation email
this . sendConfirmationEmail ( payment . customerId );
// Redirect to success page
this . redirectToSuccess ( payment . orderId );
}
Payment Expiration
handlePaymentExpired ( data ) {
const payment = data . payment ;
// Update order status
this . updateOrderStatus ( payment . orderId , 'expired' );
// Show expiration message
this . showExpirationMessage ( payment . id );
// Offer retry option
this . offerPaymentRetry ( payment . orderId );
}
React Integration
Custom Hook
import { useState , useEffect , useRef } from 'react' ;
function useTransactionWebSocket ( token ) {
const [ connectionStatus , setConnectionStatus ] = useState ( 'disconnected' );
const [ payments , setPayments ] = useState ({});
const wsRef = useRef ( null );
useEffect (() => {
if ( ! token ) return ;
const ws = new WebSocket ( `wss://api.transaction.gg/ws?token= ${ token } ` );
wsRef . current = ws ;
ws . onopen = () => {
setConnectionStatus ( 'connected' );
};
ws . onmessage = ( event ) => {
const data = JSON . parse ( event . data );
if ( data . event === 'payment.status_update' ) {
setPayments ( prev => ({
... prev ,
[data.payment.id]: data . payment
}));
}
};
ws . onclose = () => {
setConnectionStatus ( 'disconnected' );
};
return () => {
ws . close ();
};
}, [ token ]);
return { connectionStatus , payments };
}
Component Usage
function PaymentTracker ({ paymentId , token }) {
const { connectionStatus , payments } = useTransactionWebSocket ( token );
const payment = payments [ paymentId ];
if ( connectionStatus === 'disconnected' ) {
return < div > Connecting to real-time updates... </ div > ;
}
if ( ! payment ) {
return < div > Loading payment... </ div > ;
}
return (
< div >
< h3 > Payment Status: { payment . status } </ h3 >
{ payment . confirmations && (
< div >
Confirmations: { payment . confirmations } / { payment . requiredConfirmations }
</ div >
) }
</ div >
);
}
Error Handling
Connection Errors
class WebSocketErrorHandler {
constructor ( ws ) {
this . ws = ws ;
this . setupErrorHandling ();
}
setupErrorHandling () {
this . ws . onerror = ( error ) => {
console . error ( 'WebSocket error:' , error );
this . handleError ( error );
};
this . ws . onclose = ( event ) => {
if ( ! event . wasClean ) {
console . error ( 'WebSocket closed unexpectedly:' , event . code , event . reason );
this . handleUnexpectedClose ( event );
}
};
}
handleError ( error ) {
// Log error for debugging
console . error ( 'WebSocket error details:' , error );
// Attempt to reconnect
this . attemptReconnect ();
}
handleUnexpectedClose ( event ) {
// Handle different close codes
switch ( event . code ) {
case 1006 : // Abnormal closure
this . attemptReconnect ();
break ;
case 1011 : // Server error
this . handleServerError ();
break ;
default :
this . handleGenericClose ( event );
}
}
}
Best Practices
Connection Management
Implement Reconnection
Always implement automatic reconnection for production applications.
Handle Connection States
Track connection status and show appropriate UI feedback.
Use Heartbeats
Implement ping/pong to detect dead connections.
Graceful Degradation
Fall back to polling if WebSocket connection fails.
// Throttle updates to prevent UI flooding
class ThrottledWebSocket extends TransactionWebSocket {
constructor ( token , throttleMs = 1000 ) {
super ( token );
this . throttleMs = throttleMs ;
this . updateQueue = [];
this . throttleTimer = null ;
}
handleMessage ( data ) {
this . updateQueue . push ( data );
if ( ! this . throttleTimer ) {
this . throttleTimer = setTimeout (() => {
this . processUpdateQueue ();
this . throttleTimer = null ;
}, this . throttleMs );
}
}
processUpdateQueue () {
// Process all queued updates
this . updateQueue . forEach ( data => super . handleMessage ( data ));
this . updateQueue = [];
}
}
WebSocket vs Webhooks
WebSocket Best for:
Real-time UI updates
Client-side applications
Interactive dashboards
Mobile apps
Pros:
Real-time updates
Low latency
Persistent connection
Webhooks Best for:
Server-to-server communication
Backend processing
Reliable delivery
Audit trails
Pros:
Reliable delivery
Retry mechanism
Server-side processing
Better for critical operations
Testing WebSocket Connections
Local Testing
// Test WebSocket connection locally
function testWebSocketConnection () {
const ws = new WebSocket ( 'wss://api.transaction.gg/ws?token=test_token' );
ws . onopen = () => {
console . log ( '✅ WebSocket connected successfully' );
};
ws . onmessage = ( event ) => {
console . log ( '📨 Received message:' , JSON . parse ( event . data ));
};
ws . onerror = ( error ) => {
console . error ( '❌ WebSocket error:' , error );
};
ws . onclose = ( event ) => {
console . log ( '🔌 WebSocket closed:' , event . code , event . reason );
};
}
Production Monitoring
// Monitor WebSocket health in production
class WebSocketMonitor {
constructor ( ws ) {
this . ws = ws ;
this . metrics = {
messagesReceived: 0 ,
connectionUptime: 0 ,
lastMessageTime: null
};
this . startMonitoring ();
}
startMonitoring () {
setInterval (() => {
this . checkConnectionHealth ();
}, 30000 ); // Check every 30 seconds
}
checkConnectionHealth () {
const now = Date . now ();
const timeSinceLastMessage = now - this . metrics . lastMessageTime ;
if ( timeSinceLastMessage > 60000 ) { // 1 minute
console . warn ( 'No messages received in the last minute' );
}
}
}
Production Tip: Use both WebSocket and webhooks for critical applications. WebSocket for real-time UI updates and webhooks for reliable server-side processing.