微信公众号开发及h5分享兼容性问题总结 解决:微信授权登录、微信判断是否关注公众号,没关注先关注、微信分享到朋友及朋友圈
上源码以后项目遇见会有更多补充
php源码以thinkphp6框架为例
app/BaseController.php
// 初始化
//判断access_token是否到期已经用户是否授权登录,没有进行授权
protected function initialize()
{
$controller = Request::controller();
if($controller!="Wechat"){
if(!session('openid')||!session('access_token')||!Cache::get("token")){
$this->redirect(url('wechat/actionScopeRedirectUriAppid'));
}else{
$res=Db::table("users")->where("openid",session('openid'))->count();
if(!$res){
$this->redirect(url('wechat/actionScopeRedirectUriAppid'));
}
}
}
}
app/index/controller/Wechat.php
<?php
namespace app\index\controller;
use app\BaseController;
use think\facade\View;
use think\facade\Db;
use think\facade\Cache;
class Wechat extends BaseController
{
public function clear(){
// Cache::clear();
$tasks=Db::table("tasks")->select();
foreach($tasks as $task){
Cache::set("daka_taskdetail".$task['id'],null);
}
Cache::set("daka_tasklist",null);
Cache::set("daka_settings",null);
Cache::set("daka_images",null);
Cache::set("daka_gg",null);
Cache::set("daka_hb",null);
Cache::set("daka_qun",null);
echo "清除缓存成功";
}
//授权登录
public function actionScopeRedirectUriAppid(){
$APPID = $this->appId;
$REDIRECT_URI= 'http://'.$_SERVER['HTTP_HOST'].'/index/wechat/actionWeixinOpenidCallback';
$scope='snsapi_userinfo'; //手动授权snsapi_userinfo 静默授权snsapi_base
$url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$APPID.'&redirect_uri='.urlencode($REDIRECT_URI).'&response_type=code&scope='.$scope.'&state=scene#wechat_redirect';
header("Location:{$url}");
die();
}
##微信回调,获取openid
public function actionWeixinOpenidCallback(){
if($code= input('code')){
$APPID = $this->appId;
$SECRET = $this->secret;
//h5的access_token
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$APPID}&secret={$SECRET}&code={$code}&grant_type=authorization_code";
$UserOpenidArr = json_decode($this->dogetCurl($url),1);
if(empty($UserOpenidArr ['openid']) ) {
print_r( $UserOpenidArr );
die("授权失败");
}
$openid=$UserOpenidArr ['openid'];
session('openid',$openid);
\think\facade\Session::save();
session('access_token',$UserOpenidArr['access_token']);
\think\facade\Session::save();
$openid=session('openid');
$access_token=session('access_token');
$token=$this -> getAccessToken();;
// var_dump($openid);
// var_dump($access_token);
// var_dump($access_token);
//跳转公众号获取用户
// header("Location:http://dk.zlhdsg.com/index/wechat/actionWeixinOpenidGetUserInfocgi?openid={$openid}&&token={$token}&&access_token={$access_token}" );
//跳转h5获取用户信息
header("Location:http://dk.zlhdsg.com/index/wechat/actionWeixinOpenidGetUserInfo?openid={$openid}&&access_token={$access_token}" );
die();
}else{
die("微信授权失败");
}
}
//获取公众号用户信息
public function actionWeixinOpenidGetUserInfocgi(){
$openid= input('openid');
$token=input('token');
$access_token=input('access_token');
$res=$this->getapktj("https://api.weixin.qq.com/cgi-bin/user/info?access_token={$token}&openid={$openid}&lang=zh_CN");
if($res["subscribe"]){
//跳转h5获取用户
header("Location:http://dk.zlhdsg.com/index/wechat/actionWeixinOpenidGetUserInfo?openid={$openid}&&access_token={$access_token}" );
}else{
echo '
<style>
.inc{
position:fixed;
left:0;
top:0;
background:rgba(0,0,0,0.5);
width:100%;
height:100%;
z-index:998;
/*pointer-events: none;*/
}
</style>
<div class="inc"><img src="https://135editor.cdn.bcebos.com/files/users/1006/10062944/202103/Y8JpSQgR_BtsZ.jpg" style="text-align:center;position:absolute;left:170;top: 140;opacity:1;width:640px;height:640px " data-ratio="1"><p style="font-size:40;position:absolute;left:220;top: 800;color:#fff;text-align:center;" >长按上方↑二维码关注公众号<br>关注后重新打开链接</p></div>
';
}
die();
}
//获取公众号用户信息
public function actionWeixinOpenidGetUserInfocgi2(){
$openid= input('openid');
$token=input('token');
$access_token=input('access_token');
$res=$this->getapktj("https://api.weixin.qq.com/cgi-bin/user/info?access_token={$token}&openid={$openid}&lang=zh_CN");
header("Location:http://dk.zlhdsg.com/index/index/index?sub={$res['subscribe']}" );
die();
}
//h5获取用户信息
public function actionWeixinOpenidGetUserInfo(){
$openid= input('openid');
$access_token=input('access_token');
$res=$this->getapktj("https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN");
// echo("<pre>");
// var_dump($res);
// var_dump(Cache::get("token"));
// var_dump(session('access_token'));
// var_dump(session('openid'));exit;
$res['nickname']=preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $res['nickname']);
$id=Db::table("users")->where("openid",$res['openid'])->value("id");
if($id){
$res1=Db::table("users")->where('id',$id)->update(['nickname'=>$res['nickname'],'headimgurl'=>$res['headimgurl'],'updated_at'=>date("Y-m-d H:i:s")]);
}else{
$id=$res1=Db::table("users")->insertGetId(['openid'=>$res['openid'],'nickname'=>$res['nickname'],'headimgurl'=>$res['headimgurl'],'created_at'=>date("Y-m-d H:i:s"),'updated_at'=>date("Y-m-d H:i:s")]);
}
if($res1){
$this->redirect(url("index/index"));
}else{
echo "error";
}
}
//跨服务器高级用法
public function getapktj($url){
$method ="GET";
$curl = curl_init();
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_FAILONERROR, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, false);
$ret = curl_exec($curl);
$all=json_decode($ret,true);
return $all;
//返回数组
}
public function message(){
$echoStr = input("get.echostr");
//valid signature , option
if(!empty($echoStr)){
if($this->checkSignature()){
echo $echoStr;
exit;
}
}else{
$this->responseMsg();
}
}
public function getAccessToken(){
if(!Cache::get("token")){
$APPID = $this->appId;
$SECRET = $this->secret;
//公众号的access_token
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$APPID&secret=$SECRET";
$UserOpenidArrcgi = json_decode($this->dogetCurl($url),1);
$token=$UserOpenidArrcgi['access_token'];
Cache::set('token',$token,4800);
}
$accessToken = Cache::get("token");
return $accessToken;
}
/*
响应信息
*/
public function responseMsg(){
/*
获得请求时POST:XML字符串
不能用$_POST获取,因为没有key
*/
$xml_str = file_get_contents("php://input");
if(empty($xml_str)){
die('');
}
if(!empty($xml_str)){
// 解析该xml字符串,利用simpleXML
libxml_disable_entity_loader(true);
//禁止xml实体解析,防止xml注入
$request_xml = simplexml_load_string($xml_str, 'SimpleXMLElement', LIBXML_NOCDATA);
var_dump($request_xml);
//判断该消息的类型,通过元素MsgType
switch ($request_xml->MsgType){
case 'event':
//判断具体的时间类型(关注、取消、点击)
$event = $request_xml->Event;
if ($event=='subscribe') { // 关注事件
$this->_doSubscribe($request_xml);
}elseif ($event=='CLICK') {//菜单点击事件
$this->_doClick($request_xml);
}elseif ($event=='VIEW') {//连接跳转事件
$this->_doView($request_xml);
}else{
}
break;
case 'text'://文本消息
$this->_doText($request_xml);
break;
case 'image'://图片消息
$this->_doImage($request_xml);
break;
case 'voice'://语音消息
$this->_doVoice($request_xml);
break;
case 'video'://视频消息
$this->_doVideo($request_xml);
break;
case 'shortvideo'://短视频消息
$this->_doShortvideo($request_xml);
break;
case 'location'://位置消息
$this->_doLocation($request_xml);
break;
case 'link'://链接消息
$this->_doLink($request_xml);
break;
}
}
}
//关注事件
private function _doSubscribe($request_xml){
//处理该关注事件,向用户发送关注信息
$content = '感谢你关注,请输入 帮助,了解公众号基本口令。';
// $this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
$item_list = array(
array('title'=>'打卡','desc'=>'学习打卡免费领书哟','picurl'=>'https://135editor.cdn.bcebos.com/files/users/1006/10062944/202104/NGzT2bHD_P6gE.png','url'=>'http://www.baidu.com'),
);
$this->_msgNews($request_xml->FromUserName,$request_xml->ToUserName,$item_list);
}
/******************用户输入消息********************/
//文本消息
private function _doText($request_xml){
//接受文本信息
$content = $request_xml->Content;
// var_dump($content);
if($content == '活动'){
//显示帮助消息
$response_content = '输入对应序号或名称,获取相应资源' . "\n" . '[1]打卡领书'."\n". '[2]快递查询' . "\n" . '[3]加学生群';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}elseif($content=='帮助'){
$response_content = '本公众号支持以下口令:' . "\n" . '活动'."\n".'快递';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}elseif (strtolower($content)=='1'||stristr('打卡领书',strtolower($content))) {
$response_content='打卡领书:'."\n".'http://www.baidu.com';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}elseif (strtolower($content)=='2'||stristr('快递查询',strtolower($content))) {
$response_content='快递查询:'."\n".'http://www.baidu.com';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}elseif (strtolower($content)=='3'||stristr('加学生群',strtolower($content))) {
$response_content='加学生群:'."\n".'http://www.baidu.com';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}elseif('新闻' == $content){
$item_list = array(
array('title'=>'生日快乐','desc'=>'其实你应该用母亲的方式回报母亲','picurl'=>'图片地址','url'=>'http://www.baidu.com'),
array('title'=>'生日快乐1','desc'=>'其实你应该用母亲的方式回报母亲','picurl'=>'图片地址','url'=>'http://www.baidu.com'),
);
$this->_msgNews($request_xml->FromUserName,$request_xml->ToUserName,$item_list);
}else{
$response_content='暂无此关键词';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}
}
//图片消息
private function _doImage($request_xml){
$content = '上传图片成功,请输入 图片 随机获取一张图片'.$request_xml->MediaId;
$this->_img_list[] = $request_xml->MediaId;
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
}
/**
* 发送文本信息
* @param [type] $to 目标用户ID
* @param [type] $from 来源用户ID
* @param [type] $content 内容
* @return [type] [description]
*/
private function _msgText($to, $from, $content) {
$response = sprintf($this->_msg_template['text'], $to, $from, time(), $content);
echo($response);
}
//发送图片消息
/**
* @param $to [description]
* @param [type] $from [description]
* @param [type] $file [description]
* @return
*/
//发送图片
private function _msgImage($to,$from,$file,$is_id=false){
//判断是不是media_id
if($is_id){
$media_id=$file;
}else{
// 上传图片到微信公众服务器,获取mediaID
$result_obj = $this->uploadTmp($file, 'image');
$media_id = $result_obj->media_id;
}
//拼凑xml图片发给微信平台,然后平台返回图片给用户
$response = sprintf($this->_msg_template['image'],$to,$from,time(),$media_id);
die($response);
}
//发送新闻
private function _msgNews($to,$from,$item_list=array()){
//拼凑文章部分
$item_str = '';
foreach ($item_list as $item) {
$item_str .= sprintf($this->_msg_template['news_item'],$item['title'],$item['desc'],$item['picurl'],$item['url']);
}
//拼凑主体部分
$response = sprintf($this->_msg_template['news'], $to, $from, time(), count($item_list), $item_str);
die($response);
}
private $_msg_template = array(
'text' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>',//文本回复XML模板
'image' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[%s]]></MediaId></Image></xml>',//图片回复XML模板
'music' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[music]]></MsgType><Music><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><MusicUrl><![CDATA[%s]]></MusicUrl><HQMusicUrl><![CDATA[%s]]></HQMusicUrl><ThumbMediaId><![CDATA[%s]]></ThumbMediaId></Music></xml>',//音乐模板
'news' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>%s</ArticleCount><Articles>%s</Articles></xml>',// 新闻主体
'news_item' => '<item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item>',//某个新闻模板
);
private function checkSignature()
{
$signature = input("get.signature");
$timestamp = input("get.timestamp");
$nonce = input("get.nonce");
$token = "rdjdaka";
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
private function createNonceStr($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
public function getSignPackage() {
$jsapiTicket = $this->getJsApiTicket();
// 注意 URL 一定要动态获取,不能 hardcode.
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$timestamp = time();
$nonceStr = $this->createNonceStr();
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = array(
"appId" => $this->appId,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
// var_dump($signPackage);exit;
return json_encode($signPackage);
}
private function getJsApiTicket() {
// jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
$data = json_decode(Cache::get("jsapi_ticket"),true);
if(empty($data->expire_time)){
$expire=0;
}else{
$expire=$data->expire_time;
}
if ($expire < time()) {
$accessToken =$this -> getAccessToken();
// 如果是企业号用以下 URL 获取 ticket
// $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
$res = $this->getapktj($url);
$ticket = $res['ticket'];
if ($ticket) {
$data['expire_time'] = time() + 4600;
$data['jsapi_ticket'] = $ticket;
Cache::set("jsapi_ticket", json_encode($data));
}
} else {
$ticket = $data->jsapi_ticket;
}
return $ticket;
}
public function dogetCurl( $url ='' )
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt ( $ch, CURLOPT_HTTPHEADER, array( 'Connection: Keep-Alive', 'Keep-Alive: 300' ));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close ( $ch );
return $data;
}
//创建菜单
public function menuSet($menu) {
$url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $this->getAccessToken();
$data = $menu;
$result_obj = json_decode($this->_request('post',$url, $data));
if ($result_obj->errcode == 0) {
return true;
} else {
echo $result_obj->errmsg, '<br>';
return false;
}
}
//菜单删除
public function menuDelete(){
$url ='https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=' . $this->getAccessToken();
$result = $this->_request('get',$url);
$result_obj = json_decode($result);
if($result_obj->errcode == 0){
return true;
}else{
return false;
}
}
}
app/index/controller/Index.php
<?php
namespace app\index\controller;
use app\BaseController;
use think\facade\View;
use think\facade\Db;
use think\facade\Cache;
use app\index\controller\Wechat;
class Index extends BaseController
{
//微信分享
public function taskdoit(){
$data=$wechat->getSignPackage();
$wx=json_decode($data);
View::assign('wx',$wx);
return View::fetch();
}
}
h5分享到朋友或朋友圈app/index/view/wechat/taskdoit.html
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script type="text/javascript" src="/form/img/js/jquery.min.js"></script>
<script>
wx.config({
debug: false,
appId: "{$wx->appId}",
timestamp: "{$wx->timestamp}",
nonceStr: "{$wx->nonceStr}",
signature: "{$wx->signature}",
jsApiList: [
// 所有要调用的 API 都要加到这个列表中
'onMenuShareTimeline', //分享到朋友圈
'onMenuShareAppMessage' //分享给好友
]
});
wx.ready(function () {
wx.onMenuShareTimeline({
title: "{$share.title}", // 分享标题
desc: "{$share.des}", // 分享描述
link: "{$share.href}",
imgUrl: "http://daka.zlhdsg.com/{$share.url}",
success: function () {
shareSuccess();
},
cancel: function () {
// 用户取消分享后执行的回调函数
alert('已取消');
}
});
wx.onMenuShareAppMessage({
title: "{$share.title}", // 分享标题
desc: "{$share.des}", // 分享描述
link: "{$share.href}",
imgUrl: "http://daka.zlhdsg.com/{$share.url}",
success: function () {
// 用户确认分享后执行的回调函数
alert('感谢分享给好友,请分享到朋友圈');
// shareSuccess();
},
cancel: function () {
// 用户取消分享后执行的回调函数
alert('已取消');
}
});
});
function shareSuccess(){
$.ajax({
url:"{:url('shareit')}",
type:"POST",
async:true,
cache: false,
dataType: "json",
success:function(json){
alert(json.msg);
if (json.url) {
//parent.location.reload();
window.location.href = json.url;
}
}
});
}
$(".sharebtn").click(function(){
var path=$(this).attr("path");
console.log(path);
$(".inc").css("display",'block');
});
$(document).click(function(e){
var target = $(e.target);
if(target.closest(".sharebtn").length != 0) return;
$(".inc").append('');
$(".inc").css("display",'none');
})
</script>
<style>
.inc{
display: none;
position:fixed;
left:0;
top:0;
background:rgba(0,0,0,0.5);
width:100%;
height:100%;
z-index:998;
/*pointer-events: none;*/
}
</style>
//引导遮罩层
<div class="inc">
<img src="http://daka.zlhdsg.com/upload/image/6066dd2fb8b3b.jpg" style="text-align:center;position:absolute;right:20;top: -80;opacity:1;width:440px;height:640px " data-ratio="1"><p style="font-size:40;position:absolute;left:300;top: 500;color:#fff;" >点击右上角... 分享朋友圈</p>
</div>
注意一点的是苹果手机用以上方法alert不能提示!!解决方法
添加js方法
function bottoncart(msg,url) {
var cart='<div class="cleanwap"> <div class="well"id="well1"> <p>'+msg+'</p> <span class="text-center pull-right"><a href="'+url+'" class="btn btn-primary">朕知道了</a></span></div></div>';
$('body').append(cart);
}
添加css
<style>
.well{
background: #fff;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
left: 15%;
position: fixed;
text-align: center;
top: 30%;
width: 70%;
z-index:10000;
font-size: 30px;
padding: 5px;
}
.cleanwap{
position: fixed;top: 0px;width: 100%;bottom:0px;right:0px; background:rgba(0,0,0,0.6);z-index:20000000
}
.pull-right {
float: right!important;
}
a {
text-decoration: none;
}
.btn {
padding: 7.5px 12px;
font-size: 12px;
border: 1px solid #cccccc;
border-radius: 4px;
box-shadow: inset 0 1px 0 rgb(255 255 255 / 20%), 0 1px 2px rgb(0 0 0 / 5%);
}
.btn-primary{
font-size: 30px;
position: relative;
bottom: 10px;
background: #333;
color:#fff;
}
</style>
if是安卓调用bottoncart方法
自定义菜单
创建菜单需要我们传一个json格式参数,同一样已关注的用户也会24小时后生效
1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“…”代替。
一般公众号底部都有1-3个菜单选项,选项里可能还有子菜单,这个如何通过php代码进行创建?
菜单创建
菜单创建和删除都是针对所有的,不能单独操作某一个菜单
//菜单删除
public function menuDelete(){
$url ='https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=' . $this->getAccessToken();
$result = $this->_request('get',$url);
$result_obj = json_decode($result);
if($result_obj->errcode == 0){
return true;
}else{
return false;
}
}
菜单删除
//创建菜单
public function menuSet($menu) {
$url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $this->getAccessToken();
$data = $menu;
$result_obj = json_decode($this->_request('post',$url, $data));
if ($result_obj->errcode == 0) {
return true;
} else {
echo $result_obj->errmsg, '<br>';
return false;
}
}
自定义菜单立即生效方法
直接用微信测试工具填写立即生效
https://mp.weixin.qq.com/debug
菜单格式
{
"button": [
{
"name": "扫码",
"sub_button": [
{
"type": "scancode_waitmsg",
"name": "扫码带提示",
"key": "scancode_waitmsg",
"sub_button": [ ]
},
{
"type": "scancode_push",
"name": "扫码推事件",
"key": "scancode_push",
"sub_button": [ ]
}
]
},
{
"name": "发图",
"sub_button": [
{
"type": "pic_sysphoto",
"name": "系统拍照发图",
"key": "pic_sysphoto",
"sub_button": [ ]
},
{
"type": "pic_photo_or_album",
"name": "拍照或者相册发图",
"key": "pic_photo_or_album",
"sub_button": [ ]
},
{
"type": "pic_weixin",
"name": "微信相册发图",
"key": "pic_weixin",
"sub_button": [ ]
}
]
},
{
"name": "快捷操作",
"sub_button" : [
{
"name": "地理位置",
"type": "location_select",
"key": "location_select"
},
{
"name": "普通点击",
"type": "click",
"key": "click"
},
{
"name": "查看URL",
"type": "view",
"url" : "http://www.soso.com/"
},
]
},
]
}
彩蛋:屏蔽微信用户特殊符号
$res['nickname']=preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $res['nickname']);
仅用于网站测试