微信公众号开发(一)服务器及其接口的配置

我是用测试号来进行开发的,因为可以用高级权限,非常适合学习使用。
在开始微信号开发之前需要准备好两样东西,1、一个测试号,2、需要一个拥有域名(有公网ip也可以)的服务器,下面将分别介绍怎样获取这两样东西。
1、测试号
点击
此链接测试号登录可直接用微信扫一扫注册一个测试号

在这里插入图片描述

2、进入测试号界面之后可以获得一些开发所需要的东西,以及关注者列表和开发权限等,如下所示

在这里插入图片描述

2、服务器
我用的是阿里云的服务器,有学生优惠,怎么购买还有配置那些就不说了。
3、配置接口

在这里插入图片描述

这里的URL就是填写服务器中的域名或者公网ip就好了,当然了要注意加上http://前缀,以后用户发送的消息都会经过微信服务器转发到该接口。Token可以随便填写一些东西,这里填写了weixin。关于Token的用途下面会讲到。


现在先别急着点击提交,因为我们还没有在URL指向的服务器里编写任何的代码,还不能正确响应微信服务器的请求。

在编写任何的代码之前,我先说一下本博客的一些习惯,为了便于理解,我会先将文件的结构和代码先贴出来,然后才解释具体代码的含义,这样如果熟悉的人就可以直接跳过该部分了。

在这里插入图片描述

index.php用于处理消息。


output_log.php和output_query.php分别用来输出post过来的数据和请求的查询字符串,Utils.php主要用来将数据输出到文件中,看了下面的代码你就明白了,其实相当简单,这三个东西是我用来调试用的,相比起微信公众号提供的在线调试接口而言(需要设置一堆的信息),我觉得这样更加简单。


Utils.php,提供了两个函数,traceHttp()将请求的时间、远程主机地址和查询字符串输出到query.xml文件中。logger()将类型、时间和post数据输出到log.xml中。

<?php
class Utils
{
    public static function traceHttp()
    {
        $content = date('Y-m-d H:i:s')."\\\\n\\\\rremote_ip:".$_SERVER["REMOTE_ADDR"].
            "\\\\n\\\\r".$_SERVER["QUERY_STRING"]."\\\\n\\\\r\\\\n\\\\r";
        $max_size = 1000;
        $log_filename = "./query.xml";
        if (file_exists($log_filename) and (abs(filesize($log_filename))) > $max_size){
            unlink($log_filename);
        }else {
 
        }
        file_put_contents($log_filename, $content, FILE_APPEND);
    }
 
    public static function logger($log_content, $type = '用户')
    {
        $max_size = 3000;
        $log_filename = "./log.xml";
        if (file_exists($log_filename) and (abs(filesize($log_filename)) >
                $max_size)) {
            unlink($log_filename);
        }
        file_put_contents($log_filename, "$type  ".date('Y-m-d H:i:s')."\\\\n\\\\r".$log_content."\\\\n\\\\r",
            FILE_APPEND);
    }
}

output_query.php,输出query.xml的内容

<?php
@header('Content-type: text/plain;charset=UTF-8');
$filepath = './query.xml';
readfile($filepath);

output_log.php,输出log.xml的内容。

<?php
@header('Content-type: text/plain;charset=UTF-8');
$filepath = './log.xml';
readfile($filepath);

是不是非常简单,然后我们开始写处理消息index.php

<?php
//设置时区
date_default_timezone_set("Asia/Shanghai");
//定义TOKEN常量,这里的"weixin"就是在公众号里配置的TOKEN
define("TOKEN", "weixin");
 
require_once("Utils.php");
//打印请求的URL查询字符串到query.xml
Utils::traceHttp();
 
$wechatObj = new wechatCallBackapiTest();
/**
 * 如果有"echostr"字段,说明是一个URL验证请求,
 * 否则是微信用户发过来的信息
 */
if (isset($_GET["echostr"])){
    $wechatObj->valid();
}else {
    $wechatObj->responseMsg();
}
 
class wechatCallBackapiTest
{
    /**
     * 用于微信公众号里填写的URL的验证,
     * 如果合格则直接将"echostr"字段原样返回
     */
    public function valid()
    {
        $echoStr = $_GET["echostr"];
        if ($this->checkSignature()){
            echo $echoStr;
            exit;
        }
    }
 
    /**
     * 用于验证是否是微信服务器发来的消息
     * @return bool
     */
    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()
    {
        //获取post过来的数据,它一个XML格式的数据
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        //将数据打印到log.xml
        Utils::logger($postStr);
        if (!empty($postStr)){
            //将XML数据解析为一个对象
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);
            //消息类型分离
            switch($RX_TYPE){
                case "event":
                    $result = $this->receiveEvent($postObj);
                    break;
                default:
                    $result = "unknow msg type:".$RX_TYPE;
                    break;
            }
            //打印输出的数据到log.xml
            Utils::logger($result, '公众号');
            echo $result;
        }else{
            echo "";
            exit;
        }
    }
 
    /**
     * 接收事件消息
     */
    private function receiveEvent($object)
    {
        switch ($object->Event){
            //关注公众号事件
            case "subscribe":
                $content = "欢迎关注微微一笑很倾城";
                break;
            default:
                $content = "";
                break;
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }
 
    /**
     * 回复文本消息
     */
    private function transmitText($object, $content)
    {
        $xmlTpl = "<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime><![CDATA[%s]]></CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[%s]]></Content>
</xml>";
        $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $result;
    }
}

这几个文件写好之后,如果设置了快捷发布,过1、2秒钟就会自动发布了,状态里面会显示绿色的"正常",如果没有设置快捷发布,上传代码后需要手动点击右边的快捷发布按钮。


这时我们就可以点击测试号界面里面的那个提交按钮了。如果配置正确,则会提示配置成功。


4、调试

在浏览器地址栏上输入,xxx/output_query.php,xxx是你的域名。则会出现你点击提交后发送过来的请求,类似如下

在这里插入图片描述

可以看到该查询字符串有4个字段


signature:微信加密签名

echostr:随机字符串

timestamp:时间戳

nonce:随机数

只有在验证URL的时候查询字符串中才会有“echostr”这个字段,验证的方法是


将token、timestamp、nonce三个参数进行字典序排序

将三个参数字符串拼接成一个字符串进行sha1加密

开发者获得加密后的字符串可与signature对比,标识该请求来源于微信


验证通过之后,我们可以用微信扫一扫,扫描测试号里面的公众号二维码,关注该公众号,关注之后,公众号列表会显示出关注者的列表。

此时微信应该会回复一条文本消息,也就是以上在index.php中设置的“欢迎关注XXX”。

在这里插入图片描述

这时我们重新刷新一下xxx/output_query.php,发现没有“echostr”这个字段了,因为这个是用户发来的消息,而不是验证URL的消息。多出来的openid字段是用户的微信号,如果采用的是加密模式,还会有encrypt_type和msg_signature等字段。测试号只有明文模式。

在这里插入图片描述

接着我们重新打开一个标签,访问XXX/log.xml,查看发送的post数据,下面是一个关注公众号的事件,和我们返回给微信的XML数据。

在这里插入图片描述

现在不比纠结这些数据格式的问题,以后我们会提到,这样我们的微信公众号开发就准备好了,记得把这两个日志URL保存为浏览器的标签方便下次访问,以后调试只要F5一下就可以了,是不是比微信提供的在线调试容易多了。


注意:必须在5秒内响应微信的服务器,否则会导致重传或者报错


—————————————————————————————————————

亲爱的用户,您好!如果您喜欢这个网站,欢迎赞助我,您的支持是我的动力。

赞赏款用于服务器、文章等网站的固定支出。欢迎大家支持,谢谢!

51cb4e9a9397260f1f774ee07de0b77.jpg