淘宝开放平台 PHP版消息服务TMC客户端开发过程

背景

最近在对接淘宝的接口,在异步回调通知这块,淘宝消息服务采用的是websocket长链接方式进行事件监听,在以往的PHP FPM架构下,PHP语言是一个短生命周期的Web编程语言,做稳定的WebSocket客户端是很困难的,所以在淘宝官方SDK中,只有Java和.Net的WS客户端demo,我们的业务基于PHP8+Swoole,做长链接很简单,而且比较稳定,所以准备自己做一个消息服务TMC客户端来代替用传统HTTP轮训方式的不稳定和低效问题。

中间遇到的问题:

1、无接口文档(通过读java源码和抓包模式)因为官方没有接口文档,只能自己找方法去实现。

2、数据包的封包解包算法需要按照java源码重构一套

3、断线机制导致不得不写个WebSocket抓包工具

实现过程

过程分析:

😁按照国际惯例,先找Github是否有淘宝TMC客户端的代码,找了一番,只找到了一个消息封包解包器,没有完整的代码,不过有了这个解包器,可以减少大量时间。
通讯消息类型分析:

MessageType = 1  握手消息

MessageType = 2 服务器推送消息

MessageType = 3  主动拉取后返回的消息

具体过程如下:

下文按照Hyperf框架,进行过程讲解。

1、创建TMC进程,用来专门监听TMC消息,继承AbstractProcess加上注册进程的注解。

TMCClient为封装的WebSocket客户端 (后续会开源淘宝消息服务TMC PHP版 的composer包)
1、具体实现流程如下,ws建立链接后,发送如下消息进行登录

2、链接成功后,会实时收到当前链接的token信息

3、收到登录成功后,收到了type为1的握手消息,需要将token保存,后续所有操作会使用该token,同时启动一个10秒的定时器,进行心跳处理。

通过以上操作,客户端链接到淘宝ws服务器没问题,能收到token信息,也可以收到下单事件消息,但是客户端只要以发送心跳,服务端立马就断开了链接,为此断点调试N次java代码,找是否遗漏细节问题?心跳代码是否写错?最终对比结构都没问题,陷入了僵局,眼看就要成功了,来了这一出。

无奈只能使用杀手锏 – 抓包,通过抓包来检查细节是否有错,那么又有一个棘手的问题:常规的抓包工具无法解密淘宝TMC的包内容,所以只能自己写一个WebSocket的抓包工具,眼看即将成功的代码,也不想放弃,只能用这个方法了。


WebSocket抓包工具实现原理:

完整逻辑是:

1、主进程,创建一个WebSocket服务器,用来模拟淘宝客户端,供Java连接  下文称:代理客户端1

2、启动一个新协程,创建一个WebSocket客户端,来连接淘宝TMC服务器 下文称 代理客户端2

3、整个链路是发消息:

Java客户端 -> 代理客户端1 -> 解包打印数据结构 -> 重新封包 -> 代理客户端2 -> 淘宝服务器

收消息:淘宝服务器-> 代理客户端2 ->  解包打印数据结构 -> 重新封包-> 代理客户端1 ->Java客户端

通过以上梳理,开始码代码
服务入口文件

代理客户端1 收到Java的事件,打印解密,然后重新封包发给淘宝服务器

 

淘宝客户端 收到淘宝服务消息,通过fd转发给Java客户端

花了将近1个多小时,撸了这个客户端,开始调试的时候,也出现登录连接成功,但是java客户端一发心跳,就出现服务器主动断开的问题,于是猜想:肯定不是包结构的问题造成断开的,然后就把完整的通讯包结构打印了出来,一眼看到了问题所在,push给服务器的消息flags 的值错的,淘宝用的是自定义值33,而我的客户端未设置flags值,没想到居然是这个原因,抓包客户端还没搞完整问题已经找到了….

最终问题分析:封包、解包过程没有问题,忽略了flags的设置,比较坑的是,在发送登录时没有做flags验证,所以问题一直到最后的时候才暴露出来。

小结:

1、本文主要讲述了在没有文档的情况下实现一个三方客户端的接入过程,希望能给大家带来一些感悟,在开发过程中,只要主动思考,有很多方法能够实现最终目标

2、简单实现了一个WebSocket抓包工具,通过代理抓包,获取包内容,实现对应逻辑,通过逆向分析的过程,不需要一行 一行读别人源码,“重要的部分花时间仔细理解”,“其余部分大概知道怎么回事就好”,先整体对这个业务进行了解,就能很快的开展业务,也可以通过该方法,学习一些三方的技术架构以及设计的思路等。

参考:

封包解包器 https://github.com/period331/phptmc

PHP微服务框架:https://hyperf.wiki/2.2/#/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注