支付宝小程序 WebSocket 仅支持单实例,多次调用 my.connectSocket 会强制关闭前连接;multiple: true 不改变单连接本质;全局事件需统一注册与清除;心跳、重连、域名、header 等均需手动严格配置。
支付宝
小程序的
websocket
不支持多实例,
每次调用都会关闭前一个连接——这不是 bug,是设计限制。如果你在多个页面或组件里各自调用
,后一次会直接干掉前一次,导致前页收不到消息、状态错乱、重连冲突。必须统一管理单个连接实例。
为什么
在多数场景下没用
支付宝文档写明
参数控制是否返回
实例,但关键事实是:即使设为
,底层仍只允许一个活跃连接。基础库 2.9.1+ 默认行为还受
中
影响,但无论怎么配,系统检测到新连接时,旧连接必然被强制关闭。
真机上
只影响返回值类型(是否封装成
),不改变单连接本质
开发工具模拟器可能表现宽松,但真机和线上环境严格遵循单实例策略
试图靠
实现“页面隔离连接”会失败,
回调可能丢失或错配
全局监听器必须集中注册与销毁
支付宝的 WebSocket 事件不是绑定在
上,而是全局注册的:
、
等。这意味着:你在一个页面注册了
,另一个页面也注册,两个回调都会被执行——消息会被重复处理,甚至引发竞态。
所有
必须在 App 或公共模块中统一注册一次,不能在 Page 中多次注册
页面卸载时不能只调用
,还必须显式调用
等清除监听,否则残留监听器会持续触发
推荐做法:在
初始化连接并注册全局监听,在
清理(或按需暂停),避免跨页面污染
心跳 + 重连必须自己实现,SDK 不提供保活逻辑
支付宝没有内置心跳或自动重连机制。
的
参数仅控制连接建立阶段超时(默认 30s),对已建立连接的保活完全无效。弱网、切后台、路由切换都可能导致静默断连,而你收不到任何通知。
ThinkPHP5支付宝支付类库(超级简单,超级好用!)
ThinkPHP5支付宝支付类库(超级简单,超级好用!)
下载
必须手动维护两个定时器:一个发心跳(
),一个等响应(服务端回包);任一超时即判定失联
重连前要加锁(如
),防止
和网络恢复事件同时触发多次重连
服务端必须配合返回心跳应答,且建议带上时间戳或唯一 ID,避免因网络延迟造成误判
注意 iOS 后台限制:小程序进入后台 5 分钟后连接会被系统回收,
里应主动
并清空状态,
再判断是否需要重建
URL 域名和 header 配置容易被忽略的硬性要求
连接失败常卡在配置层,而非代码逻辑。支付宝对 WebSocket 的域名和请求头校验比
更严格,且错误提示模糊(常报 “fail” 无具体原因)。
必须是
(生产)或
(本地调试),HTTP 协议直接拒绝;域名必须提前在开放平台「服务器域名白名单」中添加,且仅支持一级域名(如
,不支持
)
仅在 IDE 3.8.2+ 支持,iOS 客户端要求 header key 全小写(如
),大写会被过滤
URL 中含特殊字符(空格、中文、# 等)必须
编码,否则
直接抛错,不走
回调
服务端若需鉴权,建议把 token 放在 URL query(如
)或
,避免因 header 大小写或版本兼容问题失效
最易被忽略的点是:连接管理必须脱离页面生命周期。把
实例挂在
或独立 store 中,而不是 Page.data;否则页面跳转、销毁时连接状态就丢了,重连逻辑会失控。这和微信小程序的模式完全不同,不能套用经验。
my.connectsocketmy.connectsocketmultiple: truemultipleSocketTasktrueapp.jsonconnectSocketDefaultMultiplemultiple: trueSocketTaskmultiple: trueonMessagemy.onSocket*SocketTaskmy.onSocketOpenmy.onSocketMessagemy.onSocketMessagemy.onSocket*socket.close()my.offSocketMessageApp.onLaunchApp.onHidemy.connectSockettimeoutmy.sendSocketMessageisReconnecting: trueonCloseonHidecloseonShowmy.requesturlwss://ws://wss://api.example.comwss://sub.api.example.comheaderauthorizationencodeURIComponentmy.connectSocketfailwss://x.com?token=xxxheadersocketgetApp()