解決:php
看我把這些坑都總結了一下:要命的invalid signature。css
https://segmentfault.com/q/1010000002520634html
有人這樣說:json
出現問題的緣由是參與簽名的URL地址不正確,須要動態獲取當前頁面完整的URL地址(包括?後面的參數,但不能包含#號),如若URL地址爲:http://www.xxx.xxx/payment/wxpay/jspay?oid=xxxx&attr=xxxx#wechat,那麼完整的URL地址應該是截取#號以前的部份。爲何會出現#號呢?由於你的URL在被分享到朋友圈等微信系統自動會添加一些參數。segmentfault
invalid signature出現可能還有其餘緣由的api
http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign安全
示例代碼:服務器
http://203.195.235.76/jssdk/#menu-voice微信
http://demo.open.weixin.qq.com/jssdk/sample.zipapp
經對比,微信 JS 接口簽名校驗正確,往下走
sample.php
<?php
require_once "jssdk.php";
$jssdk = new JSSDK("appid", "ssss");
$signPackage = $jssdk->GetSignPackage();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<link rel="stylesheet" href="http://203.195.235.76/jssdk/css/style.css">
<body>
appId: '<?php echo $signPackage["appId"];?>
<br>
timestamp: <?php echo $signPackage["timestamp"];?>
<br>
nonceStr: '<?php echo $signPackage["nonceStr"];?>
<br>
$ticket:<?php echo $ticket; ?>
<br>
<?php echo $signPackage["signature"];?>
<br>
<button class="btn btn_primary" id="startRecord">startRecord</button>
</body>
<button class="btn btn_primary" id="stopRecord">stopRecord</button>
<button class="btn btn_primary" id="playVoice">playVoice</button>
<button class="btn btn_primary" id="pauseVoice">pauseVoice</button>
<button class="btn btn_primary" id="stopVoice">stopVoice</button>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></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: true,
appId: '<?php echo $signPackage["appId"];?>', timestamp: <?php echo $signPackage["timestamp"];?>, nonceStr: '<?php echo $signPackage["nonceStr"];?>', signature: '<?php echo $signPackage["signature"];?>', jsApiList: [ // 全部要調用的 API 都要加到這個列表中 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'translateVoice', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'onVoicePlayEnd', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard' ] }); wx.ready(function () { // 在這裏調用 API // 4 音頻接口 // 4.2 開始錄音 document.querySelector('#startRecord').onclick = function () { wx.startRecord({ cancel: function () { alert('用戶拒絕受權錄音'); } }); }; // 4.3 中止錄音 document.querySelector('#stopRecord').onclick = function () { wx.stopRecord({ success: function (res) { voice.localId = res.localId; }, fail: function (res) { alert(JSON.stringify(res)); } }); }; // 4.4 監聽錄音自動中止 wx.onVoiceRecordEnd({ complete: function (res) { voice.localId = res.localId; alert('錄音時間已超過一分鐘'); } }); // 4.5 播放音頻 document.querySelector('#playVoice').onclick = function () { if (voice.localId == '') { alert('請先使用 startRecord 接口錄製一段聲音'); return; } wx.playVoice({ localId: voice.localId }); }; // 4.6 暫停播放音頻 document.querySelector('#pauseVoice').onclick = function () { wx.pauseVoice({ localId: voice.localId }); }; // 4.7 中止播放音頻 document.querySelector('#stopVoice').onclick = function () { wx.stopVoice({ localId: voice.localId }); }; // 4.8 監聽錄音播放中止 wx.onVoicePlayEnd({ complete: function (res) { alert('錄音(' + res.localId + ')播放結束'); } }); // 4.8 上傳語音 document.querySelector('#uploadVoice').onclick = function () { if (voice.localId == '') { alert('請先使用 startRecord 接口錄製一段聲音'); return; } wx.uploadVoice({ localId: voice.localId, success: function (res) { alert('上傳語音成功,serverId 爲' + res.serverId); voice.serverId = res.serverId; } }); }; // 4.9 下載語音 document.querySelector('#downloadVoice').onclick = function () { if (voice.serverId == '') { alert('請先使用 uploadVoice 上傳聲音'); return; } wx.downloadVoice({ serverId: voice.serverId, success: function (res) { alert('下載語音成功,localId 爲' + res.localId); voice.localId = res.localId; } }); }; });</script></html>
jssdk.php
<?php class JSSDK { private $appId; private $appSecret; public function __construct($appId, $appSecret) { $this->appId = $appId; $this->appSecret = $appSecret; } 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 ); return $signPackage; } 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; } private function getJsApiTicket() { // jsapi_ticket 應該全局存儲與更新,如下代碼以寫入到文件中作示例 $data =123; if ($data) { $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 = json_decode($this->httpGet($url)); $ticket = $res->ticket; if ($ticket) { $data->expire_time = time() + 7000; $data->jsapi_ticket = $ticket; $this->set_php_file("jsapi_ticket.php", json_encode($data)); } } else { $ticket = $data->jsapi_ticket; } // print_r(1232); return $ticket; } private function getAccessToken() { // access_token 應該全局存儲與更新,如下代碼以寫入到文件中作示例 $data = 12333; if ($data) { // 若是是企業號用如下URL獲取access_token // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret"; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret"; $res = json_decode($this->httpGet($url)); print_r($res); $access_token = $res->access_token; if ($access_token) { $data->expire_time = time() + 7000; $data->access_token = $access_token; $this->set_php_file("access_token.php", json_encode($data)); } } else { $access_token = $data->access_token; } echo 'access+token:'.$access_token."<br>"; return $access_token; } private function httpGet($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_TIMEOUT, 500); // 爲保證第三方服務器與微信服務器之間數據傳輸的安全性,全部微信接口採用https方式調用,必須使用下面2行代碼打開ssl安全校驗。 // 若是在部署過程當中代碼在此處驗證失敗,請到 http://curl.haxx.se/ca/cacert.pem 下載新的證書判別文件。 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true); curl_setopt($curl, CURLOPT_URL, $url); $res = curl_exec($curl); curl_close($curl); return $res; } private function get_php_file($filename) { return trim(substr(file_get_contents($filename), 15)); } private function set_php_file($filename, $content) { $fp = fopen($filename, "w"); fwrite($fp, "<?php exit();?>" . $content); fclose($fp); } }
在正常空間服務器上運行成功,免費空間原來httpGet獲取時return返回值爲空對比。.服務器空間問題1.gunner.site(主題屋免費空間php curl調用https出錯
)2.正規服務器(無提示錯誤)3.本地可打印access_token
解決辦法:跳過SSL證書檢查。
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
哈哈,有開始出現新問題require subscribe,由於我用公衆平臺測試賬號,關注一下就好
關注就能夠
調用微信JS-SDK 接口成功
微信公衆平臺開發者文檔