diff --git a/.gitignore b/.gitignore
index 0f5c816..29fca42 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ config/site.php
app/command/Test.php
.env
runtime
+vendor
\ No newline at end of file
diff --git a/app/api/middleware/Auth.php b/app/api/middleware/Auth.php
index 3804d1f..c4cc702 100644
--- a/app/api/middleware/Auth.php
+++ b/app/api/middleware/Auth.php
@@ -120,6 +120,11 @@ class Auth implements MiddlewareInterface
'user' => session('admin'),
'config' => $config
]);
+ $IM = new \support\OpenImSdk\Client([
+ 'host' => 'http://127.0.0.1:10002', // OpenIM API地址
+ 'secret' => 'openIM123', // OpenIM密钥
+ ]);
+ $request->IM = $IM;
$response = $next($request);
$headers = [
'Access-Control-Allow-Credentials' => 'true',
diff --git a/app/command/OpenIm.php b/app/command/OpenIm.php
new file mode 100644
index 0000000..89cc1c5
--- /dev/null
+++ b/app/command/OpenIm.php
@@ -0,0 +1,73 @@
+addOption('action','a', InputArgument::OPTIONAL, '操作类型');
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return int
+ */
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $action = $input->getOption('action');
+ if(!$action){
+ $output->writeln('空操作');
+ return self::FAILURE;
+ }
+ if(method_exists($this, $action)){
+ return $this->$action($input, $output);
+ }
+ return self::FAILURE;
+ }
+ private function sync_users(InputInterface $input, OutputInterface $output):int{
+ $im = new \support\OpenImSdk\Client([
+ 'host' => 'http://127.0.0.1:10002', // OpenIM API地址
+ 'secret' => 'openIM123', // OpenIM密钥
+ ]);
+ $data = $im->user->getAllUsersUid(1,1000);
+ $exsit_user_ids = Db::name('user')->whereIn('id',$data['userIDs'])->column('id');
+ $not_exsit_user_ids =array_diff($data['userIDs'],$exsit_user_ids);
+ if(count($not_exsit_user_ids)> 0){
+ //同步用户
+ $res = $im->user->getUsersInfo($not_exsit_user_ids);
+ $save_data = [];
+ foreach($res['usersInfo'] as $k=>$_user){
+ array_push($save_data,[
+ 'id' => $_user['userID'],
+ 'nickname' => $_user['nickname'],
+ 'password' => '123456',
+ 'avatar' => $_user['faceURL']
+ ]);
+
+ // "ex": "",
+ // "createTime": 1688454168302,
+ // "appMangerLevel": 18,
+ // "globalRecvMsgOpt": 0
+ }
+ if(!empty($save_data)){
+ Db::name('user')->insertAll($save_data);
+ }
+ }
+ return self::SUCCESS;
+ }
+}
diff --git a/app/command/Otop.php b/app/command/Otop.php
index 6900369..e7f0ff4 100644
--- a/app/command/Otop.php
+++ b/app/command/Otop.php
@@ -20,7 +20,7 @@ class Otop extends Command
*/
protected function configure()
{
- $this->addOption('user_id','uid', InputArgument::OPTIONAL, 'user_id');
+ $this->addOption('user_id','u', InputArgument::OPTIONAL, 'user_id');
}
/**
diff --git a/app/middleware/ActionHook.php b/app/middleware/ActionHook.php
index 246f7ad..1d6b3ab 100644
--- a/app/middleware/ActionHook.php
+++ b/app/middleware/ActionHook.php
@@ -36,6 +36,7 @@ class ActionHook implements MiddlewareInterface
return $after_response;
}
}
+
return $response;
}
return $next($request);
diff --git a/app/model/User.php b/app/model/User.php
index e080fc9..3cddbf7 100644
--- a/app/model/User.php
+++ b/app/model/User.php
@@ -75,6 +75,38 @@ use support\think\Db;
*/
class User extends Base
{
+ use \think\model\concern\SoftDelete;
+ public static function onAfterInsert($row){
+ $res = request()->IM->user->userRegister($row->id,$row->nickname,cdnurl($row->avatar));
+ }
+ public static function onAfterUpdate($row){
+ $changeData = $row->getChangedData();
+ $orgData = $row->getOrigin();
+ //cp($changeData);
+ if(isset($changeData['avatar']) || isset($changeData['nickname'])){
+ request()->IM->user->updateUserInfo($row->id,[
+ 'nickname' => $row->nickname,
+ 'faceURL' => cdnurl($row->avatar)
+ ]);
+ }
+ if(isset($changeData['status']) || $changeData['status'] == '0'){
+ request()->IM->user->forceLogout($row->id);
+ }
+ }
+ public static function onAfterDelete($row)
+ {
+ Db::name('address')->where('user_id',$row->id)->delete();
+ Db::name('recharge')->where('user_id',$row->id)->delete();
+ Db::name('record')->where('user_id',$row->id)->delete();
+ Db::name('withdrawl')->where('user_id',$row->id)->delete();
+ Db::name('user_extend')->where('user_id',$row->id)->delete();
+ Db::name('user_team')->where('descendant_id|ancestor_id','=',$row->id)->delete();
+ Db::name('withdrawl')->where('user_id',$row->id)->delete();
+ foreach(Config('site.allow_currencys') as $currency){
+ (new \app\model\BalanceLog)->setSuffix('_'.$currency)->where('user_id',(int)$row->id)->delete();
+ }
+ request()->IM->user->forceLogout($row->id);
+ }
public function role()
{
return $this->belongsTo('\\app\\model\\UserRole', 'role_id', 'id');//->bind(['name']);
diff --git a/composer.json b/composer.json
index 8bc75cf..f04e3b0 100644
--- a/composer.json
+++ b/composer.json
@@ -45,7 +45,8 @@
"spomky-labs/otphp": "^11.3.0",
"firebase/php-jwt": "6.8",
"php-mcp/server": "^3.3",
- "intervention/image": "^2.7.2"
+ "intervention/image": "^2.7.2",
+ "guzzlehttp/guzzle": "^7.5.0"
},
"suggest": {
"ext-event": "For better performance. "
diff --git a/plugin/admin/app/controller/AccountController.php b/plugin/admin/app/controller/AccountController.php
index f815675..83a7927 100644
--- a/plugin/admin/app/controller/AccountController.php
+++ b/plugin/admin/app/controller/AccountController.php
@@ -98,7 +98,7 @@ class AccountController extends Crud
// return $this->fail('账户不存在或密码错误');
// }
//$secret = $admin['totp_secret'] ?:'EJGYB7OZR2W46XRX7VB3PXHSOY4LUAWCA5GTDAVTWKHXNDAAAIIP7AQ3JSO3XZJNX5J5OTIDEQVKLYFYIYNAXSCYF4GNZ2EMA4ORA3Y';
- \support\Log::alert($admin['totp_secret']);
+ //\support\Log::alert($admin['totp_secret']);
$totp = \OTPHP\TOTP::create($admin->totp_secret);
//$secret = $totp->getSecret();
//$totp->setLabel('cansnow');
diff --git a/plugin/admin/app/controller/ConfigController.php b/plugin/admin/app/controller/ConfigController.php
index 865f8f0..956464a 100644
--- a/plugin/admin/app/controller/ConfigController.php
+++ b/plugin/admin/app/controller/ConfigController.php
@@ -143,9 +143,9 @@ class ConfigController extends Base
$post = $request->post('row');
Db::startTrans();
try {
- if($post['type'] == 'selects'){
- $post['value'] = implode(',',$post['value']);
- }
+ // if($post['type'] == 'selects'){
+ // $post['value'] = implode(',',$post['value']);
+ // }
$user = ConfigModel::create($post);
Db::commit();
$this->buildcache();
@@ -165,7 +165,7 @@ class ConfigController extends Base
$v['value'] = json_decode($v['value'], true);
}
if(in_array($v['type'] ,['selects']) && !is_array($v['value'])){
- $v['value'] = explode(',',$v['value']);
+ $v['value'] = explode(',',$v['value']??'');
}
$list[$v['name']] = $v['value'];
}
diff --git a/plugin/admin/app/controller/IndexController.php b/plugin/admin/app/controller/IndexController.php
index cf03994..254cd9e 100644
--- a/plugin/admin/app/controller/IndexController.php
+++ b/plugin/admin/app/controller/IndexController.php
@@ -70,7 +70,7 @@ class IndexController extends Base
//$day7_user_recharge_sum = Recharge::where('status',2)->whereTime('created_at', '-7 days')->sum('amount');
// 总用户数
$user_count = \app\model\User::where('status',1)->count('id');
- $recharge_total = \app\model\Recharge::where('status',\app\enum\RechargeStatus::COMPLETE->value)->sum('amount');
+ $recharge_total = 0;//\app\model\Recharge::where('status',\app\enum\RechargeStatus::COMPLETE->value)->sum('amount');
// mysql版本
$withdrawl_total = \app\model\Withdrawl::where('status',\app\enum\WithdrawlStatus::COMPLETE->value)->sum('recive_amount');
// mysql版本
diff --git a/plugin/admin/app/controller/OpenimController.php b/plugin/admin/app/controller/OpenimController.php
new file mode 100644
index 0000000..dc42028
--- /dev/null
+++ b/plugin/admin/app/controller/OpenimController.php
@@ -0,0 +1,110 @@
+model = new UserModel();
+ $groupList = [
+ ['value'=>0,'label'=>"普通用户"],
+ ['value'=>1,'label'=>"内部用户"],
+ ['value'=>2,'label'=>"联盟商"],
+ ];
+ $roleList = \app\model\UserRole::order('id','desc')->column('name as label,id as value');
+ $this->assign('groupList',$groupList);
+ $this->assignconfig('groupList',$groupList);
+ $this->assign('roleList',$roleList);
+ $this->assignconfig('roleList',$roleList);
+ }
+ public function team(Request $request): Response
+ {
+ return view();
+ }
+ // public function select(Request $request): Response
+ // {
+ // $this->model = $this->model->with(['referrer','role']);
+ // return parent::select($request);
+ // }
+ /**
+ * 浏览
+ * @return Response
+ * @throws Throwable
+ */
+ public function index(Request $request): Response
+ {
+ return view('user/index');
+ }
+ public function select(Request $request): Response{
+ $res = $request->IM->user->getUsers(1,20);
+ //cp($request->IM->user->getAllUsersUid());
+ if($res['errCode']!==0){
+ return $this->fail($res['errDlt']);
+ }
+ return json([
+ 'code' => 0,
+ "msg" => "ok",
+ 'count' => $res['data']['total'],
+ 'data' =>$res['data']['users'],
+ ]);
+ }
+
+ /**
+ * 插入
+ * @param Request $request
+ * @return Response
+ * @throws BusinessException|Throwable
+ */
+ public function insert(Request $request): Response
+ {
+ if ($request->method() === 'POST') {
+ return parent::insert($request);
+ }
+ return view('user/update',[
+ 'row' => UserModel::findOrEmpty(0)
+ ]);
+ }
+
+ /**
+ * 更新
+ * @param Request $request
+ * @return Response
+ * @throws BusinessException|Throwable
+ */
+ public function update(Request $request): Response
+ {
+ if ($request->method() === 'POST') {
+ [$id, $data] = $this->updateInput($request);
+ $this->doUpdate($id, $data);
+ $ret = $this->success('操作成功');
+ return $ret;
+ }
+ $ids = Request()->get('ids');
+ $user = $this->model->where('id',$ids)->find();
+ return view('user/update',[
+ 'row' => $user
+ ]);
+ }
+}
diff --git a/plugin/admin/app/controller/UserController.php b/plugin/admin/app/controller/UserController.php
index 343bd39..1e7d4cd 100644
--- a/plugin/admin/app/controller/UserController.php
+++ b/plugin/admin/app/controller/UserController.php
@@ -68,6 +68,7 @@ class UserController extends Crud
{
if ($request->method() === 'POST') {
return parent::insert($request);
+
}
return view('user/update',[
'row' => UserModel::findOrEmpty(0)
diff --git a/plugin/admin/app/middleware/AccessControl.php b/plugin/admin/app/middleware/AccessControl.php
index 6cee5a5..b694ad7 100644
--- a/plugin/admin/app/middleware/AccessControl.php
+++ b/plugin/admin/app/middleware/AccessControl.php
@@ -39,25 +39,8 @@ class AccessControl implements MiddlewareInterface
$response = view('common/403')->withStatus(403);
}
}
- } else {
- $config = Config('site');
- $config['debug'] = config('app.debug');
- $config['controller'] = $request->controller_name;
- $config['action'] = $request->action_name;
- $config['moduleurl'] = '/app/admin';
- $request->_view_vars = array_merge((array) $request->_view_vars,[
- 'user' => session('admin'),
- 'config' => $config
- ]);
- $response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
- $response->withBody(str_replace([
- '__SELF__'
- ],[
- request()->path()
- //url(request()->action)
- ],$response->rawBody()))->getStatusCode();
+ return $response;
}
-
- return $response;
+ return $handler($request);
}
}
diff --git a/plugin/admin/app/middleware/Config.php b/plugin/admin/app/middleware/Config.php
new file mode 100644
index 0000000..631e36f
--- /dev/null
+++ b/plugin/admin/app/middleware/Config.php
@@ -0,0 +1,41 @@
+controller_name = get_controller_name();
+ $request->action_name = get_action_name();
+
+ $config = Config('site');
+ $config['debug'] = config('app.debug');
+ $config['controller'] = $request->controller_name;
+ $config['action'] = $request->action_name;
+ $config['moduleurl'] = '/app/admin';
+ $request->_view_vars = array_merge((array) $request->_view_vars,[
+ 'user' => session('admin'),
+ 'config' => $config
+ ]);
+ $IM = new \support\OpenImSdk\Client([
+ 'host' => 'http://127.0.0.1:10002', // OpenIM API地址
+ 'secret' => 'openIM123', // OpenIM密钥
+ ]);
+ $request->IM = $IM;
+ return $handler($request);
+ }
+}
diff --git a/plugin/admin/app/middleware/Tpl.php b/plugin/admin/app/middleware/Tpl.php
new file mode 100644
index 0000000..8e89fa8
--- /dev/null
+++ b/plugin/admin/app/middleware/Tpl.php
@@ -0,0 +1,34 @@
+method() == 'OPTIONS' ? response('') : $handler($request);
+ $response->withBody(str_replace([
+ '__SELF__',
+ '__2__'
+ ],[
+ request()->path(),
+ '-'
+ //url(request()->action)
+ ],$response->rawBody()))->getStatusCode();
+
+ return $response;
+ }
+}
diff --git a/plugin/admin/app/model/User.php b/plugin/admin/app/model/User.php
index 4eb4766..eacc21f 100644
--- a/plugin/admin/app/model/User.php
+++ b/plugin/admin/app/model/User.php
@@ -30,6 +30,7 @@ class User extends \app\model\User
{
public static function onAfterUpdate($row){
+ parent::onAfterUpdate($row);
$changeData = $row->getChangedData();
$orgData = $row->getOrigin();
foreach(Config('site.allow_currencys') as $currency){
@@ -41,17 +42,4 @@ class User extends \app\model\User
}
}
}
- public static function onAfterDelete($row)
- {
- Db::name('address')->where('user_id',$row->id)->delete();
- Db::name('recharge')->where('user_id',$row->id)->delete();
- Db::name('record')->where('user_id',$row->id)->delete();
- Db::name('withdrawl')->where('user_id',$row->id)->delete();
- Db::name('user_extend')->where('user_id',$row->id)->delete();
- Db::name('user_team')->where('descendant_id|ancestor_id','=',$row->id)->delete();
- Db::name('withdrawl')->where('user_id',$row->id)->delete();
- (new \app\model\BalanceLog)->setSuffix('_money')->where('user_id',(int)$row->id)->delete();
- (new \app\model\BalanceLog)->setSuffix('_score')->where('user_id',(int)$row->id)->delete();
- (new \app\model\BalanceLog)->setSuffix('_currency1')->where('user_id',(int)$row->id)->delete();
- }
}
diff --git a/plugin/admin/app/view/index/dashboard.html b/plugin/admin/app/view/index/dashboard.html
index 4e6f939..81b0bc2 100644
--- a/plugin/admin/app/view/index/dashboard.html
+++ b/plugin/admin/app/view/index/dashboard.html
@@ -97,11 +97,6 @@
?>
-
- |
-
- |
-
| 用户余额总和 |
{$user_money_total} |
diff --git a/plugin/admin/config/middleware.php b/plugin/admin/config/middleware.php
index 5577139..094c575 100644
--- a/plugin/admin/config/middleware.php
+++ b/plugin/admin/config/middleware.php
@@ -11,12 +11,14 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
-
- use plugin\admin\app\middleware\AccessControl;
-
return [
'' => [
- AccessControl::class,
+ \plugin\admin\app\middleware\AccessControl::class,
+ \plugin\admin\app\middleware\Config::class,
+ //\plugin\admin\app\middleware\OpenIM::class,
\app\middleware\ActionHook::class,
+ //\app\middleware\BeforeActionHook::class,
+ //\app\middleware\AfterActionHook::class,
+ \plugin\admin\app\middleware\Tpl::class,
]
];
\ No newline at end of file
diff --git a/plugin/admin/public/js/user.js b/plugin/admin/public/js/user.js
index f0721a0..c092c93 100644
--- a/plugin/admin/public/js/user.js
+++ b/plugin/admin/public/js/user.js
@@ -18,202 +18,101 @@ define(['table', 'upload','form'], function (Table,Upload,Form) {
table: 'user',
}
});
-
+ console.log(Config)
var table = $("#table");
+ var columns = [
+ {checkbox: true},
+ {
+ field: 'id',
+ title: 'ID',
+ filter: "number",
+ sortable: true // 是否排序
+ },
+ // {
+ // title: "角色",
+ // field: "role_id",
+ // formatter:function(v,row){
+ // return row.role ? row.role.name : '用户';
+ // },
+ // filter: "select",
+ // filterOption:"roleOption",
+ // visible: false,
+ // },
+ {
+ title: "昵称",
+ field: "nickname"
+ },
+ {
+ title: "头像",
+ field: "avatar",
+ formatter: function (v,d) {
+ return '
'
+ },
+ visible: false
+ },
+ // {
+ // title: "等级",
+ // field: "level",
+ // visible: false,
+ // },
+ // {
+ // title: "生日",
+ // field: "birthday",
+ // visible: false,
+ // },
+ // {
+ // title: "后缀",
+ // field: "decimal_part",
+ // //visible: false,
+ // },
+ ];
+ var currencys = ['money','score','currency1','currency2','currency3','currency4','currency5','currency6','currency7','currency8','currency9'];
+ for (let i = 0; i < currencys.length; i++) {
+ if(Config.allow_currencys.indexOf(currencys[i])!==-1){
+ columns.push({
+ title: __(currencys[i]),
+ field: currencys[i],
+ formatter:Table.api.formatter.number,
+ //sortable: true,
+ //visible: false,
+ });
+ }
+ };
+ columns.push({
+ title: "注册时间",
+ field: "createTime",
+ formatter:function(v,row){
+ return Table.api.formatter.datetime(parseInt(v/1000));
+ },
+ filter:'datetime'
+ });
+ columns.push({
+ title: "状态",
+ field: "status",
+ formatter: Table.api.formatter.switch
+ });
+ columns.push({
+ field: 'operate', title: '操作',
+ table: table,
+ events: Table.api.events.operate,
+ formatter: Table.api.formatter.operate,
+ buttons:[
+ {
+ text:"团队",
+ name:"team",
+ icon:"mdi mdi-account-group-outline",
+ classname:"btn btn-xs btn-info btn-dialog",
+ url:'/app/admin/user/team'
+ }
+ ]
+ });
var tableOptions = {
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
commonSearch: false,
search: false,
- columns: [
- [
- {checkbox: true},
- {
- field: 'id',
- title: 'ID',
- filter: "number",
- sortable: true // 是否排序
- },
- {
- title: "推荐人",
- field: "parent_id",
- formatter:function(v,row){
- return row.referrer ? row.referrer.username : '';
- },
- visible: false,
- },
- {
- title: "分组",
- field: "group",
- formatter:function(v,row){
- for (let i = 0; i < Config.groupList.length; i++) {
- if(Config.groupList[i].value == v){
- return Config.groupList[i].label;
- }
- }
- return '';
- },
- filter: "select",
- filterOption:"groupOption",
- visible: false,
- },
- {
- title: "角色",
- field: "role_id",
- formatter:function(v,row){
- return row.role ? row.role.name : '用户';
- },
- filter: "select",
- filterOption:"roleOption",
- visible: false,
- },
- {
- title: "用户名",
- field: "username",
- filter: "string",
- },
- {
- title: "昵称",
- field: "nickname",
- visible: false
- },
- {
- field: 'domain',
- title: '域名',
- filter: "string",
- visible: false
- },
- {
- title: "头像",
- field: "avatar",
- formatter: function (v,d) {
- return '
'
- },
- visible: false
- },
- {
- title: "邮箱",
- field: "email",
- visible: false
- },
- {
- title: "手机",
- field: "mobile",
- visible: false
- },
- // {
- // title: "等级",
- // field: "level",
- // visible: false,
- // },
- // {
- // title: "生日",
- // field: "birthday",
- // visible: false,
- // },
- // {
- // title: "后缀",
- // field: "decimal_part",
- // //visible: false,
- // },
- {
- title: "调研币",
- field: "money",
- formatter:Table.api.formatter.number,
- sortable: true,
- //visible: false,
- },
- {
- title: "积分",
- field: "score",
- sortable: true,
- visible: false,
- formatter:Table.api.formatter.number
- },
- {
- title: "调研豆",
- field: "currency1",
- formatter:Table.api.formatter.number
- },
- {
- title: "可领取",
- field: "currency6",
- sortable: true,
- formatter:Table.api.formatter.number
- },
- {
- title: "待分配",
- field: "currency7",
- sortable: true,
- formatter:Table.api.formatter.number
- },
- {
- title: "已分配",
- field: "currency8",
- sortable: true,
- formatter:Table.api.formatter.number
- },
- {
- title: "未通过",
- field: "currency9",
- sortable: true,
- formatter:Table.api.formatter.number
- },
- {
- title: "登录时间",
- field: "last_time",
- formatter:Table.api.formatter.datetime,
- visible: false,
- },
- {
- title: "登录ip",
- field: "last_ip",
- visible: false,
- },
- {
- title: "注册时间",
- field: "join_time",
- formatter:Table.api.formatter.datetime,
- filter:'datetime'
- },
- {
- title: "注册ip",
- field: "join_ip",
- visible: false,
- },
- {
- title: "创建时间",
- field: "created_at",
- visible: false,
- },
- {
- title: "更新时间",
- field: "updated_at",
- formatter:Table.api.formatter.datetime,
- visible: false,
- },
- {
- title: "状态",
- field: "status",
- formatter: Table.api.formatter.switch
- },
- {
- field: 'operate', title: '操作',
- table: table, events: Table.api.events.operate,
- formatter: Table.api.formatter.operate,
- buttons:[
- {
- text:"团队",
- name:"team",
- icon:"mdi mdi-account-group-outline",
- classname:"btn btn-xs btn-info btn-dialog",
- url:'/app/admin/user/team'
- }
- ]
- }
- ]
- ]
+ columns: [columns]
};
// 初始化表格
table.bootstrapTable(tableOptions);
diff --git a/support/OpenIM.php b/support/OpenIM.php
new file mode 100644
index 0000000..7109a6f
--- /dev/null
+++ b/support/OpenIM.php
@@ -0,0 +1,38 @@
+ 'openIM123',
+ 'baseUrl' => 'http://127.0.0.1:10002'
+ ];
+ function get_admin_token($username='imAdmin'){
+
+ }
+ function get_user_token($username='imAdmin'){
+
+ }
+ /**
+ * 统一API请求方法
+ */
+ function api(){
+
+ }
+ /**
+ * 发送GET请求
+ */
+ function get(){
+
+ }
+ /**
+ * 发送POST请求
+ */
+ function post(){
+
+ }
+}
\ No newline at end of file
diff --git a/support/OpenImSdk/Api/Auth.php b/support/OpenImSdk/Api/Auth.php
new file mode 100644
index 0000000..61a3a8f
--- /dev/null
+++ b/support/OpenImSdk/Api/Auth.php
@@ -0,0 +1,79 @@
+ $userID,
+ 'secret' => Config::getSecret()
+ ];
+ return Utils::send(Url::$getAdminToken, $data, '获取管理员token错误');
+ }
+
+ /**
+ * 获取用户token
+ * 直接从服务器获取,不使用缓存
+ * @param string $userID 用户ID
+ * @param int $platformID 平台ID,默认为1
+ * @return array
+ */
+ public function getUserToken(string $userID, int $platformID = 1): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getUserToken, ['userID' => $userID, 'platformID' => $platformID], '获取用户token错误', $adminToken);
+ }
+
+ /**
+ * 强制登出
+ * @param string $userID 要登出的用户ID
+ * @param int $platformID 平台ID,默认为1
+ * @return array
+ */
+ public function forceLogout(string $userID, int $platformID = 1): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+
+ // 清除本地缓存的用户token
+ Utils::clearToken($userID);
+
+ return Utils::send(Url::$forceLogout, ['userID' => $userID, 'platformID' => $platformID], '强制登出错误', $adminToken);
+ }
+
+ /**
+ * 解析当前用户token
+ * @param string $token 用户token
+ * @return array
+ */
+ public function parseToken(string $token): array
+ {
+ return Utils::send(Url::$parseToken, [], '解析当前用户token错误', $token);
+ }
+
+
+ /**
+ * 用户登录 (旧版,建议使用getUserToken)
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function userToken(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$userToken, ['userID' => $userID], '用户登录错误', $adminToken);
+ }
+}
diff --git a/support/OpenImSdk/Api/Conversation.php b/support/OpenImSdk/Api/Conversation.php
new file mode 100644
index 0000000..14be9a7
--- /dev/null
+++ b/support/OpenImSdk/Api/Conversation.php
@@ -0,0 +1,77 @@
+ $userID,
+ 'pagination' => [
+ 'pageNumber' => $pageNumber,
+ 'showNumber' => $showNumber
+ ]
+ ];
+ return Utils::send(Url::$getOwnerConversation, $data, '获取当前用户分页会话列表失败', $adminToken);
+ }
+
+ /**
+ * 获取排序的会话列表
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getSortedConversationList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getSortedConversationList, ['userID' => $userID], '获取排序的会话列表失败', $adminToken);
+ }
+
+ /**
+ * 为多个用户设置相同会话ID的字段
+ * @param string $conversationID 会话ID
+ * @param array $userIDs 用户ID列表
+ * @param int $recvMsgOpt 接收消息选项
+ * @param bool $isPinned 是否置顶
+ * @param bool $isPrivateChat 是否私聊
+ * @param int $groupAtType 群@类型
+ * @param string $ex 扩展字段
+ * @param bool $isMsgDestruct 是否开启消息销毁
+ * @param int $msgDestructTime 消息销毁时间
+ * @param int $burnDuration 阅后即焚时长
+ * @return array
+ */
+ public function setConversations(string $conversationID, array $userIDs, int $recvMsgOpt = 0, bool $isPinned = false, bool $isPrivateChat = false, int $groupAtType = 0, string $ex = '', bool $isMsgDestruct = false, int $msgDestructTime = 0, int $burnDuration = 0): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'conversationID' => $conversationID,
+ 'userIDs' => $userIDs,
+ 'conversation' => [
+ 'recvMsgOpt' => $recvMsgOpt,
+ 'isPinned' => $isPinned,
+ 'isPrivateChat' => $isPrivateChat,
+ 'groupAtType' => $groupAtType,
+ 'ex' => $ex,
+ 'isMsgDestruct' => $isMsgDestruct,
+ 'msgDestructTime' => $msgDestructTime,
+ 'burnDuration' => $burnDuration
+ ]
+ ];
+ return Utils::send(Url::$setConversations, $data, '为多个用户设置相同会话ID的字段失败', $adminToken);
+ }
+}
diff --git a/support/OpenImSdk/Api/Friend.php b/support/OpenImSdk/Api/Friend.php
new file mode 100644
index 0000000..140b97c
--- /dev/null
+++ b/support/OpenImSdk/Api/Friend.php
@@ -0,0 +1,212 @@
+ $ownerUserID, 'blackUserID' => $blackUserID];
+ return Utils::send(Url::$addBlack, $data, '添加黑名单错误', $adminToken);
+ }
+
+ /**
+ * 添加好友
+ * @param string $fromUserID 发送者ID
+ * @param string $toUserID 接收者ID
+ * @param string $reqMsg 请求消息
+ * @return array
+ */
+ public function addFriend(string $fromUserID, string $toUserID, string $reqMsg): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['fromUserID' => $fromUserID, 'toUserID' => $toUserID, 'reqMsg' => $reqMsg];
+ return Utils::send(Url::$addFriend, $data, '添加好友错误', $adminToken);
+ }
+
+ /**
+ * 同意/拒绝好友请求
+ * @param string $ownerUserID 处理者ID
+ * @param string $friendUserID 好友ID
+ * @param string $handleMsg 处理消息
+ * @param int $handleResult 处理结果,1同意,2拒绝
+ * @return array
+ */
+ public function addFriendResponse(string $ownerUserID, string $friendUserID, string $handleMsg, int $handleResult): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'ownerUserID' => $ownerUserID,
+ 'friendUserID' => $friendUserID,
+ 'handleMsg' => $handleMsg,
+ 'handleResult' => $handleResult
+ ];
+ return Utils::send(Url::$addFriendResponse, $data, '同意/拒绝好友请求错误', $adminToken);
+ }
+
+ /**
+ * 删除好友
+ * @param string $ownerUserID 用户ID
+ * @param string $friendUserID 好友ID
+ * @return array
+ */
+ public function deleteFriend(string $ownerUserID, string $friendUserID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['ownerUserID' => $ownerUserID, 'friendUserID' => $friendUserID];
+ return Utils::send(Url::$deleteFriend, $data, '删除好友错误', $adminToken);
+ }
+
+ /**
+ * 获取黑名单列表
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getBlackList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getBlackList, ['userID' => $userID], '获取黑名单列表错误', $adminToken);
+ }
+
+ /**
+ * 获取好友申请列表(收到的申请)
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getFriendApplyList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getFriendApplyList, ['userID' => $userID], '获取好友申请列表错误', $adminToken);
+ }
+
+ /**
+ * 获取用户的好友列表
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getFriendList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getFriendList, ['userID' => $userID], '获取用户的好友列表错误', $adminToken);
+ }
+
+ /**
+ * 获取自己的好友申请列表(发出的申请)
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getSelfFriendApplyList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getSelfFriendApplyList, ['userID' => $userID], '获取自己的好友申请列表错误', $adminToken);
+ }
+
+ /**
+ * 批量导入好友
+ * @param string $ownerUserID 用户ID
+ * @param array $friendUserIDs 好友ID列表
+ * @return array
+ */
+ public function importFriend(string $ownerUserID, array $friendUserIDs = []): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['ownerUserID' => $ownerUserID, 'friendUserIDs' => $friendUserIDs];
+ return Utils::send(Url::$importFriend, $data, '批量导入好友错误', $adminToken);
+ }
+
+ /**
+ * 检查用户之间是否为好友
+ * @param string $userID1 用户ID1
+ * @param string $userID2 用户ID2
+ * @return array
+ */
+ public function isFriend(string $userID1, string $userID2): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['userID1' => $userID1, 'userID2' => $userID2];
+ return Utils::send(Url::$isFriend, $data, '检查用户之间是否为好友错误', $adminToken);
+ }
+
+ /**
+ * 把用户移除黑名单
+ * @param string $ownerUserID 用户ID
+ * @param string $blackUserID 被移除黑名单的用户ID
+ * @return array
+ */
+ public function removeBlack(string $ownerUserID, string $blackUserID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['ownerUserID' => $ownerUserID, 'blackUserID' => $blackUserID];
+ return Utils::send(Url::$removeBlack, $data, '把用户移除黑名单错误', $adminToken);
+ }
+
+ /**
+ * 设置好友备注
+ * @param string $fromUserID 用户ID
+ * @param string $toUserID 好友ID
+ * @param string $remark 备注
+ * @return array
+ */
+ public function setFriendRemark(string $fromUserID, string $toUserID, string $remark): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['fromUserID' => $fromUserID, 'toUserID' => $toUserID, 'remark' => $remark];
+ return Utils::send(Url::$setFriendRemark, $data, '设置好友备注错误', $adminToken);
+ }
+
+ /**
+ * 更新好友信息
+ * @param string $ownerUserID 用户ID
+ * @param string $friendUserID 好友ID
+ * @param string $remark 备注
+ * @param bool $isPinned 是否置顶
+ * @param string $ex 扩展字段
+ * @return array
+ */
+ public function updateFriends(string $ownerUserID, string $friendUserID, string $remark = '', bool $isPinned = false, string $ex = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'ownerUserID' => $ownerUserID,
+ 'friendUserID' => $friendUserID
+ ];
+
+ // 只添加非空参数
+ if ($remark !== '') {
+ $data['remark'] = $remark;
+ }
+
+ if ($isPinned) {
+ $data['isPinned'] = $isPinned;
+ }
+
+ if ($ex !== '') {
+ $data['ex'] = $ex;
+ }
+
+ return Utils::send(Url::$updateFriends, $data, '更新好友信息失败', $adminToken);
+ }
+}
diff --git a/support/OpenImSdk/Api/Group.php b/support/OpenImSdk/Api/Group.php
new file mode 100644
index 0000000..aa065e5
--- /dev/null
+++ b/support/OpenImSdk/Api/Group.php
@@ -0,0 +1,391 @@
+ $ownerUserID,
+ 'memberUserIDs' => $memberUserIDs,
+ 'adminUserIDs' => $adminUserIDs,
+ 'groupInfo' => [
+ 'groupID' => $groupID,
+ 'groupName' => $groupName,
+ 'notification' => $notification,
+ 'introduction' => $introduction,
+ 'faceURL' => $faceURL,
+ 'ex' => $ex,
+ 'groupType' => $groupType,
+ 'needVerification' => $needVerification,
+ 'lookMemberInfo' => $lookMemberInfo,
+ 'applyMemberFriend' => $applyMemberFriend
+ ]
+ ];
+ return Utils::send(Url::$createGroup, $data, '创建群组失败', $adminToken);
+ }
+
+ /**
+ * 申请加入群组
+ * @param string $token 用户token
+ * @param string $groupID 群组ID
+ * @param string $reqMsg 申请消息
+ * @param int $joinSource 加入来源
+ * @return array
+ */
+ public function joinGroup(string $token, string $groupID, string $reqMsg = '', int $joinSource = 0): array
+ {
+ $data = [
+ 'groupID' => $groupID,
+ 'reqMsg' => $reqMsg,
+ 'joinSource' => $joinSource
+ ];
+ return Utils::send(Url::$joinGroup, $data, '申请加入群组失败', $token);
+ }
+
+ /**
+ * 退出群组
+ * @param string $token 用户token
+ * @param string $groupID 群组ID
+ * @return array
+ */
+ public function quitGroup(string $token, string $groupID): array
+ {
+ return Utils::send(Url::$quitGroup, ['groupID' => $groupID], '退出群组失败', $token);
+ }
+
+ /**
+ * 获取群组信息
+ * @param array $groupIDs 群组ID列表
+ * @return array
+ */
+ public function getGroupsInfo(array $groupIDs): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getGroupsInfo, ['groupIDs' => $groupIDs], '获取群组信息失败', $adminToken);
+ }
+
+ /**
+ * 获取群成员列表
+ * @param string $groupID 群组ID
+ * @param int $filter 过滤类型,0所有,1群主,2管理员,3普通成员,4禁言,5进入黑名单
+ * @param int $offset 偏移量
+ * @param int $count 数量
+ * @return array
+ */
+ public function getGroupMemberList(string $groupID, int $filter = 0, int $offset = 0, int $count = 100): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'filter' => $filter,
+ 'offset' => $offset,
+ 'count' => $count
+ ];
+ return Utils::send(Url::$getGroupMemberList, $data, '获取群成员列表失败', $adminToken);
+ }
+
+ /**
+ * 获取指定群成员信息
+ * @param string $groupID 群组ID
+ * @param array $userIDs 用户ID列表
+ * @return array
+ */
+ public function getGroupMembersInfo(string $groupID, array $userIDs): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'userIDs' => $userIDs
+ ];
+ return Utils::send(Url::$getGroupMembersInfo, $data, '获取指定群成员信息失败', $adminToken);
+ }
+
+ /**
+ * 将用户拉入群组
+ * @param string $groupID 群组ID
+ * @param string $inviterUserID 邀请者ID
+ * @param array $invitedUserIDList 被邀请的用户ID列表
+ * @param string $reason 邀请原因
+ * @return array
+ */
+ public function inviteUserToGroup(string $groupID, string $inviterUserID, array $invitedUserIDList, string $reason = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'inviterUserID' => $inviterUserID,
+ 'invitedUserIDList' => $invitedUserIDList,
+ 'reason' => $reason,
+ ];
+ return Utils::send(Url::$inviteUserToGroup, $data, '将用户拉入群组失败', $adminToken);
+ }
+
+ /**
+ * 踢出群成员
+ * @param string $groupID 群组ID
+ * @param string $kickUserID 踢出者ID
+ * @param array $kickedUserIDs 被踢出的用户ID列表
+ * @param string $reason 踢出原因
+ * @return array
+ */
+ public function kickGroupMember(string $groupID, string $kickUserID, array $kickedUserIDs, string $reason = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'kickUserID' => $kickUserID,
+ 'kickedUserIDs' => $kickedUserIDs,
+ 'reason' => $reason
+ ];
+ return Utils::send(Url::$kickGroupMember, $data, '踢出群成员失败', $adminToken);
+ }
+
+ /**
+ * 转让群主
+ * @param string $groupID 群组ID
+ * @param string $oldOwnerUserID 原群主ID
+ * @param string $newOwnerUserID 新群主ID
+ * @return array
+ */
+ public function transferGroupOwner(string $groupID, string $oldOwnerUserID, string $newOwnerUserID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'oldOwnerUserID' => $oldOwnerUserID,
+ 'newOwnerUserID' => $newOwnerUserID
+ ];
+ return Utils::send(Url::$transferGroupOwner, $data, '转让群主失败', $adminToken);
+ }
+
+ /**
+ * 获取用户加入的群组列表
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getJoinedGroupList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getJoinedGroupList, ['userID' => $userID], '获取用户加入的群组列表失败', $adminToken);
+ }
+
+ /**
+ * 解散群组
+ * @param string $groupID 群组ID
+ * @return array
+ */
+ public function dismissGroup(string $groupID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$dismissGroup, ['groupID' => $groupID], '解散群组失败', $adminToken);
+ }
+
+ /**
+ * 设置群成员昵称
+ * @param string $groupID 群组ID
+ * @param string $userID 用户ID
+ * @param string $nickname 群内昵称
+ * @return array
+ */
+ public function setGroupMemberNickname(string $groupID, string $userID, string $nickname): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'userID' => $userID,
+ 'nickname' => $nickname
+ ];
+ return Utils::send(Url::$setGroupMemberNickname, $data, '设置群成员昵称失败', $adminToken);
+ }
+
+ /**
+ * 设置群成员信息
+ * @param string $groupID 群组ID
+ * @param string $userID 用户ID
+ * @param array $data 群成员信息
+ * @return array
+ */
+ public function setGroupMemberInfo(string $groupID, string $userID, array $data): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = array_merge([
+ 'groupID' => $groupID,
+ 'userID' => $userID
+ ], $data);
+ return Utils::send(Url::$setGroupMemberInfo, $data, '设置群成员信息失败', $adminToken);
+ }
+
+ /**
+ * 获取群成员用户ID列表
+ * @param string $groupID 群组ID
+ * @return array
+ */
+ public function getGroupMemberUserIDs(string $groupID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getGroupMemberUserIDs, ['groupID' => $groupID], '获取群成员用户ID列表失败', $adminToken);
+ }
+
+ /**
+ * 获取群成员列表
+ * @param string $groupID 群组ID
+ * @param int $offset 偏移量
+ * @param int $count 数量
+ * @return array
+ */
+ public function getGroupAllMemberList(string $groupID, int $offset = 0, int $count = 100): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'pagination' => [
+ 'pageNumber' => intval($offset / $count) + 1,
+ 'showNumber' => $count
+ ]
+ ];
+ return Utils::send(Url::$getGroupAllMemberList, $data, '获取群成员列表失败', $adminToken);
+ }
+
+ /**
+ * 获取用户加群申请列表
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getUserReqGroupApplicationList(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getUserReqGroupApplicationList, ['userID' => $userID], '获取用户加群申请列表失败', $adminToken);
+ }
+
+ /**
+ * 获取指定用户对指定群组的加群请求
+ * @param string $groupID 群组ID
+ * @param array $userIDs 用户ID列表
+ * @return array
+ */
+ public function getGroupApplicationListByUserID(string $groupID, array $userIDs): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'userIDs' => $userIDs
+ ];
+ return Utils::send(Url::$getGroupUsersReqApplicationList, $data, '获取指定用户对指定群组的加群请求失败', $adminToken);
+ }
+
+ /**
+ * 处理群组申请
+ * @param string $groupID 群组ID
+ * @param string $fromUserID 申请者ID
+ * @param string $handledUserID 处理者ID
+ * @param int $handleResult 处理结果,1同意,2拒绝
+ * @param string $handleMsg 处理消息
+ * @return array
+ */
+ public function groupApplicationResponse(string $groupID, string $fromUserID, string $handledUserID, int $handleResult, string $handleMsg = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'groupID' => $groupID,
+ 'fromUserID' => $fromUserID,
+ 'handledUserID' => $handledUserID,
+ 'handleResult' => $handleResult,
+ 'handleMsg' => $handleMsg
+ ];
+ return Utils::send(Url::$groupApplicationResponse, $data, '处理群组申请失败', $adminToken);
+ }
+
+ /**
+ * 禁言群组,只有群主和管理员可以发送消息
+ * @param string $groupID 群组ID
+ * @return array
+ */
+ public function muteGroup(string $groupID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$muteGroup, ['groupID' => $groupID], '禁言群组失败', $adminToken);
+ }
+
+ /**
+ * 取消禁言群组,所有成员都可以发送消息
+ * @param string $groupID 群组ID
+ * @return array
+ */
+ public function cancelMuteGroup(string $groupID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$cancelMuteGroup, ['groupID' => $groupID], '取消禁言群组失败', $adminToken);
+ }
+
+ /**
+ * 禁言群成员
+ * @param string $groupID 群组ID
+ * @param string $userID 群成员ID
+ * @param int $mutedSeconds 禁言时间(秒)
+ * @return array
+ */
+ public function muteGroupMember(string $groupID, string $userID, int $mutedSeconds = 0): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['groupID' => $groupID, 'userID' => $userID, 'mutedSeconds' => $mutedSeconds];
+ return Utils::send(Url::$muteGroupMember, $data, '禁言群成员失败', $adminToken);
+ }
+
+ /**
+ * 取消禁言群成员
+ * @param string $groupID 群组ID
+ * @param string $userID 群成员ID
+ * @return array
+ */
+ public function cancelMuteGroupMember(string $groupID, string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = ['groupID' => $groupID, 'userID' => $userID];
+ return Utils::send(Url::$cancelMuteGroupMember, $data, '取消禁言群成员失败', $adminToken);
+ }
+}
diff --git a/support/OpenImSdk/Api/Message.php b/support/OpenImSdk/Api/Message.php
new file mode 100644
index 0000000..1fb6041
--- /dev/null
+++ b/support/OpenImSdk/Api/Message.php
@@ -0,0 +1,217 @@
+ $sendID,
+ 'senderNickname' => $senderNickname,
+ 'senderFaceURL' => $senderFaceURL,
+ 'senderPlatformID' => $senderPlatformID,
+ 'contentType' => $contentType,
+ 'sessionType' => $sessionType,
+ 'isOnlineOnly' => $isOnlineOnly,
+ 'notOfflinePush' => $notOfflinePush,
+ 'ex' => $ex
+ ];
+
+ // 根据会话类型设置recvID或groupID
+ if ($sessionType == 1 && !empty($recvID)) {
+ $data['recvID'] = $recvID;
+ } elseif ($sessionType == 2 && !empty($groupID)) {
+ $data['groupID'] = $groupID;
+ }
+
+ // 设置消息内容
+ if (empty($content)) {
+ $data['content'] = ['text' => ''];
+ } else {
+ $data['content'] = $content;
+ }
+
+ // 设置发送时间,如果有的话
+ if ($sendTime > 0) {
+ $data['sendTime'] = $sendTime;
+ }
+
+ // 设置离线推送信息,如果有的话
+ if (!empty($offlinePushInfo)) {
+ $data['offlinePushInfo'] = $offlinePushInfo;
+ }
+
+ return Utils::send(Url::$sendMsg, $data, '发送消息失败', $adminToken);
+ }
+
+ /**
+ * 批量发送消息
+ * @param string $sendID 发送者ID
+ * @param string $senderNickname 发送者昵称
+ * @param string $senderFaceURL 发送者头像
+ * @param int $sessionType 会话类型
+ * @param int $contentType 消息类型
+ * @param string $content 消息内容
+ * @return array
+ */
+ public function batchSendMsg(string $sendID, string $senderNickname, string $senderFaceURL, int $sessionType, int $contentType, string $content): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'senderPlatformID' => 0,
+ 'sendID' => $sendID,
+ 'senderNickname' => $senderNickname,
+ 'senderFaceURL' => $senderFaceURL,
+ 'sessionType' => $sessionType,
+ 'contentType' => $contentType,
+ 'content' => ['text' => $content]
+ ];
+ return Utils::send(Url::$batchSendMsg, $data, '批量发送消息失败', $adminToken);
+ }
+
+ /**
+ * 清空用户消息
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function clearMsg(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$clearMsg, ['userID' => $userID], '清空用户消息失败', $adminToken);
+ }
+
+ /**
+ * 根据seq列表删除消息
+ * @param string $userID 用户ID
+ * @param string $conversationID 会话ID
+ * @param array $seqs seq列表
+ * @return array
+ */
+ public function delMsg(string $userID, string $conversationID, array $seqs): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'userID' => $userID,
+ 'conversationID' => $conversationID,
+ 'seqs' => $seqs
+ ];
+ return Utils::send(Url::$delMsg, $data, '删除消息失败', $adminToken);
+ }
+
+ /**
+ * 撤回消息
+ * @param string $conversationID 会话ID
+ * @param string $seq 消息seq
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function revokeMessage(string $conversationID, string $seq, string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'conversationID' => $conversationID,
+ 'seq' => intval($seq),
+ 'userID' => $userID
+ ];
+ return Utils::send(Url::$revokeMessage, $data, '撤回消息失败', $adminToken);
+ }
+
+ /**
+ * 发送业务通知
+ * @param string $sendID 发送者ID
+ * @param string $recvID 接收者ID
+ * @param string $title 通知标题
+ * @param string $content 通知内容
+ * @param string $notificationUrl 通知点击跳转链接
+ * @param string $ex 扩展字段
+ * @return array
+ */
+ public function sendBusinessNotification(string $sendID, string $recvID, string $title, string $content, string $notificationUrl = '', string $ex = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'sendID' => $sendID,
+ 'recvID' => $recvID,
+ 'title' => $title,
+ 'content' => $content,
+ 'notificationUrl' => $notificationUrl,
+ 'ex' => $ex
+ ];
+ return Utils::send(Url::$sendBusinessNotification, $data, '发送业务通知失败', $adminToken);
+ }
+
+ /**
+ * 获取用户所有会话
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getAllConversations(string $userID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getAllConversations, ['userID' => $userID], '获取用户所有会话失败', $adminToken);
+ }
+
+ /**
+ * 根据会话ID获取会话
+ * @param string $userID 用户ID
+ * @param string $conversationID 会话ID
+ * @return array
+ */
+ public function getConversation(string $userID, string $conversationID): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'userID' => $userID,
+ 'conversationID' => $conversationID
+ ];
+ return Utils::send(Url::$getConversation, $data, '获取会话失败', $adminToken);
+ }
+
+ /**
+ * 根据会话ID列表获取会话
+ * @param string $userID 用户ID
+ * @param array $conversationIDs 会话ID列表
+ * @return array
+ */
+ public function getConversations(string $userID, array $conversationIDs): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'userID' => $userID,
+ 'conversationIDs' => $conversationIDs
+ ];
+ return Utils::send(Url::$getConversations, $data, '获取会话列表失败', $adminToken);
+ }
+}
diff --git a/support/OpenImSdk/Api/User.php b/support/OpenImSdk/Api/User.php
new file mode 100644
index 0000000..478e46e
--- /dev/null
+++ b/support/OpenImSdk/Api/User.php
@@ -0,0 +1,262 @@
+ [
+ 'pageNumber' => $pagination,
+ 'showNumber' => $showNumber
+ ]
+ ];
+ return Utils::send(Url::$getUsers, $data, '获取用户列表错误', $adminToken);
+ }
+
+ /**
+ * 获取用户在线状态
+ * @param array $userIDList 用户ID列表
+ * @return array
+ */
+ public function getUsersOnlineStatus(array $userIDList): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getUsersOnlineStatus, ['userIDList' => $userIDList], '获取用户在线状态错误', $adminToken);
+ }
+
+ /**
+ * 获取用户在线token详情
+ * @param array $userIDList 用户ID列表
+ * @return array
+ */
+ public function getUsersOnlineTokenDetail(array $userIDList): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getUsersOnlineTokenDetail, ['userIDList' => $userIDList], '获取用户在线token详情错误', $adminToken);
+ }
+
+ /**
+ * 获取订阅用户状态
+ * @return array
+ */
+ public function getSubscribeUsersStatus(): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getSubscribeUsersStatus, [], '获取订阅用户状态错误', $adminToken);
+ }
+
+ /**
+ * 订阅用户状态
+ * @param string $token 管理员token
+ * @param array $userIDList 用户ID列表
+ * @return array
+ */
+ public function subscribeUsersStatus(array $userIDList): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$subscribeUsersStatus, ['userIDList' => $userIDList], '订阅用户状态错误', $adminToken);
+ }
+
+ /**
+ * 设置全局免打扰
+ * @param int $globalRecvMsgOpt 全局消息接收选项
+ * @return array
+ */
+ public function setGlobalMsgRecvOpt(int $globalRecvMsgOpt): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$setGlobalMsgRecvOpt, ['globalRecvMsgOpt' => $globalRecvMsgOpt], '设置全局免打扰错误', $adminToken);
+ }
+
+ /**
+ * 修改用户信息
+ * @param string $userID 用户ID
+ * @param array $data 用户信息
+ * @return array
+ */
+ public function updateUserInfo(string $userID, array $data): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = array_merge(['userID' => $userID], $data);
+ return Utils::send(Url::$updateUserInfo, $data, '修改用户信息错误', $adminToken);
+ }
+
+ /**
+ * 搜索通知账号
+ * @param string $keyword 搜索关键词
+ * @param int $pagination 页码
+ * @param int $showNumber 每页数量
+ * @return array
+ */
+ public function searchNotificationAccount(string $keyword, int $pagination = 1, int $showNumber = 20): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'keyword' => $keyword,
+ 'pagination' => [
+ 'pageNumber' => $pagination,
+ 'showNumber' => $showNumber
+ ]
+ ];
+ return Utils::send(Url::$searchNotificationAccount, $data, '搜索通知账号错误', $adminToken);
+ }
+
+ /**
+ * 添加通知账号
+ * @param string $userID 用户ID
+ * @param string $nickname 昵称
+ * @param string $faceURL 头像
+ * @param int $gender 性别
+ * @param string $phoneNumber 手机号
+ * @param string $birth 生日
+ * @param string $email 邮箱
+ * @param string $ex 扩展字段
+ * @return array
+ */
+ public function addNotificationAccount(string $userID, string $nickname = '', string $faceURL = '', int $gender = 1, string $phoneNumber = '', string $birth = '', string $email = '', string $ex = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'userID' => $userID,
+ 'nickname' => $nickname,
+ 'faceURL' => $faceURL,
+ 'gender' => $gender,
+ 'phoneNumber' => $phoneNumber,
+ 'birth' => $birth,
+ 'email' => $email,
+ 'ex' => $ex
+ ];
+ return Utils::send(Url::$addNotificationAccount, $data, '添加通知账号错误');
+ }
+
+ /**
+ * 更新通知账号
+ * @param string $userID 用户ID
+ * @param string $nickname 昵称
+ * @param string $faceURL 头像
+ * @param int $gender 性别
+ * @param string $phoneNumber 手机号
+ * @param string $birth 生日
+ * @param string $email 邮箱
+ * @param string $ex 扩展字段
+ * @return array
+ */
+ public function updateNotificationAccount(string $userID, string $nickname = '', string $faceURL = '', int $gender = 1, string $phoneNumber = '', string $birth = '', string $email = '', string $ex = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'userID' => $userID,
+ 'nickname' => $nickname,
+ 'faceURL' => $faceURL,
+ 'gender' => $gender,
+ 'phoneNumber' => $phoneNumber,
+ 'birth' => $birth,
+ 'email' => $email,
+ 'ex' => $ex
+ ];
+ return Utils::send(Url::$updateNotificationAccount, $data, '更新通知账号错误', $adminToken);
+ }
+
+ /**
+ * 检查列表账户注册状态
+ * @param array $checkUserIDList 用户ID列表
+ * @return array
+ */
+ public function accountCheck(array $checkUserIDList): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$accountCheck, ['checkUserIDList' => $checkUserIDList], '检查列表账户注册状态错误', $adminToken);
+ }
+
+ /**
+ * 获取所有用户uid列表
+ * @return array
+ */
+ public function getAllUsersUid($page=1,$limit=100): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getAllUsersUid, ['pagination'=>['pageNumber'=>$page,"showNumber"=>$limit]], '获取所有用户uid列表错误', $adminToken);
+ }
+
+ /**
+ * 获取自己的信息
+ * @param string $userID 用户ID
+ * @return array
+ */
+ public function getSelfUserInfo(string $userID): array
+ {
+ // 获取管理员token
+ $userToken = Utils::getUserToken($userID);
+ return Utils::send(Url::$getSelfUserInfo, ['userID' => $userID], '获取自己的信息错误', $userToken);
+ }
+
+ /**
+ * 获取用户信息
+ * @param array $userIDList 用户ID列表
+ * @return array
+ */
+ public function getUsersInfo(array $userIDList): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ return Utils::send(Url::$getUsersInfo, ['userIDList' => $userIDList], '获取用户信息错误', $adminToken);
+ }
+
+ //Header
+ //
+ //Header Name Example Value Required Type Description
+ //operationID 1646445464564 Required string Used for global traceability, suggested as a unique timestamp per request
+ //token eyJhbxxxx3Xs Required string Admin token
+
+ //Field Name Required Type Description
+ //users Required array List of users
+ //users.userID Required string User ID
+ //users.nickname Required string User nickname
+ //users.faceURL Required string User avatar URL
+ /**
+ * 用户注册
+ * @param string $userID 用户ID
+ * @param string $nickname 昵称
+ * @param string $faceURL 头像地址
+ * @return array
+ */
+ public function userRegister(string $userID, string $nickname = '', string $faceURL = ''): array
+ {
+ // 获取管理员token
+ $adminToken = Utils::getAdminToken();
+ $data = [
+ 'users' => [
+ [
+ 'userID' => $userID,
+ 'nickname' => $nickname,
+ 'faceURL' => $faceURL
+ ]
+ ]
+ ];
+ return Utils::send(Url::$userRegister, $data, '注册IM错误', $adminToken);
+ }
+}
diff --git a/support/OpenImSdk/Client.php b/support/OpenImSdk/Client.php
new file mode 100644
index 0000000..76eb4ac
--- /dev/null
+++ b/support/OpenImSdk/Client.php
@@ -0,0 +1,75 @@
+auth = new Auth();
+ $this->friend = new Friend();
+ $this->group = new Group();
+ $this->message = new Message();
+ $this->user = new User();
+ $this->conversation = new Conversation();
+ }
+}
diff --git a/support/OpenImSdk/Core/Config.php b/support/OpenImSdk/Core/Config.php
new file mode 100644
index 0000000..8aba346
--- /dev/null
+++ b/support/OpenImSdk/Core/Config.php
@@ -0,0 +1,39 @@
+ 'http://127.0.0.1:10002',
+ 'secret' => 'openIM123',
+ ];
+
+ /**
+ * 设置配置项
+ * @param array $config
+ * @return void
+ */
+ public static function setConfig(array $config)
+ {
+ self::$config = array_merge(self::$config, $config);
+ }
+
+ /**
+ * 获取密钥
+ * @return string
+ */
+ public static function getSecret(): string
+ {
+ return self::$config['secret'];
+ }
+
+ /**
+ * 获取API主机地址
+ * @return string
+ */
+ public static function getHost(): string
+ {
+ return self::$config['host'];
+ }
+}
diff --git a/support/OpenImSdk/Core/TokenManager.php b/support/OpenImSdk/Core/TokenManager.php
new file mode 100644
index 0000000..d83a125
--- /dev/null
+++ b/support/OpenImSdk/Core/TokenManager.php
@@ -0,0 +1,157 @@
+defaultTokenExpire = $seconds;
+ return $this;
+ }
+
+ /**
+ * 获取管理员Token
+ * @param string $userID 管理员ID
+ * @return string|null
+ */
+ public function getAdminToken(string $userID = 'imAdmin'): ?string
+ {
+ $key = "admin_token_{$userID}";
+ $tokenData = $this->getCache($key);
+
+ if (!$tokenData) {
+ // Token不存在或已过期,需要重新获取
+ return null;
+ }
+
+ $data = json_decode($tokenData, true);
+ return $data['token'] ?? null;
+ }
+
+ /**
+ * 保存管理员Token
+ * @param string $userID 管理员ID
+ * @param string $token Token
+ * @param int|null $expireTimeSeconds Token过期时间(秒)
+ * @return bool
+ */
+ public function saveAdminToken(string $userID, string $token, ?int $expireTimeSeconds = null): bool
+ {
+ $key = "admin_token_{$userID}";
+ $expireTime = $expireTimeSeconds ?? $this->defaultTokenExpire;
+
+ // 存储token和过期时间
+ $data = [
+ 'token' => $token,
+ 'expireTimeSeconds' => $expireTime
+ ];
+
+ return $this->setCache($key, json_encode($data), $expireTime);
+ }
+
+ /**
+ * 获取用户Token
+ * @param string $userID 用户ID
+ * @return string|null
+ */
+ public function getUserToken(string $userID): ?string
+ {
+ $key = "user_token_{$userID}";
+ $tokenData = $this->getCache($key);
+
+ if (!$tokenData) {
+ // Token不存在或已过期,需要重新获取
+ return null;
+ }
+
+ $data = json_decode($tokenData, true);
+ return $data['token'] ?? null;
+ }
+
+ /**
+ * 保存用户Token
+ * @param string $userID 用户ID
+ * @param string $token Token
+ * @param int|null $expireTimeSeconds Token过期时间(秒)
+ * @return bool
+ */
+ public function saveUserToken(string $userID, string $token, ?int $expireTimeSeconds = null): bool
+ {
+ $key = "user_token_{$userID}";
+ $expireTime = $expireTimeSeconds ?? $this->defaultTokenExpire;
+
+ // 存储token和过期时间
+ $data = [
+ 'token' => $token,
+ 'expireTimeSeconds' => $expireTime
+ ];
+
+ return $this->setCache($key, json_encode($data), $expireTime);
+ }
+
+ /**
+ * 清除Token
+ * @param string $userID 用户ID
+ * @param bool $isAdmin 是否为管理员Token
+ * @return bool
+ */
+ public function clearToken(string $userID, bool $isAdmin = false): bool
+ {
+ $key = $isAdmin ? "admin_token_{$userID}" : "user_token_{$userID}";
+ return $this->deleteCache($key);
+ }
+
+ /**
+ * 获取缓存
+ * @param string $key 缓存键
+ * @return string|null
+ */
+ private function getCache(string $key): ?string
+ {
+ return cache($key);
+ }
+
+ /**
+ * 设置缓存
+ * @param string $key 缓存键
+ * @param string $value 缓存值
+ * @param int $expire 过期时间(秒)
+ * @return bool
+ */
+ private function setCache(string $key, string $value, int $expire): bool
+ {
+ return cache($key,$value,$expire);
+ }
+
+ /**
+ * 删除缓存
+ * @param string $key 缓存键
+ * @return bool
+ */
+ private function deleteCache(string $key): bool
+ {
+ return cache($key,null);
+ }
+}
diff --git a/support/OpenImSdk/Core/Url.php b/support/OpenImSdk/Core/Url.php
new file mode 100644
index 0000000..a0ce0b2
--- /dev/null
+++ b/support/OpenImSdk/Core/Url.php
@@ -0,0 +1,96 @@
+post($uri, $options)->getBody()->getContents();
+ }
+
+ /**
+ * 发送API请求
+ * @param string $path API路径
+ * @param array $data 请求数据
+ * @param string $errMsg 错误信息
+ * @param string $token 认证令牌
+ * @return array 响应数据
+ */
+ public static function send(string $path, array $data, string $errMsg, string $token = ''): array|bool
+ {
+ $url = Url::buildUrl($path);
+ //cp($url);
+ $res = json_decode(self::request($url, $data, $token), true);
+ if($res['errCode'] !==0 ){
+ throw new \Exception($res['errMsg'],$res['errCode']);
+ //throw new \Exception($res['errDlt'],$res['errCode']);
+ }
+ if(isset($res['data'])){
+ return $res['data'];
+ }
+ return true;
+
+ try {
+ $url = Url::buildUrl($path);
+ cp($url);
+ return json_decode(self::request($url, $data, $token), true);
+ } catch (GuzzleException $e) {
+ return ['errCode' => $e->getCode(), 'errMsg' => $errMsg, 'errDlt' => $e->getMessage()];
+ } catch (ValidatorException $e) {
+ return ['errCode' => 400, 'errMsg' => $errMsg, 'errDlt' => $e->getMessage()];
+ }
+ }
+
+ /**
+ * 获取管理员Token
+ * 如果缓存中没有,则自动获取并缓存
+ * @param string $userID 管理员ID
+ * @return string|null
+ */
+ public static function getAdminToken(string $userID = 'imAdmin'): ?string
+ {
+ $tokenManager = self::getTokenManager();
+ $token = $tokenManager->getAdminToken($userID);
+
+ if (!$token) {
+ // 从服务器获取新的Token
+ $result = self::send(Url::$getAdminToken, [
+ 'userID' => $userID,
+ 'secret' => Config::getSecret()
+ ], '获取管理员Token失败');
+ $token = $result['token'];
+ // 使用API返回的过期时间
+ $expireTimeSeconds = $result['expireTimeSeconds'] ?? null;
+
+ // 保存token,使用API返回的过期时间
+ $tokenManager->saveAdminToken($userID, $token, $expireTimeSeconds);
+
+ }
+
+ return $token;
+ }
+
+ /**
+ * 获取用户Token
+ * 如果缓存中没有,则自动获取并缓存
+ * @param string $userID 用户ID
+ * @param int $platformID 平台ID
+ * @return string|null
+ */
+ public static function getUserToken(string $userID, int $platformID = 1): ?string
+ {
+ $tokenManager = self::getTokenManager();
+ $token = $tokenManager->getUserToken($userID);
+
+ if (!$token) {
+ // 从服务器获取新的Token
+ $adminToken = self::getAdminToken();
+ if (!$adminToken) {
+ return null;
+ }
+
+ $result = self::send(Url::$getUserToken, [
+ 'userID' => $userID,
+ 'platformID' => $platformID
+ ], '获取用户Token失败', $adminToken);
+
+ $token = $result['token'];
+
+ // 使用API返回的过期时间
+ $expireTimeSeconds = $result['expireTimeSeconds'] ?? null;
+
+ // 保存token,使用API返回的过期时间
+ $tokenManager->saveUserToken($userID, $token, $expireTimeSeconds);
+ }
+
+ return $token;
+ }
+
+ /**
+ * 清除Token缓存
+ * @param string $userID 用户ID
+ * @param bool $isAdmin 是否为管理员Token
+ * @return bool
+ */
+ public static function clearToken(string $userID, bool $isAdmin = false): bool
+ {
+ return self::getTokenManager()->clearToken($userID, $isAdmin);
+ }
+}
diff --git a/support/OpenImSdk/Core/Validator.php b/support/OpenImSdk/Core/Validator.php
new file mode 100644
index 0000000..00e1511
--- /dev/null
+++ b/support/OpenImSdk/Core/Validator.php
@@ -0,0 +1,91 @@
+ 'max:64',
+ 'userID1' => 'max:64',
+ 'userID2' => 'max:64',
+ 'ownerUserID' => 'max:64',
+ 'friendUserID' => 'max:64',
+ 'blackUserID' => 'max:64',
+ 'fromUserID' => 'max:64',
+ 'toUserID' => 'max:64',
+ 'sendID' => 'max:64',
+ 'recvID' => 'max:64',
+ 'inviterUserID' => 'max:64',
+ 'nickname' => 'max:255',
+ 'faceURL' => 'max:255',
+ 'gender' => 'in:1,2',
+ 'groupID' => 'max:64',
+ 'groupName' => 'max:255',
+ 'introduction' => 'max:255',
+ 'notification' => 'max:255',
+ 'groupType' => 'in:0,1,2',
+ 'oldOwnerUserID' => 'max:64',
+ 'newOwnerUserID' => 'max:64',
+ 'conversationID' => 'max:128',
+ 'handleResult' => 'in:1,2',
+ ];
+
+ /**
+ * 验证数组
+ * @param array $data 要验证的数据
+ * @return array 验证后的数据
+ * @throws ValidatorException
+ */
+ public static function validateArray(array $data): array
+ {
+ foreach ($data as $field => $value) {
+ foreach (self::$rules as $key => $rules) {
+ if ($field == $key) {
+ $ruleList = explode('|', $rules);
+ foreach ($ruleList as $rule) {
+ $ruleParts = explode(':', $rule);
+ $method = $ruleParts[0];
+ $param = $ruleParts[1] ?? null;
+ self::$method($field, $value, $param);
+ }
+ }
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 长度最大验证
+ * @param string $field 字段名
+ * @param mixed $value 字段值
+ * @param int $maxLength 最大长度
+ * @throws ValidatorException
+ */
+ private static function max(string $field, $value, $maxLength)
+ {
+ if (strlen($value) > (int)$maxLength) {
+ throw new ValidatorException("参数 {$field} 长度不能超过 {$maxLength} 位");
+ }
+ }
+
+ /**
+ * 枚举值验证
+ * @param string $field 字段名
+ * @param mixed $value 字段值
+ * @param string $allowedValues 允许的值(逗号分隔)
+ * @throws ValidatorException
+ */
+ private static function in(string $field, $value, $allowedValues)
+ {
+ $allowed = explode(',', $allowedValues);
+ if (!in_array($value, $allowed)) {
+ throw new ValidatorException("参数 {$field} 的值必须是以下之一: {$allowedValues},当前值: {$value}");
+ }
+ }
+}
diff --git a/support/OpenImSdk/Exception/ValidatorException.php b/support/OpenImSdk/Exception/ValidatorException.php
new file mode 100644
index 0000000..f0a1b76
--- /dev/null
+++ b/support/OpenImSdk/Exception/ValidatorException.php
@@ -0,0 +1,8 @@
+ 基于 [OpenIM](https://github.com/orgs/OpenIMSDK) 的 PHP SDK
+>
+> API文档: [https://docs.openim.io/restapi/apis/introduction](https://docs.openim.io/restapi/apis/introduction)
+
+## 安装
+
+```bash
+composer require MrYzYs/OpenImSdk
+```
+
+## 配置
+
+```php
+$config = [
+ 'host' => 'http://127.0.0.1:10002', // OpenIM API地址
+ 'secret' => 'openIM123', // OpenIM密钥
+];
+```
+
+## 基本使用
+
+### 初始化客户端
+
+```php
+// 使用文件缓存(默认)
+$IM = new OpenImSdk\Client($config);
+
+// 使用Redis缓存 (phpredis)
+$redis = new Redis();
+$redis->connect('127.0.0.1', 6379);
+$IM = new OpenImSdk\Client($config, $redis);
+
+// 使用Redis缓存 (predis)
+$redis = new Predis\Client([
+ 'scheme' => 'tcp',
+ 'host' => '127.0.0.1',
+ 'port' => 6379,
+]);
+$IM = new OpenImSdk\Client($config, $redis);
+
+// 指定文件缓存目录
+$IM = new OpenImSdk\Client($config, null, '/path/to/cache');
+```
+
+### 认证管理
+
+```php
+// 用户注册
+$result = $IM->auth->userRegister('user123', '测试用户', 'https://example.com/avatar.jpg');
+
+// 强制登出
+$logout = $IM->auth->forceLogout('user123');
+
+// 解析token
+$tokenInfo = $IM->auth->parseToken($userToken);
+```
+
+### 用户管理
+
+```php
+// 获取用户列表
+$users = $IM->user->getUsers($adminToken);
+
+// 获取用户在线状态
+$onlineStatus = $IM->user->getUsersOnlineStatus($adminToken, ['user123', 'user456']);
+
+// 更新用户信息
+$updateUser = $IM->user->updateUserInfo($adminToken, 'user123', [
+ 'nickname' => '新昵称',
+ 'faceURL' => 'https://example.com/new-avatar.jpg'
+]);
+```
+
+### 消息管理
+
+```php
+// 发送消息
+$sendMsg = $IM->message->sendMsg(
+ $adminToken,
+ 'admin', // 发送者ID
+ 'user123', // 接收者ID
+ '', // 群组ID(单聊时为空)
+ '管理员', // 发送者昵称
+ 'https://example.com/admin-avatar.jpg', // 发送者头像
+ 1, // 发送者平台ID
+ ['text' => '你好,这是一条测试消息'], // 消息内容
+ 101, // 消息类型(101为文本消息)
+ 1 // 会话类型(1为单聊)
+);
+
+// 撤回消息
+$revokeMsg = $IM->message->revokeMessage(
+ $adminToken,
+ 'single_user123', // 会话ID
+ '123456', // 消息seq
+ 'user123' // 用户ID
+);
+```
+
+### 会话管理
+
+```php
+// 获取用户分页会话列表
+$conversations = $IM->conversation->getOwnerConversation(
+ $adminToken,
+ 'user123', // 用户ID
+ 1, // 页码
+ 20 // 每页数量
+);
+
+// 获取排序的会话列表
+$sortedConversations = $IM->conversation->getSortedConversationList(
+ $adminToken,
+ 'user123' // 用户ID
+);
+```
+
+### 好友管理
+
+```php
+// 批量导入好友
+$importFriend = $IM->friend->importFriend(
+ $adminToken,
+ 'user123', // 用户ID
+ ['user456', 'user789'] // 好友ID列表
+);
+
+// 获取好友列表
+$friendList = $IM->friend->getFriendList(
+ $adminToken,
+ 'user123' // 用户ID
+);
+
+// 检查是否为好友
+$isFriend = $IM->friend->isFriend(
+ $adminToken,
+ 'user123', // 用户ID1
+ 'user456' // 用户ID2
+);
+```
+
+### 群组管理
+
+```php
+// 创建群组
+$createGroup = $IM->group->createGroup(
+ $adminToken,
+ 'user123', // 群主ID
+ [], // 普通成员ID列表
+ [], // 管理员ID列表
+ '测试群组', // 群名称
+ '', // 群ID(可选)
+ 'https://example.com/group-avatar.jpg', // 群头像
+ '群简介', // 群简介
+ '群公告' // 群公告
+);
+
+// 邀请用户加入群组
+$inviteToGroup = $IM->group->inviteUserToGroup(
+ $adminToken,
+ 'group123', // 群组ID
+ 'user123', // 邀请者ID
+ ['user456', 'user789'] // 被邀请的用户ID列表
+);
+
+// 获取群成员列表
+$groupMembers = $IM->group->getGroupAllMemberList(
+ $adminToken,
+ 'group123', // 群组ID
+ 0, // 偏移量
+ 100 // 数量
+);
+
+// 申请加入群组
+$joinGroup = $IM->group->joinGroup(
+ $userToken, // 用户token
+ 'group123', // 群组ID
+ '我想加入这个群组' // 申请消息
+);
+
+// 处理群组申请
+$handleApplication = $IM->group->groupApplicationResponse(
+ $adminToken,
+ 'group123', // 群组ID
+ 'user456', // 申请者ID
+ 'user123', // 处理者ID
+ 1, // 处理结果,1同意,2拒绝
+ '欢迎加入' // 处理消息
+);
+
+// 踢出群成员
+$kickMember = $IM->group->kickGroupMember(
+ $adminToken,
+ 'group123', // 群组ID
+ 'user123', // 踢出者ID
+ ['user456'], // 被踢出的用户ID列表
+ '违反群规' // 踢出原因
+);
+
+// 转让群主
+$transferOwner = $IM->group->transferGroupOwner(
+ $adminToken,
+ 'group123', // 群组ID
+ 'user123', // 原群主ID
+ 'user456' // 新群主ID
+);
+```
+
+## 目录结构
+
+```
+src/
+├── Api/ # API接口类
+│ ├── Auth.php # 认证相关API
+│ ├── Conversation.php # 会话相关API
+│ ├── Friend.php # 好友相关API
+│ ├── Group.php # 群组相关API
+│ ├── Message.php # 消息相关API
+│ └── User.php # 用户相关API
+├── Core/ # 核心类
+│ ├── Config.php # 配置类
+│ ├── TokenManager.php # Token管理类
+│ ├── Url.php # URL管理
+│ ├── Utils.php # 工具类
+│ └── Validator.php # 验证器
+├── Exception/ # 异常处理
+│ └── ValidatorException.php # 验证异常
+└── Client.php # 客户端入口
+```
+
+许可协议: GPL-V3
\ No newline at end of file
diff --git a/support/OpenImSdk/composer.json b/support/OpenImSdk/composer.json
new file mode 100644
index 0000000..05d0f83
--- /dev/null
+++ b/support/OpenImSdk/composer.json
@@ -0,0 +1,24 @@
+{
+ "name": "mryzys/openim-sdk",
+ "description": "OpenIM PHP SDK - A PHP client for OpenIM REST API",
+ "keywords": [
+ "openimsdk", "openim", "im", "chat", "messaging"
+ ],
+ "license": "GPL-3.0-only",
+ "authors": [
+ {
+ "name": "mryzys",
+ "email": "mryzys@163.com"
+ }
+ ],
+ "require": {
+ "php": "^8.0",
+ "guzzlehttp/guzzle": "^7.5.0",
+ "ext-json": "*"
+ },
+ "autoload": {
+ "psr-4": {
+ "OpenImSdk\\": "src/"
+ }
+ }
+}
diff --git a/support/helpers.php b/support/helpers.php
index efa8b7c..5ad4b10 100644
--- a/support/helpers.php
+++ b/support/helpers.php
@@ -1,4 +1,2 @@