sdk = new LiveMessage($appId, $appKey, $appSign, $accessKeyId, $accessKeySecret, $dataCenter); } /** * 发送消息到群组 * @param string $groupId 群组ID * @param string $body 消息体 * @param int $msgType 消息类型(业务 type 映射后的阿里云 MsgType) * @param string $senderId 发送者ID * @param string $senderMeta 发送者扩展信息 * @param string $msgTid 消息唯一标识 * @return Result data 含 msg_tid */ public function send($groupId, $body, $msgType = 10001, $senderId = '', $senderMeta = '', $msgTid = '') { // 若未传入 senderId,使用系统默认(管理员发送场景) if ($senderId === '') { $senderId = 'system'; } $result = $this->sdk->sendGroupMessage($groupId, $body, $msgType, $senderId, $senderMeta, $msgTid); if ($result['success']) { return Result::success([ 'msg_tid' => isset($result['data']['msg_tid']) ? $result['data']['msg_tid'] : '', ], $result['raw']); } return Result::fail($result['error'], $result['raw']); } /** * 撤回/删除消息 * @param string $groupId 群组ID * @param string $msgTid 阿里云消息唯一标识 * @return Result */ public function del($groupId, $msgTid) { $result = $this->sdk->deleteGroupMessage($groupId, $msgTid); if ($result['success']) { return Result::success($result['data'], $result['raw']); } return Result::fail($result['error'], $result['raw']); } /** * 获取群组在线用户 * 对于超过 2000 人的超级大群,返回 success=false 且 error='SuperLargeGroup',业务层可降级处理 * @param string $groupId 群组ID * @param int $pageSize 每页数量(10-30,阿里云实际限制) * @param int $nextPageToken 下一页起始位置 * @return Result data 含 total、list、next_page_token、has_more */ public function getOnlineUser($groupId, $pageSize = 20, $nextPageToken = 0) { $result = $this->sdk->listGroupUsers($groupId, $pageSize, $nextPageToken); if ($result['success']) { $data = $result['data']; $userIds = []; if (isset($data['user_list']) && is_array($data['user_list'])) { foreach ($data['user_list'] as $user) { if (isset($user['user_id'])) { $userIds[] = $user['user_id']; } } } return Result::success([ 'total' => count($userIds), 'list' => $userIds, 'next_page_token' => isset($data['next_page_token']) ? $data['next_page_token'] : 0, 'has_more' => isset($data['has_more']) ? $data['has_more'] : false, ], $result['raw']); } // 超级大群特殊错误码,保持与接口约定一致 if ($result['error_code'] === 'SuperLargeGroup') { return Result::fail('SuperLargeGroup', $result['raw']); } return Result::fail($result['error'], $result['raw']); } /** * 获取客户端登录鉴权信息 * 实现 token = sha256(appId + appKey + userId + nonce + timestamp + role) * @param string $userId 用户ID(需过滤,仅保留 A-Z a-z 0-9 -,最长 64 字节) * @param string $role 角色(admin 或空字符串) * @return Result data 含 app_id、app_sign、auth、app_token */ public function getLoginAuth($userId, $role = '') { $appId = $this->sdk->getAppId(); $appKey = $this->sdk->getAppKey(); // userId 过滤:仅保留 [A-Za-z0-9-],最长 64 字节 $filteredUserId = $this->filterUserId($userId); if ($filteredUserId === '') { return Result::fail('userId 无效,过滤后为空', null); } // nonce 生成:AK- + md5(uniqid(mt_rand, true)) $nonce = 'AK-' . md5(uniqid(mt_rand(), true)); // timestamp:当前时间 + 86400 秒 $timestamp = time() + 86400; // role 仅允许 admin 或空字符串 $role = ($role === 'admin') ? 'admin' : ''; // 计算 token $token = hash('sha256', $appId . $appKey . $filteredUserId . $nonce . $timestamp . $role); $data = [ 'app_id' => $appId, 'app_sign' => $this->sdk->getAppSign(), 'auth' => [ 'nonce' => $nonce, 'timestamp' => $timestamp, 'role' => $role, 'user_id' => $filteredUserId, ], 'app_token' => $token, ]; return Result::success($data, null); } /** * 创建群组 * @param string $groupId 群组ID * @param string $groupName 群组名称 * @param string $groupMeta 群组扩展信息 * @return Result */ public function createGroup($groupId, $groupName = '', $groupMeta = '') { $result = $this->sdk->createGroup($groupId, $groupName, $groupMeta); if ($result['success']) { return Result::success($result['data'], $result['raw']); } return Result::fail($result['error'], $result['raw']); } /** * 删除群组 * @param string $groupId 群组ID * @param string $operatorId 操作者ID(可选) * @return Result */ public function deleteGroup($groupId, $operatorId = '') { $result = $this->sdk->deleteGroup($groupId, $operatorId); if ($result['success']) { return Result::success($result['data'], $result['raw']); } return Result::fail($result['error'], $result['raw']); } /** * 获取底层 SDK 实例(供扩展调用,如 listGroups) * @return LiveMessage */ public function getSdk() { return $this->sdk; } /** * 过滤 userId,仅保留 [A-Za-z0-9-],最长 64 字节 * @param string $userId 原始用户ID * @return string */ protected function filterUserId($userId) { $filtered = preg_replace('/[^A-Za-z0-9\-]/', '', (string)$userId); // 截断到 64 字节 if (strlen($filtered) > 64) { $filtered = substr($filtered, 0, 64); } return $filtered; } }