微信公众号开发模型WeChat

模型:WeChat (回复参考weiphp)

<?php
namespace Org;
/**
 * 微信开发工具类
 * Class WeChat
 * Author chenqionghe
 * @package Org
 */
class WeChat
{
    const LOG_NAME  = "PHP_LOG_%s.log.php"; //日志名
    const LOG_DIR   = "./Log/%s/";          //日志目录

    static private $fromUser = ‘‘;  //当前消息的发送者
    static private $toUser = ‘‘;    //当前消息的接收者
    static private $member = ‘‘;    //公众号会员记录

    /**
     * 设置要操作的微信公众号
     * @param $mid  公众号id
     */
    static public function setMember($mid)
    {
        self::$member = M(‘Member‘)->find($mid);
    }
    /**
     * 处理来自微信服务器的消息
     * @param $callback
     * @access public
     * @return void
     */
    static public function process($callback)
    {
        //如果回调函数没有设置,则退出
        if (!is_callable($callback))
        {
            return;
        }
        $postData = $GLOBALS[‘HTTP_RAW_POST_DATA‘];
        if (empty($postData)) return;  //如果没有POST数据,则退出
        $object = simplexml_load_string($postData, ‘SimpleXMLElement‘, LIBXML_NOCDATA);//解析POST数据(XML格式)
        $messgeType = trim($object->MsgType);    //取得消息类型
        self::$fromUser = $object->FromUserName; //记录消息发送方(不是发送者的微信号,而是一个加密后的OpenID)
        self::$toUser = $object->ToUserName;     //记录消息接收方(就是公共平台的OpenID)
        self::addLog($postData,1,$messgeType);       //记录日志

        //根据不同的消息类型,分别处理
        switch($messgeType)
        {
            case "text":   //文本消息
                //调用回调函数
                call_user_func($callback, "Text", array(‘Content‘=>$object->Content));
                break;
            case "image":  //图片消息
                call_user_func($callback, "Image",array(‘PicUrl‘=>$object->PicUrl, ‘MediaId‘=>$object->MediaId));
                break;
            case "voice":  //音频消息
                call_user_func($callback, "Voice",array(‘MediaId‘=>$object->MediaId, ‘Format‘=>$object->Format,‘Recognition‘=>$object->Recognition) );
                break;
            case "video":  //视频消息
                call_user_func($callback, "Video", array(‘MediaId‘=>$object->MediaId, ‘ThumbMediaId‘=>$object->ThumbMediaId));
                break;
            case "shortvideo":  //小视频消息
                call_user_func($callback, "Shortvideo", array(‘MediaId‘=>$object->MediaId, ‘ThumbMediaId‘=>$object->ThumbMediaId));
                break;
            case "location": //定位信息
                call_user_func($callback, "Location", array(‘Label‘=>$object->Label, ‘Location_X‘=>$object->Location_X, ‘Location_Y‘=>$object->Location_Y,‘Scale‘=>$object->Scale));
                break;
            case "link":  //链接信息
                call_user_func($callback, "Link", array(‘Url‘=>$object->Url, ‘Title‘=>$object->Title, ‘Description‘=>$object->Description));
                break;
            case "event":  //事件
                switch ($object->Event)
                {
                    case "subscribe":           //订阅事件
                        call_user_func($callback, "Subscribe",array( ‘EventKey‘=>$object->EventKey, ‘Ticket‘=>$object->Ticket));
                        break;
                    case "unsubscribe":         //取消订阅事件
                        call_user_func($callback, "UnSubscribe", array(‘FromUserName‘=>$object->FromUserName));
                        break;
                    case "CLICK":               //点击菜单拉取消息时的事件
                        call_user_func($callback, "Click", array(‘EventKey‘=>$object->EventKey));
                        break;
                    case "VIEW":                //点击菜单跳转链接时的事件
                        call_user_func($callback, "View",array(‘EventKey‘=> $object->EventKey));
                        break;
                    case "scancode_push":       //扫码推事件的事件推送
                        call_user_func($callback, "ScanPush",array( ‘EventKey‘=>$object->EventKey,‘ScanCodeInfo‘=>$object->ScanCodeInfo,‘ScanType‘=>$object->ScanType,‘ScanResult‘=>$object->ScanResult));
                        break;
                    case "scancode_waitmsg":    //扫码推事件且弹出“消息接收中”提示框的事件推送
                        call_user_func($callback, "ScanWaitmsg",array( ‘EventKey‘=>$object->EventKey,‘ScanCodeInfo‘=>$object->ScanCodeInfo,‘ScanType‘=>$object->ScanType,‘ScanResult‘=>$object->ScanResult));
                        break;
                    case "pic_sysphoto":        //弹出系统拍照发图的事件推送
                        call_user_func($callback, "PicSysPhoto",array( ‘EventKey‘=>$object->EventKey, ‘SendPicsInfo‘=>$object->SendPicsInfo,‘Count‘=>$object->Count,‘PicList‘=>$object->PicList,‘PicMd5Sum‘=>$object->PicMd5Sum));
                        break;
                    case "pic_photo_or_album":  //弹出拍照或者相册发图的事件推送
                        call_user_func($callback, "PicPhotoOrAlbum",array( ‘EventKey‘=>$object->EventKey, ‘SendPicsInfo‘=>$object->SendPicsInfo,‘Count‘=>$object->Count,‘PicList‘=>$object->PicList,‘PicMd5Sum‘=>$object->PicMd5Sum));
                        break;
                    case "pic_weixin":          //弹出微信相册发图器的事件推送
                        call_user_func($callback, "PicWeixin",array( ‘EventKey‘=>$object->EventKey, ‘SendPicsInfo‘=>$object->SendPicsInfo,‘Count‘=>$object->Count,‘PicList‘=>$object->PicList,‘PicMd5Sum‘=>$object->PicMd5Sum));
                        break;
                    case "location_select":     //弹出地理位置选择器的事件推送
                        call_user_func($callback, "LocationSelect",array( ‘EventKey‘=>$object->EventKey, ‘SendLocationInfo‘=>$object->SendLocationInfo,‘Location_X‘=>$object->Location_X,‘Location_Y‘=>$object->Location_Y,‘Scale‘=>$object->Scale,‘Label‘=>$object->Label,‘Poiname‘=>$object->Poiname));
                        break;
                    case ‘LOCATION‘:            //上报地址位置事件
                        call_user_func($callback, "UpLocation",array( ‘Latitude‘=>$object->Latitude, ‘Longitude‘=>$object->Longitude, ‘Precision‘=>$object->Precision));
                        break;
                    default :
                        //Unknow Event
                        break;
                }
                break;
            default:
                //未知消息类型
                break;
        }
    }

    /**
     * 获取access_token
     * $mid 公众号id
     * @access public
     * @return mixed
     */
    static public function getAcctoken ($mid=‘‘)
    {
        if(empty($mid)) {
            $mid = defined(‘MID‘) ? MID : session(‘mid‘);   //如果定义了常量MID说明是微信请求的 ,否则是本地
        }
        $token = S(‘access_token‘.$mid);
        if ($token === false)
        {
            if(empty(self::$member)) {
                self::$member = M(‘Member‘)->find($mid);
            }
            $url = ‘https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=‘.self::$member[‘appid‘].‘&secret=‘.self::$member[‘secret‘];
            $result = self::http_get($url);
            $result = json_decode($result, true);
            $token = $result[‘access_token‘];
            S(‘access_token‘.$mid, $token, $result[‘expires_in‘] - 1000);
        }
        return $token;
    }

    /**
     * 验证签名是否正确
     * @access public
     * @param $token
     */
    static public function checkSignature($token)
    {
        $tmpArr = array($token,$_GET ["timestamp"],$_GET ["nonce"]);
        sort($tmpArr, SORT_STRING );
        $tmpStr = sha1(implode( $tmpArr));
        if ($tmpStr == $_GET ["signature"])
        {
            ob_clean();
            echo $_GET ["echostr"];
        }
        self::addLog($_GET,4,‘微信接入‘);//记录日志
        exit;
    }

    /*************************************************** 发送消息响应微信 begin ***************************************************/
    /**
     * 回复文本消息
     * @param $content 文本内容
     * @access public
     * @return void
     */
    static public function replyText($content)
    {
        $msg [‘Content‘] = $content;
        self::_replyData ( $msg, ‘text‘ );
    }

    /**
     * 回复图片消息
     * @param $media_id MediaId
     */
    static public function replyImage($media_id)
    {
        $msg [‘Image‘] [‘MediaId‘] = $media_id;
        self::_replyData ( $msg, ‘image‘ );
    }

    /**
     * 回复语音消息
     * @param $media_id MediaId
     * @access public
     * @return void
     */
    static public function replyVoice($media_id)
    {
        $msg [‘Voice‘] [‘MediaId‘] = $media_id;
        $msg [‘Voice‘] [‘MediaId‘] = $media_id;
        self::_replyData ( $msg, ‘voice‘ );
    }

    /**
     * 回复视频消息
     * @param $media_id MediaId
     * @param string $title 标题
     * @param string $description 简介
     * @access public
     * @return void
     */
    static public function replyVideo($media_id, $title = ‘‘, $description = ‘‘)
    {
        $msg [‘Video‘] [‘MediaId‘] = $media_id;
        $msg [‘Video‘] [‘Title‘] = $title;
        $msg [‘Video‘] [‘Description‘] = $description;
        self::_replyData ( $msg, ‘video‘ );
    }

    /**
     * 回复音乐消息
     * @param $media_id MediaId
     * @param string $title 标题
     * @param string $description 简介
     * @param $music_url 音乐地址
     * @param $HQ_music_url 高品质音乐地址
     * @access public
     * @return void
     */
    static function replyMusic($media_id, $title = ‘‘, $description = ‘‘, $music_url, $HQ_music_url)
    {
        $msg [‘Music‘] [‘ThumbMediaId‘] = $media_id;
        $msg [‘Music‘] [‘Title‘] = $title;
        $msg [‘Music‘] [‘Description‘] = $description;
        $msg [‘Music‘] [‘MusicURL‘] = $music_url;
        $msg [‘Music‘] [‘HQMusicUrl‘] = $HQ_music_url;
        self::_replyData ( $msg, ‘music‘ );
    }

    /**
     * 回复图文消息 格式如下:
        array(
            array($Title, $Description, $PicUrl , $Url),
            array($Title, $Description, $PicUrl , $Url),
        );
     * @param array $articles
     * @access public
     * @return void
     */
    static public function replyNews($articles)
    {
        foreach($articles as $k=>$v)
        {
            $arr[] = array(‘Title‘=>$v[0],‘Description‘=>$v[1],‘PicUrl‘=>$v[2],‘Url‘=>$v[3]);
        }
        $msg [‘ArticleCount‘] = count ( $articles );
        $msg [‘Articles‘] = $arr;

        self::_replyData ( $msg, ‘news‘ );
    }

    /**
     * 将消息转发给客服
     * @param string $kf_account 指定客服的账号,不传则由微信分配
     * @access public
     * @return void
     */
    static public function replyKefu($kf_account=‘‘)
    {
        if(!empty($kf_account))
        {
            $msg [‘TransInfo‘][] = $kf_account;
        }
        self::_replyData($msg,‘transfer_customer_service‘,‘KfAccount‘);
    }

    /**
     * 发送回复消息到微信平台
     * @param array $msg 消息数组
     * @param $msgType 消息类型
     * @param string $item 包含子元素的元素名
     * @access private
     * @return void
     */
    static private function _replyData($msg, $msgType, $item = ‘item‘)
    {
        $msg [‘ToUserName‘] = strval(self::$fromUser);
        $msg [‘FromUserName‘] = strval(self::$toUser);
        $msg [‘CreateTime‘] = NOW_TIME;
        $msg [‘MsgType‘] = $msgType;
        if($_REQUEST [‘doNotInit‘])
        {
            dump($msg);
            exit;
        }
        $xml = new \SimpleXMLElement ( ‘<xml></xml>‘ );
        self::_data2xml ( $xml, $msg ,$item);
        $str = $xml->asXML ();
        self::addLog($str,2,‘发送消息‘);//记录日志
        echo $str;
    }

    /**
     * 组装xml数据
     * @param $xml xml对象
     * @param $data 要格式化的数组
     * @param string $item 包含子元素的元素名
     * @access public
     * @return void
     */
    static public function _data2xml($xml, $data, $item = ‘item‘)
    {
        foreach ( $data as $key => $value )
        {
            is_numeric ( $key ) && ($key = $item);
            if (is_array ( $value ) || is_object ( $value ))
            {
                $child = $xml->addChild ( $key );
                self::_data2xml ( $child, $value, $item );
            } else
            {
                if (is_numeric ( $value ))
                {
                    $child = $xml->addChild ( $key, $value );
                } else {
                    $child = $xml->addChild ( $key );
                    $node = dom_import_simplexml ( $child );
                    $node->appendChild ( $node->ownerDocument->createCDATASection ( $value ) );
                }
            }
        }
    }
    /*************************************************** 发送消息响应微信 end ***************************************************/

    /*************************************************** 上传下载文件 begin ***************************************************/
    /**
     * 上传临时素材
     * @param $file 要发送的文件
     * @param string $type 文件类型
     * @access public
     * @return mixed
     */
    static public function uploadFile($file, $type = ‘image‘)
    {
        // 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
        $post_data = array(‘meida‘=>"@".$file,‘type‘=>$type);
        $url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=".self::getAcctoken() ."&type=".$type;
        return self::http_post($url,$post_data);
    }

    /* 上传永久素材*/
    static public function uploadYJFile($file, $type = ‘image‘)
    {
        // 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
        $post_data = array(‘meida‘=>"@".$file,‘type‘=>$type);
        $url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=".self::getAcctoken();
        return self::http_post($url,$post_data);
    }

    /**
     * 下载多媒体文件
     * @param $media_id MediaId
     * @access public
     * @return void
     */
    static public function downloadFile($media_id)
    {
        $url = ‘‘;
        $filename = date(‘Y-m-d_H_i_s‘,time()).‘.jpg‘;//设置保存的文件名
        $ch = curl_init ();
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_TIMEOUT, 60 );
        $temp = curl_exec($ch);
        if(@file_get_contents($filename,$temp) && !curl_errno($ch)) {
            echo $filename;
        }
        else  {
            echo false;
        } // TODO
    }
    /*************************************************** 上传下载文件 end ***************************************************/

    /*************************************************** 执行http请求方法 begin ***************************************************/
    /**
     * 发送GET 请求
     * @param string $url 地址
     * @access public
     * @return mixed
     */
    static public function http_get($url)
    {
        $oCurl = curl_init ();
        if (stripos ( $url, "https://" ) !== FALSE)
        {
            curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYPEER, FALSE );
            curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYHOST, FALSE );
        }
        curl_setopt ( $oCurl, CURLOPT_URL, $url );
        curl_setopt ( $oCurl, CURLOPT_RETURNTRANSFER, 1 );
        $sContent = curl_exec ( $oCurl );
        $aStatus = curl_getinfo ( $oCurl );
        curl_close ( $oCurl );
        return intval ( $aStatus ["http_code"] ) == 200 ? $sContent : false;
    }

    /**
     * 发送POST 请求
     * @param string $url 地址
     * @param array $param 参数
     * @access public
     * @return string content
     */
    static public function http_post($url, $param)
    {
        $oCurl = curl_init ();
        if (stripos ( $url, "https://" ) !== FALSE)
        {
            curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYPEER, FALSE );
            curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYHOST, false );
        }
        curl_setopt ( $oCurl, CURLOPT_URL, $url );
        curl_setopt ( $oCurl, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $oCurl, CURLOPT_POST, true );
        curl_setopt ( $oCurl, CURLOPT_POSTFIELDS, $param );
        $sContent = curl_exec ( $oCurl );
        $aStatus = curl_getinfo ( $oCurl );
        curl_close ( $oCurl );
        return intval ( $aStatus ["http_code"] ) == 200 ? $sContent : false;
    }
    /*************************************************** 执行http请求方法 end ***************************************************/

    /*************************************************** 记录日志 begin ***************************************************/
    /**
     * @param $data 要记录的内容
     * @param int $type 日志类型(1:Receive,2:Send,3:Sql,4:Signature)
     * @param string $comment 备注信息
     * @return null
     */
    static public function addLog($data,$type=1,$comment=‘‘)
    {
        //日志存放文件夹名
        $dirName = array(‘1‘ => ‘Receive‘,‘2‘ => ‘Send‘,‘3‘ => ‘Sql‘,‘4‘=>‘Signature‘);

        //构造日志文件名
        $logDir = sprintf(self::LOG_DIR, $dirName[$type]); //格式化文件夹
        $logName = sprintf(self::LOG_NAME,date(‘ymd‘));            //格式化文件名
        if(!is_dir($logDir)) mkdir($logDir,0777,true);             //如果文件夹不存在,创建
        $logFile = $logDir.$logName;                                //日志最终文件名

        //构造日志文件内容
        $separator = str_repeat(‘*‘,42);
        $content[] = "/$separator <- Begin:".date(‘Y-m-d H:i:s‘)." --> $separator/";
        $content[] = trim(var_export($data,true),‘\‘‘);
        if(!empty($comment)) $content[] = ‘备注: ‘.$comment;
        $content[] = "/$separator <------------  End ------------> $separator/";
        $logContent =   PHP_EOL.implode(PHP_EOL,$content);

        //写入日志文件
        $fp = fopen($logFile,"a+");
        flock($fp, LOCK_EX) ;
        fwrite($fp,$logContent);
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    /*************************************************** 记录日志 end ***************************************************/

    /*************************************************** oAuth网页授权获取用户信息 begin ***************************************************/

    /**
     * 网页授权获取用户信息
     * @param $type 类型为openid或者userinfo
     * @return mixed
     */
    public static function oAuthGet($type)
    {
        if (!isset($_GET[‘code‘]))
        {
            //获取code码,以获取openid
            $scopeArr = array(‘openid‘=>‘snsapi_base‘,‘userinfo‘=>‘snsapi_userinfo‘);
            $scope = $scopeArr[$type];
            $redirect_url = urlencode(‘http://‘.$_SERVER[‘HTTP_HOST‘].$_SERVER[‘PHP_SELF‘].$_SERVER[‘QUERY_STRING‘]);
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".self::$member[‘appid‘]."&redirect_uri=$redirect_url&response_type=code&scope=$scope&state=oAuthInfo#wechat_redirect";
            header ( ‘Location: ‘ . $url );
        }
        else
        {
            /******************* 1.回调页面得到code *******************/
            $code = $_GET[‘code‘];
            /******************* 2.用code去获取access_token和openid *******************/
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".self::$member[‘appid‘]."&secret=".self::$member[‘secret‘]."&code=$code&grant_type=authorization_code";
            $result = self::http_get($url);
            $result = json_decode($result,true);
            $openid =  $result[‘openid‘];
            if($result[‘scope‘] == ‘snsapi_base‘)   //如果类型是snsapi_base,只返回openid
                return $openid;
            else
            {
                $access_token = $result[‘access_token‘];    //access_token
                /******************* 3.用获取到的openid和access_token获取获取用户详细信息 *******************/
                $url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
                $result = self::http_get($url);
                return json_decode($result,true);
            }
        }

    }
    /*************************************************** oAuth网页授权获取用户信息 end ***************************************************/

    /*************************************************** 获取jssdk配置 begin ***************************************************/

    /**
     * 获取 JSSDK 配置
     * @param bool $debug 是否开启调试模式
     * @access public
     * @return array
     */
    public static function getJssdkConf($debug = false) {
        $data = array(
            ‘noncestr‘ => self::createNonceStr(),
            ‘jsapi_ticket‘ => self::getJsApiTicket(),
            ‘timestamp‘ => time(),
            ‘url‘ => SERVER.__SELF__,
        );
        $str = ‘jsapi_ticket=‘.$data[‘jsapi_ticket‘].‘&noncestr=‘.$data[‘noncestr‘].‘&timestamp=‘.$data[‘timestamp‘].‘&url=‘.$data[‘url‘];
        return array(
            ‘debug‘	    => $debug,
            ‘appId‘		=> self::$member[‘appid‘],
            ‘timestamp‘	=> $data[‘timestamp‘],
            ‘nonceStr‘	=> $data[‘noncestr‘],
            ‘signature‘	=> sha1($str),
        );
    }

    private static function getJsApiTicket() {
        $mid = self::$member[‘id‘];
        $ticket = S(‘jsapi_ticket‘.$mid);
        if ($ticket == false) {
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".self::getAcctoken($mid);
            $result =WeChat::http_get($url);
            $result = json_decode($result, true);
            $ticket = $result[‘ticket‘];
            S(‘jsapi_ticket‘.$mid, $ticket, $result[‘expires_in‘] - 1000);
        }
        return $ticket;
    }

    private static function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    /*************************************************** 获取jssdk配置 end ***************************************************/

}

回复微信控制器:WeChatController

<?php
namespace Manage\Controller;
use Think\Controller;
use \Org\WeChat;
class WeChatController extends Controller
{
    /* 接收微信的消息 */
    public function index()
    {
        $id = intval(I(‘get.id‘));
        $info = M(‘Member‘)->where("status=‘1‘")->find($id);
        if (!is_array($info)) exit(‘请求无效!‘);
        if (!empty ($_GET [‘echostr‘]) && !empty ($_GET ["signature"]) && !empty ($_GET ["nonce"])) {
            WeChat::checkSignature($info[‘token‘]);  //微信接入验证
        }
        define(‘MID‘, $id);                         //定义公众号常量MID
        WeChat::process(array($this, ‘reply‘));    //处理消息
    }

    /* 回复微信消息  */
    public function reply($messageType, $data)
    {
        $controller = ‘Process‘ . ‘\\Controller\\‘ . $messageType . ‘Controller‘;
        $class = new \ReflectionClass($controller);
        $method = $class->getMethod(‘run‘);
        $instance = $class->newInstance();
        $method->invokeArgs($instance, array($data));
    }
}

WeChat控制器,负责将请求分发给Process模块下对应控制器处理, 如Click类型由ClickController处理, Text类型由TextController处理,下面给出一个TextController控制器

<?php
namespace Process\Controller;
use \Org\WeChat;

class TextController extends ProcessController
{
    /* 用户点击菜单 */
    public function run($data)
    {
            WeChat::replyText("您输入的内容是:" .$data[‘Content‘]);
        }
    }

}

oAuth网页授权获取用户信息示例TestController

<?php
namespace Test\Controller;
use Think\Controller;
use \Org\WeChat;
class TestController extends Controller
{
    /* 获取用户openid */
    public function get_openid()
    {
        WeChat::setMember(2);
        $openid =  WeChat::oAuthGet(‘openid‘);
    }

    /* 获取用户信息 */
    public function get_userInfo()
    {
        WeChat::setMember(2);
        $userinfo = WeChat::oAuthGet(‘userinfo‘);
        var_dump($userinfo);
    }
}
时间: 2024-10-28 03:27:39

微信公众号开发模型WeChat的相关文章

自己写的微信公众号开发模型WeChat (回复参考weiphp)

模型:WeChat <?php namespace Org; /** * 微信开发工具类 * Class WeChat * Author 陈琼和 * @package Org */ class WeChat { const LOG_NAME = "PHP_LOG_%s.log.php"; //日志名 const LOG_DIR = "./Log/%s/"; //日志目录 static private $fromUser = ''; //当前消息的发送者 sta

微信公众号开发总结

最近公司用到了微信公众平台,所以研究了一下微信公众号的开发技术,总体来说比较简单,结合现有的平台核技术,实现起来非常方便. 首先先来了解一下微信公众平台. "微信,是一个生活方式" ,这是微信的自我评价,是不是觉得如果那天不在朋友圈里分享一下自己的最新状态, 并且收到几个赞和评价的话,会觉得空虚寂寞呢?它实实在在的改变了我们的生活方式. " 微信,也是一个生意方式 ",在微信成为我们日常必备之app的同时,它同样具备巨大的的商业 或许不应该称为潜力,因为有很多人已经

利用OpenShift托管Node.js Web服务进行微信公众号开发

最近写了一个微信的翻译机器人.用户只要关注该微信号,发送英文的消息,就能收到中文翻译的回复.后台是用Node.js写的,托管在OpenShift的Paas平台上.翻译过程实际上是调用微软的Bing translation API做的,代码中用到了alexu84的bing-translate和JacksonTian的wechat这两个npm模块.下面把做的过程详细说一下. 1. 微信公众号开发 首先是要到https://mp.weixin.qq.com 申请一个公众号,并申请成为开发者.目前个人只

nodejs + BAE 搭建微信公众号开发平台

闲来无事创建了一个微信公众账号,名曰“深圳生活小助手”, 关注的人不多,平时发一些深圳新闻,趣事啥的,为了丰富公众号的内容,准备添加一些便民查询功能,例如天气预报.快递查询等等. 于是就有了本文的内容. 深圳的读者扫描关注支持下啊... 闲话不多说,本文主要介绍的就是如何基于nodejs和百度云搭建微信公众号开发平台,下一节介绍如何基于该平台实现了一个简单的天气预报查询功能的小例子. 1. 使用Express搭建本地站点 Express 是一个简洁.灵活的 node.js Web 应用开发框架,

微信公众号开发前期准备工作

随着移动互联网越来越普及,众多企业都注册了微信公众号,于是微信公众号的开发也越来越多,为了不被世界所淘汰,特地学习下微信公众号的开发,已备不时之需! 按照惯例,学习一门新技术或者新框架,咱们还是从官方提供的文档开始,于是找到微信公众平台开发者文档(http://mp.weixin.qq.com/wiki/home/index.html) 1.微信公众平台接口测试号申请 按照文档指引,咱们得先申请一个微信公众平台接口测试账号(http://mp.weixin.qq.com/debug/cgi-bi

nodejs 中koa框架下的微信公众号开发初始篇

最近在搞微信公众号开发,后端采用的是nodejs下的koa框架,初识后端的菜鸟,自己搞难度太大了,网上找了很多文章,采用的中间件大都是express框架下的,不过好在爬了许多坑之后总算看见点曙光了,遂把探索出来的一点东西拿出来分享,毕竟能力有限,拿出来也是希望大神看到了给点建议, 主要用 koa-wechat 处理验证和消息解析 ,用wechat-api来进行按钮组等api操作,刚开始没什么内容,大家随意看看就好, 废话不多说,直接上代码(这是一个route的代码): var koa = req

微信公众号开发之自动消息回复和自定义菜单

(一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 前言 上一篇我们大致讲解了下微信公众号开发的基本原理和流程概述.本章主要是对文本消息回复和自定义菜单做一个记录和分解 消息回复 处理请求,并响应 1)关注 也可参考官网文档:https://mp.weixin.qq.com/wiki 当微信用户关注公众账号时,可以给其适当的提示.可以是欢迎词,可以是帮助提示.示例代码如下: class EventHandler : IHandler

微信公众号开发之院校行业应用

本方案适用于大学院系,职业学院等官方公众号建设,院校公众号,采用微信服务号定制开发,面向学生,以微信互动为主,让学生通过微信公众号认识了解同学,了解院校.帮助院校了解学生需求,建立一种新的院校与学生的沟通方式. 院校微信公众号需求模型 微信公众号功能模块 1.微社区 学生可以在微社区各个板块发言跟帖,并分享到朋友圈 2.校园生活 以图文,或视频的形式发布关系校园的趣事,新闻等. 3.院校工作 院校的微官网,院校介绍,公告通知消息等查询,办公室联系人等 4.个人主页 学生的个人微信主页,可以互动留

.NET开发者如何愉快的进行微信公众号开发

此文章同时发表在本人微信公众号“dotNET每日精华文章”,欢迎右边二维码来关注.) 题记:这篇文章只是一个如何提高开发效率的简单指导和记录,不会涉及具体的微信公众号开发内容. 就我理解,微信作为半个移动互联网入口,且已经在代替大量APP的趋势下,进行微信公众号开发是一个开发者必须面对的命运.那么.NET开发者如何高效的进行微信公众号开发呢?从我有限的经验来看,如下两个方面是特别需要解决的. 1,SDK的选择和使用 由于微信公众平台的访问接口庞大繁杂且基于HTTP API的,如果从底层开始写每一