初始化项目:添加后端代码、ThinkPHP框架、前端资源
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user