Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

微信公众号开发 #13

Open
coneo opened this issue Apr 18, 2015 · 0 comments
Open

微信公众号开发 #13

coneo opened this issue Apr 18, 2015 · 0 comments
Labels

Comments

@coneo
Copy link
Owner

coneo commented Apr 18, 2015

微信公众号对我们并不陌生,打开微信,或多或少你都有订阅一些公众号。我个人也订阅了很多公众号,涉及多个领域:学习,健身,读书,旅游,行业资讯,游戏,还有一些鸡汤公众号。每天打开微信,他都会推送一些消息给我,对我来说,这就类似于rss订阅。当然,他的功能远远不止于rss,它可以有交互,你可以与它进行互动。比如我订阅了游戏【十万个冷笑话】的公众号,通过它可以绑定我的游戏角色,每天可以签到领取一些奖励。我比较好奇他们是如何来管理微信公众号的,因此我尝试了下微信公众号开发。该文章并不是一个完整的教程,只是记录我的微信公众号开发过程,另外我想用php搭建一个服务器,也顺便学习下php。

公众号的维护并非需要技术开发实现。当你申请号公众号之后,可以通过微信的公众平台来管理该公众号,比如自动回复,自定义菜单的管理。及时你不懂技术,通过网上的教程你也可以很轻松的管理一个公众号。这里我们并不是来教大家通过微信的公众平台来管理公众号,而是搭建一个后台服务器来管理公众号。

先说下微信公众号的消息流程。
编辑模式: 客户端 ----------> 微信服务器 ----------> 客户端
开发者模式: 客户端 --------> 微信服务器 -------> 自己搭建的服务器 -------> 微信服务器------> 客户端

编辑模式就是可以直接在网页中管理微信公众号,设置公众号如何响应前台的请求,当前台向公众号发送消息的时候,会把消息转发到微信服务器去处理,然后把结果返回给前台。只有前台和微信服务器之间有交互。 开发者模式就是我正在做的,它会最终把客户端的请求转发到我搭建的服务器中,处理完之后依然返回给客户端。因此,编辑模式和开发者模式是不能共存的,只能开启其中的一个。

申请公众号
公众号分订阅号和服务号,服务号只有公司才能申请,订阅号可以个人申请,也可以公司申请。现在个人订阅号不能认证了,在开发者模式下很多接口都没有权限,比如:自定义菜单,群发等。服务号比订阅号的功能又要多一些。这些差异可以到微信公众平台上去查看。这里我是申请了一个个人订阅号,作为个人玩玩应该足够了。

服务器
这里申请了一个新浪云的服务器(全称:Sina App Engine)。它也是付费的服务器,消耗的是新浪云豆,按你流量的比例来收费的,不过如果你流量不大的话,基本上不用花钱。注册的时候会送500云豆,我用了几天了,只用了0.5云豆,因为流量小。在写服务器时,我想把日志输出到本地(也就是输出到SAE服务器上),但是SAE为了安全和分布式考虑,关闭了本地写的权限。因此我不能以写文件的方式来保存日志,但是SAE提供了一套日志接口。但是实际使用过程中发现,日志有时候会显示延迟,导致我们不能很好的对日志进行分析。

接入
这里的接入就是把微信服务器的url绑定好我搭建的服务器上。绑定的过程实际上是一次微信服务器和我搭建的服务器之间的一次对话。这个什么意思呢?微信需要认证你这个服务器是不是一个有效的服务器,需要提供url和token进行验证,加密/校验流程如下:

  1. 将token、timestamp、nonce三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
    这需要一小段代码来处理。
private function checkSignature()
{
    $signature = $_GET["signature"];
    $timestamp = $_GET["timestamp"];
    $nonce = $_GET["nonce"];    

    $token = TOKEN;
    $tmpArr = array($token, $timestamp, $nonce);
    sort($tmpArr, SORT_STRING);
    $tmpStr = implode( $tmpArr );
    $tmpStr = sha1( $tmpStr );

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

逻辑处理
此处处理客户端的请求,比如消息自动回复,位置的处理,就看具体的处理了。消息是以xml格式发送过来,不同的消息类型xml会有不同的组织。比如,文本消息如下:

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>

图文消息如下:

 <xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[this is a url]]></PicUrl>
 <MediaId><![CDATA[media_id]]></MediaId>
 <MsgId>1234567890123456</MsgId>
 </xml>

我们在收到一个请求的时候,会先解析出消息的类型,然后根据不同类型可以作出不同的处理。以下是一个例子,如果客户端发送过来是 【请求】关键字,那么会回复系统当前时间过去。

 public function responseMsg()
    {
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

        if (!empty($postStr)){
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $fromUsername = $postObj->FromUserName;
            $toUsername = $postObj->ToUserName;
            $keyword = trim($postObj->Content);
            $time = time();
            $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[%s]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                        <FuncFlag>0</FuncFlag>
                        </xml>";
            if($keyword == "请求")
            {
                $msgType = "text";
                $contentStr = date("Y-m-d H:i:s",time());
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                echo $resultStr;
            }
        }else{
            echo "";
            exit;
        }
    }
@coneo coneo added the toys label Apr 18, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant