Wscats / articles

🔖My Learning Notes and Memories - 分享我的学习片段和与你的回忆

Home Page:https://github.com/Wscats/articles

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

微信公众号开发

Wscats opened this issue · comments

首先去微信公众号官网
注册订阅号
微信接入官方文档
这里写图片描述
这里写图片描述
在新浪服务器下新建一个SAE应用
这里写图片描述
配置服务器,并把地址带到公众号的
这里演示的是用新浪SAE云服务器
新浪云

这里写图片描述
在新浪云的代码管理中把链接粘贴到微信的基本配置中的URL输入框
可参考官方token的设置方法
或者用下面的代码

<?php
/**
 * wechat php wsscat test
 */

//define your token
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (isset($_GET['echostr'])) {
    $wechatObj -> valid();
} else {
    $wechatObj -> responseMsg();
}

class wechatCallbackapiTest {
    public function valid() {
        $echoStr = $_GET["echostr"];

        //valid signature , option
        if ($this -> checkSignature()) {
            echo $echoStr;
            exit ;
        }
    }

    public function responseMsg() {
        //get post data, May be due to the different environments
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

        //extract post data
        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);
            $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)) {
                $msgType = "text";
                $contentStr = "Welcome to wechat world! I'am wsscat,nice to meet you";
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                echo $resultStr;
            } else {
                echo "Input something...";
            }

        } else {
            echo "";
            exit ;
        }
    }

    private function checkSignature() {
        // you must define TOKEN by yourself
        if (!defined("TOKEN")) {
            throw new Exception('TOKEN is not defined!');
        }

        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $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;
        }
    }

}
?>

token可以自行更改,现在这里我用的是weixin

  • URL:应用所在服务器地址[云应用的域名]
  • Token:填weixin即可 [服务器中设置]
  • EncodingAESKey:随机生成即可
    这里写图片描述

设置成功后微信的服务器配置项会变成如下

这里写图片描述
配置成功后按启动

如果是官方的示例代码,再启动成功后记得再更改服务器上面的这部分代码为下面,让它接受信息后调用responseMsg()函数

//define your token
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (isset($_GET['echostr'])) {
    $wechatObj -> valid();
} else {
    $wechatObj -> responseMsg();
}

在微信搜索或者扫描二维码并关注公众号即可看到以下回复
这里写图片描述

来到这一步我们可以接入图灵测试的接口来测试
图灵机器人接口

public function responseMsg() {
        //get post data, May be due to the different environments
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

        //extract post data
        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);
            $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)) {
                $apiKey = "输入自己的apiKey";
                $apiURL = "http://www.tuling123.com/openapi/api?key=KEY&info=INFO";
                $reqInfo = $keyword;
                $url = str_replace("INFO", $reqInfo, str_replace("KEY", $apiKey, $apiURL));
                $res = file_get_contents($url);
                $resObj = json_decode($res);
                $contentStr = $resObj->text;
                $msgType = "text";
                //$contentStr = "Welcome to wechat world! I'am wsscat,nice to meet you";
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                echo $resultStr;
            } else {
                echo "Input something...";
            }

        } else {
            echo "";
            exit ;
        }
    }

这里如果要回复非文本的消息我们就要更改回复的XML格式
首先我们先在代码中打印后台接受微信的**$postObj**数据,里面包括ToUserName,FromUserName,CreateTime,MsgType,Content和MsgId这几个重要信息,后面我们封装回复的消息体时候就会用到
$contentStr = json_encode($postObj)
然后包装返回的信息格式,格式是XML的格式
被动回复用户消息
比如图文的模版

$textTpl = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <ArticleCount>2</ArticleCount>
                            <Articles>
                            <item>
                            <Title><![CDATA[你好,我是Wsscat]]></Title> 
                            <Description><![CDATA[谢谢您的关注]]></Description>
                            <PicUrl><![CDATA[http://avatar.csdn.net/1/E/E/2_qq_27080247.jpg]]></PicUrl>
                            <Url><![CDATA[http://blog.csdn.net/qq_27080247]]></Url>
                            </item>
                            <item>
                            <Title><![CDATA[Wsscat是一只猫]]></Title>
                            <Description><![CDATA[这是我第一条发布的信息]]></Description>
                            <PicUrl><![CDATA[http://avatar.csdn.net/1/E/E/2_qq_27080247.jpg]]></PicUrl>
                            <Url><![CDATA[http://blog.csdn.net/qq_27080247]]></Url>
                            </item>
                            </Articles>
                            </xml>";

                $msgType = "news";
//              $contentStr = json_encode($postObj);
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType);
                echo $resultStr;

图片的模版

$textTpl = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Image>
                            <MediaId><![CDATA[IIljTxbQ7VV7HhXWZrmR361nqd9dpyncq23YewYb6NkgQdMdytYsOD3ewKmZWARN]]></MediaId>
                            </Image>
                            </xml>";
                $msgType = "image";

                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType);
                echo $resultStr;

常见问题:
部署新浪云token验证失败

header("Content-Type:text/html; charset=utf-8");//添加这行
/**
  * wechat php test
  */

//define your token
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
$wechatObj->valid();
if ($this -> checkSignature()) {
            header('content-type:text');//再添加这行
            echo $echoStr;
            exit ;
        }

微信JS-SDK

微信JS-SDK官方说明文档
jweixin-1.0.0.js
JS-SDK官方DEMO

首先绑定域名
先登录微信公众平台左边设置进入公众号设置功能设置里填写“JS接口安全域名”
这里写图片描述

然后,如果要JSSDK开动,必须满足下面三个条件:

  • 你有一个域名
  • 你有一个微信公众号,服务号或者订阅号
  • 有后台生成签名(php、java、nodejs等)

第一二步我们前面都配置好了,现在我们缺的是第三步
我们下载后台生成签名的代码官网JSSDK后台服务代码DEMO并替换里面的AppIDAppSecret
打开上传的后端代码测试,新浪SAE有可能会报以下的错误,原因是没有权限读写,JSSDK要把access_token和expire_time写到本地被SAE拒绝了
这里写图片描述

这里可以参考这两篇文章来解决
解决新浪SAE无法写入jssdk.php的问题
http://www.henkuai.com/thread-1404-1-1.html

当然也可以用我的方法来解决
在SAE上用Storage的Bucket管理管理,把需要的文件放上去,这里我放了主要产生问题的access_token.phpjsapi_ticket.php
这里写图片描述
然后获取这些文件的路径,并把他替换到jssdk.php对应的地方,如下
这里写图片描述
那么我们就可以打开微信访问我们服务器上的这个测试文件来检测是否可以调用微信的接口了
这里提醒下,分享功能必须要通过验证才可以使用,参考segmentfault的这个问答
最新的微信JSSDK分享接口的问题

微信WEB开发者工具

微信web开发者工具官方文档
首先绑定自己的微信号,并下载开发者工具
Windows64位
这里写图片描述
下载完安装并且连接上手机代理,手机和电脑必须在同一个局域网内
这里写图片描述
这里写图片描述
在微信打开的网页都能在PC端的开发者工具看到页面结构(DOM)和JS调试的输出,对手机端开发调试有很好的帮助,也可以像在Chrome一样用console.log输出参数方便查看,也可以在侧边栏打内链的样式实时看到页面的变化

微信支付

微信支付DEMO下载
打开demo的index.php会看到以下的测试页面
这里写图片描述
这是一个重要的配置文件,在lib目录下的WxPay.Config.php

/**
     * TODO: 修改这里配置为您自己申请的商户信息
     * 微信公众号信息配置
     * 
     * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
     * 
     * MCHID:商户号(必须配置,开户邮件中可查看)
     * 
     * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
     * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
     * 
     * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
     * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
     * @var string
     */
    const APPID = 'wx426b3015555a46be';
    const MCHID = '1900009851';
    const KEY = '8934e7d15453e97507ef794cf7b0519d';
    const APPSECRET = '7813490da6f1265e4901ffb80afaa36f';

其中APPIDAPPSECRECT在公众号的开发配置信息中能获取,上面是微信提供的测试帐号
MCHIDKEY为支付接入后邮件中的商户号和支付密钥

把测试的PHP文件丢到腾讯云的服务器(可以运行PHP),在公众号URL和tooken里面配置成功,但是公众号发送消息没有任何回复,新浪云的就可以,怎么解决