初始化项目:添加后端代码、ThinkPHP框架、前端资源

This commit is contained in:
amb
2026-09-03 12:42:39 +08:00
commit 482bece22e
3726 changed files with 416708 additions and 0 deletions
+460
View File
@@ -0,0 +1,460 @@
<?php
namespace aliyun;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
/**
* 阿里云直播互动消息 SDK 封装
* 基于 AlibabaCloud RPC 调用方式封装:
* - SendLiveMessageGroup 发送消息到群组
* - DeleteLiveMessageGroupMessage 删除(撤回)某条群组消息
* - ListLiveMessageGroupUsers 查询群组用户列表
* - CheckLiveMessageUsersOnline 查询指定的用户是否在线
* - CreateLiveMessageGroup 创建互动消息群组
*
* 统一异常处理:捕获 ServerException/ClientException,转换为统一错误返回数组
* 返回数组结构:['success' => bool, 'data' => mixed, 'error' => string, 'error_code' => string, 'raw' => mixed]
*/
class LiveMessage
{
/**
* @var string 互动消息应用 AppId
*/
protected $appId;
/**
* @var string 互动消息应用 AppKey(仅后端使用)
*/
protected $appKey;
/**
* @var string 互动消息应用 AppSign
*/
protected $appSign;
/**
* @var string 阿里云 RAM 用户 AccessKeyId
*/
protected $accessKeyId;
/**
* @var string 阿里云 RAM 用户 AccessKeySecret
*/
protected $accessKeySecret;
/**
* @var string 数据中心(cn-shanghai / ap-southeast-1
*/
protected $dataCenter;
/**
* @var bool 是否已初始化默认客户端
*/
protected static $clientInited = false;
/**
* 构造函数
* @param string $appId 互动消息应用 AppId
* @param string $appKey 互动消息应用 AppKey
* @param string $appSign 互动消息应用 AppSign
* @param string $accessKeyId 阿里云 RAM 用户 AccessKeyId
* @param string $accessKeySecret 阿里云 RAM 用户 AccessKeySecret
* @param string $dataCenter 数据中心
*/
public function __construct($appId, $appKey, $appSign, $accessKeyId, $accessKeySecret, $dataCenter)
{
$this->appId = $appId;
$this->appKey = $appKey;
$this->appSign = $appSign;
$this->accessKeyId = $accessKeyId;
$this->accessKeySecret = $accessKeySecret;
// 兼容历史脏数据:中文 label 归一化为 region id
$regionMap = ['上海' => 'cn-shanghai', '新加坡' => 'ap-southeast-1'];
$this->dataCenter = $regionMap[$dataCenter] ?? ($dataCenter ?: 'cn-shanghai');
$this->initClient();
}
/**
* 初始化阿里云默认客户端(全局只初始化一次)
* @return void
*/
protected function initClient()
{
if (self::$clientInited) {
return;
}
try {
AlibabaCloud::accessKeyClient($this->accessKeyId, $this->accessKeySecret)
->connectTimeout(5000)
->timeout(10000)
->asDefaultClient();
self::$clientInited = true;
} catch (\Exception $e) {
// 初始化失败时记录日志,后续调用会抛出异常
\think\Log::error('[aliyun LiveMessage] initClient failed: ' . $e->getMessage());
}
}
/**
* 发起 RPC 请求
* @param string $action 接口动作名
* @param array $params 请求参数
* @return array 统一返回结构
*/
protected function rpc($action, array $params = [])
{
try {
// RPC 调用需要指定 RegionId,阿里云互动消息服务与直播服务共用 live 产品,默认使用 cn-shanghai
$regionId = $this->dataCenter ? $this->dataCenter : 'cn-shanghai';
$request = AlibabaCloud::rpc()
->product('live')
->version('2016-11-01')
->action($action)
->method('POST')
->scheme('https')
->regionId($regionId);
if ($params) {
$request->options(['query' => $params]);
}
$result = $request->request();
$dataArray = $result->toArray();
return [
'success' => true,
'data' => $dataArray,
'error' => '',
'error_code' => '',
'raw' => $dataArray,
];
} catch (ServerException $e) {
return [
'success' => false,
'data' => null,
'error' => $e->getErrorMessage(),
'error_code' => $e->getErrorCode(),
'raw' => $e->getResult() ? $e->getResult()->toArray() : null,
];
} catch (ClientException $e) {
return [
'success' => false,
'data' => null,
'error' => $e->getErrorMessage(),
'error_code' => $e->getErrorCode(),
'raw' => null,
];
} catch (\Exception $e) {
return [
'success' => false,
'data' => null,
'error' => $e->getMessage(),
'error_code' => 'Unknown',
'raw' => null,
];
}
}
/**
* 发送消息到群组(SendLiveMessageGroup
* @param string $groupId 群组ID
* @param string $body 消息体
* @param int $msgType 消息类型
* @param string $senderId 发送者ID
* @param string $senderMeta 发送者扩展信息
* @param string $msgTid 消息唯一标识
* @return array data 含 msg_tid
*/
public function sendGroupMessage($groupId, $body, $msgType, $senderId, $senderMeta, $msgTid)
{
$params = [
'AppId' => $this->appId,
'GroupId' => $groupId,
'SenderId' => $senderId,
'Body' => $body,
'DataCenter' => $this->dataCenter,
];
if ($msgType) {
$params['MsgType'] = (int)$msgType;
}
if ($senderMeta !== '') {
$params['SenderMetaInfo'] = $senderMeta;
}
if ($msgTid !== '') {
$params['MsgTid'] = $msgTid;
}
$result = $this->rpc('SendLiveMessageGroup', $params);
if ($result['success']) {
$data = $result['data'];
$result['data'] = [
'msg_tid' => isset($data['MsgTid']) ? $data['MsgTid'] : '',
'request_id' => isset($data['RequestId']) ? $data['RequestId'] : '',
];
}
return $result;
}
/**
* 删除(撤回)某条群组消息(DeleteLiveMessageGroupMessage
* @param string $groupId 群组ID
* @param string $messageId 消息ID(与发送消息返回的 MsgTid 对应)
* @return array data 含 group_id、message_id
*/
public function deleteGroupMessage($groupId, $messageId)
{
$params = [
'AppId' => $this->appId,
'GroupId' => $groupId,
'MessageId' => $messageId,
'DataCenter' => $this->dataCenter,
];
$result = $this->rpc('DeleteLiveMessageGroupMessage', $params);
if ($result['success']) {
$data = $result['data'];
$result['data'] = [
'group_id' => isset($data['GroupId']) ? $data['GroupId'] : '',
'message_id' => isset($data['MessageId']) ? $data['MessageId'] : '',
];
}
return $result;
}
/**
* 查询群组用户列表(ListLiveMessageGroupUsers
* 对于超过 2000 人的超级大群,返回 error_code=SuperLargeGroup,业务层可降级处理
* @param string $groupId 群组ID
* @param int $pageSize 每页数量(10-30,阿里云实际限制)
* @param int $nextPageToken 下一页起始位置,0 表示首页
* @param int $sortType 排序方式:1 正序,2 逆序
* @return array data 含 group_id、next_page_token、has_more、user_list
*/
public function listGroupUsers($groupId, $pageSize = 20, $nextPageToken = 0, $sortType = 2)
{
$pageSize = max(10, min(30, (int)$pageSize));
$sortType = in_array((int)$sortType, [1, 2]) ? (int)$sortType : 2;
$params = [
'AppId' => $this->appId,
'GroupId' => $groupId,
'PageSize' => $pageSize,
'SortType' => $sortType,
'DataCenter' => $this->dataCenter,
];
if ($nextPageToken) {
$params['NextPageToken'] = (int)$nextPageToken;
}
$result = $this->rpc('ListLiveMessageGroupUsers', $params);
if ($result['success']) {
$data = $result['data'];
$userList = [];
if (isset($data['UserList']) && is_array($data['UserList'])) {
// SDK 可能返回 UserList.Users 或 UserList(直接数组)
$users = isset($data['UserList']['Users']) ? $data['UserList']['Users'] : $data['UserList'];
foreach ((array)$users as $user) {
if (!is_array($user)) {
continue;
}
$userList[] = [
'user_id' => isset($user['UserId']) ? $user['UserId'] : '',
'user_info' => isset($user['UserInfo']) ? $user['UserInfo'] : '',
];
}
}
$result['data'] = [
'group_id' => isset($data['GroupId']) ? $data['GroupId'] : $groupId,
'next_page_token' => isset($data['NextPageToken']) ? (int)$data['NextPageToken'] : 0,
'has_more' => isset($data['Hasmore']) ? (bool)$data['Hasmore'] : false,
'user_list' => $userList,
];
}
return $result;
}
/**
* 查询指定的用户是否在线(CheckLiveMessageUsersOnline
* @param array $userIds 用户ID列表(单次最多 10 个)
* @return array data 含 user_list
*/
public function checkUsersOnline($userIds)
{
$userIds = is_array($userIds) ? $userIds : [$userIds];
$userIds = array_slice($userIds, 0, 10);
$params = [
'AppId' => $this->appId,
'UserIds' => implode(',', $userIds),
'DataCenter' => $this->dataCenter,
];
$result = $this->rpc('CheckLiveMessageUsersOnline', $params);
if ($result['success']) {
$data = $result['data'];
$userList = [];
if (isset($data['UserList']) && is_array($data['UserList'])) {
$users = isset($data['UserList']['Users']) ? $data['UserList']['Users'] : $data['UserList'];
foreach ((array)$users as $user) {
if (!is_array($user)) {
continue;
}
$userList[] = [
'user_id' => isset($user['UserId']) ? $user['UserId'] : '',
'online' => isset($user['Online']) ? (bool)$user['Online'] : false,
];
}
}
$result['data'] = ['user_list' => $userList];
}
return $result;
}
/**
* 创建互动消息群组(CreateLiveMessageGroup
* @param string $groupId 群组ID
* @param string $groupName 群组名称
* @param string $groupMeta 群组扩展信息
* @return array data 含 group_id
*/
public function createGroup($groupId, $groupName = '', $groupMeta = '')
{
$params = [
'AppId' => $this->appId,
'GroupId' => $groupId,
'DataCenter' => $this->dataCenter,
];
if ($groupName !== '') {
$params['GroupName'] = $groupName;
}
if ($groupMeta !== '') {
$params['GroupMeta'] = $groupMeta;
}
$result = $this->rpc('CreateLiveMessageGroup', $params);
if ($result['success']) {
$data = $result['data'];
$result['data'] = [
'group_id' => isset($data['GroupId']) ? $data['GroupId'] : $groupId,
'request_id' => isset($data['RequestId']) ? $data['RequestId'] : '',
];
}
return $result;
}
/**
* 获取 AppId
* @return string
*/
public function getAppId()
{
return $this->appId;
}
/**
* 获取 AppKey
* @return string
*/
public function getAppKey()
{
return $this->appKey;
}
/**
* 获取 AppSign
* @return string
*/
public function getAppSign()
{
return $this->appSign;
}
/**
* 获取数据中心
* @return string
*/
public function getDataCenter()
{
return $this->dataCenter;
}
/**
* 删除互动消息群组(DeleteLiveMessageGroup
* 群组删除后不再可用,在线用户会被通知群已结束
* @param string $groupId 群组ID
* @param string $operatorId 操作者ID(可选,用于后台记录)
* @return array data 含 group_id、request_id
*/
public function deleteGroup($groupId, $operatorId = '')
{
$params = [
'AppId' => $this->appId,
'GroupId' => $groupId,
'DataCenter' => $this->dataCenter,
];
if ($operatorId !== '') {
$params['OperatorId'] = $operatorId;
}
$result = $this->rpc('DeleteLiveMessageGroup', $params);
if ($result['success']) {
$data = $result['data'];
$result['data'] = [
'group_id' => isset($data['GroupId']) ? $data['GroupId'] : $groupId,
'request_id' => isset($data['RequestId']) ? $data['RequestId'] : '',
];
}
return $result;
}
/**
* 查询互动消息群组列表(ListLiveMessageGroups
* @param int $sortType 排序方式:1 正序(按创建时间),2 逆序
* @param int $nextPageToken 分页起始位置,-1 或 0 表示首页
* @param int $groupStatus 群组状态:0 全部,1 未删除,2 已删除
* @return array data 含 group_list、has_more、next_page_token
*/
public function listGroups($sortType = 1, $nextPageToken = -1, $groupStatus = 1)
{
$params = [
'AppId' => $this->appId,
'SortType' => in_array((int)$sortType, [1, 2]) ? (int)$sortType : 1,
'GroupStatus' => in_array((int)$groupStatus, [0, 1, 2]) ? (int)$groupStatus : 1,
'DataCenter' => $this->dataCenter,
];
if ((int)$nextPageToken > 0) {
$params['NextPageToken'] = (int)$nextPageToken;
}
$result = $this->rpc('ListLiveMessageGroups', $params);
if ($result['success']) {
$data = $result['data'];
$groupList = [];
if (isset($data['GroupList']) && is_array($data['GroupList'])) {
foreach ($data['GroupList'] as $group) {
if (!is_array($group)) {
continue;
}
$groupList[] = [
'group_id' => isset($group['GroupId']) ? $group['GroupId'] : '',
'group_name' => isset($group['GroupName']) ? $group['GroupName'] : '',
'creator_id' => isset($group['CreatorId']) ? $group['CreatorId'] : '',
'createtime' => isset($group['Createtime']) ? (int)$group['Createtime'] : 0,
'deleted' => isset($group['Delete']) ? (bool)$group['Delete'] : false,
];
}
}
$result['data'] = [
'group_list' => $groupList,
'has_more' => isset($data['Hasmore']) ? (bool)$data['Hasmore'] : false,
'next_page_token' => isset($data['NextpageToken']) ? (int)$data['NextpageToken'] : 0,
];
}
return $result;
}
}