Files
amb_wechatapp/extend/aliyun/LiveMessage.php
T

461 lines
16 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
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;
}
}