微信公众号

作者: 平安喜乐698 | 来源:发表于2018-03-30 22:45 被阅读17次
    目录
        1. 概念
          1.1. 微信小程序和公众号的区别
          1.2. 分类(3种)
          1.3. 模式
    
    1. 概念

    1.1 微信小程序和公众号的区别

    1. 技术上:
        公众号基于H5,小程序基于微信自己的开发环境和语言
    2. 交互上:
        小程序比公众号交互性体验更好
    3. 定位上:
        公众号用来信息展示和营销,小程序面向产品和服务
    

    1.2. 分类(3种)

    分为:
    
    1.订阅号
        订阅号用于提供信息资讯.
    2.服务号
        服务号用于提供服务——给企业提供更强大的业务服务与用户管理能力。
    3.企业号
        企业号为企业提供移动应用入口,帮助企业建立与员工、上下游供应链及企业应用间的连接。
    

    1.3 模式(2种)

    分为:
    
    1.开发模式
        通过界面编辑来设置自动回复、服务号及底部自定义菜单功能。
        1.1 接收消息 
            用来接收普通用户发送的文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息
        1.2 回复消息
            用来向用户回复文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息
        1.3 消息推送
            用户关注和取消关注微信公众账号时将触发关注和取消关注事件
    
    2.编辑模式
        通过公众平台提供的接口实现自动回复、获取订阅者、自定义菜单功能
    
    2. 使用

    微信公众号开放平台
    新浪云服务注册
    微信公众号测试账号
    微信公众号在线测试接口

    2.1 新浪云服务平台

        注册账号
        控制台|创建应用( 二级域名:自定义)
                    |创建版本 拿到URL
                    |点击 上传代码包
                    |点击 编辑代码
    
    代码包(将以下php文件打包成zip)
    
    index.php
    <?php
    header('Content-type:text');
    // 需和微信公众号token一致
    define("TOKEN", "weixin");
    
    $wechatObj = new wechatCallbackapiTest();
    if (!isset($_GET['echostr'])) {
        $wechatObj->responseMsg();
    }else{
        $wechatObj->valid();
    }
    
    class wechatCallbackapiTest
    {
        public function valid()
        {
            // 随机字符串
            $echoStr = $_GET["echostr"];
            
            // 验证消息是否来自微信服务器
            if($this->checkSignature()){
                echo $echoStr;
                exit;
            }
        }
    
        // 验证消息是否来自微信服务器
        private function checkSignature()
        {
            // 微信加密签名
            $signature = $_GET["signature"];
            // 时间戳
            $timestamp = $_GET["timestamp"];
            // 随机数
            $nonce = $_GET["nonce"];
    
            $token = TOKEN;
            $tmpArr = array($token, $timestamp, $nonce);
            sort($tmpArr);
            $tmpStr = implode($tmpArr);
            $tmpStr = sha1($tmpStr);
    
            if($tmpStr == $signature){
                return true;
            }else{
                return false;
            }
        }
    
        public function responseMsg()
        {
            $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
            if (!empty($postStr)){
                $this->logger("R ".$postStr);
                $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
                $RX_TYPE = trim($postObj->MsgType);
    
                switch ($RX_TYPE)
                {
                    case "event":
                        $result = $this->receiveEvent($postObj);
                        break;
                    case "text":
                        $result = $this->receiveText($postObj);
                        break;
                }
                $this->logger("T ".$result);
                echo $result;
            }else {
                echo "";
                exit;
            }
        }
        
    
        // 接收到事件
        private function receiveEvent($object)
        {
            $content = "";
            switch ($object->Event)
            {
                case "subscribe":    // 关注事件
                    $content = "欢迎关注";
                    break;
                case "unsubscribe":  // 取消关注事件
                    $content = "取消关注";
                    break;
            }
            // 发送消息
            $result = $this->transmitText($object, $content);
            return $result;
        }
        
        //接收文本消息
        private function receiveText($object)
        {
            $keyword = trim($object->Content);
            $content = date("Y-m-d H:i:s",time())."\n技术支持";
            
            if(is_array($content)){
                if (isset($content[0]['PicUrl'])){
                    $result = $this->transmitNews($object, $content);
                }else if (isset($content['MusicUrl'])){
                    $result = $this->transmitMusic($object, $content);
                }
            }else{
                $result = $this->transmitText($object, $content);
            }
    
            return $result;
        }
    
        
        private 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);
            return $result;
        }
    
        private function transmitNews($object, $arr_item)
        {
            if(!is_array($arr_item))
                return;
    
            $itemTpl = "    <item>
            <Title><![CDATA[%s]]></Title>
            <Description><![CDATA[%s]]></Description>
            <PicUrl><![CDATA[%s]]></PicUrl>
            <Url><![CDATA[%s]]></Url>
        </item>
    ";
            $item_str = "";
            foreach ($arr_item as $item)
                $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
    
            $newsTpl = "<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime>%s</CreateTime>
    <MsgType><![CDATA[news]]></MsgType>
    <Content><![CDATA[]]></Content>
    <ArticleCount>%s</ArticleCount>
    <Articles>
    $item_str</Articles>
    </xml>";
    
            $result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($arr_item));
            return $result;
        }
    
        private function transmitMusic($object, $musicArray)
        {
            $itemTpl = "<Music>
        <Title><![CDATA[%s]]></Title>
        <Description><![CDATA[%s]]></Description>
        <MusicUrl><![CDATA[%s]]></MusicUrl>
        <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
    </Music>";
    
            $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
    
            $textTpl = "<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime>%s</CreateTime>
    <MsgType><![CDATA[music]]></MsgType>
    $item_str
    </xml>";
    
            $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
            return $result;
        }
        
        private function logger($log_content)
        {
            if(isset($_SERVER['HTTP_APPNAME'])){   //SAE
                sae_set_display_errors(false);
                sae_debug($log_content);
                sae_set_display_errors(true);
            }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
                $max_size = 10000;
                $log_filename = "log.xml";
                if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
                file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
            }
        }
    }
    
    
    ?>
    
    创建应用 创建版本

    2.2 微信平台

    微信测试号平台(个人测试)

        注册账号
            填写URL:http://1.qq号.applinzi.com/ (新浪云创建应用的链接)
                    token:weixin
            提交
            手机微信扫描测试公众号,并发送消息
    
    微信公众平台
        选择类型进行注册
    
    
    

    2.2.1 订阅号

    订阅号 订阅号2 订阅号3
    功能|自动回复(可设置 :)
        关键字回复(可设置随机内容)|收到消息回复|添加关注后立即回复
        
    功能|自定义菜单(可设置:)
        底部菜单栏及子栏 (点击---》发消息(图文、图片、语音、视频)|跳网页|跳小程序)
    
    功能|投票
        设置问题及选项(可查看投票详情)
    
    功能|页面模版(放入文章链接)
        用于菜单栏跳转到该页面
    
    功能|原创声明
    
    功能|添加其他功能
    
    小程序|小程序管理
        可管联或创建小程序
    
    管理|消息管理
        查看用户发的消息
    
    管理|用户管理
        查看用户列表和黑名单列表
    
    管理|素材管理
        查看素材信息(文字、图片、语音、视频)用于发布文章
    
    推广|广告
    推广|流量
    
    统计|用户分析
        用户增减、属性(性别,城市,终端,机型)
    统计|图文分析
        文章创建时间、阅读数、分享数
    统计|菜单分析
        菜单栏按钮点击数
    统计|消息分析
        消息关键字、发送人数
    统计|接口分析
        调用次数、失败率、耗时
    统计|网页分析
        访问量
    
    设置|公众号设置(扫描二维码关注)
        修改账号详情
    设置|微信认证
        个人账号无法认证
    设置|安全中心
        
    设置|违规记录
        违规内容、时间
    
    开发|基本配置
        服务器url(http://1.qq号.applinzi.com/ (新浪云创建应用的链接))
             token(需和代码中设置的token一致)
             EncodingAESKey(随机生成)
        开启后,自定义菜单栏、自动回复失效!!!!
    开发|开发者工具
    开发|运维中心
        统计接口调用次数
    开发|接口权限
        查看已获得的接口权限
    
    3.开启服务器配置

    获取access token

    1.临时获取
        测试平台 | 选择 基础支持-access token
    
    2.
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=&secret=
    

    3.1 消息管理

    《1》 接收消息

    
    

    《2》 自动回复

    用户向公众号发送消息,微信服务器请求开发服务器,自动回复
        若服务器无法保证在五秒内处理回复,则必须回复“success”或者“”(空串),否则微信后台会发起三次重试。
        ToUserName      是   接收方帐号(收到的OpenID)
        FromUserName    是   开发者微信号
        CreateTime      是   消息创建时间 (整型)
        MsgType         是   text
        Content         是   回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)
    
    回复文本消息
    <xml> 
    <ToUserName>< ![CDATA[粉丝号] ]></ToUserName> 
    <FromUserName>< ![CDATA[公众号] ]></FromUserName> <CreateTime>12345678</CreateTime> 
    <MsgType>< ![CDATA[text] ]></MsgType> 
    <Content>< ![CDATA[要回复的文本] ]></Content> 
    </xml>
    
    回复图片消息
    <xml>
     <ToUserName><![CDATA[粉丝号]]></ToUserName>
     <FromUserName><![CDATA[公众号]]></FromUserName>
     <CreateTime>1460536576</CreateTime>
     <MsgType><![CDATA[image]]></MsgType>
     <Image> <MediaId><![CDATA[素材ID]]></MediaId> </Image>
     </xml>
    
    回复语音消息
    <xml>
    <ToUserName>< ![CDATA[粉丝号] ]></ToUserName>
    <FromUserName>< ![CDATA[公众号] ]></FromUserName><CreateTime>12345678</CreateTime>
    <MsgType>< ![CDATA[voice] ]></MsgType>
    <Voice><MediaId>< ![CDATA[语音ID] ]></MediaId></Voice>
    </xml>
    
    回复视频消息
    <xml><ToUserName>< ![CDATA[粉丝号] ]></ToUserName>
    <FromUserName>< ![CDATA[公众号] ]></FromUserName><CreateTime>12345678</CreateTime>
    <MsgType>< ![CDATA[video] ]></MsgType>
    <Video><MediaId>< ![CDATA[视频ID] ]></MediaId><Title>< ![CDATA[标题] ]></Title><Description>< ![CDATA[内容描述] ]></Description></Video> 
    </xml>
    
    回复音乐消息
    <xml>
    <ToUserName>< ![CDATA[粉丝号] ]></ToUserName>
    <FromUserName>< ![CDATA[公众号] ]></FromUserName><CreateTime>12345678</CreateTime>
    <MsgType>< ![CDATA[music] ]></MsgType>
    <Music><Title>< ![CDATA[标题] ]></Title><Description>< ![CDATA[内容描述] ]></Description><MusicUrl>< ![CDATA[音乐URL] ]></MusicUrl><HQMusicUrl>< ![CDATA[高质量音乐URL] ]></HQMusicUrl><ThumbMediaId>< ![CDATA[音频ID] ]></ThumbMediaId></Music>
    </xml>
    
    回复图文消息
    <xml>
    <ToUserName>< ![CDATA[粉丝号] ]></ToUserName>
    <FromUserName>< ![CDATA[公众号] ]></FromUserName><CreateTime>12345678</CreateTime>
    <MsgType>< ![CDATA[news] ]></MsgType>
    <ArticleCount>2</ArticleCount>
    <Articles>
      <item><Title>< ![CDATA[标题1] ]></Title> <Description>< ![CDATA[内容1] ]></Description><PicUrl>< ![CDATA[图片URL] ]></PicUrl><Url>< ![CDATA[点击图跳转URL] ]></Url></item>
      <item><Title>< ![CDATA[标题2] ]></Title><Description>< ![CDATA[内容2] ]></Description><PicUrl>< ![CDATA[图片URL] ]></PicUrl><Url>< ![CDATA[点击图跳转URL] ]></Url></item>
    </Articles>
    </xml>
    

    例1:根据文本回复文本

    在receiveText方法中+以下代码片段并保存
        if($object->MsgType=='text'){
            if("1"==$object->Content){
                $content = date("Y-m-d H:i:s",time())."\n2222技术支持111111";
            }
        }
    

    例2:根据图片回复图片

        // 返回响应数据
        public function responseMsg()
        {
            $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
            if (!empty($postStr)){
                $this->logger("R ".$postStr);
                $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
                $RX_TYPE = trim($postObj->MsgType);
    
                switch ($RX_TYPE)
                {
                    case "event":
                        $result = $this->receiveEvent($postObj);
                        break;
                    case "text":
                        $result = $this->receiveText($postObj);
                    case "image":      // 添加处理图片方法
                        $result = $this->receiveImage($postObj);
                        break;
                }
                $this->logger("T ".$result);
                echo $result;
            }else {
                echo "";
                exit;
            }
        }
    
            // 处理图片
            private function receiveImage($object){
                $result = $this->transmitImage($object, $object->MediaId);    
                return $result;
            }
         private function transmitImage($object, $content)
        {
            $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(), $content);
            return $result;
        }
    

    《3》 接收事件推送

    用户的某些操作(如:关注和取消关注)会推送事件给开发服务器。
    
    1 关注/取消关注事件
        开发服务器接收到的数据格式(分析后向用户发送消息) 
            subscribe(订阅)、unsubscribe(取消订阅)
    <xml>
    <ToUserName>< ![CDATA[公众号] ]></ToUserName>
    <FromUserName>< ![CDATA[粉丝号] ]></FromUserName><CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[subscribe] ]></Event>
    </xml>
    
    
    2 扫描带参数二维码事件
    用户未关注时推送,开发服务器接收到的数据格式:
    <xml>
    <ToUserName>< ![CDATA[toUser] ]></ToUserName>
    <FromUserName>< ![CDATA[FromUser] ]></FromUserName><CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[subscribe] ]></Event>
    <EventKey>< ![CDATA[qrscene_123123] ]></EventKey>
    <Ticket>< ![CDATA[TICKET] ]></Ticket>
    </xml>
    用户已关注时推送,开发服务器接收到的数据格式:
    <xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> <FromUserName>< ![CDATA[FromUser] ]></FromUserName> <CreateTime>123456789</CreateTime> 
    <MsgType>< ![CDATA[event] ]></MsgType> 
    <Event>< ![CDATA[事件类型SCAN] ]></Event> 
    <EventKey>< ![CDATA[事件KEY值 二维码scene_id SCENE_VALUE] ]></EventKey>
    <Ticket>< ![CDATA[二维码的ticket,可用来换取二维码图片TICKET] ]></Ticket> 
    </xml>
    
    3 上报地理位置事件
        用户同意上报地理位置后,每次进入公众号会话时都会上报
       开发服务器接收到的数据格式
    <xml>
    <ToUserName>< ![CDATA[公众号] ]></ToUserName>
    <FromUserName>< ![CDATA[粉丝号] ]></FromUserName><CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[事件类型LOCATION] ]></Event>
    <Latitude>纬度23.137466</Latitude>
    <Longitude>经度113.352425</Longitude>
    <Precision>精度119.385040</Precision>
    </xml>
    
    
    4 自定义菜单事件
        点击菜单弹出子菜单,不会产生上报
    
    
    5 点击菜单拉取消息时的事件推送
       开发服务器接收到的数据格式
    <xml>
    <ToUserName>< ![CDATA[公众号] ]></ToUserName>
    <FromUserName>< ![CDATA[粉丝号] ]></FromUserName><CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[事件类型CLICK] ]></Event>
    <EventKey>< ![CDATA[事件key值EVENTKEY] ]></EventKey>
    </xml>
    
    
    6 点击菜单跳转链接时的事件推送
       开发服务器接收到的数据格式
    <xml><ToUserName>< ![CDATA[公众号] ]></ToUserName>
    <FromUserName>< ![CDATA[粉丝号] ]></FromUserName><CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[事件类型VIEW] ]></Event>
    <EventKey>< ![CDATA[事件key值设置的跳转URLwww.qq.com] ]></EventKey>
    </xml>
    
    1. 自定义菜单栏接口
    注意:
        1、一级菜单最多3个,一个一级菜单可包含最多5个二级菜单。
        2、一级菜单最多4个汉字,二级菜单最多7个汉字,超出则以...代替。
        3、在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,有变化则更新。
    
    
    可实现以下类型按钮:
        1、click类型:点击后,微信服务器会通过消息接口推送消息类型为event的结构给开发者,并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
        2、view类型:点击后,打开按钮中填写的URL。可与网页授权获取用户基本信息接口结合,获得用户基本信息。
        3、scancode_push类型:点击后,调起扫一扫,扫码后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
        4、scancode_waitmsg类型:点击后,调起扫一扫,扫码后将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
        5、pic_sysphoto类型:点击后,调起相机,拍照后将照片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
        6、pic_photo_or_album类型:点击后,弹出选择器(拍照|相册)。
        7、pic_weixin类型:点击后,调起相册,选择后将照片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
        8、location_select类型:点击后,调起地理位置选择工具,选择后将位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
        9、media_id类型(用于订阅号):点击后,将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
        10、view_limited类型(用于订阅号):点击后,打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
    

    相关文章

      网友评论

        本文标题:微信公众号

        本文链接:https://www.haomeiwen.com/subject/jkdwcftx.html