Chuyển tới nội dung chính

Kết Nối & Xác Thực

Endpoint

wss://api.simplize.vn/v2/ws

Không cần query parameter. Yêu cầu TLS (wss://).


Trình Tự Handshake

Client                    Server
│ │
│──── TCP/WS connect ─────▶│
│◀─── connected ───────────│ ← thông số kết nối
│ │
│──── auth {token} ────────▶│ ← trong vòng 10 giây
│◀─── auth_ok ─────────────│
│ │
│ ... sẵn sàng ... │

Bước 1: Nhận connected

Server gửi ngay sau khi kết nối TCP thành công:

{
"type": "connected",
"sid": "550e8400-e29b-41d4-a716",
"ping_interval": 25000,
"ping_timeout": 20000,
"max_payload": 2097152
}
FieldKiểuMô tả
sidstringConnection ID dùng để debug
ping_intervalnumberServer gửi ping mỗi X ms
ping_timeoutnumberThời gian chờ pong tối đa (ms)
max_payloadnumberKích thước message tối đa (bytes)

Bước 2: Gửi auth

{
"type": "auth",
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Phải gửi trong 10 giây sau khi nhận connected. Nếu không, server đóng với code 4001.

Bước 3: Nhận auth_ok

{
"type": "auth_ok"
}

Từ đây có thể gửi chat, subscribe, ...


Mã Lỗi Kết Nối

CodeNguyên nhânXử lý
4001Timeout auth hoặc không gửi authLấy token mới rồi connect lại
4003Token không hợp lệ hoặc hết hạnRefresh token rồi connect lại
4008Không phản hồi heartbeat (zombie)Tự động connect lại

Heartbeat

Server gửi {"type": "ping"} mỗi 25 giây. Client phải phản hồi {"type": "pong"} trong 20 giây. Sau 2 lần miss liên tiếp, server đóng với code 4008.

Client cũng có thể chủ động gửi ping; server sẽ trả pong.


Ví Dụ: React.js

import { useEffect, useRef } from 'react'

function useAgentWS(token) {
const wsRef = useRef(null)

useEffect(() => {
const ws = new WebSocket('wss://api.simplize.vn/v2/ws')
wsRef.current = ws

ws.onmessage = (e) => {
const msg = JSON.parse(e.data)

if (msg.type === 'connected') {
ws.send(JSON.stringify({ type: 'auth', token }))
}

if (msg.type === 'auth_ok') {
console.log('Sẵn sàng')
}

if (msg.type === 'ping') {
ws.send(JSON.stringify({ type: 'pong' }))
}

if (msg.type === 'error') {
console.error('Lỗi:', msg.code, msg.message)
}
}

ws.onclose = (e) => {
if (e.code !== 4001 && e.code !== 4003) {
// Reconnect sau 3 giây
setTimeout(() => reconnect(), 3000)
}
}

return () => ws.close()
}, [token])

return wsRef
}

Ví Dụ: Flutter (Dart)

import 'dart:convert';
import 'package:web_socket_channel/web_socket_channel.dart';

class AgentWebSocket {
WebSocketChannel? _channel;
final String _token;

AgentWebSocket(this._token);

void connect() {
_channel = WebSocketChannel.connect(
Uri.parse('wss://api.simplize.vn/v2/ws'),
);

_channel!.stream.listen(
(data) => _handleMessage(jsonDecode(data as String)),
onDone: _handleDisconnect,
onError: (e) => print('WS Error: $e'),
);
}

void _handleMessage(Map<String, dynamic> msg) {
switch (msg['type']) {
case 'connected':
_send({'type': 'auth', 'token': _token});
break;
case 'auth_ok':
print('Sẵn sàng');
break;
case 'ping':
_send({'type': 'pong'});
break;
case 'error':
print('Lỗi: ${msg['code']} - ${msg['message']}');
break;
}
}

void _handleDisconnect() {
// Reconnect sau 3 giây
Future.delayed(const Duration(seconds: 3), connect);
}

void _send(Map<String, dynamic> data) {
_channel?.sink.add(jsonEncode(data));
}

void dispose() {
_channel?.sink.close();
}
}