ws-sdk是什么

229 阅读8分钟

介绍

ws-sdk是前端抽出的与后端建立长链接通信的一个工具包。

特点

基于WebSocket包装器Sockette

  1. 断线重连
  2. 错误数据上报(todo)

流程

SOCKETCONFIG

格式

 const configs = {
    tenantId,
    id,
    keyValue,
    keyIv,
    token,
  };
  localStorage.SOCKETCONFIG = JSON.stringify({
    ...configs,
  });
	connect({...configs});
名称类型含义
tenantIdlong租户id
idint用户id
keyValuestring密钥(16位字符串)
keyIvstring密钥(16位字符串)
tokenstring登陆后鉴权服务返回的token

密钥(keyIv+keyValue 均16位字符串)由用户鉴权服务下发,服务端与客户端依此对通信数据进行AES加密与解密。

来源

登陆接口返回字段 admin/v1/enterprise/user/login 返回如下:

{
    "code": 1,
    "ts": 1692799178,
    "msg": "服务接口调用成功",
    "data": {
        "token": "06369b511fe74990b4f774c91c9f1583",
        "userInfo": {
            "id": 249,
            "tenantId": 1,
            "name": "杜佳桧",
            "account": "dujiahui@huxun",
            "mobile": "18883543938",
            "mainAccount": 0,
            "disabled": null
        },
        "socketVO": {
            "keyValue": "na63neqpwowb3fnt",
            "keyIv": "hnpei6oj91lvtqqk",
            "token": "06369b511fe74990b4f774c91c9f1583"
        }
    }
}

数据协议

数据结构

请求和返回都是二进制数据。数据包含两部分:头部数据+业务二进制数据。

{
  actionType: 7, // 通信的动作类型
	bizType: 0,  // 
	mid: 0, // 消息id 唯一id 
	status: 1,  // 状态 1为成功 其他为失败场景
  // 业务数据
  payload: "{\"actionType\":1,\"bizType\":1,\"content\":\"你可以选择\\\"立即下载\\\"或稍后在下载中心查看\",\"ext\":\"{\\\"name\\\":\\\"客户账单报表_20230823.zip\\\",\\\"path\\\":\\\"convoy/export/20230823/5364ca4c31384bc09bf1d7319414ea4b.xlsx\\\"}\",\"showTime\":5,\"title\":\"导出文件准备完成\"}",
  timestamp: 1692779497702 // 时间
}

字段含义:

名称类型含义
actionTypeint通信的动作类型
bizTypeint业务类型(见数据类)
midlong消息id 唯一id
statusint状态 1为成功 其他为失败场景(具体见数据类)
timestamplong当前时间戳毫秒
payloadstring业务数据

actionType

含义
1建立连接(CONNECT)
2上行业务 (UP)
3下行业务 (DOWN)
5回执 (ACK)
6心跳 (PING)
7心跳响应 (PONG)
8断开连接 (DISCONNECT)

payload

{
  actionType: 1 // 消息展示样式
	bizType: 1 //业务类型
	content: "你可以选择\"立即下载\"或稍后在下载中心查看"
	ext: "{\"name\":\"客户账单报表_20230823.zip\",\"path\":\"convoy/export/20230823/5364ca4c31384bc09bf1d7319414ea4b.xlsx\"}"
	showTime: 5
	title: "导出文件准备完成"
  id: 80800
}
名称类型含义
actionTypeint消息展示样式(具体见3.3.1)
bizTypeint业务类型(具体见3.3.2)
showTimeint气泡展示时长(0-常驻;3-停留3秒;
当actionType为0或者1时必填)
titlestring/reactNode卡片标题
contentstring/reactNode卡片内容

actionType

含义
0全部执行
1只推送气泡
2只保存到消息盒子

bizType

货代 1xx 车队2xx 每个业务组自己占用一段

含义归属业务
1下载类基础公共
2港区数据变更基础公共
100开截港变更货代
101进港异常货代
102码放异常货代
103车队接单货代
104确认费用货代
105车队拒单货代
106到厂预警货代
107运抵预警货代
200货代生成派车单车队
201货代退关车队
202预录异常车队
203箱货对比异常车队
204开截港变更车队
205货代确认费用车队
206货代变更费用车队

ext

{
  name: '客户账单报表_20230823.zip', 
  path: 'convoy/export/20230823/5364ca4c31384bc09bf1d7319414ea4b.xlsx'
}

业务数据

业务数据是需要经过序列化、压缩和加密的二进制数据 流程图如下: image.png 在发送数据之前需要将业务对象实体经过序列化、压缩和加密成二进制数据,在读取则反之。

  • 序列化协议:json
    • 经过json序列化并以UTF-8编码转成二进制字节流。
  • 压缩:zlib
    • 标准zlib压缩算法。
  • 加解密:AES/CBC/PKCS7Padding (128位)
    • 密钥(keyIv+keyValue 均16位字符串)由用户鉴权服务下发,服务端与客户端依此对通信数据进行AES加密与解密

接口

建立连接

头部动作类型:1(CONNECT) 解释: 用户在登陆成功后,带着认证token信息,申请与websocket服务端建立连接,在建连成功后即可传输数据。 注意:这与上面的数据读写流程并不一致(传输的二进制数据只有序列化,没有压缩/加密),因为是初次连接,需要拿到token等信息,但里面的body字段仍然是序列化&压缩&加密的二进制字节数组。

入参定义

名称类型含义
tokenstring登陆后鉴权服务返回的token
terminalint设备类型
bodybyte[]消息体经过序列化并已UTF-8转为字节数组、压缩、加密

消息体:

名称类型含义
timestamplong当前时间戳毫秒
deviceTokenint设备信息,要求非空,可取mac地址
osint端上操作系统类型,0:android,1:ios,2:windows
keepAliveint默认空闲时长 默认15s
appVersionstring客户端版本,要求非空

ACK回执

头部动作类型:5(ACK) 解释: 客户端火服务端在收到对方的消息并处理后,都会给对方返回消息处理结果,即收到ack代表消息已被接收处理。

  1. 比如客户端在请求建连后,服务端可能会回复"成功"(status=1),也可能会回复"鉴权失败"(status=1505)。
  2. 客户端在收到服务端push的消息后,也会给服务端回复"成功"(status=1),同时带上确认的mid。

入参定义

名称类型含义
timestamplong当前时间戳毫秒
midlong消息id 唯一id 不可重复 用于确认当前消息已接收
bizTypeint业务类型
statusint状态 1为成功 其他为失败场景

注意: 前端能处理的最大数为16位,切记不能超过16位,超过会出现精度丢失,导致mid匹配不上。 mid精度丢失的问题,原因是mid是个大数,js的number类型有个最大值(安全值)。即2的53次方减1,为9007199254740991。如果超过这个值,那么js会出现不精确的问题。这个值为16位。现在我们的mid是18位。

心跳机制PING/PONG

头部动作类型:6(PING)或7(PONG) 解释: 为了保持连接通道活跃,客户端每隔一段时间向服务端发送PING数据,服务端则回PONG数据 默认心跳间隔时间: 15s 入参定义

名称类型含义
timestamplong当前时间戳毫秒
midlong消息id 唯一id 不可重复 用于确认当前消息已接收

客户端主动断连

头部动作类型:8(DISCONNECT)。 解释: 客户端或者服务端向另外一端发起关闭连接请求(比如在用户在页面退出登陆时或者多端登陆踢登) 入参定义

名称类型含义
timestamplong当前时间戳毫秒
midlong消息id 唯一id 不可重复 用于确认当前消息已接收

数据上行

头部动作类型:2(UP)。 解释: 客户端向服务器发送数据,即为“上行”。 其中payload存放业务特定的消息对象,由业务自定义,通常为json格式。

入参定义

名称类型含义
timestamplong当前时间戳毫秒
midlong消息id 唯一id 不可重复 用于确认当前消息已接收
bizTypeint业务类型
payloadstring消息体 业务自定义数据的json格式

数据下行

头部动作类型:3(DOWN)。 解释: 服务端向客户端发送数据,即为“下行”。 其中payload存放业务特定的消息对象,由业务方自定义,通常为json格式。

入参定义

名称类型含义
timestamplong当前时间戳毫秒
midlong消息id 唯一id 不可重复 用于确认当前消息已接收
bizTypeint业务类型
payloadstring消息体 业务自定义数据的json格式

数据类

terminal

public enum TerminalEnum {
  ENTERPRISE(0, "企业中心"),
  AGENT(1,  "货代"),
  CONVOY(2,  "车队"),
  YARD(3, "堆场"),
  WAREHOUSE(4, "仓库"),
  SHIPPING_COMPANY(5, "船公司"),
  SHIP_AGENCY(6, "船代"),
  WHARF(7, "码头"),
  BOX_AGENT(8, "放箱代理"),
  LEASING_COMPANY(9,  "租箱公司"),
  MOBILE(20,"司机端"),
  ;
}

bizType

各自业务占用1段code码,不要直接累加

public enum BizTypeEnum {

    UNKNOWN(0, "unknown"),
    /**
     * 手机状态  上行
     */
    APP_STATUS(1, "app_status"),
    /**
     * 系统消息  下行
     */
    SYSTEM(10, "system"),

    /**
     * 订单创建  下行
     */
    ORDER_CREATE(100, "order_create"),
    ;
}

status

public enum SocketStatusEnum {
    SUCCESS(1, "success"),
    PARAM_ERROR(1501, "illegal param"),
    CONNECT_TIMEOUT(1502, "connect timeout"),
    CONNECT_SERVER_UNAVALILABLE(1503, "server unavailable"),
    CONNECT_BODY_NULL(1504, "body is null"),
    AUTH_FAILED(1505, "auto failed"),
    CHANNEL_NOT_EXISTS(1506, "Channel not be found."),
    ILLEGAL_TYPE(1507, "Illegal type."),
    TOO_MANY_REQUEST(1508, "Too many request."),
    DECRY_DATA_FAILED(1509, "Decrypt data failed."),
    DECOMPRESS_DATA_FAILED(1510, "Decompress data failed."),
    MULTI_TERMINAL_FAILED(1511, "Push multi-terminal failed."),
    MULTI_TERMINAL_NOT_SURE(1512, "Push multi-terminal success or failed, not sure."),
    RATELIMIT_PUSHMESSAGE(1513, "Rate limit push socket message."),
    ACM_CONFIG_CANNOT_SEND(1514, "BizType not in ACM config,cannot push socket message."),
    BATCHPUSHMESSAGE_SOME_FAILED(1515, "Batch push message,but some failed.");
}

参考文档

  1. Sockette:GitHub - lukeed/sockette: The cutest little WebSocket wrapper! 🧦