微信公众号图文回复验证码并写入数据库的基本思路
接了个小活:要求公众号中用户回复1,公众号被动回复7位数验证码,同时把用户openId和验证码写入数据库
简单写了各测试demo:工具 thinkphp 订阅号子钦有话说内申请的测试账号
接口配置信息修改
Controller控制器 输入1得到被动回复验证码(里面大多数代码与标题无关,想必大家能用到,所以没有删除)
<?php namespace Home\Controller; use Home\Common\CommonController; /** *@parame 微信公众号开发 */ class WeChatController extends CommonController { //配置接口信息接入api public function index() { //1.获得参数 signature nonce token timestamp echostr $nonce = $_GET[\'nonce\']; $token = \'zhangmangde\'; $timestamp = $_GET[\'timestamp\']; $echostr = $_GET[\'echostr\']; $signature = $_GET[\'signature\']; //2.拼成数组,然后按字典序排序 $array = array(); $array = array($nonce,$timestamp,$token); sort($array); //3.拼成字符串,sha1加密,然后和$signature进行比较 $str = sha1(implode($array)); if($str == $signature && $echostr){ //第一次接入微信api的时候 echo $echostr; exit; }else{ $this->responseMsg(); } } /*public function show(){ echo \'zhangmangde\'; }*/ //接受事件,推送并回复 public function responseMsg(){ //1.获取到微信推送过来的post数据(xml格式) $postArr = $GLOBALS[\'HTTP_RAW_POST_DATA\']; //2.处理消息类型,并设置回复内容和类型 /*<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[subscribe]]></Event> </xml>*/ $postObj = simplexml_load_string($postArr);//将xml字符串载入对象中 //$postObj->ToUserName = \'\'; //$postObj->FromUserName = \'\'; //$postObj->CreateTime = \'\'; //$postObj->MsgType = \'\'; //$postObj->Event = \'\'; //判断该数据包是否是订阅的事件推送 if(strtolower($postObj->MsgType) == \'event\'){ //如果是关注subcribe事件 if(strtolower($postObj->Event) == \'subscribe\'){ //回复用户消息 $arr = array( array( \'title\' => \'欢迎关注子钦的公众号开发版哟^^~~^^\', \'description\' => \'张子钦很酷哦 or ziqin is very cool 哈哈!关注有惊喜哦\', \'picUrl\' => \'http://waphd.simufengyun.com/Public/Home/images/zmd123.png\', \'url\' => \'http://wap.simufengyun.com/\', ), ); //实例化模型 $weChatModel = new \Home\Model\WeChatModel;//实例化时,一定要注意Model的路径问题 下面a()方法是测试路径问题 $weChatModel->responseSubscribe($postObj,$arr);//调用模型中的方法 } //点击事件 if(strtolower($postObj->Event) == \'click\'){ //如果是自定义菜单中的event->click if(strtolower($postObj->EventKey) == \'item1\'){ $content = "这是菜单一事件的推送"; } if(strtolower($postObj->EventKey) == \'songs\'){ $content = "这是歌曲事件的推送"; } //实例化模型 //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } //跳转事件 if(strtolower($postObj->Event) == \'view\'){ //如果是自定义菜单中的event->view $content = "要跳转的链接是".$postObj->EventKey; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } // if(strtolower($postObj->Event) == \'SCAN\'){ //自定义菜单中的event->scan $content = "扫描场景".$postObj->EventKey; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'LOCATION\'){ //自定义菜单中的event->LOCATION $content = "上传位置:纬度".$postObj->Latitude.";经度".$postObj->Longitude; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'scancode_waitmsg\'){ //自定义菜单中的event->scancode_waitmsg $content = "扫描带提示:类型".$postObj->ScanCodeInfo->ScanType."结果:".$postObj->ScanCodeInfo->ScanResult; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'scancode_push\'){ //自定义菜单中的event->scancode_push $content = "扫码推事件"; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'pic_sysphoto\'){ //自定义菜单中的event->pic_sysphoto $content = "系统拍照"; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'pic_weixin\'){ //自定义菜单中的event->pic_weixin $content = "相册发图:数量".$postObj->SendPicsInfo->Count; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'pic_photo_or_album\'){ //自定义菜单中的event->pic_photo_or_album $content = "拍照或者相册:数量".$postObj->SendPicsInfo->Count; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } if(strtolower($postObj->Event) == \'location_select\'){ //自定义菜单中的event->location_select $content = "发送位置:标签".$postObj->SendLocationInfo->Label; //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } } //判断是否是纯文本 /*if(strtolower($postObj->MsgType) == \'text\'){ switch(trim($postObj->Content)){ case 1: $content = \'您输入的数字是1\'; break; case 2: $content = \'您输入的数字是2\'; break; case 3: $content = \'您输入的数字是3\'; break; case \'英文\': $content = \'ziqin is very good\'; break; case \'电话\': $content = \'15236272691\'; break; case \'百度\': $content = \'<a href="https://www.baidu.com">百度搜索</a>\'; break; } $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $time = time(); $msgType = \'text\'; echo sprintf($template,$toUser,$fromUser,$time,$msgType,$content); }*/ //用户发送tuwen1关键字的时候,发送一个图文 或者发送纯文本 或者多图文 if(strtolower($postObj->MsgType) == \'text\' && trim($postObj->Content)==\'tuwen1\'){ $arr = array( array( \'title\' => \'私募风云网年度峰会报名开始啦\', \'description\' => \'ziqin is very cool\', \'picUrl\' => \'http://wap.simufengyun.com//Public/Home/images/ban1.jpg\', \'url\' => \'http://wap.simufengyun.com/\', ), array( \'title\' => \'私募风云网官方网站\', \'description\' => \'simufengyun is very cool\', \'picUrl\' => \'http://wap.simufengyun.com//Public/Home/images/ban2.jpg\', \'url\' => \'http://wap.simufengyun.com/\', ), array( \'title\' => \'我是子钦有话说\', \'description\' => \'ziqin is very cool\', \'picUrl\' => \'http://wap.simufengyun.com//Public/Home/images/ban3.jpg\', \'url\' => \'http://wap.simufengyun.com/\', ), ); //实例化模型 $weChatModel = new \Home\Model\WeChatModel;//实例化时,一定要注意Model的路径问题 下面a()方法是测试路径问题 $weChatModel->responseNews($postObj,$arr);//调用模型中的方法 }else{ switch(trim($postObj->Content)){ case 1: $openId = $postObj->FromUserName;//获取用户openId
$content .= \'您的验证码是:\'.getsRandChar(7)."\n";//回复随机7位数验证码
$content .=\'您的openId是:\'.$openId;
//此处可以操作写入数据库 break; case 2: $content = \'您输入的数字是2\'; break; case 3: $content = \'您输入的数字是3\'; break; case 4: $content = \'张\'; break; case \'英文\': $content = \'ziqin is very good\'; break; case \'电话\': $content = \'15236272691\'; break; case \'百度\': $content = \'<a href="https://www.baidu.com">百度搜索</a>\'; break; default: $content = "没有找到相关信息"; break; } //实例化模型 $weChatModel = new \Home\Model\WeChatModel; $weChatModel->responseText($postObj,$content);//调用方法 } } //接收事件消息 /* private function receiveEvent($object) { $content = ""; switch ($object->Event) { case "subscribe": $content = "欢迎关注方倍工作室 "; $content .= (!empty($object->EventKey))?("\n来自二维码场景 ".str_replace("qrscene_","",$object->EventKey)):""; break; case "unsubscribe": $content = "取消关注"; break; case "CLICK": switch ($object->EventKey) { case "COMPANY": $content = array(); $content[] = array("Title"=>"方倍工作室", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"); break; default: $content = "点击菜单:".$object->EventKey; break; } break; case "VIEW": $content = "跳转链接 ".$object->EventKey; break; case "SCAN": $content = "扫描场景 ".$object->EventKey; break; case "LOCATION": $content = "上传位置:纬度 ".$object->Latitude.";经度 ".$object->Longitude; break; case "scancode_waitmsg": $content = "扫码带提示:类型 ".$object->ScanCodeInfo->ScanType." 结果:".$object->ScanCodeInfo->ScanResult; break; case "scancode_push": $content = "扫码推事件"; break; case "pic_sysphoto": $content = "系统拍照"; break; case "pic_weixin": $content = "相册发图:数量 ".$object->SendPicsInfo->Count; break; case "pic_photo_or_album": $content = "拍照或者相册:数量 ".$object->SendPicsInfo->Count; break; case "location_select": $content = "发送位置:标签 ".$object->SendLocationInfo->Label; break; default: $content = "receive a new event: ".$object->Event." \n技术支持 方倍工作室"; break; } if(is_array($content)){ if (isset($content[0][\'PicUrl\'])){ $result = $this->transmitNews($object, $content); }else if (isset($content[\'MusicUrl\'])){ $result = $this->transmitMusic($object, $content); } }else{ $result = $this->transmitText($object, $content); } return $result; }*/ //采集远程数据 /*function http_curl(){ //获取远程数据 //1.初始化curl $ch = curl_init(); $url = \'http://wap.simufengyun.com\'; //2.设置curl参数 curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); //3.采集 $output = curl_exec($ch); //4.关闭 curl_close($ch); var_dump($output); }*/ /** *$url 接口url string *$type 请求类型 string *$res 返回数据类型 string *$arr post请求参数 string */ function http_curl($url,$type=\'get\',$res=\'json\',$arr=\'\'){ //获取远程数据 //1.初始化curl $ch = curl_init(); //$url = \'http://wap.simufengyun.com\'; //2.设置curl参数 curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); if($type == \'post\'){ curl_setopt($ch,CURLOPT_POST,1); curl_setopt($ch,CURLOPT_POSTFIELDS,$arr); } //3.采集 $output = curl_exec($ch); //4.关闭 curl_close($ch); if($res == \'json\'){ if(curl_error($ch)){ //请求失败,返回错误信息 return curl_error($ch); }else{ return json_decode($output,true); } } //var_dump($output); } //获取access_token和微信服务器ip地址 /*function getWxAccessToken(){ //1.请求url地址 $appid = \'wxd3a57f24b4e021b2\'; $appsecret = \'feffb8659a14792c9323fdf27b4b35f7\'; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; //2.初始化 $ch = curl_init(); //3.设置参数 curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); //4.调用接口(采集) $res = curl_exec($ch); //5.关闭curl curl_close($ch); if(curl_errno($ch)){ var_dump(curl_error($ch)); } $arr = json_decode($res,true); var_dump($arr); }*/ //获取微信服务器ip function getWxServerIp(){ $accessToken = "9E_hA1sd77bpRQ0GqhyU4G5zpLxKZM3Yrxa1za0yyYQpWJmXif5AI3nRNUBe6xESQtQR5SbHHTkvYx5XkcnXkcXn6gVpGVGGbCswbLMMtqEfD1mGXHobq3nKtUkwFXvVSLXgABAFYK"; $url = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=".$accessToken; $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); $res = curl_exec($ch); curl_close($ch); if(curl_errno($ch)){ var_dump(curl_error($ch)); } $arr = json_decode($res,true); echo "<pre>"; var_dump($arr); echo "<pre>"; } //测试实例化Model模型路径问题 public function a(){ $weChatModel = new \Home\Model\WeChatModel; var_dump($weChatModel); } //返回access_token; access_token存入session避免重复调用 public function getWxAccessToken(){ //将access_token 存在session/cookie中 if($_SESSION[\'access_token\'] && $_SESSION[\'expires_time\']>time()){ //如果access_token在session并没有过期 return $_SESSION[\'access_token\']; }else{ //如果access_token在session不存在或者已经过期,重新取access_token $appid = \'wxd3a\';//此处用你自己的appid $appsecret = \'feffb8659a14792c9323fdf\';//用你自己的appsecret $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; $res = $this->http_curl($url,\'get\',\'json\'); $access_token = $res[\'access_token\']; //将重新获取到的access_token存入session $_SESSION[\'access_token\'] = $access_token; $_SESSION[\'expires_time\'] = time() + 7200; return $access_token; } } //自定义菜单 public function definedItem(){ //创建微信菜单 //目前微信接口的调用方式都是通过curl post/get header(\'content-type:text/html;charset=utf-8\');//解决中文乱码 echo $access_token = $this->getWxAccessToken(); $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token; $postArr = array( \'button\'=>array( array( \'name\'=>urlencode(\'子钦\'), \'type\'=>\'click\', \'key\'=>\'item1\', ),//第一个一级菜单 array( \'name\'=>urlencode(\'子钦语录\'), \'sub_button\'=>array( array( \'name\'=>urlencode(\'歌曲\'), \'type\'=>\'click\', \'key\'=>\'songs\', ),//第一个二级菜单 array( \'name\'=>urlencode(\'私募风云网\'), \'type\'=>\'view\', \'url\'=>\'http://wap.simufengyun.com\', ),//第二个二级菜单 ), ),//第二个一级菜单 array( \'name\' =>urlencode(\'子钦心语\'), \'type\' =>\'view\', \'url\' => \'http://wap.simufengyun.com\', ),//第三个一级菜单 ), ); //其他按钮类型 $postArr2 = array( \'button\'=>array( array( \'name\'=>urlencode(\'扫码\'), \'sub_button\'=>array( array( \'type\'=>"scancode_waitmsg", \'name\'=>urlencode("扫码带提示"), \'key\'=>"rselfmenu_0_0", ),//第一个二级菜单 array( \'type\'=>"scancode_push", \'name\'=>urlencode("扫码推事件"), \'key\'=>"rselfmenu_0_1", ),//第二个二级菜单 ), ),//第一个一级菜单 array( \'name\'=>urlencode("发图"), \'sub_button\'=>array( array( \'type\'=>\'pic_sysphoto\', \'name\'=>urlencode("系统拍照发图"), \'key\'=>"rselfmenu_1_0", ),//第一个二级菜单 array( \'type\'=>\'pic_photo_or_album\', \'name\'=>urlencode("拍照或者相册发图"), \'key\'=>"rselfmenu_1_1", ),//第二个二级菜单 array( \'type\'=>\'pic_weixin\', \'name\'=>urlencode("微信相册发图"), \'key\'=>"rselfmenu_1_2", ),//第三个二级菜单 ), ),//第二个一级菜单 array( \'name\'=>urlencode("发送位置"), \'type\'=>"location_select", "key"=>"rselfmenu_2_0", ),//第三个一级菜单 ), ); /*echo \'<hr />\'; var_dump($postArr); echo \'<hr />\'; echo $postJson = urldecode(json_encode($postArr)); $res = $this->http_curl($url,\'post\',\'json\',$postJson); echo "<hr/>"; var_dump($res);*/ echo \'<hr />\'; var_dump($postArr2); echo \'<hr />\'; echo $postJson = urldecode(json_encode($postArr2)); $res = $this->http_curl($url,\'post\',\'json\',$postJson); echo "<hr/>"; var_dump($res); }
}
Model类
<?php namespace Home\Model; use Think\Model; class WeChatModel extends Model{ //多图文的回复微信方法 public function responseNews($postObj,$arr) { $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $time = time(); $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <ArticleCount>".count($arr)."</ArticleCount> <Articles>"; foreach($arr as $k=>$v){ $template .="<item> <Title><![CDATA[".$v[\'title\']."]]></Title> <Description><![CDATA[".$v[\'description\']."]]></Description> <PicUrl><![CDATA[".$v[\'picUrl\']."]]></PicUrl> <Url><![CDATA[".$v[\'url\']."]]></Url> </item>"; } $template .= "</Articles> </xml>"; echo sprintf($template,$toUser,$fromUser,$time,\'news\'); } //回复单文本 public function responseText($postObj,$content){ $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $time = time(); $msgType = \'text\'; echo sprintf($template,$toUser,$fromUser,$time,$msgType,$content); } //回复用户关注消息 public function responseSubscribe($postObj,$arr){ $this->responseNews($postObj,$arr); } }
7位验证的函数方法
//生成随机数,length长度 function getsRandChar($length){ $str = null; $strPol = "0123456789abcdefghijklmnopqrstuvwxyz";//不区分大小写
//$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";//区分大小写 $max = strlen($strPol)-1; for($i=0;$i<$length;$i++){ $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数 } return $str; }
有不明白的加微信咨询zmd1047773569