WeChat ページの承認 – (JS-SDK は許可署名アルゴリズムを使用します)
使用法: このクラスをインスタンス化し、その中で getSignPackage() メソッドを呼び出します。
注: access_token と jsapi_ticket を取得する場合は、自分でキャッシュする必要があり、頻繁に取得することはできません。
<code><span><span><?php</span><span>/** * Author: helen * CreateTime: 2016/4/11 10:39 * description: 微信页面授权--(JS-SDK使用权限签名算法) */</span><span><span>class</span><span>JSSDK</span>{</span><span>private</span><span>$appId</span>; <span>private</span><span>$appSecret</span>; <span>public</span><span><span>function</span><span>__construct</span><span>(<span>$appId</span>, <span>$appSecret</span>)</span> {</span><span>$this</span>->appId = <span>$appId</span>; <span>$this</span>->appSecret = <span>$appSecret</span>; } <span>/* * 获取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"} * */</span><span>private</span><span><span>function</span><span>getAccessToken</span><span>()</span>{</span><span>$appId</span> = <span>$this</span>->appId; <span>$appSecret</span> = <span>$this</span>->appSecret; <span>$url</span> = <span>'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='</span>.<span>$appId</span>.<span>'&secret='</span>.<span>$appSecret</span>; <span>$res</span> = <span>$this</span>->api_request(<span>$url</span>); <span>if</span>(<span>isset</span>(<span>$res</span>->access_token)){ <span>return</span><span>array</span>( <span>'errcode'</span> =><span>0</span>, <span>'errmsg'</span> =><span>'success'</span>, <span>'access_token'</span> =><span>$res</span>->access_token, <span>'expires_in'</span> =><span>$res</span>->expires_in ); }<span>else</span>{ <span>return</span><span>array</span>( <span>'errcode'</span> =><span>$res</span>->errcode, <span>'errmsg'</span> =><span>$res</span>->errmsg, <span>'access_token'</span> =><span>null</span>, <span>'expires_in'</span> =><span>null</span> ); } } <span>/* * 获取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 } * */</span><span>private</span><span><span>function</span><span>getJsApiTicket</span><span>()</span>{</span><span>$access_token_data</span> = <span>$this</span>->getAccessToken(); <span>if</span>(<span>$access_token_data</span>[<span>'errcode'</span>]==<span>0</span>){ <span>$access_token</span> = <span>$access_token_data</span>[<span>'access_token'</span>]; <span>$url</span> = <span>'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='</span>.<span>$access_token</span>.<span>'&type=jsapi'</span>; <span>$res</span> = <span>$this</span>->api_request(<span>$url</span>); <span>if</span>(<span>$res</span>->errcode==<span>0</span>){ <span>return</span><span>array</span>( <span>'errcode'</span> =><span>$res</span>->errcode, <span>'errmsg'</span> =><span>$res</span>->errmsg, <span>'ticket'</span> =><span>$res</span>->ticket, <span>'expires_in'</span> =><span>$res</span>->expires_in ); }<span>else</span>{ <span>return</span><span>array</span>( <span>'errcode'</span> =><span>$res</span>->errcode, <span>'errmsg'</span> =><span>$res</span>->errmsg, <span>'ticket'</span> =><span>null</span>, <span>'expires_in'</span> =><span>null</span> ); } }<span>else</span>{ <span>return</span><span>array</span>( <span>'errcode'</span> =><span>$access_token_data</span>[<span>'errcode'</span>], <span>'errmsg'</span> =><span>$access_token_data</span>[<span>'errmsg'</span>], <span>'ticket'</span> =><span>null</span>, <span>'expires_in'</span> =><span>null</span> ); } } <span>/* * 签名算法 * 签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。 * 1、对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后, * 2、使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。 * 这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。 * */</span><span>/* * 获取随机字符串 * mt_rand() 使用 Mersenne Twister 算法返回随机整数。 * mt_rand(min,max)如果没有提供可选参数 min 和 max,mt_rand() 返回 0 到 RAND_MAX 之间的伪随机数。 * 想要 5 到 15(包括 5 和 15)之间的随机数,用 mt_rand(5, 15)。 * 此函数rand()快四倍 * */</span><span>/* * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。 * 2.签名用的url必须是调用JS接口页面的完整URL。 * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。 * 注意: * 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。 * 如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent), * 因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。 * */</span><span>public</span><span><span>function</span><span>getSignPackage</span><span>()</span> {</span><span>$jsapiTicket_data</span> = <span>$this</span>->getJsApiTicket(); <span>$nonceStr</span> = <span>$this</span>->getNonceStr(); <span>$timestamp</span> = time(); <span>$url</span> = <span>$this</span>->getUrl(); <span>if</span>(<span>$jsapiTicket_data</span>[<span>'errcode'</span>]==<span>0</span>){ <span>$jsapiTicket</span> = <span>$jsapiTicket_data</span>[<span>'ticket'</span>]; <span>// 这里参数的顺序要按照 key 值 ASCII 码升序排序</span><span>$string</span> = <span>"jsapi_ticket=$jsapiTicket&n/span>; <span>$signature</span> = sha1(<span>$string</span>); <span>return</span><span>array</span>( <span>"appId"</span> => <span>$this</span>->appId, <span>"nonceStr"</span> => <span>$nonceStr</span>, <span>"timestamp"</span> => <span>$timestamp</span>, <span>"url"</span> => <span>$url</span>, <span>"signature"</span> => <span>$signature</span>, <span>"rawString"</span> => <span>$string</span>, <span>"errcode"</span> => <span>$jsapiTicket_data</span>[<span>'errcode'</span>], <span>"errmsg"</span> => <span>$jsapiTicket_data</span>[<span>'errmsg'</span>] ); }<span>else</span>{ <span>return</span><span>array</span>( <span>"appId"</span> => <span>$this</span>->appId, <span>"nonceStr"</span> => <span>$nonceStr</span>, <span>"timestamp"</span> => <span>$timestamp</span>, <span>"url"</span> => <span>$url</span>, <span>"signature"</span> => <span>null</span>, <span>"rawString"</span> => <span>null</span>, <span>"errcode"</span> => <span>$jsapiTicket_data</span>[<span>'errcode'</span>], <span>"errmsg"</span> => <span>$jsapiTicket_data</span>[<span>'errmsg'</span>] ); } } <span>/* * 获取nonceStr * */</span><span>private</span><span><span>function</span><span>getNonceStr</span><span>(<span>$length</span> = <span>16</span>)</span> {</span><span>$chars</span> = <span>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"</span>; <span>$nonceStr</span> = <span>""</span>; <span>for</span> (<span>$i</span> = <span>0</span>; <span>$i</span> < <span>$length</span>; <span>$i</span>++) { <span>$nonceStr</span> .= substr(<span>$chars</span>, mt_rand(<span>0</span>, strlen(<span>$chars</span>) - <span>1</span>), <span>1</span>); } <span>return</span><span>$nonceStr</span>; } <span>/* * 获取url * url(当前网页的URL,不包含#及其后面部分) * */</span><span>private</span><span><span>function</span><span>getUrl</span><span>()</span>{</span><span>$protocol</span> = (!<span>empty</span>(<span>$_SERVER</span>[<span>'HTTPS'</span>]) && <span>$_SERVER</span>[<span>'HTTPS'</span>] !== <span>'off'</span> || <span>$_SERVER</span>[<span>'SERVER_PORT'</span>] == <span>443</span>) ? <span>"https://"</span> : <span>"http://"</span>; <span>$url</span> = <span>"$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"</span>; <span>return</span><span>$url</span>; } <span>/* * 微信API调用方法 * */</span><span>private</span><span><span>function</span><span>api_request</span><span>(<span>$url</span>,<span>$data</span>=null)</span>{</span><span>//初始化cURL方法</span><span>$ch</span> = curl_init(); <span>//设置cURL参数(基本参数)</span><span>$opts</span> = <span>array</span>( <span>//在局域网内访问https站点时需要设置以下两项,关闭ssl验证!</span><span>//此两项正式上线时需要更改(不检查和验证认证)</span> CURLOPT_SSL_VERIFYPEER => <span>false</span>, CURLOPT_SSL_VERIFYHOST => <span>false</span>, CURLOPT_TIMEOUT => <span>500</span>, CURLOPT_RETURNTRANSFER => <span>true</span>, CURLOPT_URL => <span>$url</span>, ); curl_setopt_array(<span>$ch</span>, <span>$opts</span>); <span>//post请求参数</span><span>if</span> (!<span>empty</span>(<span>$data</span>)) { curl_setopt(<span>$ch</span>, CURLOPT_POST, <span>true</span>); curl_setopt(<span>$ch</span>, CURLOPT_POSTFIELDS, <span>$data</span>); } <span>//执行cURL操作</span><span>$output</span> = curl_exec(<span>$ch</span>); <span>if</span> (curl_errno(<span>$ch</span>)) { <span>//cURL操作发生错误处理。</span> var_dump(curl_error(<span>$ch</span>)); <span>die</span>; } <span>//关闭cURL</span> curl_close(<span>$ch</span>); <span>$res</span> = json_decode(<span>$output</span>); <span>return</span> (<span>$res</span>); <span>//返回json数据</span> } } </span></span></span></code>
上記では、PHP と SSD のコンテンツを含む WeChat JSSDK ページ認証の PHP 実装を紹介しました。PHP チュートリアルに興味のある友人に役立つことを願っています。