Files
YwxAppThink/addon/wxchat/worker/Message.php
T

259 lines
7.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace addon\wxchat\worker;
/**
* 消息实体类
*/
class Message implements \JsonSerializable
{
private array $fields = ['header', 'payload'];
private Header $header; // 消息扩展信息
private Payload $payload; // 消息扩展信息
public function __construct()
{
$this->header = new Header();
$this->payload = new Payload();
}
public function __set($name, $value)
{
$this->$name = $value;
}
public function __get($name)
{
if (isset($this->$name)) {
return $this->$name;
}
return null;
}
public function jsonSerialize(): array
{
$data = [];
foreach ($this->fields as $key) {
if (isset($this->$key) && $this->$key !== null) {
$data[$key] = $this->$key;
}
}
return $data;
}
// 反序列化:JSON → Message
public static function fromJson(string $json): self
{
$data = json_decode($json, true);
if (! is_array($data)) {
throw new \InvalidArgumentException('Invalid JSON structure');
}
return self::fromArray($data);
}
// 反序列化:数组 → Message
public static function fromArray(array $data): self
{
$message = new self();
foreach ($message->fields as $key) {
if (! isset($data[$key]) || empty($data[$key])) {
continue;
}
if ($key == 'header') {
$message->header = Header::fromArray($data['header']);
} else if ($key == 'payload') {
$message->payload = Payload::fromArray($data['payload']);
} else {
$message->$key = $data[$key];
}
}
return $message;
}
}
/**
* 消息头信息
*/
class Header implements \JsonSerializable
{
protected array $fields = ['frame', 'id', 'type', 'target', 'seqno', 'timestamp', 'source', 'version', 'token', 'platform', 'device_id', 'network_type'];
private string $id; // 消息唯一ID(雪花算法生成,必填)
private string $type = ''; // 消息类型(必填)
private string $target = 'system'; // 目标会话类型(single/group/room/system,选填)
private int $seqno = 0; // 消息序列号(同一会话内递增,或全局唯一)
private int $timestamp; // 消息生成时间(Unix时间戳,毫秒级)
private string $source = 'server'; // 消息来源(user_id或system,选填)
private string $version = '1.0.0'; // 协议版本(默认1.0.0,选填)
private string $token; // 认证Token(选填,连接控制帧可选)
private string $platform; // 平台类型
private string $device_id; // 设备ID
private string $network_type; // 网络类型
public function __construct()
{
$this->id = 'msg_' . substr(md5(uniqid((string) mt_rand(), true)), 0, 16);
$this->timestamp = time() * 1000; // 毫秒级时间戳
}
//__set()方法用来设置私有属性
public function __set($name, $value)
{
$this->$name = $value;
}
//__get()方法用来获取私有属性
public function __get($name)
{
return $this->$name;
}
// ✅ 严格实现接口方法
public function jsonSerialize(): array
{
$data = [];
foreach ($this->fields as $key) {
if (isset($this->$key) && $this->$key !== null) {
$data[$key] = $this->$key;
}
}
return $data;
}
public function toArray(): array
{
// 仅输出非 null 值(符合“可选字段”语义)
$data = [];
foreach ($this->fields as $key) {
if (isset($this->$key) && $value !== null) {
$data[$key] = $value;
}
}
return $data;
}
// 反序列化:JSON → Message
public static function fromJson(string $json): self
{
$data = json_decode($json, true);
if (! is_array($data)) {
throw new \InvalidArgumentException('Invalid JSON structure');
}
return self::fromArray($data);
}
public static function fromArray(array $data): self
{
$header = new self();
foreach ($header->fields as $key) {
if (isset($data[$key]) && ! empty($data[$key])) {
$header->$key = $data[$key];
}
}
return $header;
}
}
/**
* 消息扩展信息
*/
class Payload implements \JsonSerializable
{
private array $fields = ['uid', 'nickname', 'avatar', 'session_id', 'receiver', 'content', 'type', 'status', 'msg_id', 'at_user', 'ext'];
private int $uid = 0; // 用户ID(发送者)
private string $nickname; // 昵称(可选,用于显示)
private string $avatar; // 头像URL(可选,用于显示)
private string $session_id; // 会话ID(单聊为对方UID,群聊为group_id,系统消息可选)
private int $receiver; // 接收用户UID(单聊必填,群聊可选)
private mixed $content; // 消息内容(文本直接字符串,其他类型可为URL或结构化数据)
private string $type; // 消息类型(text/image/voice/video/file/system/notification/typing/read/revoke
private string $status = 'delivered'; // 消息状态(sending/sent/delivered/read/failed
private string $msg_id; // 消息ID(可选,服务端生成或客户端指定)
private array $at_user; // @了哪些人(可选,群聊中使用)
private mixed $ext; // 扩展字段(可选,根据业务需求定义)
//__set()方法用来设置私有属性
public function __set($name, $value)
{
$this->$name = $value;
}
//__get()方法用来获取私有属性
public function __get($name)
{
return $this->$name;
}
public function jsonSerialize(): array
{
$data = [];
foreach ($this->fields as $key) {
if (isset($this->$key) && $this->$key !== null) {
$data[$key] = $this->$key;
}
}
return $data;
}
public function toArray(): array
{
// 仅输出非 null 值(符合“可选字段”语义)
$data = [];
foreach ($this->fields as $key) {
$value = $this->$key ?? null;
if (isset($this->$key) && $value !== null) {
$data[$key] = $value;
}
}
return $data;
}
public static function fromJson(string $json): self
{
$data = json_decode($json, true);
if (! is_array($data)) {
throw new \InvalidArgumentException('Invalid JSON structure');
}
return self::fromArray($data);
}
public static function fromArray(array $data): self
{
$payload = new self();
foreach ($payload->fields as $key) {
if (isset($data[$key]) && ! empty($data[$key])) {
$payload->$key = $data[$key];
}
}
return $payload;
}
// 其他属性的 getter/setter 按相同模式补充...
}