配置

首先登录微信公众平台 https://mp.weixin.qq.com,在开发->基本配置中填写服务器配置(接收处理微信消息的地址)
图片描述
保存好你的配置,在加解密时需要使用。

验证

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

参数 描述
signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp 时间戳
nonce 随机数
echostr 随机字符串

开发者通过检验 signature 对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回 echostr 参数内容,则接入生效,成为开发者成功,否则接入失败。

加密/校验流程如下:

  1. tokentimestampnonce 三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行 sha1 加密
  3. 开发者获得加密后的字符串可与 signature 对比,标识该请求来源于微信
public function validate() {
    $echoStr = Input::get('echostr');
    if (!empty($echoStr)) {
        $signature = Input::get('signature');
        $timestamp = Input::get('timestamp');
        $nonce = Input::get('nonce');
        $tmpArr = [
            '你配置的Token',
            $timestamp,
            $nonce
        ];
        sort($tmpArr);
        $tmpStr = implode('', $tmpArr);
        $tmpStr = sha1($tmpStr);
        if ($tmpStr == $signature) {
            echo $echoStr;
            exit;
        }
    }
}

PHP示例代码下载:下载

消息加解密

微信官方文档:加密解密技术方案

首先获取微信发送的XML数据:

$xmlString = file_get_contents("php://input");

使用下载的示例代码解密消息:

//提供提取消息格式中的密文 XmlParse类在xmlparse.php里
$secretData = (new XmlParse())->extract($xmlString);
//对密文进行解密 Prpcrypt类在pkcs7Encoder.php里
$result = (new PrpCrypt('你配置的EncodingAESKey'))->decrypt($secretData[1]);

之后就根据具体业务来实现了:

$xmlFormatData = simplexml_load_string($result[1], 'SimpleXMLElement', LIBXML_NOCDATA);
$event = (string)$xmlFormatData->Event;
$eventKey = isset($xmlFormatData->EventKey) ? (string)$xmlFormatData->EventKey : '';
$openId = (string)$xmlFormatData->FromUserName;
$toUserName = (string)$xmlFormatData->ToUserName;

//事件处理
if ($event === 'VIEW' || $event == "CLICK") {
    //自定义菜单事件
}
if (!$eventKey && $event == "subscribe") {
    //扫描公众号二维码关注事件
}
if ($eventKey && $event == "subscribe") {
    //扫描二维码关注事件
}
if ($eventKey && $event == "SCAN") {
    //扫描生成的二维码
}
if ($event == "unsubscribe") {
    //取消关注事件
}
if ($event === 'card_pass_check' || $event === 'card_not_pass_check') {
    //卡券审核通过或审核未通过事件
}
if ($event === 'user_get_card') {
    //卡券领取事件
}
if ($event === 'user_consume_card') {
    //卡券核销事件
}

//其他事件不处理
return false;

需要发送加密消息时:

$wxBizMsg = new WxBizMsgCrypt('你配置的Token', '你配置的EncodingAESKey', '你公众号的APPID');
//加密后的消息,传引用
$encryptMsg = '';
//未加密的消息为XML格式的字符串
echo $wxBizMsg->encryptMsg('未加密的消息', time(), str_random(16), $encryptMsg);

假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。
详见下面说明:

  1. 直接回复success(推荐方式)
  2. 直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)

一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:

  1. 开发者在5秒内未回复任何内容
  2. 开发者回复了异常数据,比如JSON数据等

具体的各种XML格式见:被动回复用户消息


李罗奥
1.3k 声望52 粉丝