微信JSSDK 网页扫二维码
本文地址:http://tongxinmao.com/Article/Detail/id/128
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | <?php /** * Author: helen * CreateTime: 2016/4/11 10:39 * description: 微信页面授权--(JS-SDK使用权限签名算法) */ class JSSDK{ private $appId ; private $appSecret ; public function __construct( $appId , $appSecret ) { $this ->appId = $appId ; $this ->appSecret = $appSecret ; } /* * 获取access_token * (需要缓存,可利用数据库存储,不要频繁刷新获取) * http请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET * 接口请求参数 * 参数 是否必须 说明 grant_type 是 获取access_token填写client_credential appid 是 第三方用户唯一凭证 secret 是 第三方用户唯一凭证密钥,即appsecret * 接口返回说明 * {"access_token":"ACCESS_TOKEN","expires_in":7200} access_token 获取到的凭证 expires_in 凭证有效时间,单位:秒 * 接口错误说明 * {"errcode":40013,"errmsg":"invalid appid"} * */ private function getAccessToken(){ $appId = $this ->appId; $appSecret = $this ->appSecret; $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appId . '&secret=' . $appSecret ; $res = $this ->api_request( $url ); if (isset( $res ->access_token)){ return array ( 'errcode' =>0, 'errmsg' => 'success' , 'access_token' => $res ->access_token, 'expires_in' => $res ->expires_in ); } else { return array ( 'errcode' => $res ->errcode, 'errmsg' => $res ->errmsg, 'access_token' =>null, 'expires_in' =>null ); } } /* * 获取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 } * */ private function getJsApiTicket(){ $access_token_data = $this ->getAccessToken(); if ( $access_token_data [ 'errcode' ]==0){ $access_token = $access_token_data [ 'access_token' ]; $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $access_token . '&type=jsapi' ; $res = $this ->api_request( $url ); if ( $res ->errcode==0){ return array ( 'errcode' => $res ->errcode, 'errmsg' => $res ->errmsg, 'ticket' => $res ->ticket, 'expires_in' => $res ->expires_in ); } else { return array ( 'errcode' => $res ->errcode, 'errmsg' => $res ->errmsg, 'ticket' =>null, 'expires_in' =>null ); } } else { return array ( 'errcode' => $access_token_data [ 'errcode' ], 'errmsg' => $access_token_data [ 'errmsg' ], 'ticket' =>null, 'expires_in' =>null ); } } /* * 签名算法 * 签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。 * 1、对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后, * 2、使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。 * 这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。 * */ /* * 获取随机字符串 * mt_rand() 使用 Mersenne Twister 算法返回随机整数。 * mt_rand(min,max)如果没有提供可选参数 min 和 max,mt_rand() 返回 0 到 RAND_MAX 之间的伪随机数。 * 想要 5 到 15(包括 5 和 15)之间的随机数,用 mt_rand(5, 15)。 * 此函数rand()快四倍 * */ /* * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。 * 2.签名用的url必须是调用JS接口页面的完整URL。 * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。 * 注意: * 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。 * 如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent), * 因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。 * */ public function getSignPackage() { $jsapiTicket_data = $this ->getJsApiTicket(); $nonceStr = $this ->getNonceStr(); $timestamp = time(); $url = $this ->getUrl(); if ( $jsapiTicket_data [ 'errcode' ]==0){ $jsapiTicket = $jsapiTicket_data [ 'ticket' ]; // 这里参数的顺序要按照 key 值 ASCII 码升序排序 $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url" ; $signature = sha1( $string ); return array ( "appId" => $this ->appId, "nonceStr" => $nonceStr , "timestamp" => $timestamp , "url" => $url , "signature" => $signature , "rawString" => $string , "errcode" => $jsapiTicket_data [ 'errcode' ], "errmsg" => $jsapiTicket_data [ 'errmsg' ] ); } else { return array ( "appId" => $this ->appId, "nonceStr" => $nonceStr , "timestamp" => $timestamp , "url" => $url , "signature" => null, "rawString" => null, "errcode" => $jsapiTicket_data [ 'errcode' ], "errmsg" => $jsapiTicket_data [ 'errmsg' ] ); } } /* * 获取nonceStr * */ private function getNonceStr( $length = 16) { $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ; $nonceStr = "" ; for ( $i = 0; $i < $length ; $i ++) { $nonceStr .= substr ( $chars , mt_rand(0, strlen ( $chars ) - 1), 1); } return $nonceStr ; } /* * 获取url * url(当前网页的URL,不包含#及其后面部分) * */ private function getUrl(){ $protocol = (! empty ( $_SERVER [ 'HTTPS' ]) && $_SERVER [ 'HTTPS' ] !== 'off' || $_SERVER [ 'SERVER_PORT' ] == 443) ? "https://" : "http://" ; $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]" ; return $url ; } /* * 微信API调用方法 * */ private function api_request( $url , $data =null){ //初始化cURL方法 $ch = curl_init(); //设置cURL参数(基本参数) $opts = array ( //在局域网内访问https站点时需要设置以下两项,关闭ssl验证! //此两项正式上线时需要更改(不检查和验证认证) CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_TIMEOUT => 500, CURLOPT_RETURNTRANSFER => true, CURLOPT_URL => $url , ); curl_setopt_array( $ch , $opts ); //post请求参数 if (! empty ( $data )) { curl_setopt( $ch , CURLOPT_POST, true); curl_setopt( $ch , CURLOPT_POSTFIELDS, $data ); } //执行cURL操作 $output = curl_exec( $ch ); if (curl_errno( $ch )) { //cURL操作发生错误处理。 var_dump(curl_error( $ch )); die ; } //关闭cURL curl_close( $ch ); $res = json_decode( $output ); return ( $res ); //返回json数据 } } |
1 2 3 4 5 6 7 8 9 10 11 12 | private function setWxsdk(){ ini_set ( 'date.timezone' , 'Asia/Shanghai' ); require_once APP_ROOT. "/App/Lib/jssdk.php" ; $jssdk = new JSSDK( $this ->appid, $this ->secret ); $signPackage = $jssdk ->GetSignPackage(); $this ->assign( 'signPackage' , $signPackage ); print_r( $signPackage ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <script type= 'text/javascript' src= 'http://res.wx.qq.com/open/js/jweixin-1.0.0.js' charset= 'utf-8' ></script> <script> /* * 注意: * 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。 * 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。 * 3. 常见问题及完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html * * 开发中遇到问题详见文档“附录5-常见错误及解决办法”解决,如仍未能解决可通过以下渠道反馈: * 邮箱地址:weixin-open@qq.com * 邮件主题:【微信JS-SDK反馈】具体问题 * 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。 */ wx.config({ debug: false , appId: '<?php echo $signPackage["appId"];?>' , timestamp: <?php echo $signPackage[ "timestamp" ];?>, nonceStr: '<?php echo $signPackage["nonceStr"];?>' , signature: '<?php echo $signPackage["signature"];?>' , jsApiList: [ 'checkJsApi' , 'scanQRCode' ] }); wx.ready( function (){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 wx.checkJsApi({ jsApiList: [ 'scanQRCode' ], // 需要检测的JS接口列表,所有JS接口列表见附录2, success: function (res) { // 以键值对的形式返回,可用的api值true,不可用为false // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} wx.scanQRCode({ needResult: 1, desc: 'scanQRCode desc' , success: function (res) { alert(JSON.stringify(res)); var barcode=res.resultStr; var msg=res.errMsg; if (msg.indexOf( 'ok' )>0){ alert(res.resultStr); } } }); } }); }); wx.error( function (res){ alert( "出错了:" + res.errMsg); // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 }); </script> |
上一篇:爱宝a-58USB打印机描述符
下一篇:LINUX php mssql(odbc /pdo_dblib)