# 接口權限配置
使用 `wx.config` 進行接口權限配置。
```js
wx.config({
debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。
appId: parm.appId, // 必填,公眾號的唯一標識
timestamp: parm.timestamp, // 必填,生成簽名的時間戳
nonceStr: parm.nonceStr, // 必填,生成簽名的隨機串
signature: parm.signature , // 必填,簽名
jsApiList: [] // 必填,需要使用的JS接口列表
})
```
## 1 獲取配置參數
其中 `timestamp` 是當前時間戳, `nonceStr` 是一段隨機字串,可以自定義。
### 1.1 獲取 AppID
其中 AppID 從左邊菜單的"**開發 - 基本配置 - 公眾號開發信息**" 中可以看到:
:-: 
### 1.2 獲取 signature
要獲取 `signature` ,首先得生成一個 `access_token`。
#### 1.2.1 獲取 access_token
access_token是公眾號的全局唯一接口調用憑據,公眾號調用各接口時都需使用access_token。開發者需要進行妥善保存。access_token的存儲至少要保留512個字符空間。access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。
獲取地址:
```
https 請求方式 : GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
```
打開 https://mp.weixin.qq.com/debug 進行調試獲取 access_token,輸入自己的 `AppID` 和 `AppSecret` 即可:
:-: 
獲取`access_token`之前需要在白名單中添加自己的IP,否則將無法調用成功。
具體操作為: 打開 "**開發 - 基本設置 - 公眾號開發信息**" 進行設置:
:-: 
參考閱讀: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183
#### 1.2.2 獲取 jsapi_ticket
生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號用于調用微信JS接口的臨時票據。正常情況下,jsapi_ticket的有效期為7200秒,通過access_token來獲取。由于獲取jsapi_ticket的api調用次數非常有限,頻繁刷新jsapi_ticket會導致api調用受限,影響自身業務,開發者必須在自己的服務全局緩存jsapi_ticket 。
獲取地址:
```
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
```
獲取成功返回的大概是這樣
:-: 
可以看到,已經拿到門票了 (ticket)
#### 1.2.3 生成 signature
簽名生成規則如下:參與簽名的字段包括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
url=http://mp.weixin.qq.com?params=value
```
步驟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
```
#### 1.2.4 注意事項
1. 簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
2. 簽名用的url必須是調用JS接口頁面的完整URL。
3. 出于安全考慮,開發者必須在服務器端實現簽名的邏輯。
### 1.3 錯誤解決
如出現invalid signature 等錯誤請參看以下解決辦法:
調用config 接口的時候傳入參數 debug: true 可以開啟debug模式,頁面會alert出錯誤信息。以下為常見錯誤及解決方法:
1. invalid url domain當前頁面所在域名與使用的appid沒有綁定,請確認正確填寫綁定的域名,僅支持80(http)和443(https)兩個端口,因此不需要填寫端口號。
2. invalid signature簽名錯誤。建議按如下順序檢查:
1. 確認簽名算法正確,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 頁面工具進行校驗。
2. 確認config中nonceStr(js中駝峰標準大寫S), timestamp與用以簽名中的對應noncestr, timestamp一致。
3. 確認url是頁面完整的url(請在當前頁面alert(location.href.split('#')[0])確認),包括'http(s)://'部分,以及'?'后面的GET參數部分,但不包括'#'hash后面的部分。
4. 確認 config 中的 appid 與用來獲取 jsapi_ticket 的 appid 一致。
5. 確保一定緩存access_token和jsapi_ticket。
6. 確保你獲取用來簽名的url是動態獲取的,動態頁面可參見實例代碼中php的實現方式。如果是html的靜態頁面在前端通過ajax將url傳到后臺簽名,前端需要用js獲取當前頁面除去'#'hash部分的鏈接(可用location.href.split('#')[0]獲取,而且需要encodeURIComponent),因為頁面一旦分享,微信客戶端會在你的鏈接末尾加入其它參數,如果不是動態獲取當前鏈接,將導致分享后的頁面簽名失敗。
3. the permission value is offline verifying這個錯誤是因為config沒有正確執行,或者是調用的JSAPI沒有傳入config的jsApiList參數中。建議按如下順序檢查:
1. 確認config正確通過。
2. 如果是在頁面加載好時就調用了JSAPI,則必須寫在wx.ready的回調中。
3. 確認config的jsApiList參數包含了這個JSAPI。
4. permission denied該公眾號沒有權限使用這個JSAPI,或者是調用的JSAPI沒有傳入config的jsApiList參數中(部分接口需要認證之后才能使用)。
5. function not exist當前客戶端版本不支持該接口,請升級到新版體驗。
6. 為什么6.0.1版本config:ok,但是6.0.2版本之后不ok(因為6.0.2版本之前沒有做權限驗證,所以config都是ok,但這并不意味著你config中的簽名是OK的,請在6.0.2檢驗是否生成正確的簽名以保證config在高版本中也ok。)
7. 在iOS和Android都無法分享(請確認公眾號已經認證,只有認證的公眾號才具有分享相關接口權限,如果確實已經認證,則要檢查監聽接口是否在wx.ready回調函數中觸發)
8. 服務上線之后無法獲取jsapi_ticket,自己測試時沒問題。(因為access_token和jsapi_ticket必須要在自己的服務器緩存,否則上線后會觸發頻率限制。請確保一定對token和ticket做緩存以減少2次服務器請求,不僅可以避免觸發頻率限制,還加快你們自己的服務速度。目前為了方便測試提供了1w的獲取量,超過閥值后,服務將不再可用,請確保在服務上線前一定全局緩存access_token和jsapi_ticket,兩者有效期均為7200秒,否則一旦上線觸發頻率限制,服務將不再可用)。
9. uploadImage怎么傳多圖(目前只支持一次上傳一張,多張圖片需等前一張圖片上傳之后再調用該接口)
10. 沒法對本地選擇的圖片進行預覽(chooseImage接口本身就支持預覽,不需要額外支持)
11. 通過a鏈接(例如先通過微信授權登錄)跳轉到b鏈接,invalid signature簽名失敗(后臺生成簽名的鏈接為使用jssdk的當前鏈接,也就是跳轉后的b鏈接,請不要用微信登錄的授權鏈接進行簽名計算,后臺簽名的url一定是使用jssdk的當前頁面的完整url除去'#'部分)
12. 出現config:fail錯誤(這是由于傳入的config參數不全導致,請確保傳入正確的appId、timestamp、nonceStr、signature和需要使用的jsApiList)
13. 如何把jsapi上傳到微信的多媒體資源下載到自己的服務器(請參見文檔中uploadVoice和uploadImage接口的備注說明)
14. Android通過jssdk上傳到微信服務器,第三方再從微信下載到自己的服務器,會出現雜音(微信團隊已經修復此問題,目前后臺已優化上線)
15. 綁定父級域名,是否其子域名也是可用的(是的,合法的子域名在綁定父域名之后是完全支持的)
16. 在iOS微信6.1版本中,分享的圖片外鏈不顯示,只能顯示公眾號頁面內鏈的圖片或者微信服務器的圖片,已在6.2中修復
17. 是否需要對低版本自己做兼容(jssdk都是兼容低版本的,不需要第三方自己額外做更多工作,但有的接口是6.0.2新引入的,只有新版才可調用)
18. 該公眾號支付簽名無效,無法發起該筆交易(請確保你使用的jweixin.js是官方線上版本,不僅可以減少用戶流量,還有可能對某些bug進行修復,拷貝到第三方服務器中使用,官方將不對其出現的任何問題提供保障,具體支付簽名算法可參考 JSSDK微信支付一欄)
19. 目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題已在Android6.2中修復
20. uploadImage在chooseImage的回調中有時候Android會不執行,Android6.2會解決此問題,若需支持低版本可以把調用uploadImage放在setTimeout中延遲100ms解決
21. require subscribe錯誤說明你沒有訂閱該測試號,該錯誤僅測試號會出現
22. getLocation返回的坐標在openLocation有偏差,因為getLocation返回的是gps坐標,openLocation打開的騰訊地圖為火星坐標,需要第三方自己做轉換,6.2版本開始已經支持直接獲取火星坐標
23. 查看公眾號(未添加): "menuItem:addContact"不顯示,目前僅有從公眾號傳播出去的鏈接才能顯示,來源必須是公眾號
24. ICP備案數據同步有一天延遲,所以請在第二日綁定
## 2 使用PHP獲取簽名
這里的示例使用PHP獲取簽名
```php
<?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數據
}
}
```
參考資料: http://blog.csdn.net/helencoder/article/details/51121718
## 3 所有JS接口列表
以下接口可以配置到 wx.config 中的 jsApiList 參數,必須配置相應的接口才能使用對應的功能:
```
onMenuShareTimeline
onMenuShareAppMessage
onMenuShareQQ
onMenuShareWeibo
onMenuShareQZone
startRecord
stopRecord
onVoiceRecordEnd
playVoice
pauseVoice
stopVoice
onVoicePlayEnd
uploadVoice
downloadVoice
translateVoice
chooseImage
previewImage
uploadImage
downloadImage
getNetworkType
openLocation
getLocation
hideOptionMenu
showOptionMenu
hideMenuItems
showMenuItems
hideAllNonBaseMenuItem
showAllNonBaseMenuItem
closeWindow
scanQRCode
chooseWXPay
openProductSpecificView
addCard
chooseCard
openCard
```
- 簡介
- 第一章 公眾號開發
- 使用微信JSSDK
- 接口權限配置
- 分享接口
- 隱藏按鈕項
- 微信支付
- 第二章 小程序開發
- 基礎知識
- 分包加載
- WXSS樣式表
- 配置
- app.json配置
- window
- tabBar
- page.json配置
- 邏輯層
- app.js
- 場景值
- page.js
- 初始化數據
- 生命周期函數
- 頁面相關事件處理函數
- 事件處理函數
- 頁面實例方法
- 路由
- 文件作用域
- 模塊化
- 視圖層
- 模板語法
- 列表渲染
- 條件渲染
- 模板
- 事件
- 引用
- WXS語法規范
- WXS數據類型
- WXS控制流程
- WXS基礎類庫
- 組件
- 視圖容器
- view
- scroll-view
- swiper
- movable-view
- cover-view
- 基礎組件
- icon
- text
- rich-text
- progress
- 表單組件
- button
- checkbox
- form
- input
- label
- picker
- picker-view
- radio
- slider
- switch
- textarea
- 導航組件
- navigator
- 媒體組件
- audio
- image
- video
- camera
- 地圖組件
- map
- 畫布組件
- canvas
- 開放能力
- web-view
- 自定義組件
- 組件模版和樣式
- Component
- 組件傳值
- 組件事件
- Behaviors
- 組件間關系
- 網絡請求
- wx.request
- 微信登錄
- 獲取 openid 和 unionid
- 獲取用戶信息
- 將 wx.request 封裝為 promise
- 上傳圖片接口封裝
- 數據存儲
- 存儲數據和讀取數據
- 獲取數據緩存信息
- 移除數據緩存
- 獲取用戶設置
- openSetting
- getSetting
- 第三章 小游戲開發
- 參考資料