> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paysight.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Handling

> Learn how to handle events and messages from the Paysight Widget

<Info>
  The Paysight Widget uses a message-based system to communicate events and state changes between your application and the widget. This guide explains how to implement effective event handling.
</Info>

## Event System Overview

Events are handled through the `onMessage` callback provided during widget initialization:

```javascript theme={null}
const widget = PaySightSDK.createWidget({
  targetId: 'widget-container',
  config: { /* ... */ },
  onMessage: (message) => {
    console.log('Event received:', message.type, message.payload);
  }
});
```

<Tabs>
  <Tab title="Event Structure">
    Each event message has a consistent structure:

    ```typescript theme={null}
    interface WidgetMessage<T = unknown> {
      // Event type identifier
      type: string;
      
      // Event data (varies by event type)
      payload: T;
    }
    ```

    <Warning>
      Always check the event type before accessing payload properties, as the payload structure varies by event type.
    </Warning>
  </Tab>

  <Tab title="Event Flow">
    The Paysight Widget communicates with your application through a series of events during key stages of the payment process:

    <Note>
      The event flow typically follows this sequence: Widget initialization → Form interaction events → Payment processing events → Success or error events → Optional 3D Secure events.
    </Note>

    1. **Widget Initialization**: The widget sends a `READY` event when it's fully loaded and ready to accept input.
    2. **Form Interaction**: As users interact with the form, events like `FORM_FIELD_CHANGE` and `FORM_VALIDATION` are triggered.
    3. **Payment Processing**: When a payment is submitted, events like `PAYMENT_START`, `PAYMENT_SUCCESS`, or `PAYMENT_ERROR` are sent.
    4. **3D Secure (if enabled)**: Additional events for 3DS authentication flow.
  </Tab>
</Tabs>

## Event Types

<AccordionGroup>
  <Accordion title="Lifecycle Events" icon="circle-nodes" defaultOpen>
    Events related to the widget's lifecycle:

    ```typescript theme={null}
    // Widget Ready - Fired when the widget is fully loaded and ready
    {
      type: 'READY',
      payload: void
    }

    // Widget Destroyed - Fired when the widget is destroyed
    {
      type: 'DESTROY',
      payload: void
    }
    ```

    <Info>
      The `READY` event indicates that the widget is fully initialized and ready to accept user input. This is a good time to hide any loading indicators.
    </Info>
  </Accordion>

  <Accordion title="Payment Events" icon="credit-card">
    Events related to the payment process:

    ```typescript theme={null}
    // Payment Started - Fired when payment processing begins
    {
      type: 'PAYMENT_START',
      payload: void
    }

    // Payment Successful - Fired when payment is completed successfully
    {
      type: 'PAYMENT_SUCCESS',
      payload: {
        transactionId: string;
        amount: number;
        currency: string;
      }
    }

    // Payment Error - Fired when payment processing fails
    {
      type: 'PAYMENT_ERROR',
      payload: {
        code: string;
        message: string;
        details?: unknown;
      }
    }
    ```

    <Warning>
      Always implement handlers for `PAYMENT_SUCCESS` and `PAYMENT_ERROR` events to provide appropriate feedback to users.
    </Warning>
  </Accordion>

  <Accordion title="3D Secure Events" icon="shield-check">
    Events related to 3DS verification:

    ```typescript theme={null}
    // 3DS Started - Fired when 3DS verification begins
    {
      type: 'PAYMENT_3DS_START',
      payload: void
    }

    // 3DS Successful - Fired when 3DS verification is successful
    {
      type: 'PAYMENT_3DS_SUCCESS',
      payload: void
    }

    // 3DS Error - Fired when 3DS verification encounters an error
    {
      type: 'PAYMENT_3DS_ERROR',
      payload: {
        code: string;
        message: string;
        details?: unknown;
      }
    }

    // 3DS Failed - Fired when 3DS verification fails
    {
      type: 'PAYMENT_3DS_FAILURE',
      payload: {
        code: string;
        message: string;
        details?: unknown;
      }
    }
    ```

    <Info>
      3DS events are only triggered when 3D Secure authentication is enabled in your widget configuration.
    </Info>
  </Accordion>

  <Accordion title="Form Events" icon="rectangle-list">
    Events related to form interactions:

    ```typescript theme={null}
    // Field Change - Fired when a form field value changes
    {
      type: 'FIELD_CHANGE',
      payload: {
        field: string;
        value: unknown;
      }
    }

    // Field Blur - Fired when a form field loses focus
    {
      type: 'FIELD_BLUR',
      payload: {
        field: string;
        value: unknown;
      }
    }

    // Form Submit - Fired when the form is submitted
    {
      type: 'FORM_SUBMIT',
      payload: Record<string, unknown>
    }
    ```

    <Info>
      Form events can be useful for tracking user progress and implementing custom validation logic.
    </Info>
  </Accordion>
</AccordionGroup>

## Implementing Event Handlers

<CodeGroup>
  ```javascript Basic Event Handler theme={null}
  const widget = PaySightSDK.createWidget({
    targetId: 'widget-container',
    config: { /* ... */ },
    onMessage: (message) => {
      switch (message.type) {
        case 'PAYMENT_SUCCESS':
          handlePaymentSuccess(message.payload);
          break;
        case 'PAYMENT_ERROR':
          handlePaymentError(message.payload);
          break;
        case 'PAYMENT_3DS_START':
          show3DSLoadingUI();
          break;
        case 'FORM_SUBMIT':
          handleFormSubmit(message.payload);
          break;
      }
    }
  });
  ```

  ```javascript Complete Event Handling theme={null}
  // Event handlers
  const eventHandlers = {
    // Lifecycle events
    READY: () => {
      console.log('Widget is ready');
      hideLoadingUI();
    },
    
    DESTROY: () => {
      console.log('Widget destroyed');
      cleanupResources();
    },

    // Payment events
    PAYMENT_START: () => {
      console.log('Payment started');
      showLoadingUI();
    },
    
    PAYMENT_SUCCESS: (payload) => {
      console.log('Payment successful:', payload);
      const { transactionId, amount, currency } = payload;
      showSuccessUI(amount, currency);
      // Redirect to success page or show success message
    },
    
    PAYMENT_ERROR: (payload) => {
      console.error('Payment failed:', payload);
      const { code, message } = payload;
      showErrorUI(message);
    },

    // 3DS events
    PAYMENT_3DS_START: () => {
      console.log('3DS verification started');
      show3DSLoadingUI();
    },
    
    PAYMENT_3DS_SUCCESS: () => {
      console.log('3DS verification successful');
      hide3DSLoadingUI();
    },
    
    PAYMENT_3DS_ERROR: (payload) => {
      console.error('3DS verification error:', payload);
      hide3DSLoadingUI();
      showErrorUI(payload.message);
    },

    // Form events
    FIELD_CHANGE: (payload) => {
      console.log('Field changed:', payload);
      const { field, value } = payload;
      updateFormState(field, value);
    },
    
    FORM_SUBMIT: (payload) => {
      console.log('Form submitted:', payload);
      // Handle form data
    }
  };

  // Initialize widget with event handling
  const widget = PaySightSDK.createWidget({
    targetId: 'widget-container',
    config: { /* ... */ },
    onMessage: (message) => {
      const handler = eventHandlers[message.type];
      if (handler) {
        handler(message.payload);
      }
    }
  });
  ```

  ```typescript TypeScript Implementation theme={null}
  interface WidgetMessage<T = unknown> {
    type: string;
    payload: T;
  }

  interface PaymentSuccessPayload {
    transactionId: string;
    amount: number;
    currency: string;
  }

  interface PaymentErrorPayload {
    code: string;
    message: string;
    details?: unknown;
  }

  // Type-safe event handler
  const handleMessage = (message: WidgetMessage) => {
    switch (message.type) {
      case 'PAYMENT_SUCCESS':
        const successPayload = message.payload as PaymentSuccessPayload;
        handlePaymentSuccess(successPayload);
        break;
      case 'PAYMENT_ERROR':
        const errorPayload = message.payload as PaymentErrorPayload;
        handlePaymentError(errorPayload);
        break;
    }
  };
  ```
</CodeGroup>

## Best Practices

<Steps>
  <Step title="Handle Critical Events">
    Always implement handlers for these critical events:

    ```javascript theme={null}
    const criticalEvents = [
      'PAYMENT_SUCCESS',
      'PAYMENT_ERROR',
      'PAYMENT_3DS_ERROR',
      'ERROR'
    ];

    const widget = PaySightSDK.createWidget({
      onMessage: (message) => {
        if (criticalEvents.includes(message.type)) {
          handleCriticalEvent(message);
        }
      }
    });
    ```
  </Step>

  <Step title="Implement Error Recovery">
    ```javascript theme={null}
    const handleError = (error) => {
      // Log error for debugging
      console.error('Widget error:', error);

      // Show user-friendly error message
      showErrorUI(error.message);

      // Attempt recovery based on error type
      if (error.code === 'COMMUNICATION_ERROR') {
        retryConnection();
      }
    };
    ```
  </Step>

  <Step title="Maintain UI State">
    ```javascript theme={null}
    const updateUIState = (message) => {
      switch (message.type) {
        case 'PAYMENT_START':
          showLoadingState();
          break;
        case 'PAYMENT_SUCCESS':
          showSuccessState();
          break;
        case 'PAYMENT_ERROR':
          showErrorState();
          break;
      }
    };
    ```
  </Step>

  <Step title="Provide User Feedback">
    Always update your UI based on event messages to keep users informed about the payment process status.

    <Info>
      Clear user feedback improves conversion rates and reduces support inquiries.
    </Info>
  </Step>
</Steps>

<Accordion title="Common Event Handling Patterns">
  ### Redirect After Payment

  ```javascript theme={null}
  onMessage: (message) => {
    if (message.type === 'PAYMENT_SUCCESS') {
      // Show success message
      showSuccessMessage();
      
      // Redirect to order confirmation page
      setTimeout(() => {
        window.location.href = `/confirmation?orderId=${orderId}&transactionId=${message.payload.transactionId}`;
      }, 1000);
    }
  }
  ```

  ### Updating Order Status

  ```javascript theme={null}
  onMessage: async (message) => {
    if (message.type === 'PAYMENT_SUCCESS') {
      // Update order status in your system
      try {
        await updateOrderStatus(orderId, 'paid', message.payload.transactionId);
        showSuccessMessage('Payment successful! Your order has been confirmed.');
      } catch (error) {
        // Handle order update error
        console.error('Failed to update order status:', error);
        showWarningMessage('Payment successful, but order status update failed. Please contact support.');
      }
    }
  }
  ```
</Accordion>

## Next Steps

<CardGroup cols={3}>
  <Card title="Styling Guide" icon="palette" href="/widget-sdk/guides/styling">
    Learn how to customize the widget appearance to match your brand.
  </Card>

  <Card title="Localization Guide" icon="globe" href="/widget-sdk/guides/localization">
    Implement multi-language support for global customers.
  </Card>

  <Card title="Events Reference" icon="sheet-plastic" href="/widget-sdk/reference/events">
    Complete events documentation
  </Card>
</CardGroup>
