一、在此以前先确认一下你是否有已得到相应接口的权限,查看方法:登陆微信公众平台,开发者中心-》接口权限表-》功能服务-》分享接口。查看本身是否已经获取分享自定义的接口权限。php
如图:html
二、而后进入“公众号设置”-》“功能设置”里填写“JS接口安全域名”。jquery
如图:web
在须要调用JS接口的页面引入以下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js算法
备注:支持使用 AMD/CMD 标准模块加载方法加载sql
全部须要使用JS-SDK的页面必须先注入配置信息,不然将没法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,因此使用pushState来实现web app的页面会致使签名失败,此问题会在Android6.2中修复)。数据库
wx.config({ debug: true, // 开启调试模式,调用的全部api的返回值会在客户端alert出来,若要查看传入的参数,能够在pc端打开,参数信息会经过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的惟一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,须要使用的JS接口列表,全部JS接口列表见附录2 });
此处我为了方便测试,timestamp和nonceStr定为死的,实际应用中你们也能够写为动态的。json
下面我重点说一下signature是怎么获得的。api
jsapi_ticket数组
生成签名以前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常状况下,jsapi_ticket的有效期为7200秒,经过access_token来获取。因为获取jsapi_ticket的api调用次数很是有限,频繁刷新jsapi_ticket会致使api调用受限,影响自身业务,开发者必须在本身的服务全局缓存jsapi_ticket 。
参考如下文档获取access_token(有效期7200秒,开发者必须在本身的服务全局缓存access_token)。
用第一步拿到的access_token 采用http GET方式请求得到jsapi_ticket(有效期7200秒,开发者必须在本身的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功返回以下JSON:
{ "errcode":0, "errmsg":"ok", "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA", "expires_in":7200 }
得到jsapi_ticket以后,就能够生成JS-SDK权限验证的签名了。
签名算法
签名生成规则以下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对全部待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里须要注意的是全部参数名均为小写字符。对string1做sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
步骤1. 对全部待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
步骤2. 对string1进行sha1签名,获得signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
注意事项
签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
签名用的url必须是调用JS接口页面的完整URL。
出于安全考虑,开发者必须在服务器端实现签名的逻辑。
个人思路:
由于个人服务器没有装memcached,因此我用数据库来缓存access_token和jsapi_ticket,缓存你们能够依据本身的实际状况来定。缓存原理:在使用access_token和jsapi_ticket时,先判断数据库存的数据是否过时,若是过时就新生成新的数据并存入数据库,若是没有过时就从数据库取。
先创建两个表:
access_token缓存表:
jsapi_ticket缓存表:
代码以下:先建一个微信类Wechat,用来获取accessToken、getJSApi_ticket和signature
class Wechat { public $dsql; private function getAccessToken() //生成access_token,并存入数据库 { global $dsql; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".AppId."&secret=".AppSecret; $data = getCurl($url);//经过自定义函数getCurl获得https的内容 $resultArr = json_decode($data, true);//转为数组 //access_token插入数据库作缓存 $time=time(); $sql="insert into wx_accesstoken(access_token,uptime) value('{$resultArr["access_token"]}',$time)"; $dsql->ExecuteNoneQuery($sql); return $resultArr["access_token"];//获取access_token } private function getToken()//若是access_token有数据库缓存,就从数据库取,若是没有就从新取 { global $dsql; $time=time()-7200; $sql="select * from wx_accesstoken where uptime>$time"; $row=$dsql->GetOne($sql); if($row) { return $row['access_token'];//从数据库取 }else{ return $this->getAccessToken();//从新获取 } } public function getJSApi_ticket(){//获取JSApi_ticket global $dsql; $time=time()-7200; $sql="select * from wx_jsApiTicket where uptime>$time"; $row=$dsql->GetOne($sql); if($row) { return $row['access_token'];//从数据库取 }else{ //若是数据库没有保存有效的jsApiTicket,就从新生成并存入数据库 $accessToken = $this->getToken();//获取access_token $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$accessToken."&type=jsapi"; $data = getCurl($url);//经过自定义函数getCurl获得https的内容 $resultArr = json_decode($data, true);//转为数组 //插入数据库作缓存 $nowtime=time(); $sql="insert into wx_jsApiTicket(jsApiTicket,uptime) value('{$resultArr["ticket"]}',$nowtime)"; $dsql->ExecuteNoneQuery($sql); return $resultArr['ticket'];//获取jsApi_ticket } } public function getSignature(){ $jsApi_ticket = $this->getJSApi_ticket();//获取access_token //file_put_contents("a.txt",$jsApi_ticket."\n",FILE_APPEND);此处是作断点测试用的 //动态获取url if($_SERVER['QUERY_STRING']){ $url= 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING']; }else{ $url= 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']; } //file_put_contents("a.txt",$url."\n",FILE_APPEND); $str = "jsapi_ticket=".$jsApi_ticket."&noncestr=2nDgiWM7gCxhL8v0×tamp=1420774989&url=".$url; $signature = ""; $signature=sha1($str); return $signature; } } function getCurl($url){//get https的内容 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);//不输出内容 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $result = curl_exec($ch); curl_close ($ch); return $result; } function dataPost($post_string, $url) {//POST方式提交数据 $context = array ('http' => array ('method' => "POST", 'header' => "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) \r\n Accept: */*", 'content' => $post_string ) ); $stream_context = stream_context_create ( $context ); $data = file_get_contents ( $url, FALSE, $stream_context ); return $data; }
2.而后到须要调用JS接口的页面得到signature
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>微信JS-SDK Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"> <link rel="stylesheet" href=""> <script src="js/jquery-1.7.2.js"></script> </head> <?php
define(AppId, "本身的AppId");//定义AppId,须要在微信公众平台申请自定义菜单后会获得 define(AppSecret, "本身的AppSecret");//定义AppSecret,须要在微信公众平台申请自定义菜单后会获得
include("wechat.class.php");//引入微信类 $signatureObj = new Wechat();//实例化微信类 $signature = $signatureObj->getSignature();
?> <body ontouchstart=""> <div class="wxapi_container"> <input type="hidden" name="signature" value="<?php echo $signature;?>" id="signature"> <div class="lbox_close wxapi_form"> <h3 id="menu-basic">基础接口</h3> <span class="desc">判断当前客户端是否支持指定JS接口</span> <button class="btn btn_primary" id="checkJsApi">checkJsApi</button>
<h3 id="menu-share">分享接口</h3> <span class="desc">获取“分享到朋友圈”按钮点击状态及自定义分享内容接口</span> <button class="btn btn_primary" id="onMenuShareTimeline">onMenuShareTimeline</button> <span class="desc">获取“分享给朋友”按钮点击状态及自定义分享内容接口</span> <button class="btn btn_primary" id="onMenuShareAppMessage">onMenuShareAppMessage</button> <span class="desc">获取“分享到QQ”按钮点击状态及自定义分享内容接口</span> <button class="btn btn_primary" id="onMenuShareQQ">onMenuShareQQ</button> <span class="desc">获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口</span> <button class="btn btn_primary" id="onMenuShareWeibo">onMenuShareWeibo</button> </div> </div> </body> <script src=""> </script> <script> var signature = $("#signature").val(); var url = location.href.split('#')[0]; wx.config({ debug: true, appId: 'wx2fea4dec5cb77d24', timestamp: 1420774989,//此处同微信类里用来生成signature的timestamp要相同 nonceStr: '2nDgiWM7gCxhL8v0',//此处同微信类里用来生成signature的nonceStr要相同 signature: signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo' ] });
wx.ready(function () { wx.onMenuShareAppMessage({ title: '个人分享测试', // 分享标题 desc: '个人分享测试demo', // 分享描述 link: url, // 分享连接 imgUrl: 'http://img3.douban.com/view/movie_poster_cover/spst/public/p2166127561.jpg', // 分享图标 type: '', // 分享类型,music、video或link,不填默认为link dataUrl: '', // 若是type是music或video,则要提供数据连接,默认为空 success: function () { // 用户确认分享后执行的回调函数 alert("分享成功!"); }, cancel: function () { // 用户取消分享后执行的回调函数 alert("取消分享!"); } }); })
</script> </html>
如出现invalid signature 等错误详见微信附录5常见错误及解决办法。
好了,你们试试吧。。。