最近搞了一个微信公众号玩,后台语言用的php7,选用yii2框架,在发开公众号自动回复的时候,遇到几点问题,下面我结合开发调试流程给大家讲解一下。
说明一下,关于具体如何一步一步的操作,微信官方以及网上都有很多现成的资料,故不是本文的重点,本文重点来帮广大开发人员填坑。
1.开发第一步,在服务器上搭建微信公众号后台所需的最主要服务,微信“贴心”的提供了php的实例demo(点击下载),部署到我的服务器上,为了更好的和Yii2框架融合,我将下载下来的源码放在了model下,并添加了命名空间,然后在controller中写了一个方法来调用,WeixinController控制器下的actionIndex方法。
2.部署好后,开始在微信公众号的配置“接口配置信息”了,填写入正常访问的地址,http://xxxx.com/index.php?r=weixin/index,怀着忐忑的心理点击了“提交”。Oh!My天啊!配置成功,竟然如此简单。
3.测试“自动回复”接口,自动回复接口需要调用的url仍然是上面我们填写的url,所以要在这个url里面加一个判断,如果请求包含GET的echostr参数,那说明是验证TOKEN的请求,否则为微信消息的请求,这里我们也可以把验证TOKEN的代码删除,因为微信只在配置的时候验证一次,以后就不需要验证了。好了,现在在微信客户端可以自信满满的发言了,可以我得到的反馈确是“改公众号暂时无法提供服务,请稍后再试”。
4.开始排错,到底哪错了呢?使用微信自带的网页版调试工具试一下,返回值很坑爹,就只告诉失败了,具体为什么失败,它不说。好吧 ,我们自己一点一点排查,后来发现,原来在init方法里面随便输出点东西,用调试工具是可以看到输出的,但是在index中的内容却无法输出。那我就在init方法中调用index这个方法呗,像这样$this->actionIndex();,确实可以调用到了,调试工具显示调用成功,但是仍然看不到我们希望的返回值,在微信中试试呢?虽然不说“无法提供服务”了,但是我们期望的回复并没有输出。
5.不知道到这里算不算成功了一半,反正搞得我是有点摸不着头脑,各种调试,各种猜,后来想到了Yii2本身的安全机制,Yii2为了防止CSRF攻击,对POST的数据需要进行验证,而微信发来的请求并不会被验证通过,因此导致在尝试走到index方法中时,被拦截了。好嘛,浪费哥大半天时间,在controller中可以将CSRF拦截关闭,这样写:public $enableCsrfValidation = false;,貌似终于完事大吉了,将init中原来写的$this->actionIndex();删掉,开始再一次尝试。
6.神马?还是不对??由于我的远程服务器不是dev环境,所以一些低级错误并不会报出来,这个可麻烦了,测试不通过,还不报错!当我把报错级别变为最低后,终于发现了一个错误Undefined variable: HTTP_RAW_POST_DATA,竟然说我这个不存在?!这可以微信官方提供的呀!之前来来回回调试了好几遍,就是没有怀疑过微信提供的代码,但是我明明在之前部署过一次,是没有问题呢,上网搜了一下,说是要在php.ini中改一个配置,设置 always_populate_raw_post_data = On。当然要去试一试,但是打开php.ini才发现,我的里面根本就没有这个配置,强硬的加上,也没起作用。
7.好吧,那我去php官方找找答案,在关于HTTP_RAW_POST_DATA的介绍里,赫然发现了下面这一行字:Warning This feature has been DEPRECATED as of PHP 5.6.0. Relying on this feature is highly discouraged.好吧,原来从5.6开始就废弃了,哥用的是最新的php7,而之前做过的一个项目是php5.3。微信啊微信,你这也太不严谨了,不知道你浪费了开发者多少时间!找到问题,开始解决吧,php官方建议使用使用 php://input 代替 $HTTP_RAW_POST_DATA,所以呢,我们将原来的$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];换成$postStr = file_get_contents('php://input');。下面再试一下,OK!大功告成!顺便说一句,php官方不建议使用HTTP_RAW_POST_DATA,即使你用的5.6以下版本,也顺便换了吧~~~
总结:
一个坑不可怕,可怕的是连环坑,哥们来来回回不知道调了多少遍,才搞明白其中的奥秘,哎~~~