Skip to main content

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

1

Implement Reconnection

Always implement automatic reconnection for production applications.
2

Handle Connection States

Track connection status and show appropriate UI feedback.
3

Use Heartbeats

Implement ping/pong to detect dead connections.
4

Graceful Degradation

Fall back to polling if WebSocket connection fails.

Performance Optimization

// 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.