123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- <?php
- /**
- * Created by PhpStorm.
- * User: Elton
- * Date: 2019/3/4
- * Time: 10:56
- */
- namespace app\api\controller;
- use app\common\controller\Api;
- use app\common\library\Redis;
- use app\main\constants\AdminConstants;
- use app\main\service\ChangeMenuService;
- use EasyWeChat\Factory;
- use Symfony\Component\Cache\Simple\RedisCache;
- use think\Config;
- use fast\Http;
- use think\Db;
- use think\Log;
- class Changedomain extends Api
- {
- const CACHE_KEY_ADMIN_INFO = 'ANI:';
- const DEAD_DOMAIN_PRE = 'DEADDOMAIN:';
- const PARAM_ERROR = 0;
- const PARAM_SUCCESS = 1;
- const VALID_URL_API = 'http://123.206.179.42/WxListen/api.php?sign=3358471198&url=';
- protected $adminExtend_model = null;
- protected $adminConfig_model = null;
- protected $authGroupAccess_model = null;
- protected $ophost_model = null;
- protected $ptoken_model = null;
- protected $domain_suffix = '';
- protected $app_id = '';
- protected $pt = '';
- protected $redis = null;
- public function _initialize()
- {
- parent::_initialize();
- $this->adminExtend_model = model('AdminExtend');
- $this->adminConfig_model = model('AdminConfig');
- $this->authGroupAccess_model = model('AuthGroupAccess');
- $this->ophost_model = model('Ophost');
- $this->ptoken_model = model('Ptoken');
- $this->redis = Redis::instance();
- }
- /**
- * 1. 接收一个域名{顶级域名 | 二级域名}
- * 首先验证顶级域名是否被封了
- * { 被封,切换顶级域名 | 顶级没有被封,检查二级域名是否被封,被封,切二级域名 }
- * 2. 查找一个可用的域名{ 异步 }
- * 3. 将可用域名替换被封掉的域名 { 异步 }
- * 4. 发送企业微信 { 异步 | }
- */
- // 相关表:ophost | admin_config | ptoken | platform
- public function index()
- {
- $param = $this->request->param();
- $admin_id = $param['admin_id'] ?? 0;
- $domain = $param['domain'] ? urldecode($param['domain']) : '';
- $this->pt = $param['pt'] ?? '';
- Log::info('[ ChangeDomain ] [doAsynRequest] START');
- Log::info('[ ChangeDomain ] [Params] '. json_encode($param));
- $adminInfo = $this->_getAdminInfo($admin_id);
- Log::info('[ ChangeDomain ] [adminInfo] '. json_encode($adminInfo));
- $this->domain_suffix = $this->getDomainSuffix($domain);
- if(empty($domain)){
- echo json_encode(['msg' => '参数domain不能为空', 'status' => self::PARAM_ERROR]);
- exit();
- }
- if (!$adminInfo) {
- // admin_id = 0 && 仅传入了域名的情况
- $this->checkTopDomain($domain, $admin_id);
- Log::info('[ ChangeDomain ] [doAsynRequest] END');
- echo json_encode(['msg' => 'Success', 'status' => self::PARAM_SUCCESS]);
- } else {
- echo json_encode(['msg' => 'Success', 'status' => self::PARAM_SUCCESS]);
- fastcgi_finish_request(); /* 响应完成, 关闭连接 */
- // 异步处理
- $this->asynHandle($admin_id, urlencode($domain));
- Log::info('[ ChangeDomain ] [doAsynRequest] END');
- }
- }
- /**
- * 异步任务处理
- * @param $admin_id
- * @param $domain
- */
- public function asynHandle($admin_id, $domain)
- {
- $domain = urldecode($domain);
- Log::info('[ ChangeDomain ] [ asynHandle ] start');
- Log::info('[ ChangeDomain ] [ asynHandle ] $admin_id:' . $admin_id . '$domain:' . $domain);
- $this->domain_suffix = $this->getDomainSuffix($domain);
- Log::info('[ ChangeDomain ] [ asynHandle ] domain_suffix:' . $this->domain_suffix);
- $adminInfo = $this->_getAdminInfo($admin_id);
- $platform_list = $adminInfo['platform_list'] ?? '';
- $platform_id = $adminInfo['platform_id'] ?? '';
- $ophost_id = $adminInfo['ophost_id'] ?? '';
- $menu_platform_id = $adminInfo['menu_platform_id'] ?? '';
- $menuophost_id = $adminInfo['menuophost_id'] ?? '';
- //获取顶级域名
- $top_domain = $this->_getTopDomain($domain);
- //判断顶级域名是否被封
- if (!$this->_isValidDomain($top_domain)) {
- // 企业微信报警,顶级挂了 && 1小时内,同一个顶级不重复报警
- $this->checkTopDomain($top_domain, $admin_id);
- }else{
- $valid_ophost_domain_obj = null;
- $valid_menu_domain_obj = null;
- Log::info("[ ChangeDomain ] [ asynHandle ] [ platform_list ]" . print_r(json_encode($platform_list), true));
- $valid_ophost_domain_obj = $this->getValidHostObj($admin_id, $platform_id, $platform_list);
- $valid_menu_domain_obj = $this->getValidHostObj($admin_id, $menu_platform_id, $platform_list);
- if (!$valid_ophost_domain_obj) {
- $content = "";
- $content .= "[Error]".date('Y-m-d H:i:s');
- $content .= "\n错误原因:业务域名无域名可切";
- $content .= "\n被封域名:{$domain}";
- $content .= $this->_packageNotice($admin_id);
- Log::info("[ ChangeDomain ] [ asynHandle ] [ 业务域名 ]" . date('Y-m-d H:i:s') . "错误原因:无域名可切,被封域名:{$domain}");
- $this->_sendWorkChatMessage($content);
- }else{
- // 替换
- $this->_modifyOphost($ophost_id, $valid_ophost_domain_obj['ophost_id'], $admin_id);
- }
- if (!$valid_menu_domain_obj) {
- $content = "";
- $content .= "[Error]".date('Y-m-d H:i:s');
- $content .= "\n错误原因:菜单域名无域名可切";
- $content .= "\n被封域名:{$domain}";
- $content .= $this->_packageNotice($admin_id);
- Log::info("[ ChangeDomain ] [ asynHandle ] [ 菜单业务域名 ]" . date('Y-m-d H:i:s') . "错误原因:无域名可切,被封域名:{$domain}");
- $this->_sendWorkChatMessage($content);
- }else{
- $this->_modifyMenuOphost($menuophost_id, $valid_menu_domain_obj['ophost_id'], $admin_id);
- }
- // 清除缓存
- $this->redis->del(self::CACHE_KEY_ADMIN_INFO . $admin_id);
- }
- return json(['data'=>'ok']);
- }
- public function getDomainSuffix($domain)
- {
- $tmp_domain = str_replace('http://', '', $domain);
- $tmp_domain = str_replace('https://', '', $tmp_domain);
- $tmp_domain_arr = explode('/', $tmp_domain);
- unset($tmp_domain_arr[0]);
- $str = implode('/',$tmp_domain_arr);
- return $str;
- }
- /**
- * 顶级被封则发送企业微信 && 1小时内,同一个顶级不重复报警
- * @param $domain
- * @param $admin_id
- */
- public function checkTopDomain($domain, $admin_id)
- {
- $tmp_domain = $this->filterDomain($domain);
- if (!$this->redis->get(self::DEAD_DOMAIN_PRE . $tmp_domain)) {
- // 企业微信报警,顶级挂了 && 1小时内,同一个顶级不重复报警
- $content = "顶级域名{$tmp_domain}被封,请尽快处理!";
- $content .= $this->_packageNotice($admin_id);
- $this->_sendWorkChatMessage($content);
- $this->redis->setex(self::DEAD_DOMAIN_PRE . $tmp_domain, 3600, $tmp_domain);
- }
- }
- /**
- * 过滤url 中的 http:// https://
- * @param $domain
- * @return mixed
- */
- public function filterDomain($domain)
- {
- $tmp_domain = str_replace('http://', '', $domain);
- $tmp_domain = str_replace('https://', '', $tmp_domain);
- $tmp_domain_arr = explode('/', $tmp_domain);
- $tmp_domain = $tmp_domain_arr[0];
- return $tmp_domain;
- }
- /**
- * 获取顶级域名
- * @param $host
- * @return string
- */
- private function _getTopDomain($host)
- {
- $host = $this->filterDomain($host);
- Log::info('[ ChangeDomain ] [ TopDomain ] '.print_r($host, true));
- preg_match("/^wx\w+/i", $host, $matches);
- if ($matches) {
- $arr = explode('.', $host);
- unset($arr[0]);
- $top_domain = implode('.', $arr);
- Log::info('[ ChangeDomain ] [ TopDomain ] [ Result ]' . $top_domain);
- return $top_domain;
- }
- return $host;
- }
- /**
- * 返回可用的域名
- * @param $admin_id
- * @param $platform_id
- * @param string $platform_list
- * @return null
- */
- public function getValidHostObj($admin_id, $platform_id, $platform_list = '')
- {
- Log::info("[ ChangeDomain ] [ platform_list ] [ start ] " . print_r(json_encode($platform_list), true));
- $valid_domain_obj = null;
- $adminInfo = $this->_getAdminInfo($admin_id);
- $appid = isset($adminInfo['appid']) ? $adminInfo['appid'] : '';
- $platform_id_filter = !empty($platform_list) ? $platform_list : $platform_id;
- // 查找一个可用的域名
- $valid_domain_obj = $this->_getItemDomain($platform_id_filter, $appid);
- Log::info("[ ChangeDomain ] [ getValidHostObj ] [ 查找到的可用域名信息 ] {$admin_id}" . print_r(json_encode($valid_domain_obj), true));
- if (!$valid_domain_obj && !$platform_list) {
- // 拆解 platform_list
- $platform_arr = explode(',', $platform_list);
- $platform_arr = array_diff($platform_arr, [$platform_id]);
- Log::info("[ ChangeDomain ] [ platform_arr ] " . print_r(json_encode($platform_arr), true));
- // 检查平台是否授权,返回授权的平台
- foreach ($platform_arr as $key => $value) {
- $refresh_token = $this->ptoken_model->getToken($value, $admin_id);
- if ($refresh_token) {
- // 检查授权平台可用域名
- $valid_domain_obj = $this->_getItemDomain($value, $appid);
- if ($valid_domain_obj) {
- break;
- }
- }
- }
- }
- // 没有可用域名 ,返回NULL
- return $valid_domain_obj;
- }
- /**
- * 查找一个可用域名
- * @param $platform_id
- * @return null
- */
- private function _getItemDomain($platform_id, $appid = '')
- {
- // 查找一个可用的域名
- $valid_domain_arr = $this->_getValidDomainList($platform_id);
- Log::info("[ ChangeDomain ] [ getItemDomain ] [ 可用域名列表 ] " . print_r(json_encode($valid_domain_arr), true));
- $valid_domain_obj = null;
- if ($valid_domain_arr) {
- foreach ($valid_domain_arr as $k => $item) {
- // 请求接口,查看域名是否可用?
- // 如果可用,终止循环,返回可用域名
- if ($this->_isValidDomain($appid.'.'.$item['ophost_host'] . '/' . $this->domain_suffix)) {
- $valid_domain_obj = $item;
- break;
- }
- }
- }
- return $valid_domain_obj;
- }
- /**
- * 修改业务域名
- * @param $ophost_id
- * @param $admin_id
- * @return mixed
- */
- private function _modifyOphost($old_ophost_id, $ophost_id, $admin_id)
- {
- $adminInfo = $this->_getAdminInfo($admin_id);
- $appid = isset($adminInfo['appid']) ? $adminInfo['appid'] : '';
- $old_ophost = $this->_getOphostById($old_ophost_id);
- if (!$this->_isValidDomain($appid . '.' . $old_ophost . '/' . $this->domain_suffix)) {
- // 修改数据库
- $this->adminConfig_model->save(['ophost_id' => $ophost_id], ['admin_id' => $admin_id]);
- $ophost = $this->_getOphostById($ophost_id);
- // 发送企业微信 {成功 | 失败 都需要告知}
- $content = "";
- $content .= "[Success]" . date('Y-m-d H:i:s');
- $content .= "\n域名类型:业务域名";
- $content .= "\n被封域名:{$old_ophost}";
- $content .= "\n切换域名:{$ophost}";
- Log::info('[ ChangeDomain ] [ modifyOphost ] ' . "[Success]" . date('Y-m-d H:i:s') . "域名类型:业务域名,被封域名:{$old_ophost},切换域名:{$ophost}");
- $content .= $this->_packageNotice($admin_id);
- $this->_sendWorkChatMessage($content);
- }else{
- Log::info('[ ChangeDomain ] [ modifyOphost ] ' . "[Success]" . date('Y-m-d H:i:s') . "业务域名{$old_ophost},未被封无需替换");
- }
- }
- /**
- * 修改菜单业务域名
- * @param $menuophost_id
- * @param $admin_id
- * @return mixed
- */
- private function _modifyMenuOphost($old_ophost_id, $menuophost_id, $admin_id)
- {
- $adminInfo = $this->_getAdminInfo($admin_id);
- $appid = isset($adminInfo['appid']) ? $adminInfo['appid'] : '';
- $old_menu_ophost = $this->_getOphostById($old_ophost_id);
- if (!$this->_isValidDomain($appid . '.' . $old_menu_ophost . '/' . $this->domain_suffix)) {
- // 修改数据库
- $data = $this->adminConfig_model->save(['menuophost_id' => $menuophost_id], ['admin_id' => $admin_id]);
- if($data){
- //刷新菜单业务域名
- ChangeMenuService::instance()->setChannelId($admin_id)->setReplaceHostById($menuophost_id)->push();
- }
- $menu_ophost = $this->_getOphostById($menuophost_id);
- $content = "";
- $content .= "[Success]".date('Y-m-d H:i:s');
- $content .= "\n域名类型:菜单域名";
- $content .= "\n被封域名:{$old_menu_ophost}";
- $content .= "\n切换域名:{$menu_ophost}";
- Log::info('[ ChangeDomain ] [ modifyMenuOphost ] ' . "[Success]" . date('Y-m-d H:i:s') . "域名类型:菜单域名," . "被封域名:{$old_menu_ophost},切换域名:{$menu_ophost}");
- $content .= $this->_packageNotice($admin_id);
- $this->_sendWorkChatMessage($content);
- }else{
- Log::info('[ ChangeDomain ] [ modifyMenuOphost ] ' . "[Success]" . date('Y-m-d H:i:s') . "菜单业务域名{$old_menu_ophost},未被封无需替换");
- }
- }
- /**
- * 获取可用的域名列表
- * @param $platform_id
- * @return mixed
- */
- private function _getValidDomainList($platform_id)
- {
- $data = $this->ophost_model->getHostListByPlatformId($platform_id);
- return $data;
- }
- /**
- * 获取Admin所有信息
- * @param $admin_id
- * @return mixed
- */
- private function _getAdminInfo($admin_id)
- {
- return $this->adminConfig_model->getAdminInfoAll($admin_id);
- }
- /**
- * 获取域名信息
- * @param $ophost_id
- * @return string
- */
- private function _getOphostById($ophost_id)
- {
- $data = $this->ophost_model->get(['id' => $ophost_id]);
- return $data ? $data->host : '';
- }
- //发企业微信
- private function _sendWorkChatMessage($content)
- {
- if (empty($content)) {
- return false;
- }
- try {
- $wechat = Config::get('wechat');
- $wechat['http']['base_uri'] = $wechat['work']['base_uri'];
- $wechat['http']['timeout'] = 20;
- $wechat['corp_id'] = $wechat['work']['domain_corp_id'];
- $wechat['secret'] = $wechat['work']['domain_secret'];
- $app = Factory::work($wechat);
- $app['cache'] = new RedisCache(Redis::instanceCache());
- $res = $app->message
- ->message($content)
- ->ofAgent($wechat['work']['domain_agent_id'])
- ->toParty($wechat['work']['domain_party_id'])
- ->send();
- Log::info('[ ChangeDomain ] [ sendWorkChatMessage] '.print_r(json_encode($res), true));
- return $res;
- } catch (\Exception $exception) {
- Log::error('[ ChangeDomain ] [ sendWorkChatMessage] ' . $exception->getMessage());
- }
- }
- /**
- * 检测域名是否可以访问,是否被封
- * @param $url
- * @return bool
- */
- private function _isValidDomain($url)
- {
- sleep(1);
- Log::info('[ ChangeDomain ] [ checkurl ] ' . print_r($url, true));
- $url = self::VALID_URL_API . "{$url}";
- Log::info('[ ChangeDomain ] [ checkurl ] ' . $url);
- $json_data = Http::get($url);
- $request_count = 1;
- if (empty($json_data) && $request_count == 1) {
- $json_data = Http::get($url);
- $request_count++;
- echo $request_count;
- }
- Log::info('[ ChangeDomain ] [ checkurl ] [ Json_data] ' . $json_data);
- if(empty($json_data)){
- $this->_sendWorkChatMessage('【Error】域名监控接口返回值为空!!!');
- exit();
- }
- $data = json_decode($json_data, true);
- $ret = is_array($data) ? $data : false;
- Log::info('[ ChangeDomain ] [ checkurl ] [status] ' . $ret['status']);
- if (is_array($ret)) {
- /**
- * -2.请求失败
- * -1.cookie失效
- * 0.屏蔽
- * 1.正常域名
- * 2.白名单
- * 3.已跳转到微信110页面
- */
- if (in_array($ret['status'], [-2, -1, 2])) {
- $this->_sendWorkChatMessage('【Error】域名监控接口返回值:' . $json_data);
- exit();
- } elseif ($ret['status'] == 1) {
- Log::info('[ ChangeDomain ] [ checkurl ] [ isValidDomain ] TRUE');
- return true;
- } else {
- Log::info('[ ChangeDomain ] [ checkurl ] [ isValidDomain ] FALSE A');
- return false;
- }
- } else {
- Log::info('[ ChangeDomain ] [ checkurl ] [ isValidDomain ] FALSE B');
- return false;
- }
- }
- /**
- * 返回用户关联信息
- * @param $admin_id
- * @return string
- */
- private function _packageNotice($admin_id)
- {
- $html = '';
- $group_id = $this->authGroupAccess_model->getGroupId($admin_id);
- if($group_id == AdminConstants::ADMIN_GROUP_ID_AGENT){
- $sql = "SELECT admin.id,admin.username, admin.nickname, admin_extend.create_by,
- qd_admin.username as qd_username,qd_admin.nickname as qd_nickname
- ,qd_admin_extend.create_by as qd_create_by
- ,sw_admin.username as sw_username, sw_admin.nickname as sw_nickname
- FROM admin
- LEFT JOIN admin_extend ON admin.id= admin_extend.admin_id
- LEFT JOIN admin as qd_admin ON admin_extend.create_by = qd_admin.id
- LEFT JOIN admin_extend as qd_admin_extend ON qd_admin.id = qd_admin_extend.admin_id
- LEFT JOIN admin as sw_admin on qd_admin_extend.create_by = sw_admin.id
- WHERE admin.id ={$admin_id}
- LIMIT 1";
- $res = Db::query($sql);
- if($res){
- $data = $res[0];
- $html .= "\n代理商ID:{$data['id']} \n代理商账号:{$data['username']} \n代理商昵称:{$data['nickname']}";
- $html .= "\n渠道商ID:{$data['create_by']} \n渠道商账号:{$data['qd_username']} \n渠道商昵称:{$data['qd_nickname']}";
- $html .= "\n商务ID:{$data['qd_create_by']} \n商务账号:{$data['sw_username']} \n商务昵称:{$data['sw_nickname']}";
- }
- } elseif ($group_id == AdminConstants::ADMIN_GROUP_ID_CHANNEL){
- $sql = "SELECT admin.id,admin.username, admin.nickname, admin_extend.create_by,
- sw_admin.username as sw_username,sw_admin.nickname as sw_nickname
- FROM admin
- LEFT JOIN admin_extend ON admin.id= admin_extend.admin_id
- LEFT JOIN admin as sw_admin ON admin_extend.create_by = sw_admin.id
- LEFT JOIN admin_extend as sw_admin_extend ON sw_admin.id = sw_admin_extend.admin_id
- WHERE admin.id ={$admin_id}
- LIMIT 1";
- $res = Db::query($sql);
- if($res){
- $data = $res[0];
- $html .= "\n渠道商ID:{$data['id']} \n渠道商账号:{$data['username']} \n渠道商昵称:{$data['nickname']}";
- $html .= "\n商务ID:{$data['create_by']} \n商务账号:{$data['sw_username']} \n商务昵称:{$data['sw_nickname']}";
- }
- }elseif ($group_id == AdminConstants::ADMIN_GROUP_ID_ADMIN){
- $sql = "SELECT id,username, nickname FROM admin WHERE id ={$admin_id} LIMIT 1";
- $res = Db::query($sql);
- if($res){
- $data = $res[0];
- $html .= "\n商务ID:{$data['id']} \n商务账号:{$data['username']} \n商务昵称:{$data['nickname']}";
- }
- }
- $html .= "\n平台:{$this->pt}";
- return $html;
- }
- }
|