feat: 后端全量更新 - 含所有本次需求
- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
This commit is contained in:
@@ -0,0 +1,409 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of workerman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用于检测业务代码死循环或者长时间阻塞等问题
|
||||
* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
|
||||
* 然后观察一段时间workerman.log看是否有process_timeout异常
|
||||
*/
|
||||
|
||||
namespace addons\kefu\library\GatewayWorker\Applications\KeFu;
|
||||
|
||||
//declare(ticks=1);
|
||||
|
||||
use addons\kefu\library\Common;
|
||||
use GatewayWorker\Lib\Gateway;
|
||||
use Workerman\Lib\Timer;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 主逻辑
|
||||
* 主要是处理 onConnect onMessage onClose 三个方法
|
||||
* onConnect 和 onClose 如果不需要可以不用实现并删除
|
||||
*/
|
||||
class Events
|
||||
{
|
||||
/**
|
||||
* WebSocket 链接成功
|
||||
*
|
||||
* @param int $client_id data
|
||||
* @param $[data] [websocket握手时的http头数据,包含get、server等变量]
|
||||
*/
|
||||
public static function onWebSocketConnect($client_id, $data)
|
||||
{
|
||||
|
||||
// 安全检查
|
||||
array_walk_recursive($data, ['addons\kefu\library\Common', 'checkVariable']);
|
||||
|
||||
$now_time = time();
|
||||
$initialize_data = [];
|
||||
$initialize_data['chat_name'] = Db::name('kefu_config')->where('name', 'chat_name')->value('value');
|
||||
$agreement = (stripos($data['server']['HTTP_ORIGIN'], 'https://') === false) ? 'http://' : 'https://';
|
||||
$_SESSION['cdn_url'] = $agreement . $data['server']['SERVER_NAME']; //设置服务器域名
|
||||
$kefu_config = get_addon_config('kefu');
|
||||
|
||||
$upload = \app\common\model\Config::upload();
|
||||
// 上传信息配置后
|
||||
\think\Hook::listen("upload_config_init", $upload);
|
||||
$_SESSION['cdn_url'] = $upload['cdnurl'] ? $upload['cdnurl'] : $_SESSION['cdn_url'];
|
||||
|
||||
|
||||
// 获取连接人信息
|
||||
$token_info = false;
|
||||
|
||||
if (!isset($data['get']['modulename'])) {
|
||||
|
||||
Gateway::sendToClient($client_id, json_encode([
|
||||
'code' => 0,
|
||||
'msgtype' => 'clear',
|
||||
'msg' => $initialize_data['chat_name'] . ' 模块未知',
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($data['get']['modulename'] == 'admin' && isset($data['get']['token'])) {
|
||||
// 验证管理员身份
|
||||
$token_info = Common::checkAdmin($data['get']['token']);
|
||||
|
||||
// 设置定时器,定时检测管理员身份是否过期
|
||||
$_SESSION['auth_timer_id'] = Timer::add(30, function ($client_id, $token) {
|
||||
$token_info = Common::checkAdmin($token);
|
||||
if (!$token_info) {
|
||||
Gateway::closeClient($client_id);
|
||||
}
|
||||
}, [$client_id, $data['get']['token']]);
|
||||
|
||||
} elseif ($data['get']['modulename'] != 'admin' && isset($data['get']['token'])) {
|
||||
// 验证FA用户身份
|
||||
$user_id = Common::checkFaUser($data['get']['token']);
|
||||
if ($user_id) {
|
||||
// 验证KeFu用户身份
|
||||
$token_info = Common::checkKefuUser('', $user_id);
|
||||
if ($token_info) {
|
||||
// 设置定时器,定时检测用户身份是否过期
|
||||
$_SESSION['auth_timer_id'] = Timer::add(60, function ($client_id, $token) {
|
||||
$user_id = Common::checkFaUser($token);
|
||||
if (!$user_id) {
|
||||
Gateway::closeClient($client_id);
|
||||
}
|
||||
}, [$client_id, $data['get']['token']]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($data['get']['modulename'] != 'admin' && isset($data['get']['kefu_tourists_token']) && !$token_info) {
|
||||
// 验证KeFu用户身份
|
||||
$token_info = Common::checkKefuUser($data['get']['kefu_tourists_token'], 0);
|
||||
}
|
||||
|
||||
if ($token_info) {
|
||||
|
||||
if (isset($token_info['token'])) {
|
||||
unset($token_info['token']);
|
||||
}
|
||||
|
||||
if (isset($token_info['blacklist']) && $token_info['blacklist']) {
|
||||
Gateway::sendToClient($client_id, json_encode([
|
||||
'code' => 0,
|
||||
'msgtype' => 'clear',
|
||||
'msg' => $initialize_data['chat_name'] . ' 黑名单用户!',
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
Gateway::bindUid($client_id, $token_info['user_id']);
|
||||
$_SESSION['user_id'] = $token_info['user_id'];
|
||||
} else {
|
||||
|
||||
Gateway::sendToClient($client_id, json_encode([
|
||||
'code' => 0,
|
||||
'msgtype' => 'clear',
|
||||
'msg' => $initialize_data['chat_name'] . ' 无法识别链接用户身份,请重新登录!',
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($data['get']['modulename'] == 'admin') {
|
||||
|
||||
// 读取会话列表
|
||||
$session = Db::name('kefu_session')
|
||||
->alias('s')
|
||||
->field('s.*,CONCAT(u.id,"||user") as session_user,u.user_id as fu_user_id,u.avatar,u.nickname,u.wechat_openid,fu.avatar as fu_avatar,fu.nickname as fu_nickname')
|
||||
->join('kefu_user u', 'u.id=s.user_id')
|
||||
->join('user fu', 'u.user_id=fu.id', 'LEFT')
|
||||
->where('s.csr_id', $token_info['id'])
|
||||
->where('s.deletetime', null)
|
||||
->limit(40)
|
||||
->order('s.createtime desc')
|
||||
->select();
|
||||
|
||||
$session = array_reverse($session, false); // 会话分组时数组键将被逆转,最终给到前台的则是可以直接for in的数组
|
||||
|
||||
// 会话列表分组 在线的且上次消息时间在最近的-放入对话中 不在线的或者上次消息时间较久的放入最近沟通
|
||||
$session_temp = [];
|
||||
foreach ($session as $key => $value) {
|
||||
|
||||
// 最后一条聊天记录
|
||||
$last_message = Db::name('kefu_record')
|
||||
->where('session_id', $value['id'])
|
||||
->order('createtime desc')
|
||||
->find();
|
||||
|
||||
$value['last_message'] = Common::formatMessage($last_message);
|
||||
$value['last_time'] = Common::formatSessionTime(isset($last_message['createtime']) ? $last_message['createtime'] : null);
|
||||
|
||||
$value['online'] = $value['wechat_openid'] ? 1 : Gateway::isUidOnline($value['session_user']);
|
||||
$value['avatar'] = $value['fu_avatar'] ? $value['fu_avatar'] : $value['avatar'];
|
||||
$value['nickname'] = $value['fu_nickname'] ? $value['fu_nickname'] : $value['nickname'];
|
||||
$value['avatar'] = Common::imgSrcFill($value['avatar'], true);
|
||||
|
||||
// 用户发来的未读消息数
|
||||
$value['unread_msg_count'] = Db::name('kefu_record')
|
||||
->where('session_id', $value['id'])
|
||||
->where('sender_identity', 1)
|
||||
->where('sender_id', $value['user_id'])
|
||||
->where('status', 0)
|
||||
->count('id');
|
||||
|
||||
$last_time = isset($last_message['createtime']) ? $last_message['createtime'] : $value['createtime'];
|
||||
|
||||
$dialogue_time = $value['wechat_openid'] ? 600 : 43200; // 这个时间内的会话计入会话中
|
||||
|
||||
if ($value['online'] || ($now_time - $last_time < $dialogue_time) || $value['unread_msg_count'] > 0) {
|
||||
$session_temp['dialogue'][] = $value;
|
||||
} else {
|
||||
$session_temp['recently'][] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// 客服上线
|
||||
$reception_count = isset($session_temp['dialogue']) ? count($session_temp['dialogue']) : false;
|
||||
if ($reception_count) {
|
||||
Db::name('kefu_csr_config')->where('admin_id', $token_info['id'])->update([
|
||||
'reception_count' => $reception_count,
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取访问中(邀请中)的用户->查询对应的用户信息
|
||||
$invitation = Gateway::getAllUidList();
|
||||
$invitation_user_ids = [];
|
||||
|
||||
foreach ($invitation as $key => $value) {
|
||||
$invitation_user_id = explode('||', $value);
|
||||
|
||||
if (isset($invitation_user_id[1]) && $invitation_user_id[1] != 'csr' && (int)$invitation_user_id[0] > 0) {
|
||||
$invitation_user_ids[] = (int)$invitation_user_id[0];
|
||||
}
|
||||
}
|
||||
|
||||
$invitation_user_ids = implode(',', $invitation_user_ids);
|
||||
$invitation = Db::name('kefu_user')
|
||||
->alias('u')
|
||||
->field('u.id,u.avatar,u.nickname,u.createtime,s.id as sid,fu.avatar as fu_avatar,fu.nickname as fu_nickname')
|
||||
->join('user fu', 'u.user_id=fu.id', 'LEFT')
|
||||
->join('kefu_session s', 's.user_id=u.id', 'LEFT')
|
||||
->whereIn('u.id', $invitation_user_ids)
|
||||
->where('s.id', null)
|
||||
->select();
|
||||
|
||||
foreach ($invitation as $key => $value) {
|
||||
|
||||
/*$trajectory = Db::name('kefu_trajectory')
|
||||
->where('user_id', $value['id'])
|
||||
->order('id desc')
|
||||
->find();*/
|
||||
|
||||
$invitation[$key]['id'] = 'invitation||' . $value['id'];
|
||||
$invitation[$key]['avatar'] = $value['fu_avatar'] ? $value['fu_avatar'] : $value['avatar'];
|
||||
$invitation[$key]['avatar'] = Common::imgSrcFill($invitation[$key]['avatar'], true);
|
||||
$invitation[$key]['nickname'] = $value['fu_nickname'] ? $value['fu_nickname'] : $value['nickname'];
|
||||
$invitation[$key]['online'] = 1;
|
||||
$invitation[$key]['unread_msg_count'] = 0;
|
||||
$invitation[$key]['last_message'] = '';
|
||||
$invitation[$key]['session_user'] = $value['id'] . '||user';
|
||||
$invitation[$key]['last_time'] = Common::formatSessionTime($value['createtime']);
|
||||
}
|
||||
|
||||
$session_temp['invitation'] = $invitation;
|
||||
|
||||
$initialize_data['session'] = $session_temp;
|
||||
|
||||
// 获取状态
|
||||
$token_info['status_text'] = Common::csrStatus(null);
|
||||
$tourists = 'not';
|
||||
|
||||
} else {
|
||||
|
||||
if (!Db::name('kefu_session')->where('user_id', $token_info['id'])->value('id')) {
|
||||
|
||||
// 无客服游客-供前台建立会话
|
||||
$avatar = $token_info['fu_avatar'] ? $token_info['fu_avatar'] : $token_info['avatar'];
|
||||
$tourists = [
|
||||
'id' => 'invitation||' . $token_info['id'],
|
||||
'avatar' => Common::imgSrcFill($avatar, true),
|
||||
'nickname' => $token_info['fu_nickname'] ? $token_info['fu_nickname'] : $token_info['nickname'],
|
||||
'online' => 1,
|
||||
'unread_msg_count' => 0,
|
||||
'session_user' => $token_info['id'] . '||user',
|
||||
'last_message' => '',
|
||||
'last_time' => Common::formatSessionTime($token_info['createtime']),
|
||||
];
|
||||
} else {
|
||||
$tourists = 'not';
|
||||
}
|
||||
}
|
||||
|
||||
$initialize_data['modulename'] = $data['get']['modulename'];
|
||||
$initialize_data['user_info'] = $token_info;
|
||||
$initialize_data['new_msg'] = Common::getUnreadMessages($_SESSION['user_id'], true);
|
||||
|
||||
// 向当前client_id发送数据
|
||||
Gateway::sendToClient($client_id, json_encode(['msgtype' => 'initialize', 'data' => $initialize_data]));
|
||||
|
||||
// 向所有人发送
|
||||
Gateway::sendToAll(json_encode([
|
||||
'msgtype' => 'online',
|
||||
'user_id' => $_SESSION['user_id'],
|
||||
'user_name' => isset($token_info['fu_nickname']) ? ($token_info['fu_nickname'] . '(' . $token_info['nickname'] . ')') : $token_info['nickname'],
|
||||
'tourists' => $tourists,
|
||||
'modulename' => $data['get']['modulename'],
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当客户端发来消息时触发
|
||||
* @param int $client_id 连接id
|
||||
* @param mixed $message 具体消息
|
||||
*/
|
||||
public static function onMessage($client_id, $message)
|
||||
{
|
||||
$chat_name = Db::name('kefu_config')->where('name', 'chat_name')->value('value');
|
||||
|
||||
// 分发到控制器
|
||||
$data = json_decode($message, true);
|
||||
|
||||
// 安全检查
|
||||
array_walk_recursive($data, ['addons\kefu\library\Common', 'checkVariable']);
|
||||
|
||||
if (!is_array($data) || !isset($data['c']) || !isset($data['a'])) {
|
||||
|
||||
common::showMsg($client_id, $chat_name . ' 错误的请求!');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($data['c'] == 'clear') {
|
||||
Gateway::closeClient($client_id);
|
||||
return '';
|
||||
}
|
||||
|
||||
$filename = __DIR__ . '/controller/' . $data['c'] . '.php'; //载入文件类似/controller/index.php
|
||||
|
||||
if (file_exists($filename)) {
|
||||
|
||||
require_once $filename;
|
||||
|
||||
/*
|
||||
检查要访问的类是否存在
|
||||
*/
|
||||
if (!class_exists($data['c'], false)) {
|
||||
|
||||
common::showMsg($client_id, $chat_name . ' 您访问的控制器不存在!');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
common::showMsg($client_id, $chat_name . ' 您访问的文件并存在!');
|
||||
return;
|
||||
}
|
||||
|
||||
$o = new $data['c'](); // 新建对象
|
||||
|
||||
if (!method_exists($o, $data['a'])) {
|
||||
|
||||
common::showMsg($client_id, $chat_name . ' 您访问的方法并存在!');
|
||||
return;
|
||||
}
|
||||
|
||||
$data['data'] = isset($data['data']) ? $data['data'] : '';
|
||||
|
||||
call_user_func_array([$o, $data['a']], [$client_id, $data['data']]); //调用对象$o($c)里的方法$a
|
||||
}
|
||||
|
||||
/**
|
||||
* 当用户断开连接时触发
|
||||
* @param int $client_id 连接id
|
||||
*/
|
||||
public static function onClose($client_id)
|
||||
{
|
||||
if (isset($_SESSION['auth_timer_id'])) {
|
||||
Timer::del($_SESSION['auth_timer_id']);
|
||||
}
|
||||
|
||||
// 向所有人发送
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
|
||||
// 此user_id下还有其他链接
|
||||
try {
|
||||
if (Gateway::getClientIdByUid($_SESSION['user_id'])) {
|
||||
return;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
$user_info = Common::userInfo($_SESSION['user_id']);
|
||||
|
||||
if ($user_info['source'] == 'user') {
|
||||
|
||||
$csr_id = Db::name('kefu_session')->where('user_id', $user_info['id'])->value('csr_id');
|
||||
|
||||
if ($csr_id) {
|
||||
|
||||
$reception_count = Db::name('kefu_csr_config')
|
||||
->where('admin_id', $csr_id)
|
||||
->value('reception_count');
|
||||
|
||||
if ($reception_count > 0) {
|
||||
Db::name('kefu_csr_config')->where('admin_id', $csr_id)->setDec('reception_count');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} elseif ($user_info['source'] == 'csr' && $user_info['status'] == 3) {
|
||||
// 客服保持在线
|
||||
$keep_alive = Db::name('kefu_csr_config')->where('admin_id', $user_info['id'])->value('keep_alive');
|
||||
if ($keep_alive) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::csrStatus(0);
|
||||
|
||||
// 客服下线
|
||||
Db::name('kefu_csr_config')->where('admin_id', $user_info['id'])->update([
|
||||
'reception_count' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
Gateway::sendToAll(json_encode([
|
||||
'msgtype' => 'offline',
|
||||
'user_id' => $_SESSION['user_id'],
|
||||
]));
|
||||
|
||||
}
|
||||
|
||||
Db::clear();
|
||||
}
|
||||
|
||||
}
|
||||
+1014
File diff suppressed because it is too large
Load Diff
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of workerman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use GatewayWorker\BusinessWorker;
|
||||
use Workerman\Worker;
|
||||
|
||||
// 自动加载类
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
// 获取插件配置
|
||||
$kefu_config = get_addon_config('kefu');
|
||||
// bussinessWorker 进程
|
||||
$worker = new BusinessWorker();
|
||||
// worker名称
|
||||
$worker->name = 'KeFuBusinessWorker';
|
||||
// bussinessWorker进程数量
|
||||
$worker->count = $kefu_config['worker_process_number'];
|
||||
// 服务注册地址
|
||||
$worker->registerAddress = '127.0.0.1:' . $kefu_config['register_port'];
|
||||
//设置处理业务的类,此处制定Events的命名空间
|
||||
$worker->eventHandler = 'addons\kefu\library\GatewayWorker\Applications\KeFu\Events';
|
||||
|
||||
// 如果不是在根目录启动,则运行runAll方法
|
||||
if (!defined('GLOBAL_START')) {
|
||||
Worker::runAll();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of workerman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use GatewayWorker\Gateway;
|
||||
use Workerman\Worker;
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
// gateway 进程
|
||||
$kefu_config = get_addon_config('kefu');
|
||||
|
||||
$context = [];
|
||||
$ssl_start = false;
|
||||
if ($kefu_config['wss_switch'] && $kefu_config['ssl_cert'] && $kefu_config['ssl_cert_key']) {
|
||||
$context ['ssl'] = [
|
||||
// 使用绝对路径
|
||||
'local_cert' => $kefu_config['ssl_cert'], // 也可以是crt文件
|
||||
'local_pk' => $kefu_config['ssl_cert_key'],
|
||||
'verify_peer' => false,
|
||||
//'allow_self_signed' => true, //如果是自签名证书开启此选项
|
||||
];
|
||||
|
||||
$ssl_start = true;
|
||||
}
|
||||
|
||||
$gateway = new Gateway("websocket://0.0.0.0:" . $kefu_config['websocket_port'], $context);
|
||||
|
||||
if ($ssl_start) {
|
||||
// 开始SSL
|
||||
$gateway->transport = 'ssl';
|
||||
}
|
||||
|
||||
// gateway名称,status方便查看
|
||||
$gateway->name = 'KeFuGateway' . ($ssl_start ? '-wss' : '');
|
||||
|
||||
// gateway进程数
|
||||
$gateway->count = $kefu_config['gateway_process_number'];
|
||||
|
||||
// 本机ip,分布式部署时使用内网ip
|
||||
$gateway->lanIp = '127.0.0.1';
|
||||
|
||||
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
|
||||
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口
|
||||
$gateway->startPort = $kefu_config['internal_start_port'];
|
||||
|
||||
// 服务注册地址
|
||||
$gateway->registerAddress = '127.0.0.1:' . $kefu_config['register_port'];
|
||||
|
||||
// 心跳间隔
|
||||
$gateway->pingInterval = 30;
|
||||
|
||||
$gateway->pingNotResponseLimit = 1;
|
||||
|
||||
// 心跳数据
|
||||
$gateway->pingData = '';
|
||||
|
||||
// 如果不是在根目录启动,则运行runAll方法
|
||||
if (!defined('GLOBAL_START')) {
|
||||
Worker::runAll();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of workerman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use GatewayWorker\Register;
|
||||
use Workerman\Worker;
|
||||
|
||||
// 自动加载类
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
// 获取插件配置
|
||||
$kefu_config = get_addon_config('kefu');
|
||||
// register 必须是text协议
|
||||
$register = new Register('text://0.0.0.0:' . $kefu_config['register_port']);
|
||||
|
||||
// 如果不是在根目录启动,则运行runAll方法
|
||||
if (!defined('GLOBAL_START')) {
|
||||
Worker::runAll();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/*内部通信服务*/
|
||||
|
||||
use GatewayWorker\Gateway;
|
||||
use Workerman\Autoloader;
|
||||
use Workerman\Worker;
|
||||
|
||||
// 自动加载类
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
Autoloader::setRootPath(__DIR__);
|
||||
|
||||
$kefu_config = get_addon_config('kefu');
|
||||
|
||||
$internal_gateway = new Gateway("Text://127.0.0.1:" . ($kefu_config['register_port'] + 100));
|
||||
$internal_gateway->name = 'KeFuGateway';
|
||||
$internal_gateway->startPort = $kefu_config['internal_start_port'] + 1000;
|
||||
$internal_gateway->registerAddress = '127.0.0.1:' . $kefu_config['register_port'];// 端口为start_register.php中监听的端口
|
||||
|
||||
// 如果不是在根目录启动,则运行runAll方法
|
||||
if (!defined('GLOBAL_START')) {
|
||||
Worker::runAll();
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2009-2015 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/workerman/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
GatewayWorker windows 版本
|
||||
=================
|
||||
|
||||
GatewayWorker基于[Workerman](https://github.com/walkor/Workerman)开发的一个项目框架,用于快速开发长连接应用,例如app推送服务端、即时IM服务端、游戏服务端、物联网、智能家居等等。
|
||||
|
||||
GatewayWorker使用经典的Gateway和Worker进程模型。Gateway进程负责维持客户端连接,并转发客户端的数据给Worker进程处理;Worker进程负责处理实际的业务逻辑,并将结果推送给对应的客户端。Gateway服务和Worker服务可以分开部署在不同的服务器上,实现分布式集群。
|
||||
|
||||
GatewayWorker提供非常方便的API,可以全局广播数据、可以向某个群体广播数据、也可以向某个特定客户端推送数据。配合Workerman的定时器,也可以定时推送数据。
|
||||
|
||||
GatewayWorker Linux 版本
|
||||
======================
|
||||
Linux 版本GatewayWorker 在这里 https://github.com/walkor/GatewayWorker
|
||||
|
||||
启动
|
||||
=======
|
||||
双击start_for_win.bat
|
||||
|
||||
Applications\YourApp测试方法
|
||||
======
|
||||
使用telnet命令测试(不要使用windows自带的telnet)
|
||||
```shell
|
||||
telnet 127.0.0.1 8282
|
||||
Trying 127.0.0.1...
|
||||
Connected to 127.0.0.1.
|
||||
Escape character is '^]'.
|
||||
Hello 3
|
||||
3 login
|
||||
haha
|
||||
3 said haha
|
||||
```
|
||||
|
||||
手册
|
||||
=======
|
||||
http://www.workerman.net/gatewaydoc/
|
||||
|
||||
使用GatewayWorker-for-win开发的项目
|
||||
=======
|
||||
## [tadpole](http://kedou.workerman.net/)
|
||||
[Live demo](http://kedou.workerman.net/)
|
||||
[Source code](https://github.com/walkor/workerman)
|
||||

|
||||
|
||||
## [chat room](http://chat.workerman.net/)
|
||||
[Live demo](http://chat.workerman.net/)
|
||||
[Source code](https://github.com/walkor/workerman-chat)
|
||||

|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name" : "workerman/gateway-worker-demo",
|
||||
"keywords": ["distributed","communication"],
|
||||
"homepage": "http://www.workerman.net",
|
||||
"license" : "MIT",
|
||||
"require": {
|
||||
"workerman/gateway-worker" : ">=3.0.0"
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "ab9c3e87dac1a4a30c63a47de76a8217",
|
||||
"packages": [
|
||||
{
|
||||
"name": "workerman/gateway-worker",
|
||||
"version": "v3.0.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/walkor/GatewayWorker.git",
|
||||
"reference": "50d3a77deb7f7fb206d641ee0307ae1c41d5d41d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/walkor/GatewayWorker/zipball/50d3a77deb7f7fb206d641ee0307ae1c41d5d41d",
|
||||
"reference": "50d3a77deb7f7fb206d641ee0307ae1c41d5d41d",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"workerman/workerman": ">=3.5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GatewayWorker\\": "./src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"homepage": "http://www.workerman.net",
|
||||
"keywords": [
|
||||
"communication",
|
||||
"distributed"
|
||||
],
|
||||
"time": "2020-07-15T06:45:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "workerman/workerman",
|
||||
"version": "v4.0.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/walkor/Workerman.git",
|
||||
"reference": "132a277b1836464c8fb99e9146ca161de8d7199f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/walkor/Workerman/zipball/132a277b1836464c8fb99e9146ca161de8d7199f",
|
||||
"reference": "132a277b1836464c8fb99e9146ca161de8d7199f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Workerman\\": "./"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "http://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
|
||||
"homepage": "http://www.workerman.net",
|
||||
"keywords": [
|
||||
"asynchronous",
|
||||
"event-loop"
|
||||
],
|
||||
"time": "2020-09-15T09:22:45+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "1.1.0"
|
||||
}
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* run with command
|
||||
* php start.php start
|
||||
*/
|
||||
|
||||
namespace addons\kefu\library\gatewayworker;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
|
||||
use think\Config;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\exception\PDOException;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class start extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('kefu')
|
||||
->addArgument('action', Argument::OPTIONAL, "action start [d]|stop|restart|status")
|
||||
->addArgument('type', Argument::OPTIONAL, "d -d")
|
||||
->setDescription('KeFu 会话服务');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
global $argv;
|
||||
$action = trim($input->getArgument('action'));
|
||||
$type = trim($input->getArgument('type')) ? '-d' : '';
|
||||
|
||||
$argv[0] = 'chat';
|
||||
$argv[1] = $action;
|
||||
$argv[2] = $type ? '-d' : '';
|
||||
$this->start();
|
||||
}
|
||||
|
||||
private function start()
|
||||
{
|
||||
if (strpos(strtolower(PHP_OS), 'win') === 0) {
|
||||
exit("Windows下不支持窗口启动,请手动运行(not support windows, please use):public/kefu_start_for_win.bat\n");
|
||||
}
|
||||
|
||||
// 检查扩展
|
||||
if (!extension_loaded('pcntl')) {
|
||||
exit("Please install pcntl extension. See http://doc.workerman.net/appendices/install-extension.html\n");
|
||||
}
|
||||
|
||||
if (!extension_loaded('posix')) {
|
||||
exit("Please install posix extension. See http://doc.workerman.net/appendices/install-extension.html\n");
|
||||
}
|
||||
|
||||
// 标记是全局启动
|
||||
define('GLOBAL_START', 1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// 加载所有Applications/*/start.php,以便启动所有服务
|
||||
foreach (glob(__DIR__ . '/Applications/*/start*.php') as $start_file) {
|
||||
require_once $start_file;
|
||||
}
|
||||
|
||||
// 运行所有服务
|
||||
Worker::runAll();
|
||||
}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
php Applications\FsatChat\start_register.php Applications\FsatChat\start_gateway.php Applications\FsatChat\start_businessworker.php Applications\FsatChat\start_text_gateway.php
|
||||
pause
|
||||
Reference in New Issue
Block a user