Store WebSocket Connection
Establishes a real-time WebSocket connection for store chat functionality.
WebSocket URL
ws://localhost:8000/v1/chat/ws/store/?token=<auth_token>
wss://api.luxmart.site/v1/chat/ws/store/?token=<auth_token>
Authentication
Pass the store's authentication token as a query parameter:
Connection Lifecycle
1. Connect
const token = "your_store_token_here";
const ws = new WebSocket(`ws://localhost:8000/v1/chat/ws/store/?token=${encodeURIComponent(token)}`);
2. Connection Events
On Open:
On Message:
ws.onmessage = (event) => {
const payload = JSON.parse(event.data);
// Handle different event types
};
On Close:
On Error:
Event Types
1. Receiving Messages
Event Type: message
Payload:
{
"type": "message",
"payload": {
"message": {
"id": 123,
"session_id": 1,
"sender_type": "admin",
"content": "Hello! How can I help you?",
"is_read": false,
"created_at": "2025-12-16T10:20:00Z"
}
}
}
Example Handler:
if (payload.type === "message") {
const message = payload.payload.message;
if (message.sender_type === "admin") {
// Display admin message in chat
displayMessage(message);
}
}
2. Admin Connection Status
Event Type: admin_connected
Sent when an admin claims the session.
Payload:
{
"type": "admin_connected",
"payload": {
"admin_id": 2,
"message": "An admin has joined the chat"
}
}
3. Typing Indicator
Event Type: typing
Indicates when the admin is typing.
Payload:
Example Handler:
if (payload.type === "typing") {
if (payload.payload.sender_type === "admin") {
showTypingIndicator(payload.payload.is_typing);
}
}
4. Error Messages
Event Type: error
Payload:
Sending Messages
1. Send Text Message
Send via WebSocket:
ws.send(JSON.stringify({
type: "message",
payload: {
content: "Hello, I need help with my order"
}
}));
Response:
You'll receive the message back with full details including id and created_at.
2. Send Typing Indicator
// User started typing
ws.send(JSON.stringify({
type: "typing",
payload: {
is_typing: true
}
}));
// User stopped typing (after a delay)
setTimeout(() => {
ws.send(JSON.stringify({
type: "typing",
payload: {
is_typing: false
}
}));
}, 3000);
Complete Example
class StoreChat {
constructor(token, sessionId) {
this.token = token;
this.sessionId = sessionId;
this.ws = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
}
connect() {
const wsUrl = `ws://localhost:8000/v1/chat/ws/store/?token=${encodeURIComponent(this.token)}`;
this.ws = new WebSocket(wsUrl);
this.ws.onopen = () => {
console.log("Chat connected");
this.reconnectAttempts = 0;
};
this.ws.onmessage = (event) => {
const payload = JSON.parse(event.data);
this.handleEvent(payload);
};
this.ws.onclose = () => {
console.log("Chat disconnected");
this.reconnect();
};
this.ws.onerror = (error) => {
console.error("WebSocket error:", error);
};
}
handleEvent(payload) {
switch (payload.type) {
case "message":
if (payload.payload?.message) {
const msg = payload.payload.message;
if (msg.sender_type === "admin") {
this.displayMessage(msg);
}
}
break;
case "admin_connected":
this.showAdminConnected();
break;
case "typing":
if (payload.payload?.sender_type === "admin") {
this.showTypingIndicator(payload.payload.is_typing);
}
break;
case "error":
console.error("Chat error:", payload.payload?.message);
break;
}
}
sendMessage(content) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({
type: "message",
payload: { content }
}));
}
}
sendTyping(isTyping) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({
type: "typing",
payload: { is_typing: isTyping }
}));
}
}
reconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
console.log(`Reconnecting in ${delay}ms...`);
setTimeout(() => this.connect(), delay);
}
}
disconnect() {
if (this.ws) {
this.ws.close();
}
}
displayMessage(message) {
// Implement your UI logic here
console.log(`${message.sender_type}: ${message.content}`);
}
showAdminConnected() {
// Show UI notification that admin joined
console.log("Admin has joined the chat");
}
showTypingIndicator(isTyping) {
// Show/hide typing indicator
console.log(`Admin is ${isTyping ? "typing..." : "not typing"}`);
}
}
// Usage
const chat = new StoreChat(authToken, sessionId);
chat.connect();
Error Handling
Authentication Errors
If the token is invalid or expired, the WebSocket connection will be rejected with a 401 status.
Session Errors
If the store doesn't have an active session, create one first using the REST endpoint:
Connection Errors
Implement exponential backoff for reconnection attempts:
let reconnectDelay = 1000;
const maxDelay = 30000;
function reconnect() {
setTimeout(() => {
connect();
reconnectDelay = Math.min(reconnectDelay * 2, maxDelay);
}, reconnectDelay);
}
Best Practices
- Always URL-encode the token when passing it as a query parameter
- Implement auto-reconnection with exponential backoff
- Handle connection state before sending messages
- Send typing indicators with debouncing (e.g., after 3 seconds of no typing)
- Display connection status to the user (connected/disconnected)
- Buffer messages during disconnection and send when reconnected
- Auto-scroll to the latest message when new messages arrive