微信开发文档:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html

微信公众号(a、服务号,b、订阅号)配置:

1.基本配置->设置appSecret
2.基本配置->设置IP白名单
3.设置->公众号设置->功能设置: 业务域名、JS接口安全域名、网页授权接口域名(仅a、服务号有该功能,该功能接口可实现基于微信用户(未关注公众号的用户授权登录(静默,非静默)也可以拿到该用户的基本信息,及openid,但手机号拿不到,微信接口不给)的oauth2授权登录),将一个txt文件放在域名根目录,并且可在浏览器打开
4.基本配置->服务器配置->启用
服务器地址(URL) :该地址为唯一的与该微信公众号的token验证及消息接、转、发接口
http://shgfdgda.com/api/wx/check_sign_dyh
令牌(Token) : 用于第一次接口与微信公众号的token验证,消息解密
shaezd
消息加解密密钥(EncodingAESKey)
fdfddsssdfdggtgdrfvfrdsfdsdsssssssf
5.设置->公众号设置->授权管理 : 第三方平台授权与自己的开发者模式不冲突,且一个公众号可授权多个平台开发
6.公众号开发者模式可调用公众平台上面的图文、video等资源
7.服务号和订阅号,每次用户主动发消息或触发菜单,都会回传FromUserName(即openid),根据openid可获取unionid及用户基本信息;

WeChat.php公共基类

<?php

namespace app\common;

/**
 * 微信公众平台操作类
 */
class WeChat
{
    private $_appid;
    private $_appsecret;
    //微信公众平台请求开发者的服务器需要token
    private $_token;

    //标识qrcodeticket的类型,是永久还是临时
    const QRCODE_TYPE_TEMP = 1;
    const QRCODE_TYPE_TEMP_STR = 2;
    const QRCODE_TYPE_LIMIT = 3;
    const QRCODE_TYPE_LIMIT_STR = 4;

    /**
     * 构造函数
     * @param string $id appid
     * @param string $secret app秘钥
     */
    public function __construct($id, $secret, $token)
    {
        $this->_appid = $id;
        $this->_appsecret = $secret;
        $this->_token = $token;
    }

    /**
     * 用于第一次验证URl合法性
     */
    public function firstValid()
    {
        //校验签名的合法性
        if ($this->_checkSignature()) {
            //签名合法,告知微信服务器
            echo $_GET['echostr'];
        }
    }

    /**
     * 验证签名
     * @return [type] [description]
     */
    private function _checkSignature()
    {
        //获取由微信服务器发过来的数据
        $signature = $_GET['signature'];
        $timestamp = $_GET['timestamp'];
        $nonce = $_GET['nonce'];
        //开始验证数据
        $tmp_arr = array($this->_token, $timestamp, $nonce);
        sort($tmp_arr, SORT_STRING);
        $tmp_str = implode($tmp_arr);
        $tmp_str = sha1($tmp_str);
        //对比数据
        if ($signature == $tmp_str) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 消息类型判断
     * @return array
     */
    public function responseMsg()
    {
        //因为很多都设置了register_globals禁止,不能用$GLOBALS["HTTP_RAW_POST_DATA"] 改用file_get_contents("php://input")即可
        $postStr = file_get_contents("php://input");
        if (!empty($postStr)) {
            $postObj = $this->object_to_array(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA));
            $RX_TYPE = trim($postObj['MsgType']);
            //用户发送的消息类型判断
            switch ($RX_TYPE) {
                case "text":    //文本消息
                    return array('type' => 'text', 'msg' => '文本', 'obj' => $postObj);
                    break;
                case "image":   //图片消息
                    return array('type' => 'image', 'msg' => '图片', 'obj' => $postObj);
                    break;
                case "voice":   //语音消息
                    return array('type' => 'voice', 'msg' => '语音', 'obj' => $postObj);
                    break;
                case "video":   //视频消息
                    return array('type' => 'video', 'msg' => '视频', 'obj' => $postObj);
                    break;
                case "location"://位置消息
                    return array('type' => 'location', 'msg' => '位置', 'obj' => $postObj);
                    break;
                case "link":    //链接消息
                    return array('type' => 'link', 'msg' => '链接', 'obj' => $postObj);
                    break;
                case "event":    //触发事件
                    return array('type' => 'event', 'msg' => '事件', 'obj' => $postObj);
                    break;
                default:
                    return array('type' => 'unknow msg type', 'msg' => '未知', 'obj' => $postObj);
                    break;
            }
        } else {
            echo "";
            exit;
        }
    }


    /**
     * 获取 access_tonken值
     * @param string $token_file 用来存储的文件
     * @return access_token
     */
    public function getAccessToken($token_file = './access_token')
    {
        //处理是否过期问题,将access_token存储到文件
        $life_time = 7200;
        if (file_exists($token_file) && time() - filemtime($token_file) < $life_time) {
            // 存在有效的access_token 直接返回文件内容
            return file_get_contents($token_file);
        }
        //接口URL
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->_appid . "&secret=" . $this->_appsecret;
        //发送GET请求
        $result = $this->_request('get', $url);
        if (!$result) {
            return false;
        }
        //处理数据
        $result_obj = json_decode($result);
        //写入到文件
        file_put_contents($token_file, $result_obj->access_token);
        return $result_obj->access_token;
    }

    /**
     * 获取Ticket
     * @param string $content 二维码内容
     * @param int $type 二维码类型 1 临时整形 2临时字符串 3永久整形 4永久字符串
     * @param int $expire 有效时间
     * @return ticket
     */
    public function getQRCodeTicket($content, $type = 2, $expire = 604800)
    {
        $access_token = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' . $access_token;
        $type_list = array(
            self::QRCODE_TYPE_TEMP => 'QR_SCENE',
            self::QRCODE_TYPE_TEMP_STR => 'QR_STR_SCENE',
            self::QRCODE_TYPE_LIMIT => 'QR_LIMIT_SCENE',
            self::QRCODE_TYPE_LIMIT_STR => 'QR_LIMIT_STR_SCENE'
        );
        $action_name = $type_list[$type];
        //post发送的数据
        switch ($type) {
            case self::QRCODE_TYPE_TEMP:
                $data_arr['expire_seconds'] = $expire;
                $data_arr['action_name'] = $action_name;
                $data_arr['action_info']['scene']['scene_id'] = $content;
                break;
            case self::QRCODE_TYPE_TEMP_STR:
                $data_arr['expire_seconds'] = $expire;
                $data_arr['action_name'] = $action_name;
                $data_arr['action_info']['scene']['scene_str'] = $content;
                break;
            case self::QRCODE_TYPE_LIMIT:
                $data_arr['action_name'] = $action_name;
                $data_arr['action_info']['scene']['scene_id'] = $content;
                break;
            case self::QRCODE_TYPE_LIMIT_STR:
                $data_arr['action_name'] = $action_name;
                $data_arr['action_info']['scene']['scene_str'] = $content;
                break;
        }
        $data = json_encode($data_arr);
        $result = $this->_request('post', $url, $data);
        if (!$result) {
            return false;
        }
        $result_obj = json_decode($result);
        return $result_obj->ticket;
    }

    /**
     * 根据ticket获取二维码
     * @param int|string $content qrcode内容标识
     * @param [type] $file 存储为文件的地址,如果null直接输出
     * @param integer $type 类型
     * @param integer $expire 如果是临时,标识有效期
     * @return  [type]
     */
    public function getQRCode($content, $file = NULL, $type = 2, $expire = 604800)
    {
        //获取ticket
        $ticket = $this->getQRCodeTicket($content, $type = 2, $expire = 604800);
        $url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=$ticket";
        //发送,取得图片数据
        $result = $this->_request('get', $url);
        if ($file) {
            file_put_contents($file, $result);
        } else {
            header('Content-Type:image/jpeg');
            echo $result;
        }
    }


    /**
     * 封装发送http请求
     * @param string $method 请求方式 get/post
     * @param string $url 请求目标的url
     * @param array $data post发送的数据
     * @param bool $ssl 是否为https协议
     * @return 响应主体
     */
    private function _request($method = 'get', $url, $data = array(), $ssl = true)
    {
        //curl完成,先开启curl模块
        //初始化一个curl资源
        $curl = curl_init();
        //设置curl选项
        curl_setopt($curl, CURLOPT_URL, $url);//url
        //请求的代理信息
        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';
        curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);
        //referer头,请求来源
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);//设置超时时间
        //SSL相关
        if ($ssl) {
            //禁用后,curl将终止从服务端进行验证;
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            //检查服务器SSL证书是否存在一个公用名
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
        }
        //判断请求方式post还是get
        if (strtolower($method) == 'post') {
            /**************处理post相关选项******************/
            //是否为post请求 ,处理请求数据
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        //是否处理响应头
        curl_setopt($curl, CURLOPT_HEADER, false);
        //是否返回响应结果
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

        //发出请求
        $response = curl_exec($curl);
        if (false === $response) {
            echo '<br>', curl_error($curl), '<br>';
            return false;
        }
        //关闭curl
        curl_close($curl);
        return $response;
    }
    //对象转数组
    private function object_to_array($object) {
        $object =  json_decode( json_encode( $object),true);
        return  $object;
    }
}

控制器微信消息收发代码Wx.php

<?php

namespace app\td_api\controller;
use app\common\DesUtils;
use app\common\RedisCache;
use app\common\SimpleLog;
use app\common\WeChat;
use think\Db;

//数据采集
class Wx extends Base
{
    public function _initialize()
    {
        parent::_initialize();
        //方法token解禁

        $this->beforeActionList = [
            'api_des_decrypt' => ['except' => 'online_consulting,qm_get_msg,get_media,get_media_list,check_signature,check_signature_dyh,send_msg,get_menu,set_menu,test'],  //api_des_decrypt 必须作为第一个前置方法,位置不能跟其他的替换
            'checkToken' => ['except' => 'get_openid,online_consulting,qm_get_msg,get_media,get_media_list,check_signature,check_signature_dyh,send_msg,get_menu,set_menu,test'],
            'check_params' => ['except' => 'online_consulting,qm_get_msg,get_media,get_media_list,check_signature,check_signature_dyh,send_msg,get_menu,set_menu,test'],
        ];

    }

    //服务号配置的基本信息
    private $appid = '';
    private $app_secret = '';
    private $token = '';
    private $qm_token = '';

    //订阅号配置的基本信息 
    private $dyh_appid = '';
    private $dyh_app_secret = '';
    private $dyh_token = '';
    private $dyh_qm_token = '';

    /**
     * 根据code获取openid,并且根据openid获取unionid
     */
    public function get_openid()
    {
        $params = $this->k;//request()->param();
        $s_td_c_id = empty($params['s_td_c_id']) ? 1 : $params['s_td_c_id'];
        $td_channel_event = Db::name('td_channel_event')->where('channel_type', $s_td_c_id)->find();
        //$log = new SimpleLog('get_openid');
        //$log->write_log('channel_type:' . $td_channel_event['channel_type']);
        //$log->write_log($params);
        if ($td_channel_event['channel_type'] == 1) {
            //服务号
            if (empty($params['code'])) {
                return $this->api_des_encrypt('', 'code不能为空', 0);
                //return ['code'=>0,'msg'=>'code不能为空'];
            }
            $appid = $this->appid;
            $app_secret = $this->app_secret;
            $userinfo = $this->get_userinfo($appid, $app_secret, 1, $params['code']);
            //$log->write_log($userinfo);
            return $this->api_des_encrypt($userinfo['data'], $userinfo['msg'], $userinfo['code']);
        } elseif ($td_channel_event['channel_type'] == 2) {
            //订阅号
            $appid = $this->dyh_appid;
            $app_secret = $this->dyh_app_secret;
            if (empty($params['openId'])) {
                return $this->api_des_encrypt('', 'openId不能为空', 0);
                //return ['code'=>0,'msg'=>'code不能为空'];
            }
            $userinfo = $this->get_userinfo($appid, $app_secret, 2, '', $params['openId']);
            //$log->write_log($userinfo);
            return $this->api_des_encrypt($userinfo['data'], $userinfo['msg'], $userinfo['code']);
        }
        //$log = new SimpleLog('get_openid');
        //$log->write_log($params);
        //auth2返回的access_token,2小时内登录有效,超过2小时需要重新刷新获取
        /* $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $app_secret . '&code=' . $params['code'] . '&grant_type=authorization_code';
         $res = json_decode(curl_request($url), true);
         //$log->write_log($res);
         if (empty($res['openid'])) {
             return $this->api_des_encrypt('', 'code错误', 0);
             //return ['code'=>0,'msg'=>'code错误'];
         }
         //获取普通的openid
         $pt_access_token = $this->get_token();
         $union_url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . $pt_access_token . '&openid=' . $res['openid'] . '&lang=zh_CN';
         $union_request = curl_request($union_url);
         //$log->write_log($union_request);
         if ($union_request) {
             return $this->api_des_encrypt(json_decode($union_request, true), 'success', 1);
             //return ['code'=>1,'msg'=>'success','data'=>json_decode($union_request,true)];
         } else {
             return $this->api_des_encrypt('', 'err', 0);
             //return ['code'=>0,'msg'=>'err'];
         }*/
    }

    //服务号根据code网页授权获取openid
    private function get_oauth_openid($code)
    {
        //服务号
        if (empty($code)) {
            return false;
        }
        $appid = $this->appid;
        $app_secret = $this->app_secret;
        $userinfo = $this->get_userinfo($appid, $app_secret, 1, $code);
        $openid = empty($userinfo['data']['openid']) ? '' : $userinfo['data']['openid'];
        return $openid;
    }

    //获取用户信息及unionId,服务号可根据oauth2的access_token获取未关注该公众号的用户信息,即通过oauth2授权第三方网页登录并获取微信用户信息
    private function get_userinfo($appid, $app_secret, $channel_type = 1, $code = '', $open_id = '')
    {
        if ($channel_type == 1) {
            //服务号
            if (empty($code)) {
                return ['code' => 0, 'msg' => 'code不能为空', 'data' => ''];
            }
            //$log =new SimpleLog('get_userinfo');
            //oauth2返回的access_token,2小时内登录有效,超过2小时需要重新刷新获取
            $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $app_secret . '&code=' . $code . '&grant_type=authorization_code';
            $res = json_decode(curl_request($url), true);
            //$log->write_log('----access_token----');
            //$log->write_log($res);
            if (empty($res['openid'])) {
                //return $this->api_des_encrypt('', 'code错误', 0);
                return ['code' => 0, 'msg' => 'code错误', 'data' => ''];
            }
            $access_token = $res['access_token'];
            $open_id = $res['openid'];
            $refresh_token = $res['refresh_token'];
            //检验oauth2授权凭证access_token是否有效
            $check_auth_url = 'https://api.weixin.qq.com/sns/auth?access_token=' . $access_token . '&openid=' . $open_id;
            $check_auth = json_decode(curl_request($check_auth_url), true);
            //$log->write_log($check_auth);
            if ($check_auth['errcode'] != 0) {
                //已失效,刷新
                $refresh_token_url = 'https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=' . $appid . '&grant_type=refresh_token&refresh_token=' . $refresh_token;
                $res = json_decode(curl_request($refresh_token_url), true);
                //$log->write_log('----refresh_token----');
                //$log->write_log($res);
                $access_token = $res['access_token'];
                $open_id = $res['openid'];
                //$refresh_token = $res['refresh_token'];
                //更新access_token 和 refresh_token
            }
            //获取code的接口及参数"https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
            //如果获取code的scope=snsapi_base(静默模式,不弹出授权页面,直接跳转,只能获取用户openid),这时下面的接口报错,返回{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: tGpFvXmoRa-bPuQfa ]"}
            // 只有 scope=snsapi_userinfo 才能用下面的接口获取用户信息,
            /*$userinfo_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $open_id . '&lang=zh_CN';
            $userinfo = json_decode(curl_request($userinfo_url), true);
            //$log->write_log('----userinfo----');
            //$log->write_log($userinfo);
            if ($userinfo) {
                return ['code' => 1, 'msg' => 'success', 'data' => json_decode($userinfo, true)];
            } else {
                //return $this->api_des_encrypt('', 'err', 0);
                return ['code' => 0, 'msg' => 'err', 'data' => ''];
            }*/
        } elseif ($channel_type == 2) {
            //订阅号
            if (empty($open_id)) {
                return ['code' => 0, 'msg' => 'openid不能为空', 'data' => ''];
            }
        }

        //获取普通的unionid
        $pt_access_token = $this->get_token(0, $channel_type);
        $union_url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . $pt_access_token . '&openid=' . $open_id . '&lang=zh_CN';
        $union_request = curl_request($union_url);
        //$log->write_log($union_request);
        if ($union_request) {
            //return $this->api_des_encrypt(json_decode($union_request, true), 'success', 1);
            return ['code' => 1, 'msg' => 'success', 'data' => json_decode($union_request, true)];
        } else {
            //return $this->api_des_encrypt('', 'err', 0);
            return ['code' => 0, 'msg' => 'err', 'data' => ''];
        }
    }
    //服务号服务器配置验证接口
    /*public function check_signature()
    {
        //header('content-type:text');
        // 第三方收到公众号平台发送的消息
        //$log =new SimpleLog('wx_message');
        //$log->write_log($_GET);
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = 'shauetd';
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        //$log->write_log($tmpStr);
        if ($tmpStr == $signature) {
            //$log->write_log($_GET['echostr']);
            return (int)$_GET['echostr'];
        } else {
            //$log->write_log('err');
            return false;
        }
    }*/
    /**
     * 服务号服务器配置token验证接口及消息接收响应唯一接口
     */
    public function check_signature()
    {
        /*$params = request()->param();//request()->param();
        $type = $params['type'];
        //服务号
        $appid = $this->appid;
        $app_secret = $this->app_secret;
        $token = $this->token;*/
        //订阅号
        $appid = $this->appid;
        $app_secret = $this->app_secret;
        $token = $this->token;
        //微信公众平台配置开发者服务器信息的时候填的URL,第一次配置需要把echostr回传给微信,验证开发者服务器接收消息的接口可正常对外访问
        if (isset($_GET['echostr'])) {
            if ($this->checkSignature()) {
                echo $_GET['echostr'];
                exit;
            }
        }
        $wx = new WeChat($appid, $app_secret, $token);

        //判断消息类型
        $result = $wx->responseMsg();
        //$log = new SimpleLog('check_signature');
        //$log->write_log($result);
        //图文id
        $media_id = 'wD1UC-jxH7MPrDmL62shO4xFtW1Oqz7xC3whi7AIRSQ';
        $media = $this->get_media($media_id, 1);

        $redirect = urlencode('http://bc.xgs521.com/index.html/?s_td_c_id=1');
        $media['tz'] = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";

        //"https://ykf-webchat.7moor.com/wapchat.html?accessId=29614f30-4fff-11eb-b9d6-bbf82f53d9cd&fromUrl=http://www.baidu.com&urlTitle=AI智能实验室&language=ZHCN&otherParams={\"peerId\":\"10049041\"}"
        //$log->write_log($result['obj']->FromUserName);   //用户的openid
        //$log->write_log($result['obj']->FromUserName[0]);   //用户的openid
        //$log->write_log($result['obj']['EventKey']);
        //$this->transmitText($result['obj'], 'http://bc.td.pdvm.shuhengio.com/?s_td_c_id=4&openid='.$result['obj']->FromUserName);
        //$result['type'] == 'text'
        $this->event_produce($result, 1); //事件入库及业务逻辑处理
        //回复各种类型的消息,后面不会再执行任何代码
        if ($result['type'] == 'text') {
            //$qm_resp = $this->qm_send_msg($result['obj'], $this->appid, $this->qm_token);
            //$log->write_log('----------------------发送给七陌的消息得到的响应-----------------------');
            //$log->write_log($qm_resp);
            echo '';
            exit;
        } elseif ($result['type'] == 'event') {
            //事件
            if ($result['obj']['Event'] == 'CLICK') {
                //点击事件
                if (!empty($result['obj']['EventKey']) && $result['obj']['EventKey'] == 'tuijiancai') {
                    $this->transmitText($result['obj'], 'http://bc.xgs521.com/index.html?s_td_c_id=1');
                }if (!empty($result['obj']['EventKey']) && $result['obj']['EventKey'] == 'tuijiancai4') {
                    $this->transmitText($result['obj'], 'http://bc.xgs521.com/index2.html?s_td_c_id=1');
                } else {
                    $this->transmitNews($result['obj'], $media);
                }
            }
        }
        echo '';
        exit;

        //$log->write_log('end');
    }
//七陌第三方客服接收消息
    private function qm_send_msg($res, $appid, $qm_token)
    {
        //$log = new SimpleLog('qm_send_msg');
        $array = $this->qm_make_signature($res, $appid, $qm_token);
        //$log->write_log($array);
        $url = "https://ykf-wechat.7moor.com/Icallback";
        $json_str = json_encode($array, JSON_UNESCAPED_UNICODE);
        //eblog("请求报文",$json_str,'test_'.date("Ymd"),'test/');
        $head = array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length:' . strlen($json_str)
        );
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, true);
        //类型为json
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length:' . strlen($json_str)
            )
        );
        //post传递
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, ($json_str));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $ress = curl_exec($curl);
        $errorno = curl_errno($curl);
        curl_close($curl);
        return $ress;
        //return $result = curl_request($url,'post',$array,$head,0);
    }

    //服务号获取七陌客服回复的消息
    public function qm_get_msg()
    {
        $param = request()->param();
        //$log = new SimpleLog('qm_get_msg');
        //$log->write_log($param);
        return true;
    }
    //订阅号获取七陌客服回复的消息
    /*public function dyh_qm_get_msg(){
        $array['msg_signature']=$this->qm_make_signature($res,$appid,$qm_token);
        $url="http://wechat.7moor.com/Icallback";
        $json_str=json_encode($array,JSON_UNESCAPED_UNICODE);
        //eblog("请求报文",$json_str,'test_'.date("Ymd"),'test/');
        $head =array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length:' . strlen($json_str)
        );
        return $result = curl_request($url,'post',$array,$head);
    }*/
    private function qm_make_signature($res, $appid, $qm_token)
    {
        $nonce = rand(100000, 999999);
        $array = array(
            'app_id' => $appid,
            'open_id' => $res['FromUserName'],
            'nick_name' => $res['FromUserName'],
            'msgType' => $res['MsgType'],
            'content' => $res['Content'],
            'timestamp' => $res['CreateTime'],
            'nonce' => intval($nonce),
        );
        $mix_arr = array(
            'open_id' => $res['FromUserName'],
            'timestamp' => $res['CreateTime'],
            'nonce' => intval($nonce),
            'token' => $qm_token,
        );
        $mix_arrs = array_combine($mix_arr, $mix_arr);
        ksort($mix_arrs, 2);
        $sign_string = '';
        foreach ($mix_arrs as $val) {
            $sign_string .= $val;
        }
        //eblog("签名串",$sign_string,'test_'.date("Ymd"),'test/');
        //$new_sign = strtoupper(sha1($sign_string));
        $new_sign = sha1($sign_string);
        $array['msg_signature'] = $new_sign;
        return $array;
    }

    /**
     * 订阅号服务器配置token验证接口及消息接收响应唯一接口
     */
    public function check_signature_dyh()
    {
        /*$params = request()->param();//request()->param();
        $type = $params['type'];
        //服务号
        $appid = $this->appid;
        $app_secret = $this->app_secret;
        $token = $this->token;*/
        //订阅号
        $appid = $this->dyh_appid;
        $app_secret = $this->dyh_app_secret;
        $token = $this->dyh_token;
        //微信公众平台配置开发者服务器信息的时候填的URL,第一次配置需要把echostr回传给微信,验证开发者服务器接收消息的接口可正常对外访问
        if (isset($_GET['echostr'])) {
            if ($this->checkSignature()) {
                echo $_GET['echostr'];
                exit;
            }
        }
        $wx = new WeChat($appid, $app_secret, $token);
        //判断消息类型
        $result = $wx->responseMsg();
        //$log = new SimpleLog('check_signature_dyh');
        //$log->write_log($result);
        //$log->write_log(object_to_array($result));
        //图文id
        $media_id = 'PQfyghqX3zdaADzWLRAvYwOYY_H8_ZpqyOvK6CsxrMM';
        $media = $this->get_media($media_id, 2);
        //openid必须拼接上去
        $media['tz'] = 'http://bc.xgs521.com/index.html?s_td_c_id=4&openid=' . $result['obj']['FromUserName'];
        //$log->write_log($result['obj']['FromUserName']);
        $this->event_produce($result, 2);
        //$result['obj']->FromUserName  用户的openid
        //$this->transmitText($result['obj'], 'http://bc.td.pdvm.shuhengio.com/?s_td_c_id=4&openid='.$result['obj']->FromUserName);
        //回复各种类型的消息,后面不会再执行任何代码,view类型会自动跳转
        if ($result['type'] == 'text') {
            echo '';
            exit;
        } elseif ($result['type'] == 'event') {
            //事件
            if ($result['obj']['Event'] == 'CLICK') {
                //点击事件
                if (!empty($result['obj']['EventKey']) && $result['obj']['EventKey'] == 'tuijiancai') {
                    //$this->transmitText($result['obj'], 'http://bc.xgs521.com/index.html?s_td_c_id=4');
                    //openid必须拼接上去
                    $index = 'http://bc.xgs521.com/index.html?s_td_c_id=4&openid=' . $result['obj']['FromUserName'];
                    $media['tz'] = $index;
                    $this->transmitNews($result['obj'], $media);
                }elseif (!empty($result['obj']['EventKey']) && $result['obj']['EventKey'] == 'tuijiancai4') {
                    //$this->transmitText($result['obj'], 'http://bc.xgs521.com/index2.html?s_td_c_id=4');
                    //openid必须拼接上去
                    $index = 'http://bc.xgs521.com/index2.html?s_td_c_id=4&openid=' . $result['obj']['FromUserName'];
                    $media['tz'] = $index;
                    $this->transmitNews($result['obj'], $media);
                }elseif (!empty($result['obj']['EventKey']) && $result['obj']['EventKey'] == 'zaixianzixun') {
                    //在线咨询文章
                    $media_id = 'PQfyghqX3zdaADzWLRAvY4S0AuW4AuJhCjLCJrk37_M';
                    $media = $this->get_media($media_id, 2);

                    //
                    $customer_info = profile('','',$result['obj']['FromUserName']);
                    $customer_id = $customer_info['customer_id'];
                    $name = $customer_id.'_'.time();
                    $url = 'https://wx.td.shuhengio.com/public/static/img/'.$customer_id.'/'.$name.'.png';
                    $data = [];
                    $data['customer_id'] = $customer_id;
                    $data['name'] = $name;
                    $data['nonce'] = rand(100000,999999);
                    $data['time'] = time();
                    $curl = curl_request('http://wx.td.shuhengio.com/td_api/image_produce/merge_picture','post',$data);
                    //$log->write_log($curl);
                    $zaixianzixun = "https://ykf-webchat.7moor.com/wapchat.html?accessId=29614f30-4fff-11eb-b9d6-bbf82f53d9cd&fromUrl=http://www.baidu.com&urlTitle=AI智能实验室&language=ZHCN&otherParams={\"peerId\":\"10049041\"}&customField={\"openid\":\"" . $result['obj']['FromUserName'] . "\",\"img\":\"" . $url . "\"}";
                    //$log->write_log($zaixianzixun);
                    //$zaixianzixun = "https://ykf-webchat.7moor.com/wapchat.html?accessId=29614f30-4fff-11eb-b9d6-bbf82f53d9cd&fromUrl=http://www.baidu.com&urlTitle=AI智能实验室&language=ZHCN&otherParams={\"peerId\":\"10049041\"}&customField={\"openid\":\"" . $result['obj']['FromUserName'] . "\"}";
                    $media['tz'] = $zaixianzixun;
                    $this->transmitNews($result['obj'], $media);
                } else {
                    $this->transmitNews($result['obj'], $media);
                }
            }
        }
        echo '';
        exit;
        //$this->transmitNews($result['obj'], $media);
        //$log->write_log('end');
        /*if ($result['type'] == 'text') {
            $this->transmitText($result['obj'], 'http://bc.td.pdvm.shuhengio.com?s_td_c_id=4&openid='.$result['obj']->FromUserName);
            //文本消息
            if (strpos($result['obj']->Content, '潜力') !== false) {
                $time = time();
                $code = [];
                $code['code'] = substr($time, -6);
                //Db::name("weixin_code")->save($code);
                $this->transmitText($result['obj'], '你的随机验证码为:' . $code['code']);

            } else {
                $this->transmitText($result['obj'], '您获取验证码信息不正确,请回复:获取潜力值');

            }
        }*/
    }

    /**
     * 根据消息类型操作表
     */
    private function event_produce($result, $wx_type = 1, $type = 2, $count = 1)
    {
        //$log = new SimpleLog('event_produce');
        //$log->write_log('--------------开始---------------');
        $open_id = $result['obj']['FromUserName'];
        $event_content = ''; //事件描述
        //$log->write_log($result);
        $event = '';
        if ($result['obj']['MsgType'] == 'event') {
            if ($result['obj']['Event'] == 'subscribe' || $result['obj']['Event'] == 'unsubscribe') {
                $event_content = $result['obj']['Event'];
            } elseif ($result['obj']['Event'] == 'LOCATION') {
                $event_content = 'LOCATION';//$result['obj']['Latitude'].'*'.$result['obj']['Longitude'].':'.$result['obj']['Precision']
            }elseif ($result['obj']['Event'] == 'VIEW') {
                $event = 'VIEW';
                $event_content = $result['obj']['EventKey'];//$result['obj']['Latitude'].'*'.$result['obj']['Longitude'].':'.$result['obj']['Precision']
            } else {
                $event_content = $result['obj']['EventKey'];
            }
        }
        //$log->write_log($event_content);
        //用户发的消息暂时不处理
        /*elseif ($result['obj']->MsgType == 'text'){
            $event_content=$result['obj']->Content; //事件描述
        }*/
        if (empty($event_content)) {
            return 0;
        }
        $profile = profile('', '', $open_id);
        $customer_id = $profile['customer_id'];
        //$log->write_log($customer_id);
        $event_time = time();
        return $this->produce_event_type($event_content, $customer_id, $event_time, $count, $type, $wx_type,$event);
    }

    //处理时间类型入库
    private function produce_event_type($id, $customer_id, $event_time, $count = 1, $type = 1, $wx_type = 0,$event='')
    {
        //$log = new SimpleLog('produce_event_type');
        //$log->write_log('--------------开始---------------');
        //$log->write_log($id);
        //$log->write_log('--------------customer_id---------------');
        //$log->write_log($customer_id);
        //$log->write_log($type);
        //$log->write_log($wx_type);
        if ($type == 1) {
            //web端
            //在规则表种找到该元素事件对应的处理规则
            $regular = Db::name('td_page_element_event')->where('id', $id)->where('wx_type', $wx_type)->select();
        } elseif ($type == 2) {
            //微信端,无customer_id,有open_id
            if($event == 'VIEW'){
                $regulars = Db::name('td_wx_event')->where('event','VIEW')->where('wx_type', $wx_type)->select();
                $regular = [];
                foreach ($regulars as $k=>$v){
                    if(false !== strpos($id,$v['event_content'])){
                        $regular[] = $v;
                    }
                }
            }else{
                $regular = Db::name('td_wx_event')->where('event_content',$id)->where('wx_type', $wx_type)->select();
            }

        }
        //$log->write_log($regular);
        if (!$regular) {
            return 0;
        }
        foreach ($regular as $k=>$v){
            //$log->write_log('--------------td_wx_event---------------');
            $arr = [];
            $arr['event_type'] = $v['event_content'];
            $arr['begin_time'] = $event_time;
            $arr['end_time'] = $event_time;
            $time = date('Y-m-d H:i:s', time());
            $data = [];
            if ($v['operation'] == 1) {
                //action新增
                $data['type'] = $v['operation_type'];
                $data['name'] = $v['operation_name'];
                $data['action_id'] = $v['operation_type'] . '-' . $v['operation_name'];
                $data['article_id'] = $v['article_id'];
                $data['article_name'] = $v['article_name'];
                $data['customer_id'] = $customer_id;
                $data['create_time'] = $time;
                $data['update_time'] = $time;
                $action_id = Db::name('action')->insertGetId($data);
                $arr['new_data'] = $data;
                $arr['operation_type'] = 2;
                $arr['operation'] = 1;
                $arr['sign_id'] = $action_id;
                $arr['count'] = $v['count'];
                $arr['element_id'] = $id;
                $arr['type'] = 2;
                $this->data_log($arr);
            } elseif ($v['operation'] == 2) {
                //tag新增,先查看数据库中是否存在唯一信息,有就加
                $weight = json_decode($v['weight'], true);
                //$log->write_log($data);
                if (empty($weight[0])) {
                    continue;
                }
                $tag = Db::name('tag')->where('tag_id', $v['operation_name'])->where('customer_id', $customer_id)->find();

                if ($tag) {
                    $arr['old_data'] = $data;
                    //更新
                    if (false !== strpos($weight[0], '+')) {
                        $data['weight'] = (int)$tag['weight'] + intval($weight[0]);
                    } else {
                        $data['weight'] = intval($weight[0]);
                    }
                    $data['count'] = $tag['count'] + $v['count'];
                    //$log->write_log($data);
                    Db::name('tag')->where('tag_id', $v['operation_name'])->where('customer_id', $customer_id)->update(['count' => $data['count'], 'weight' => $data['weight']]);
                    $arr['new_data'] = $data;
                    $arr['operation_type'] = 1;
                    $arr['operation'] = 2;
                    $arr['sign_id'] = $tag['id'];
                    $arr['count'] = $count;
                    $arr['element_id'] = $id;
                    $arr['type'] = 2;
                    $this->data_log($arr);
                    continue;
                }
                $data['tag_id'] = $v['operation_name'];
                $data['name'] = $v['operation_name'];
                $data['type'] = $v['operation_type'];
                $data['count'] = intval($v['count']);
                $data['weight'] = intval($weight[0]);
                $data['is_valid'] = 1;
                $data['customer_id'] = $customer_id;
                $data['create_time'] = $time;
                $data['update_time'] = $time;
                $tag_id = Db::name('tag')->insertGetId($data);
                $arr['new_data'] = $data;
                $arr['operation_type'] = 2;
                $arr['operation'] = 2;
                $arr['sign_id'] = $tag_id;
                $arr['count'] = $count;
                $arr['element_id'] = $id;
                $arr['type'] = 2;
                $this->data_log($arr);
            }
            //$data = $regular;
            //根据处理规则入库
            //$log->write_log('--------------data---------------');
            //$log->write_log($data);
        }



        return 1;
    }

    //验证签名
    public function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = $this->token;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);

        if ($tmpStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 接收文本消息
     */
    public function receiveText($object)
    {
        $content = "你发送的是文本,内容为:" . $object['Content'];
        $result = $this->transmitText($object, $content);
        return $result;
    }

    /**
     * 回复文本消息
     */
    public function transmitText($object, $content)
    {
        $textTpl = "<xml>
            <ToUserName><![CDATA[%s]]></ToUserName>
            <FromUserName><![CDATA[%s]]></FromUserName>
            <CreateTime>%s</CreateTime>
            <MsgType><![CDATA[text]]></MsgType>
            <Content><![CDATA[%s]]></Content>
            </xml>";
        $result = sprintf($textTpl, $object['FromUserName'], $object['ToUserName'], time(), $content);
        //file_put_contents('./test.txt', $result);
        echo $result;
        die;
    }

    /**
     * 回复图文消息
     */
    public function transmitNews($object, $news)
    {
        $textTpl = "<xml>
            <ToUserName><![CDATA[%s]]></ToUserName>
            <FromUserName><![CDATA[%s]]></FromUserName>
            <CreateTime>%s</CreateTime>
            <MsgType><![CDATA[news]]></MsgType>
            <ArticleCount>1</ArticleCount>
            <Articles>
             <item>
              <Title><![CDATA[%s]]></Title>
              <Description><![CDATA[%s]]></Description>
              <PicUrl><![CDATA[%s]]></PicUrl>
              <Url><![CDATA[%s]]></Url>
             </item>
            </Articles>
            </xml>";
        $result = sprintf($textTpl, $object['FromUserName'], $object['ToUserName'], time(), $news['title'], $news['digest'], $news['thumb_url'], $news['tz']);
        echo $result;
        die;
    }

    /**
     * 回复图片消息
     */
    public function transmitImg($object, $img_id)
    {
        $textTpl = "<xml>
            <ToUserName><![CDATA[%s]]></ToUserName>
            <FromUserName><![CDATA[%s]]></FromUserName>
            <CreateTime>%s</CreateTime>
            <MsgType><![CDATA[image]]></MsgType>
            <Image>
             <MediaId><![CDATA[%s]]></MediaId>
            </Image>
            </xml>";
        $result = sprintf($textTpl, $object['FromUserName'], $object['ToUserName'], time(), $img_id);
        echo $result;
        die;
    }

    //获取素材详细信息,type=1服务号,$type=2订阅号    media_id =PQfyghqX3zdaADzWLRAvYwOYY_H8_ZpqyOvK6CsxrMM
    private function get_media($media_id, $type = 2)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=' . $this->get_token(0, $type);
        $data = [];
        $data['media_id'] = $media_id;
        $res = json_decode(curl_request($url, 'post', json_encode($data)), true);
        return $res['news_item'][0];
    }
    /* ["title"] => string(12) "测试用例"
  ["author"] => string(4) "mars"
  ["digest"] => string(24) "这是一篇测试文章"
  ["content"] => string(38) "<p>这是一篇测试文章<br  /></p>"
  ["content_source_url"] => string(0) ""
  ["thumb_media_id"] => string(43) "PQfyghqX3zdaADzWLRAvY046q2D496w35PAuJoj4ySk"
  ["show_cover_pic"] => int(0)
  ["url"] => string(190) "http://mp.weixin.qq.com/s?__biz=Mzg2NzU1NjYwMg==&mid=100000001&idx=1&sn=df360f8be89000cbdee593e73ca7537a&chksm=4eb88c9479cf0582a3840d4f6c33cb5879d0fab47dc5c00b76698e2955ac2f0eabd0d330204d#rd"
  ["thumb_url"] => string(135) "http://mmbiz.qpic.cn/mmbiz_jpg/9maSMBSfiblWsAw7PjVKX10Ohb6GPeJyBuSZ9pJGtl2G9gicQIxlIzYErnnzamxO8Ribqd5WSXDnTEbicHM8TZV5ow/0?wx_fmt=jpeg"
  ["need_open_comment"] => int(0)
  ["only_fans_can_comment"] => int(0)*/

    /*public function get_media(){
        $param = request()->param();
        $media_id =$param['media_id'];
        $type =2;
        $url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token='. $this->get_token(0, $type);
        $data = [];
        $data['media_id'] = $media_id;
        $res = json_decode(curl_request($url, 'post', json_encode($data)), true);
        dump($res['news_item'][0]);
        return $res['news_item'][0];
    }*/
    //获取公众号平台的永久图文列表
    public function get_media_list()
    {
        $param = request()->param();
        $type = empty($param['type']) ? 2 : $param['type']; //type=1服务号,$type=2订阅号
        $media_type = empty($param['media_type']) ? 'news' : $param['media_type']; //素材类型
        $arr = ['image', 'video', 'voice', 'news'];
        if (!in_array($media_type, $arr)) {
            return '参数校验未通过';
        }
        $data = [];
        $data['type'] = $media_type;//素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
        $data['offset'] = 0;
        $data['count'] = 10;
        $url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=' . $this->get_token(0, $type);
        $res = json_decode(curl_request($url, 'post', json_encode($data)), true);
        return $res;
    }

    /**
     * 获取普通的access_token,用来做除auth2(获取openid)以外的基础接口请求,如果是微信服务号根据code拿openid,则需要auth2的access_token
     */
    private function get_token($status = 0, $type = 1)
    {
        //服务号
        $appid = $this->appid;
        $app_secret = $this->app_secret;
        //订阅号
        if ($type == 2) {
            $appid = $this->dyh_appid;
            $app_secret = $this->dyh_app_secret;
        }
        //$status = empty($_GET['status'])?0:1;
        // 调用接口  curl返回access_token
        $redis = RedisCache::get_instance();
        if ($type == 2) {
            $access_token = $redis->get('td:dyh:access_token');
        } else {
            $access_token = $redis->get('td:fwh:access_token');
        }
        if (empty($access_token) || $status == 1) {
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $app_secret;
            // echo $url .'<br />' ;
            $res = curl_request($url);
            $arr = json_decode($res, true);
            $access_token = $arr['access_token'];
            if ($type == 2) {
                $redis->set('td:dyh:access_token', $access_token, 7000);
            } else {
                $redis->set('td:fwh:access_token', $access_token, 7000);
            }

        }
        return $access_token;
    }

    //获取公众号菜单
    public function get_menu()
    {
        $params = request()->param();
        $type = empty($params['type']) ? 1 : 2;
        $url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=" . $this->get_token(0, $type);
        $res = curl_request($url);
        $res = json_decode($res, true);
        if (!empty($res['errcode']) && $res['errcode'] == 40001) {
            $url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=" . $this->get_token(1, $type);
            $res = curl_request($url);
            $res = json_decode($res, true);
        }
        var_dump($res);
        return 'success';
    }
    //服务号在线咨询页面中转跳转
    public function online_consulting()
    {
        $param = request()->param();
        //$log = new SimpleLog('test');
        //$log->write_log($param);
        $code = empty($param['code']) ? '' : $param['code'];
        $openid = $this->get_oauth_openid($code);
        //$log->write_log($openid);
        $customer_info = profile('','',$openid);
        $customer_id = $customer_info['customer_id'];
        $name = $customer_id.'_'.time();
        $url = 'https://wx.td.shuhengio.com/public/static/img/'.$customer_id.'/'.$name.'.png';
        $data = [];
        $data['customer_id'] = $customer_id;
        $data['name'] = $name;
        $data['nonce'] = rand(100000,999999);
        $data['time'] = time();
        $curl = curl_request('http://wx.td.shuhengio.com/td_api/image_produce/merge_picture','post',$data);
        //$log->write_log($curl);
        $redirect_zxzx = "https://ykf-webchat.7moor.com/wapchat.html?accessId=29614f30-4fff-11eb-b9d6-bbf82f53d9cd&fromUrl=http://www.baidu.com&urlTitle=数珩信息科技&language=ZHCN&otherParams={\"peerId\":\"10049041\"}&customField={\"openid\":\"" . $openid . "\",\"img\":\"" . $url . "\"}";
        //$log->write_log($redirect_zxzx);
        header('Location:' . $redirect_zxzx);
        exit;
    }

    //设置公众号菜单
    public function set_menu()
    {
        $params = request()->param();
        $type = empty($params['type']) ? 1 : $params['type'];
        //服务号
        $appid = $this->appid;
        //$app_secret = $this->app_secret;
        $s_td_c_id = 1;
        //订阅号
        if ($type == 2) {
            $appid = $this->dyh_appid;
            //$app_secret = $this->dyh_app_secret;
            $s_td_c_id = 4;
        }
        $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" . $this->get_token(0, $type);

        //"https://ykf-webchat.7moor.com/wapchat.html?accessId=29614f30-4fff-11eb-b9d6-bbf82f53d9cd&fromUrl=http://www.baidu.com&urlTitle=AI智能实验室&language=ZHCN&otherParams={\"peerId\":\"10049041\"}"

        $data = array();
        if($type == 1){
            //服务号

            //会员福利
            $redirect = urlencode('http://bc.xgs521.com/index.html?s_td_c_id=' . $s_td_c_id);
            //个人中心
            $redirect2 = urlencode('http://bc.xgs521.com/index2.html?s_td_c_id=' . $s_td_c_id);
            //在线咨询中转页
            $redirect_third = urlencode("http://wx.td.shuhengio.com/td_api/wx_collection/online_consulting");

            //先去中转页,在线咨询
            $zaixianzixun = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect_third . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";


            $data["button"] = array(
                array(
                    'name' => "会员中心",
                    'sub_button' => array(
                        array(
                            "type" => "view",
                            "name" => "会员福利",
                            "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
                        ),
                        array(
                            "type" => "view",
                            "name" => "个人中心",
                            "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect2 . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
                        ),
                        array(
                            "type" => "view",
                            "name" => "在线咨询",
                            "url" => $zaixianzixun
                        )
                    )
                ),
                array(
                    'name' => "教育资讯",
                    'sub_button' => array(
                        array(
                            "type"=>"view_limited",
                            "name"=>"2021高考动态",
                            "media_id"=>"MEDIA_ID2"
                        )
                    )
                ),
                array(
                    'name' => "学习专区",
                    'sub_button' => array(
                        array(
                            "type"=>"view_limited",
                            "name"=>"辰读时刻",
                            "media_id"=>"MEDIA_ID2"
                        ),
                        array(
                            "type"=>"view_limited",
                            "name"=>"初中资料",
                            "media_id"=>"MEDIA_ID2"
                        ),
                        array(
                            "type"=>"view_limited",
                            "name"=>"高中资料",
                            "media_id"=>"MEDIA_ID2"
                        ),
                        array(
                            "type"=>"view_limited",
                            "name"=>"语数英测试",
                            "media_id"=>"MEDIA_ID2"
                        ),
                    )
                )
            );
        }else{
            //订阅号

            //会员福利
            $redirect = urlencode('http://bc.xgs521.com/index.html?s_td_c_id=' . $s_td_c_id);
            //个人中心
            $redirect2 = urlencode('http://bc.xgs521.com/index2.html?s_td_c_id=' . $s_td_c_id);
            //在线咨询中转页
            $redirect_third = urlencode("http://wx.td.shuhengio.com/td_api/wx_collection/online_consulting");

            //先去中转页,在线咨询
            $zaixianzixun = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect_third . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";

            $data["button"] = array(
                array(
                    'name' => "会员中心",
                    'sub_button' => array(
                        array(
                            "type" => "view",
                            "name" => "会员福利",
                            "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
                        ),
                        array(
                            "type" => "view",
                            "name" => "个人中心",
                            "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect2 . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
                        ),
                        array(
                            "type" => "view",
                            "name" => "在线咨询",
                            "url" => $zaixianzixun
                        )
                    )
                ),
                array(
                    'name' => "教育资讯",
                    'sub_button' => array(
                        array(
                            "type"=>"view_limited",
                            "name"=>"2021高考动态",
                            "media_id"=>"MEDIA_ID2"
                        )
                    )
                ),
                array(
                    'name' => "学习专区",
                    'sub_button' => array(
                        array(
                            "type"=>"view_limited",
                            "name"=>"辰读时刻",
                            "media_id"=>"MEDIA_ID2"
                        ),
                        array(
                            "type"=>"view_limited",
                            "name"=>"初中资料",
                            "media_id"=>"MEDIA_ID2"
                        ),
                        array(
                            "type"=>"view_limited",
                            "name"=>"高中资料",
                            "media_id"=>"MEDIA_ID2"
                        ),
                        array(
                            "type"=>"view_limited",
                            "name"=>"语数英测试",
                            "media_id"=>"MEDIA_ID2"
                        ),
                    )
                )
            );
        }

        //汉字不转义
        $filedata = json_encode($data, JSON_UNESCAPED_UNICODE);
        // var_dump($filedata) ;
        // include "Http.class.php" ;
        $res = curl_request($url, 'post', $filedata);
        $arr = json_decode($res, true);
        //var_dump($arr) ;
        if ($arr['errcode'] == '0') {
            return "菜单创建成功";
        } else {
            return "菜单创建失败";
        }
    }
    //备份
    public function set_menu_backend()
    {
        $params = request()->param();
        $type = empty($params['type']) ? 1 : $params['type'];
        //服务号
        $appid = $this->appid;
        //$app_secret = $this->app_secret;
        $s_td_c_id = 1;
        //订阅号
        if ($type == 2) {
            $appid = $this->dyh_appid;
            //$app_secret = $this->dyh_app_secret;
            $s_td_c_id = 4;
        }
        $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" . $this->get_token(0, $type);

        //"https://ykf-webchat.7moor.com/wapchat.html?accessId=29614f30-4fff-11eb-b9d6-bbf82f53d9cd&fromUrl=http://www.baidu.com&urlTitle=AI智能实验室&language=ZHCN&otherParams={\"peerId\":\"10049041\"}"

        $data = array();
        if($type == 1){
            //服务号
            $redirect = urlencode('http://bc.xgs521.com/index.html?s_td_c_id=' . $s_td_c_id);
            $redirect2 = urlencode('http://bc.xgs521.com/index2.html?s_td_c_id=' . $s_td_c_id);
            $redirect_third = urlencode("http://wx.td.shuhengio.com/td_api/wx_collection/online_consulting");

            //先去测试页
            $zaixianzixun = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect_third . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";


            $data["button"] = array(
                array(
                    'name' => "数珩",
                    'sub_button' => array(
                        array(
                            "type" => "view",
                            "name" => "1对1",
                            "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
                        ),
                        array(
                            "type" => "view",
                            "name" => "1对4",
                            "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appid . "&redirect_uri=" . $redirect2 . "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
                        ),
                        array(
                            "type" => "view",
                            "name" => "在线咨询",
                            "url" => $zaixianzixun
                        ),
                        array(
                            "type" => "scancode_push",
                            "name" => "扫码推送",
                            "key" => "saomatuisong"
                        )
                    )
                ),
                array(
                    'name' => "原创专栏",
                    'sub_button' => array(
                        array(
                            "type" => "scancode_waitmsg",
                            "name" => "扫码带提示",
                            "key" => "saomadaitishi"
                        ),
                        array(
                            "type" => "pic_sysphoto",
                            "name" => "系统拍照发图",
                            "key" => "xitongpaizhaofatu"
                        ),
                        array(
                            "type" => "pic_photo_or_album",
                            "name" => "拍照或者相册发图",
                            "key" => "paizhaohuozhexiangce"
                        )
                    )
                ),
                array(
                    'name' => "联系我们",
                    'sub_button' => array(
                        array(
                            "type" => "pic_weixin",
                            "name" => "微信相册发图",
                            "key" => "weixinxiangcefatu"
                        ),
                        array(
                            "type" => "location_select",
                            "name" => "发送位置",
                            "key" => "fasongweizhi"
                        ),
                    )
                )
            );
        }else{
            //订阅号
            $data["button"] = array(
                array(
                    'name' => "数珩",
                    'sub_button' => array(
                        array(
                            "type" => "click",
                            "name" => "1对1",
                            "key" => "tuijiancai"
                        ),
                        array(
                            "type" => "click",
                            "name" => "1对4",
                            "key" => "tuijiancai4"
                        ),
                        array(
                            "type" => "click",
                            "name" => "在线咨询",
                            "key" => "zaixianzixun"
                        ),
                        array(
                            "type" => "scancode_push",
                            "name" => "扫码推送",
                            "key" => "saomatuisong"
                        )
                    )
                ),
                array(
                    'name' => "原创专栏",
                    'sub_button' => array(
                        array(
                            "type" => "scancode_waitmsg",
                            "name" => "扫码带提示",
                            "key" => "saomadaitishi"
                        ),
                        array(
                            "type" => "pic_sysphoto",
                            "name" => "系统拍照发图",
                            "key" => "xitongpaizhaofatu"
                        ),
                        array(
                            "type" => "pic_photo_or_album",
                            "name" => "拍照或者相册发图",
                            "key" => "paizhaohuozhexiangce"
                        )
                    )
                ),
                array(
                    'name' => "联系我们",
                    'sub_button' => array(
                        array(
                            "type" => "pic_weixin",
                            "name" => "微信相册发图",
                            "key" => "weixinxiangcefatu"
                        ),
                        array(
                            "type" => "location_select",
                            "name" => "发送位置",
                            "key" => "fasongweizhi"
                        ),
                        /*    array(
                                    "type"=>"media_id",
                                      "name"=>"图片",
                                      "media_id"=>"MEDIA_ID1"
                                ),
                                array(
                                    "type"=>"view_limited",
                                      "name"=>"图文消息",
                                      "media_id"=>"MEDIA_ID2"
                                )*/
                    )
                )
            );
        }

        //汉字不转义
        $filedata = json_encode($data, JSON_UNESCAPED_UNICODE);
        // var_dump($filedata) ;
        // include "Http.class.php" ;
        $res = curl_request($url, 'post', $filedata);
        $arr = json_decode($res, true);
        //var_dump($arr) ;
        if ($arr['errcode'] == '0') {
            return "菜单创建成功";
        } else {
            return "菜单创建失败";
        }
    }
}

Base.php控制器基类

<?php

namespace app\td_api\controller;

use app\common\DesUtils;
use app\common\RedisCache;
use app\common\SimpleLog;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use think\Controller;
use think\Exception;
use think\Log;
use think\Request;
use think\Cache;
use think\Config;
use think\Db;
use think\Response;

/**
 * class WEB_API基类
 * Class Base
 * @package app\web_api\controller
 * @Auther  mars
 */
class Base extends Controller
{
     public $user;
     public $k;
     protected $des_key = 'ascfesqiokoweirtusdsavxsfgqiyoqwieqserwqpwqfwrpqovrvqmmgqwhrnqnj';  //des密钥
    public  function __construct(Request $request = null)
    {
        parent::__construct($request);
        //动态配置默认返回方式
        //Config::set('default_return_type','json');
    }

    /**
     * Des 前置操作,默认执行token校验,如果需要排除方法,请在对应控制器初始化函数覆盖该属性。
     * eg:  'checkToken' => ['except'=>'app_login,pad_qr,pad_qr_check']
     * Auther mars
     * @var array
     */
    protected $beforeActionList = [
        'checkToken','check_params','stripslashes_filter','htmlentities_filter','htmlspecialchars_filter','strip_tags_filter','api_des_decrypt'
    ];
    /**
     * Des stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。默认地,PHP 对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。
     * Auther mars
     * @var array
     */
    public function stripslashes_filter(){
        $params = request()->param();
        foreach ($params as &$v){
            $v = stripslashes($v);
        }
    }
    /**
     * Des 把字符转换为 HTML 实体:要把 HTML 实体转换回字符,请使用 html_entity_decode() 函数。
     * Auther mars
     * @var array
     */
    public function htmlentities_filter(){
        $params = request()->param();
        foreach ($params as &$v){
            $v = htmlentities($v);
        }
    }
    /**
     * Des 将特殊字符转换为 HTML 实体;如需把特殊的 HTML 实体转换回字符,请使用 htmlspecialchars_decode() 函数。
     * Auther mars
     * @var array
     */
    public function htmlspecialchars_filter(){
        $params = request()->param();
        foreach ($params as &$v){
            $v = htmlspecialchars($v);
        }
    }
    /**
     * Des strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。
     * Auther mars
     * @var array
     */
    public function strip_tags_filter(){
        $params = request()->param();
        foreach ($params as &$v){
            $v = strip_tags($v);
        }
    }
    /**
     * Des des解密
     * Auther mars
     * @var array
     */
    public function api_des_decrypt(){
        $params = request()->param();
        if(empty($params['k'])){
          return  $this->errorResponse('参数不合法');
        }
          //t69y5SBI8xDcQx9I%2BTCwzcPI6t0PvGzjNhxH7cfYU406hFG7HRDuPw%3D%3D
        $des =  new DesUtils();
       // dump($des->des_ecb_decrypt($params['k'],$this->des_key));exit;
        $this->k = json_decode($des->des_ecb_decrypt($params['k'],$this->des_key),true);
        if(empty($this->k)){
            return  $this->errorResponse('数据解密失败');
        }
    }
    /**
     * Des des加密
     * Auther mars
     * @var array
     */
    public function api_des_encrypt($data,$msg='success',$code=1){
        $res = [];

        $res['data'] = $data;
        $res['msg'] = $msg;
        $res['code'] = $code;
        $des= new DesUtils();
        $enc = $des->des_ecb_encrypt(json_encode($res),$this->des_key);
        //return ['k' => $enc];
        Response::create(['k' => $enc], 'json')->send();
        exit;
    }
    /**
     * Des 参数校验,防重放
     * Auther mars
     * @var array
     */
    public function check_params(){
        $params = $this->k;
        //$log = new SimpleLog('check_params');
        //$log->write_log($params);
        $arr = [0,1];
        if(!isset($params['status']) || !in_array($params['status'],$arr)){
            return $this->api_des_encrypt('','参数缺失',0);
        }
        if(!isset($params['nonce'])){
            return $this->api_des_encrypt('','参数缺失!',0);
        }
        if(!isset($params['time'])){
            return $this->api_des_encrypt('','参数缺失!!',0);
        }
        $server_time = time();
        if($server_time-$params['time']>60){
            return $this->api_des_encrypt(['server_time'=>$server_time],'请求超时',0);
        }
        $redis =RedisCache::get_instance();
        $string = 'beichen:check:params';
        $score = $server_time-60;
        $redis->zRemRangeByScore($string,0,$score);
        $range = $redis->zRange($string,0,-1);
        if(in_array($params['nonce'],$range)){
            //重放攻击的ip可以记录下来
            return $this->api_des_encrypt('','重复的请求',0);
        }else{
            $redis->zAdd($string,$params['nonce']);
        }

    }
    /**
     * 创建 token
     * @param array $data 必填 自定义参数数组
     * @param integer $exp_time 必填 token过期时间 单位:秒 例子:7200=2小时
     * @param string $scopes 选填 token标识,请求接口的token
     * @return string
     */
    public function createToken($data)
    {

        //JWT标准规定的声明,但不是必须填写的;
        //iss: jwt签发者
        //sub: jwt所面向的用户
        //aud: 接收jwt的一方
        //exp: jwt的过期时间,过期时间必须要大于签发时间
        //nbf: 定义在什么时间之前,某个时间点后才能访问
        //iat: jwt的签发时间
        //jti: jwt的唯一身份标识,主要用来作为一次性token。
        include(ROOT_PATH.'extend/firebase/php-jwt/src/JWT.php');
        try {
            $time = time(); //当前时间
            $token['aud'] = ''; //接收该JWT的一方,可选
            $token['iat'] = $time; //签发时间
            $token['nbf'] = $time; //(Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用
            $token['exp'] = $time + 28800; //token过期时间,这里设置8个小时
            if(!empty($data['nonce'])){
                $token['jti'] = $data['nonce']; //jwt的唯一身份标识,主要用来作为一次性token。
            }
            $token['data'] = $data;
            $this->user = $token;
            return JWT::encode($token, 'pdvm');

        } catch (ExpiredException $e) {  //签名不正确
            $returndata['code'] = "101";//101=签名不正确
            $returndata['msg'] = $e->getMessage();
            $returndata['data'] = "";//返回的数据
            return json_encode($returndata); //返回信息
        } catch (Exception $e) {  //其他错误
            $returndata['code'] = "199";//199=签名不正确
            $returndata['msg'] = $e->getMessage();
            $returndata['data'] = "";//返回的数据
            return json_encode($returndata); //返回信息
        }
    }
    /**
     * 验证token是否有效,默认验证exp,nbf,iat时间
     * @param string $jwt 需要验证的token
     * @return string $msg 返回消息
     */
    function checkToken()
    {
        $token = request()->header('token');
        $url = input('url');
        include(ROOT_PATH.'extend/firebase/php-jwt/src/JWT.php');
        include(ROOT_PATH.'extend/firebase/php-jwt/src/SignatureInvalidException.php');
        include(ROOT_PATH.'extend/firebase/php-jwt/src/BeforeValidException.php');
        include(ROOT_PATH.'extend/firebase/php-jwt/src/ExpiredException.php');
        if ($token == null) {
            $returndata['code'] = -1;
            $returndata['data'] = "token不能为空";
            Response::create($returndata, 'json')->send();
            exit();
        }
        $key = 'pdvm';
        try {
            JWT::$leeway = 60;//当前时间减去60,把时间留点余地
            $decoded = JWT::decode($token, $key, ['HS256']); //HS256方式,这里要和签发的时候对应
            $arr = (array)$decoded;
            $returndata = array();
            $returndata['code'] = "1";
            $returndata['msg'] = "成功";
            $returndata['data'] = $arr;//返回的数据
            $this->user = $returndata;
        } catch (\Firebase\JWT\SignatureInvalidException $e) {  //签名不正确
            $returndata['code'] = "101";//101=签名不正确
            $returndata['msg'] = $e->getMessage();
            $returndata['data'] = "签名不正确";//返回的数据
            Response::create($returndata, 'json')->send();
            exit();
        } catch (\Firebase\JWT\BeforeValidException $e) {  // 签名在某个时间点之后才能用
            $returndata['code'] = "102";
            $returndata['msg'] = $e->getMessage();
            $returndata['data'] = "";//返回的数据
            Response::create($returndata, 'json')->send();
            exit();
        } catch (\Firebase\JWT\ExpiredException $e) {  // token过期
            $returndata['code'] = "-1";
            $returndata['msg'] = $e->getMessage();
            $returndata['data'] = "token过期";//返回的数据
            Response::create($returndata, 'json')->send();
            exit();
        } catch (Exception $e) {  //其他错误
            $returndata['code'] = "-1";
            $returndata['msg'] = $e->getMessage();
            $returndata['data'] = "系统错误";//返回的数据
            Response::create($returndata, 'json')->send();
            exit();
        }
    }

    public function successResponse($msg = 'success',  $data = '',  array $header = [])
    {
        $result = [
            'code' => 1,
            'msg'  => $msg,
            'data' => !empty($data)?$data:null,
            'server_time'=>time()
        ];

        return json($result);
    }

    public function errorResponse($msg = 'error',  $data = '',  array $header = [])
    {
        $result = [
            'code' => 0,
            'msg'  => $msg,
            'data' => !empty($data)?$data:null,
            'server_time'=>time()
        ];
        return json($result);
    }
    //数据日志
    protected function data_log($arr)
    {
        $time = time();
        $data_log = [];
        $data_log['operation_type'] = $arr['operation_type'];
        $data_log['new_data'] = empty($arr['new_data']) ? '' : json_encode($arr['new_data']);
        $data_log['old_data'] = empty($arr['old_data']) ? '' : json_encode($arr['old_data']);
        $data_log['begin_time'] = empty($arr['begin_time']) ? $time : $arr['begin_time'];
        $data_log['end_time'] = empty($arr['end_time']) ? $time : $arr['end_time'];
        $data_log['event_type'] = empty($arr['event_type']) ? '' : $arr['event_type'];
        $data_log['response_msg'] = empty($arr['response_msg']) ? '' : $arr['response_msg'];
        $data_log['create_time'] = $time;
        $data_log['operation'] = $arr['operation'];
        $data_log['sign_id'] = $arr['sign_id'];
        $data_log['count'] = $arr['count'];
        $data_log['element_id'] = $arr['element_id'];
        $data_log['type'] = empty($arr['type']) ? '' : $arr['type'];
        $td_data_log = Db::name('td_data_log')->insert($data_log);
        if ($td_data_log) {
            return 1;
        } else {
            return 0;
        }
    }
}

common.php中curl_request函数

/**
 * 封装发送http请求
 * @param string $method 请求方式 get/post
 * @param string $url 请求目标的url
 * @param array $data post发送的数据
 * @param array  $head  请求、响应头信息  array('Content-Type: application/json; charset=utf-8','Content-Length:' . strlen($json_str))
 * @param bool $ssl 是否为https协议
 * @return 响应主体
 */
function curl_request($url, $method = 'get', $data = [], $head = [],$user_agnet=1, $ssl = true)
{
    //curl完成,先开启curl模块
    //初始化一个curl资源
    $curl = curl_init();
    //设置curl选项
    curl_setopt($curl, CURLOPT_URL, $url);//url
    //请求的代理信息
    if($user_agnet == 1){
        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';
        curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);
        //referer头,请求来源
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);//设置超时时间
    }
    //SSL相关
    if ($ssl) {
        //禁用后,curl将终止从服务端进行验证;
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        //检查服务器SSL证书是否存在一个公用名
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
    }
    //判断请求方式post还是get
    if (strtolower($method) == 'post') {
        /**************处理post相关选项******************/
        //是否为post请求 ,处理请求数据
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    //是否处理响应头
    if (!empty($head)) {
        curl_setopt($curl, CURLOPT_HEADER, true);
        //类型为json
        curl_setopt($curl, CURLOPT_HTTPHEADER, $head);
    } else {
        curl_setopt($curl, CURLOPT_HEADER, false);
    }

    //是否返回响应结果
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    //发出请求
    $response = curl_exec($curl);
    if (false === $response) {
        echo '<br>', curl_error($curl), '<br>';
        return false;
    }
    //关闭curl
    curl_close($curl);
    return $response;
}

SimpleLog.php日志

<?php
/**
 * des: 日志记录类
 * User: Mars Jane
 */

namespace app\common;
class SimpleLog
{
    const LOG_FILE_TYPE_DEFAULT = 1;
    const LOG_FILE_TYPE_JSON = 1;
    const LOG_FILE_TYPE_XML = 2;
    const LOG_FILE_TYPE_PHP_ARRAY = 3;
    const LOG_FILE_TYPE_PHP_INI = 4;
    const LOG_FILE_TYPE_TEXT = 5;
    
    private $base_path = '';
    private $path = '';
    private $file = '';
    private $file_name = '';
    private $log_file_type = 0;
    
    public function __construct($file_name = '',$file_type = self::LOG_FILE_TYPE_JSON)
    {
        if($file_name)
        {
            $this->file_name = trim($file_name);
        }
        else
        {
            $this->file_name = 'fres';
        }
        $this->create_file($file_type);
    }
    /**
     * des:写日志
     * @param mixed $data  日志记录
     * @param string $capture  日志模块
     */
    public function write_log($data,$capture='common')
    {
        file_put_contents($this->path,'['.date('Y-m-d H:i:s').' <<'.$capture.'>> ]'."\n",FILE_APPEND);
        $this->write($data);
        file_put_contents($this->path,"\n",FILE_APPEND);
    }
    protected function create_file($file_type)
    {
       // define('WWW_PATH',str_replace('\\','/',realpath(dirname(__FILE__).'/../')));  //定义站点目录
        //var_dump(WWW_PATH);
        $root_path =str_replace('\\','/',ROOT_PATH);
        $this->base_path = $root_path.'runtime/log';
        $this->set_logFileType($file_type);
        $dir = $this->base_path.'/'.date('Y-m-d');
        if(!is_dir($dir))@mkdir($dir);
        $this->path = $dir.'/'.$this->file;
        //var_dump($this->path );
        if(is_dir($dir))
        {
            if(!is_file($this->path))
            {
                @touch($this->path);
            }
        }
    }

    private function set_logFileType($file_type = self::LOG_FILE_TYPE_JSON)
    {
        if($file_type == self::LOG_FILE_TYPE_JSON)
        {
            $this->file = $this->file_name.'.json';
            $this->log_file_type = self::LOG_FILE_TYPE_JSON;
        }
        elseif($file_type == self::LOG_FILE_TYPE_XML)
        {
            $this->file = $this->file_name.'.xml';
            $this->log_file_type = self::LOG_FILE_TYPE_XML;
        }
        elseif($file_type == self::LOG_FILE_TYPE_PHP_ARRAY)
        {
            $this->file = $this->file_name.'.plog';
            $this->log_file_type = self::LOG_FILE_TYPE_PHP_ARRAY;
        }
        elseif($file_type == self::LOG_FILE_TYPE_PHP_INI)
        {
            $this->file = $this->file_name.'.ini';
            $this->log_file_type = self::LOG_FILE_TYPE_PHP_INI;
        }
        elseif($file_type == self::LOG_FILE_TYPE_TEXT)
        {
            $this->file = $this->file_name.'.txt';
            $this->log_file_type = self::LOG_FILE_TYPE_TEXT;
        }
        else
        {
            $this->file = $this->file_name.'.json';
            $this->log_file_type = self::LOG_FILE_TYPE_DEFAULT;
        }
    }

    protected function write($data)
    {
        if(is_null($data))
        {
            return false;
        }
        elseif(is_string($data))
        {
            return $this->_write_string($data);
        }
        elseif(is_numeric($data))
        {
            return $this->_write_numeric($data);
        }
        elseif(is_bool($data))
        {
            return $this->_write_bool($data);
        }
        elseif(is_array($data))
        {
            return $this->_write_array($data);
        }
        elseif(is_object($data))
        {
            return $this->_write_object($data);
        }
        else{
            return false;
        }
    }
    private function _write_string($strs)
    {
        file_put_contents($this->path,$strs,FILE_APPEND);
    }
    private function _write_numeric($num)
    {
        file_put_contents($this->path,$num,FILE_APPEND);
    }
    private function _write_bool($bool)
    {
        $bool_str = $bool ? 'true' : 'false';
        file_put_contents($this->path,$bool_str,FILE_APPEND);
    }
    private function _write_array($arr)
    {
        file_put_contents($this->path,'<?php'."\n",FILE_APPEND);
        file_put_contents($this->path,var_export($arr,true),FILE_APPEND);
        file_put_contents($this->path,';'."\n?>",FILE_APPEND);
    }
    private function _write_object($obj)
    {
        file_put_contents($this->path,'<?php'."\n",FILE_APPEND);
        file_put_contents($this->path,var_export($obj,true),FILE_APPEND);
        file_put_contents($this->path,';'."\n?>",FILE_APPEND);
    }
}

php7版本DES加密工具类

<?php
namespace app\common;

class DesUtils
{
    /**
     * des-ecb加密
     * @param string  $data 要被加密的数据
     * @param string  $key 加密密钥(64位的字符串)
     */
    function des_ecb_encrypt($data, $key){
        return urlencode(openssl_encrypt ($data, 'des-ecb', $key));
    }

    /**
     * des-ecb解密
     * @param string  $data 加密数据
     * @param string  $key 加密密钥
     */
    function des_ecb_decrypt ($data, $key)
    {
        return openssl_decrypt($data, 'des-ecb', $key);
    }
}

Redis基类

<?php

namespace app\common\service;

//1.创建一个单例类
use think\Config;

class RedisCache
{
    private static $redis;

    private function __construct()
    {
        echo '我被实例化了!';
    }

    private function __clone()
    {
        trigger_error('Clone is not allow', E_USER_ERROR);
    }

    public static function get_instance()
    {
        if (!isset(self::$redis)) {
            self::$redis = new \Redis();
            $config = Config::get('cache.redis');
            self::$redis->connect($config['host'],$config['port'],$config['timeout']);
            if(!empty($config['password'])){
                self::$redis->auth($config['password']);
            }
        }
        return self::$redis;
    }

    //类中的方法只会有一个实例执行它
    public function test()
    {
        echo("单例模式设计成功");
    }


}

发表评论

电子邮件地址不会被公开。 必填项已用*标注