SyncSubmitTaskService.php 14.2 KB
<?php


namespace App\Services;

use App\Exceptions\InquiryFilterException;
use App\Models\Inquiry\InquiryForm;
use App\Models\Inquiry\InquiryFormData;
use App\Models\Project\InquiryFilterConfig;
use App\Models\Project\Project;
use App\Models\Subscribe\Email;
use App\Models\SyncSubmitTask\SyncSubmitTask;
use App\Models\Visit\Visit;
use App\Models\Workchat\MessagePush;
use App\Utils\LogUtils;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
use function Symfony\Component\String\s;


/**
 * Class SyncSubmitTaskService
 * @package App\Services
 * @author zbj
 * @date 2023/12/4
 */
class SyncSubmitTaskService
{
    /**
     * @param $task
     * @return mixed
     * @throws InquiryFilterException
     * @author zbj
     * @date 2023/11/28
     */
    public static function handler($task, $date = '')
    {
        $data = $task['data'];
        $checkIpCountry = self::checkIpCountry($data['domain'], $data['ip'], $task['type']);

        $data['ip'] = $checkIpCountry['ip'];
        $data['country'] = $checkIpCountry['country'];
        $data['submit_at'] = $task['created_at'];
        $project = $checkIpCountry['project'];
        $data['project_id'] = $project['id'];

        //特殊处理
        if($project['id'] == 455 && !empty($data['email']) && $data['email'] == 'alb@marketingtu.org'){
            return false;
        }

        //过滤url参数 清除全部参数
        if($project['id'] == 1442 && !empty($data['data']['url'])){
            $query = parse_url($data['data']['url'], PHP_URL_QUERY);
            if($query){
                $data['data']['url'] = str_replace('?'.$query, '', $data['data']['url']);
            }
        }

        // 项目ID:448, 过滤被刷访问
        if ($project['id'] == 448 && $task['type'] == 'visit') {
            if ($data['country'] == '约旦' && empty($data['referrer_url'])) {
                $url_array = parse_url($data['url']);
                $path_array = explode('/', $url_array['path']);
                if (FALSE == empty($path_array[1]) && strlen($path_array[1]) <= 3)
                    return false;
            }
        }

        if(!ProjectServer::useProject($project['id'])){
            return false;
        }

        $action = $task['type'];

        //是否是订阅邮箱
        if($action == 'inquiry' && !empty($project['is_subscribe'])){
            //是否只有email字段
            $filed = '';
            foreach ($data['data'] as $k => $v){
                if(Str::startsWith(strtolower($k),'globalso-')){
                    continue;
                }
                $filed .= $k;
            }
            $filed == 'email' && $action = 'subscribe';
        }

        $handler = new self();
        return $handler->$action($data, $date, $task['id']);
    }


    /**
     * 特殊处理项目  去掉来源url的全部参数
     */
    public function handle_referer($referer){
        $url = [
           'www.shphe.ru',
           'www.mainpaper.ru',
           'www.jinbiao.ru',
           'www.gyhockey.ru',
        ];

        if(Str::contains($referer, $url)){
            $referer = parse_url($referer);
            $referer = !empty($referer['host']) ? $referer['scheme'] . '://' . $referer['host']  . '/' : $referer['path'];
        }
        return $referer;
    }

    /**
     *
     * 订阅邮箱
     * @param $data
     * @param $date
     * @throws InquiryFilterException
     * @author zbj
     * @date 2024/8/27
     */
    public function subscribe($data, $date, $task_id){
        $email = $data['data']['email'];
        if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $model = Email::where('email', $email)->first();
            if($model){
                return true;
            }
            $model->email = $email;
            $model->save();
        }else{
            throw new InquiryFilterException( '邮箱格式异常:' . $email);
        }
    }

    /**
     * 询盘
     * @param $data
     * @return bool
     * @throws InquiryFilterException
     * @author zbj
     * @date 2023/12/4
     */
    public function inquiry($data, $date, $task_id)
    {
        //数组key转为小写
        $data['data'] = array_change_key_case($data['data'], CASE_LOWER);

        $this->inquiryFilter($data['project_id'], $data);

        //特殊处理1986的表单
        if($data['project_id'] == 1986){
            $fields = ['乘用车', '商用车', '能源存储', '探索新业务'];
            $form_fields = array_keys($data['data']);
            if(array_intersect($form_fields, $fields)){
                foreach ($fields as $field){
                    if (!isset($data['data'][$field])){
                        $data['data'][$field] = [];
                    }
                }
            }
        }

        $form_id = InquiryForm::getFromId($data['data'], $data['project_id']);

        $data['referer'] = $this->handle_referer($data['referer']);

        $id = InquiryFormData::saveData($form_id, $data['domain'], $data['ip'], $data['country'], $data['referer'], $data['user_agent'], $data['submit_at'], $data['data']);


        //转化询盘
        Visit::isInquiry($data['ip']);

        //推送企微消息
        Log::channel('inquiry')->info($task_id . '询盘结果', [$id]);
        if($id){
            try {
                $name = empty($data['data']['name']) ? '' : ' ' . $data['data']['name'];
                MessagePush::addInquiryMessage($id, $data['project_id'], $data['country'], $name, $data['submit_at']);
            }catch (\Exception $e){
                Log::channel('inquiry')->info($task_id . '询盘失败', [$e->getMessage(), $e->getFile(), $e->getLine()]);
                LogUtils::error('询盘消息'.$id.'写入企微消息队列失败' . $e->getMessage());
            }
        }
        Log::channel('inquiry')->info($task_id . '询盘完成' . PHP_EOL);

        return true;
    }

    /**
     * 访问
     * @param $data
     * @return bool
     * @throws \Exception
     * @author zbj
     * @date 2023/12/4
     */
    public function visit($data, $date, $task_id)
    {

        $visit_data = $data['data'];
        $referrer_url = '';
        if($data['data']['referrer_url']){
            $url_arr = parse_url($data['data']['referrer_url']);
            if(!empty($url_arr['scheme']) && !empty($url_arr['host'])){
                $referrer_url = $url_arr['scheme'] . '://' . $url_arr['host'] . '/';
            }
        }

        $visit_data['referrer_url'] = $this->handle_referer($referrer_url);
        $visit_data['device_port'] = $data['data']['device_port']??'';
        $visit_data['url'] = $data['data']['url']??'';
        $visit_data['domain'] = $data['domain']??'';
        $visit_data['ip'] = $data['ip'];
        $visit_data['country'] = $data['country'];
        $visit_data['updated_date'] = $data['submit_at']->toDateString();
        $visit_data['created_at'] = $data['submit_at'];
        $visit_data['user_agent'] = $data['user_agent'];
        if(!empty($data['is_cf'])){
            $visit_data['is_inquiry'] = 1;
        }
        Visit::saveData($visit_data, $visit_data['updated_date']);

        return true;
    }

    /**
     * 根据ip查地区
     * @param $ip
     * @return string
     * @author zbj
     * @date 2023/11/28
     */
    public static function getCountryByIp($ip){
        if(!$ip){
            return '';
        }
        $res = Http::withoutVerifying()->get('http://ip.globalso.com', ['ip' => $ip]);
        if($res->status() == 200){
            return $res->body();
        }else{
            return '';
        }
    }

    /**
     * 是否开始测试站或中国内地询盘和访问记录
     * @param $domain
     * @param $ip
     * @param $type
     * @return array
     * @throws InquiryFilterException
     * @author zbj
     * @date 2023/11/30
     */
    public static function checkIpCountry($domain, $ip, $type){
        $project = Project::getProjectByDomain($domain);
        if(empty($project)){
            throw new InquiryFilterException('项目不存在');
        }

        // 访问记录过滤测试环境
        if ($type == SyncSubmitTask::TYPE_VISIT && FALSE !== strpos($domain, 'globalso.site') && !$project->is_record_test_visit) {
            throw new InquiryFilterException('测试环境过滤');
        }

        // 访问记录过滤测试环境
        if ($type == SyncSubmitTask::TYPE_INQUIRY && FALSE !== strpos($domain, 'globalso.site') && !$project->is_record_test_inquiry) {
            throw new InquiryFilterException('测试环境过滤');
        }

        if($ip == "127.0.0.1"){
            throw new InquiryFilterException('127.0.0.1过滤');
        }
        $country = self::getCountryByIp($ip);
        //访问记录过滤国内
        if ($type == SyncSubmitTask::TYPE_VISIT && $country == "中国" && !$project->is_record_china_visit){
            throw new InquiryFilterException('中国内地过滤');
        }
        return [
            'project' => $project,
            'ip' => $ip,
            'country' => $country
        ];
    }


    /**
     * 询盘配置过滤
     * @author zbj
     * @date 2024/1/20
     */
    public static function inquiryFilter($project_id, $data){
        if(empty($data['referer']) || empty($data['user_agent']) || empty($data['data'])){
            throw new InquiryFilterException( '数据异常:' . $data['country']);
        }
        $config = InquiryFilterConfig::getCacheInfoByProjectId($project_id);
        //没配置 则默认开启且使用全局
        if(!$config){
            $config['is_global_rule'] = 1;
            $config['status'] = 1;
        }
        //是否开启过滤
        if($config && $config['status']){
            //是否包含全局规则(就是project_id=1的配置)
            if($project_id != Project::DEMO_PROJECT_ID && $config['is_global_rule']){
                self::inquiryFilter(Project::DEMO_PROJECT_ID, $data);
            }
            //过滤国家
            if(!empty($config['filter_countries']) && in_array($data['country'], $config['filter_countries'])){
                throw new InquiryFilterException( '过滤国家:' . $data['country']);
            }
            //过滤ip
            if(!empty($config['black_ips'])){
                $black_ips = $config['black_ips'];
                //后端获取的ip
                if(in_array($data['ip'], $black_ips)){
                    throw new InquiryFilterException( '过滤黑名单IP:' . $data['ip']);
                }
                //前端获取的ip
                if(!empty($data['data']['ip']) && in_array($data['data']['ip'], $black_ips)){
                    throw new InquiryFilterException( '过滤黑名单IP:' . $data['data']['ip']);
                }
            }
            //过滤内容
            if(!empty($data['data']['message'])) {
                //过滤内容关键字
                if (!empty($config['filter_contents'])) {
                    foreach ($config['filter_contents'] as $filter_content) {
                        //中文直接包含
                        if (preg_match("/^[\x{4e00}-\x{9fa5}]+$/u", $filter_content)) {
                            if (Str::contains($data['data']['message'], $filter_content)) {
                                throw new InquiryFilterException('过滤内容:' . $filter_content);
                            }
                        } else {
                            //英文要指定词才过滤
                            if (preg_match("/\b" . preg_quote($filter_content, "/") . "\b/i", $data['data']['message'])) {
                                throw new InquiryFilterException('过滤内容:' . $filter_content);
                            }
                        }
                    }
                }

                //是否允许包含链接
                if(isset($config['is_allow_link']) && !$config['is_allow_link']){
                    if (Str::contains(strtolower($data['data']['message']), ['http://', 'https://', 'www.'])) {
                        throw new InquiryFilterException('不允许包含链接');
                    }
                }
            }
            //过滤来源
            if(!empty($config['filter_referers'])){
                //只比较path路径
                $paths = array_map(function ($v){
                    return trim(parse_url(Url::to($v), PHP_URL_PATH), '/');
                },$config['filter_referers']);

                //后端获取的referer
                if(in_array(trim(parse_url($data['referer'], PHP_URL_PATH), '/'), $paths)){
                    throw new InquiryFilterException( '过滤来源链接:' . $data['referer']);
                }
                //前端获取的referer
                if(!empty($data['data']['globalso-domain_host_url']) && in_array(parse_url($data['data']['globalso-domain_host_url'], PHP_URL_PATH), $paths)){
                    throw new InquiryFilterException( '过滤来源链接:' . $data['data']['globalso-domain_host_url']);
                }
            }
            //过滤邮箱
            if(!empty($config['filter_emails']) && !empty($data['data']['email'])){
                foreach ($config['filter_emails'] as $filter_email){
                    if(Str::contains(strtolower($data['data']['email']), strtolower($filter_email))){
                        throw new InquiryFilterException( '过滤邮箱:' . $filter_email);
                    }
                }
            }
            //过滤电话
            if(!empty($config['filter_mobiles']) && !empty($data['data']['phone'])){
                foreach ($config['filter_mobiles'] as $filter_mobile){
                    if(Str::contains(strtolower($data['data']['phone']), strtolower($filter_mobile))){
                        throw new InquiryFilterException( '过滤电话:' . $filter_mobile);
                    }
                }
            }
            //过滤姓名
            if(!empty($config['filter_names']) && !empty($data['data']['name'])){
                foreach ($config['filter_names'] as $filter_name){
                    if( Str::contains(strtolower($data['data']['name']), strtolower($filter_name))){
                        throw new InquiryFilterException( '过滤姓名:' . $filter_name);
                    }
                }
            }
        }
        return true;
    }

}