php搭建微信公众号服务端程序

  • A+
所属分类:php基础

最近研究了下微信订阅号,尝试了下利用php搭建订阅号的后台服务端,遇到些问题,网上搜了很久,才得以解决 =。=,总结下过程,分享一下。

 

第一步:在服务器搭建php+mysql+Apache运行环境;

由于对后端不太熟悉,我这里就选用了比较简单易用的集成环境,试用过很多种,这里给大家推荐:PHPWAMP 绿色集成环境;

下载地址:PHPWAMP

php搭建微信公众号服务端程序

如果你的服务器已经架设IIS,可以选择修改端口,避免端口冲突;

第二步:设置公众号服务器配置

在公众号管理后台 启用 服务器配置并填写;

php搭建微信公众号服务端程序

这里的Token就是服务器与微信之间的暗号,由开发者自由填写,但必须在后面的php文件中填写一致;

在服务器集成php环境中编写app.php代码

在这里,我踩了一个很大的坑,也是我写这篇博文的初衷,花了了好长时间才得以解决,希望遇到同样问题的朋友,可以得到帮助。

在网上我搜到的php服务端代码基本上都是这样的:

<?php
/**
  * wechat php test
  */
header('Content-type:text');
//define your token
//定义TOKEN密钥
define("TOKEN", "ishangxx");
//实例化微信对象
$wechatObj = new wechatCallbackapiTest();
//验证成功后注释掉valid方法
$wechatObj->valid();
//开启自动回复功能
$wechatObj->responseMsg();
//定义类文件
class wechatCallbackapiTest
{
    //实现valid验证方法:实现对接微信公众平台
    public function valid()
    {
        //通过GET请求接收随机字符串
        $echoStr = $_GET["echostr"];
        //调用checkSignature方法进行用户(开发者)数字签名验证
        //valid signature , option
        if($this->checkSignature()){
            //如果成功,则返回接收到的随机字符串
            echo $echoStr;
            //并退出
            exit;
        }
    }

    public function responseMsg()
    {
        //get post data, May be due to the different environments
        //接收用户端(客户)发送过来的XML数据
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

          //extract post data
        //判断XML数据是否为空
        if (!empty($postStr)){
                /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
                   the best way is to check the validity of xml by yourself */
                libxml_disable_entity_loader(true);
                //通过simplexml进行xml解析     PHP中有两大类可以完成对XML的解析,1.PHP的Dom模型2.通过simplexml模型
                  $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(!empty( $keyword ))
                {
                    //回复类型,如果为"text",代表文本类型
                      $msgType = "text";
                    //回复内容
                    $contentStr = "Welcome to wechat world!";
                    //格式化字符串(对xml进行格式化操作,把里面相关的变量格式化成字符串)
                    $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                    //把XML数据返回给手机端
                    echo $resultStr;
                }
                //如果用户发送的关键词为空,则返回下列字符串
                else{
                    echo "Input something...";
                }

        }else {
            echo "";
            exit;
        }
    }
    
    //定义checkSignature方法
    private function checkSignature()
    {
        // you must define TOKEN by yourself
        
        //判断TOKEN密钥是否定义
        if (!defined("TOKEN")) {
            //如果没有定义则抛出异常,返回'TOKEN is not defined!'字符串
            throw new Exception('TOKEN is not defined!');
        }
        //接收微信加密签名
        $signature = $_GET["signature"];
        //接收时间戳信息
        $timestamp = $_GET["timestamp"];
        //接收随机数
        $nonce = $_GET["nonce"];
        //把TOKEN常量赋值给$token变量    
        $token = TOKEN;
        //把相关参数组装为数组(密钥文件、时间戳、随机数)
        $tmpArr = array($token, $timestamp, $nonce);
        // use SORT_STRING rule
        //通过字典法进行排序
        sort($tmpArr, SORT_STRING);
        //把排序后的数组转化为字符串
        $tmpStr = implode( $tmpArr );
        //通过哈希算法对字符串进行加密操作
        $tmpStr = sha1( $tmpStr );
        //与加密签名进行对比
        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }
}

?>

到这里,可以在公众号后台提交服务器配置,一般第一次都会提示失败,如果没有配置错误 第二次肯定会成功。

此时,说明微信公众号已经成功与服务器之间勾搭上了 ^_^;

再试试往公众号发送消息测试,可无论怎么尝试,都一直提示:“该公众号提供的服务出现故障,请稍后再试“的字样;

网上搜索很多关于这个报错提示的解决方案,都没能解决我这个问题。

想了一会,要解决这个问题还是得看看这个请求过去之后,返回给我的信息啊。

于是,我打开了我的超人Postman;

php搭建微信公众号服务端程序

对,就是他。

请求的具体参数可以从服务器 PHPWAMP 控制台打开日志查看具体请求参数;

php搭建微信公众号服务端程序

根据返回值,才发现原来是:

$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

这一句代码的问题;

将其改成:

$postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");

保存文件,重新测试。完美解决~

php搭建微信公众号服务端程序

 

 

weinxin
我的微信
爱生活、爱学习的小伙伴可以通过扫一扫二维码添加我的个人微信一起交流!
青青子衿

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: