微信 客服消息 发送 微信会回调三次的问题

在做微信接口调用的时候,需求是这样的 用户回复“666”-----》给用户发送一段文字,再给用户发送一张图片,,,,因为微信模板消息发送只能给用户发送一条消息,所以只用模板消息发送不行了,看大家用的是 客服消息发送,,所以果断用起,把过程记录一下,中间不少坑

1、用 客服消息发送 接口 第一步要先启用 客服消息 接口 ,不启用的话调不通,位置看图片
这里写图片描述

2、里面的具体接口调用就不说了,我是用 php ,curl 走起一般没啥问题 ,坑在后面
当用户 回复 666 的时候,当时想 先用模板消息发送,再调用微信客服接口发图片,结果发现不行,只发图片不发文字,而且微信那边没收到回复,会一直请求三次,结果给用户发了三次图片,这个不行,那只用客服消息,先发文字,再发图片,结果还是因为微信那边没收到消息,给用户发了三次文字,三次图片,这条路也不行,,,,,,,,,然后在网上找,看大家都用 ob 函数,我们也用起,结果发现不行,不起作用(怀疑微信那边改版了),期间也试了给微信那边回复 echo " " , echo “null” , echo “success”,等,都不行,,这可难为死我了
最后实在没办法就给数据库加了个字段,用来记录微信请求了几次,当用户第一次请求后,改变字段状态(0改为1),微信再次请求时判断转态,为1,直接exit(); 即使微信那边请求了三次,但就只给用户发一次,不说了,上代码![这里写图片描述]

补充,为什么微信那边一直收不到信息,因为上传图片这里太耗时了,加上这句话就可以解决了,红色箭头出,我上源码吧在这里插入代码片<?php
date_default_timezone_set(“Asia/Shanghai”);
header(‘content-type:text/html;charset=utf-8’);

define(“xxx”, “xxxx”); //define your token

$wx = new wechatCallbackapiTest();
//增加自定义菜单
w x − &gt; c r e a t e m e n u ( ) ; / / 第 一 步 是 接 收 微 信 后 台 发 送 的 验 证 消 息 , 微 信 后 台 会 发 送 一 个 G E T 请 求 到 上 面 的 U R L , 并 附 带 以 下 参 数 : / / s i g n a t u r e , t i m e s t a m p , n o n c e , e c h o s t r / / 我 们 的 服 务 器 在 接 收 到 上 述 参 数 后 , 需 要 验 证 s i g n a t u r e 是 否 正 确 , 验 证 方 法 是 先 对 t i m e s t a m p 、 n o n c e 和 t o k e n 先 排 序 , 再 拼 接 成 一 个 字 符 串 , 计 算 出 s h a 1 , 并 和 s i g n a t u r e 对 比 : i f ( wx-&gt;createmenu(); // 第一步是接收微信后台发送的验证消息,微信后台会发送一个GET请求到上面的URL,并附带以下参数: // signature,timestamp,nonce,echostr // 我们的服务器在接收到上述参数后,需要验证signature是否正确,验证方法是先对timestamp、nonce和token先排序,再拼接成一个字符串,计算出sha1,并和signature对比: if( wx>createmenu();//GETURL//signaturetimestampnonceechostr//signaturetimestampnoncetokensha1signatureif(_GET[‘echostr’]){

$wx->valid(); //如果发来了echostr则进行验证

}else{

$wx->responseMsg(); //如果没有echostr,则返回消息

}

class wechatCallbackapiTest{
private $_cache=array(‘uid’ => 0);

 public function valid(){ //valid signature , option
 
    $echoStr = $_GET["echostr"];
    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"]; //接收微信发来的XML数据
     
      //extract post data
     if(!empty($postStr)){  

           //解析post来的XML为一个对象$postObj
           //把 XML 字符串载入对象中,返回类 SimpleXMLElement 的一个对象,该对象的属性包含 XML 文档中的数据
           $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
           
           $fromUsername = $postObj->FromUserName; //请求消息的用户
           $toUsername = $postObj->ToUserName; //"我"的公众号id
           $keyword = trim($postObj->Content); //消息内容
           $eventKey = trim($postObj->EventKey);//获取微信返回信息的类型
           $time = time(); //时间戳
           $msgtype = 'text'; //消息类型:文本
           $textTpl = "<xml>
            <ToUserName><![CDATA[%s]]></ToUserName>
            <FromUserName><![CDATA[%s]]></FromUserName>
            <CreateTime>%s</CreateTime>
            <MsgType><![CDATA[%s]]></MsgType>
            <Content><![CDATA[%s]]></Content>
          </xml>";
          $textImgTpl = "<xml>
            <ToUserName><![CDATA[%s]]></ToUserName>
            <FromUserName><![CDATA[%s]]></FromUserName>
            <CreateTime>%s</CreateTime>
            <MsgType><![CDATA[%s]]></MsgType>
            <Image>
            <MediaId><![CDATA[%s]]></MediaId>
            </Image>
            <FuncFlag>0</FuncFlag>
          </xml>";
          //在新用户关注你的公众号时,自动返回信息:(把这段代码加在判断$keyword之前)。
          if($postObj->MsgType == 'event'){ //如果XML信息里消息类型为event
             if($postObj->Event == 'subscribe'){ //如果是订阅事件
                  $contentStr = "欢迎进入5xxx";
                  $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgtype, $contentStr);
                  echo $resultStr;
                  if (empty($eventKey)) {
                    $userPic = $this->getUserInfos($fromUsername);
                    $pdo= new PDO('mysql:host=localhost;dbname=weixin','root','*oscent#51testing');
                    $sql1 = 'select openId from `sharerecord` where openId="'.$fromUsername.'"';
                    $stmt=$pdo->prepare($sql1);
                    $stmt->execute();
                    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
                    if (empty($data[0])) {
                      $sql = 'insert into `sharerecord` (openId,nickname,picture,city,country,attenTime) values ("'.$fromUsername.'","'.$userPic['nickname'].'","'.$userPic['headimgurl'].'","'.$userPic['city'].'","'.$userPic['country'].'","'.time().'")';
                      $stmt=$pdo->prepare($sql);
                      $stmt->execute();
                    }
                  }
                  $keyArray = explode('_',$eventKey);//截取判断是否是已关注还是未关注用户
                  if (!empty($keyArray['1']) && is_numeric($keyArray['1'])) {
                    //判断该用户之前是否已关注过本公众号,还是取消后再关注过的
                    $pdo= new PDO('mysql:host=localhost;dbname=weixin','root','*oscent#51testing');
                    $sql = 'select openId from `sharerecord` where openId="'.$fromUsername.'"';
                    $stmt=$pdo->prepare($sql);
                    $stmt->execute();
                    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
                    if (empty($data['0']['openId'])) {
                      //同时处理数据库,拿到scene_id  将分享者分享次数加一,并发送消息给分享者
                       // $pdo= new PDO('mysql:host=localhost;dbname=weixin','root','*oscent#51testing');
                      $sql1 = 'update `sharerecord` set `shareNum`= shareNum+1 where num="'.$keyArray['1'].'"';
                      //获取数据,执行语句
                      $stmt=$pdo->prepare($sql1);
                      $stmt->execute();
                      //给分享者发送模板消息
                      $this->sendTplToShare($keyArray['1']);
                      file_put_contents('num3.txt', $keyArray['1']);
                      //将用户保存在数据库
                      $userPic = $this->getUserInfos($fromUsername);
                      $sql = 'insert into `sharerecord` (openId,nickname,picture,city,country,attenTime) values ("'.$fromUsername.'","'.$userPic['nickname'].'","'.$userPic['headimgurl'].'","'.$userPic['city'].'","'.$userPic['city'].'","'.time().'")';
                      $stmt=$pdo->prepare($sql);
                      $stmt->execute();
                    }
                  }
             }
             exit();  
          }

            if($keyword == '666'){
                $pdo= new PDO('mysql:host=localhost;dbname=weixin','root','*oscent#51testing');
                $sql = 'select isAdd,imageId from `sharerecord` where openId="'.$fromUsername.'"';
                $stmt=$pdo->prepare($sql);
                $stmt->execute();
                $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
                if (!$data) {
                  $userPic = $this->getUserInfos($fromUsername);
                    $sql2 = 'insert into `sharerecord` (openId,nickname,picture,city,country,attenTime) values ("'.$fromUsername.'","'.$userPic['nickname'].'","'.$userPic['headimgurl'].'","'.$userPic['city'].'","'.$userPic['city'].'","'.time().'")';
                      $stmt=$pdo->prepare($sql2);
                      $stmt->execute();
                }
                if ( $data[0]['isAdd']) {
                  if (!empty($data[0]['imageId'])) {
                    $msgtype = 'image';
                    $contentStr = $data[0]['imageId'];
                    $resultStr = sprintf($textImgTpl, $fromUsername, $toUsername, $time, $msgtype, $contentStr);
                    echo $resultStr;
                  }
                  exit();
                }
                //将isAdd 字段加1
                $sql1 = 'update `sharerecord` set `isAdd`=1 where openId="'.$fromUsername.'"';
                //获取数据,执行语句
                $stmt1=$pdo->prepare($sql1);
                $stmt1->execute();

                ignore_user_abort(true);
                ob_start();
                header('Connection: close');
                header('Content-Length: ' . ob_get_length());
                ob_end_flush();
                ob_flush();
                flush();
                echo '';
                $accessToken = $this->getAccessToken();
                //发送文本
                $this->getSeverice($fromUsername,$accessToken);
                //发送图片前先检查用户之前是否生成过,生成过则直接发送
                // if ($data[0]['imageId']) {
                //   $msgtype = 'image';
                //   $contentStr = $data[0]['imageId'];
                //   $resultStr = sprintf($textImgTpl, $fromUsername, $toUsername, $time, $msgtype, $contentStr);
                //   echo $resultStr;
                //   exit();
                // }
                //发送图片
                $this->backImg($fromUsername,$accessToken);           
           }else{
                $contentStr = '输入666试试';
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgtype, $contentStr);
                echo $resultStr;
                exit();
           }
     
      }else {
           echo "";
           exit;
      }
 }

 //验证字段
 private function checkSignature()
 {
    $signature = $_GET["signature"];
    $timestamp = $_GET["timestamp"];
    $nonce = $_GET["nonce"]; 
    
    $token = TOKEN;
    $tmpArr = array($token, $timestamp, $nonce);
    //排序
    sort($tmpArr);
    //字符串
    $tmpStr = implode( $tmpArr );
    //SHA-1 散列
    $tmpStr = sha1( $tmpStr );
      
    if( $tmpStr == $signature ){
      return true;
    }else{
      return false;
    }
 }

 //获取access_token
 public function getAccessToken()
 {
    //先从缓存中拿token,过期再更新token
      $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxxx";
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      $outp
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值