微信JS-SDK之影象介面開發詳解
由於現在手頭的專案中有一個上傳證件照認證的功能(手機端),之前的思路是直接點選上傳,然後直接將圖片上傳到伺服器去,這篇文章有講到( http://www.cnblogs.com/it-cen/p/4535219.html ),但在微信裡開啟網頁去上傳,速度並不快,而且,假如我上傳一張2M大的圖片,也沒有對其進行壓縮處理,這樣很影響上傳和下載的速度。
所以,我這裡藉助微信JSSDK的影象介面對其進行開發實現圖片上傳的功能,為何我選擇此介面?第一,目前的專案是在微信中開啟的網頁,利用此介面,效能肯定是好一點的啦,畢竟是微信自己的東西;第二,用此介面,開發效率更高嘛;第三,最重要的一點,就是它能對圖片進行壓縮,假如一張2M的圖片,通過微信圖片上傳介面可以將圖片壓縮成幾百K的大小,這對網站的效能是很有幫助的。
一、我的思路是:
先呼叫“拍照或從手機相簿選擇圖片介面”—>選擇成功圖片後—>呼叫“上傳圖片介面”—>上傳成功後(也就是圖片上傳到了微信伺服器上)—>呼叫“下載圖片介面”—>將圖片下載到自己的伺服器儲存。
二、JSSDK的使用步驟
1、概述
微信JS-SDK是微信公眾平臺面向網頁開發者提供的基於微信內的網頁開發工具包。
通過使用微信JS-SDK,網頁開發者可 藉助微信高效地使用拍照、選圖、語音、位置等手機系統的能力 ,同時可以 直接使用微信分享、掃一掃、卡券、支付等微信特有的能力 ,為微信使用者提供更優質的網頁體驗。
2、使用步驟
步驟一:繫結域名
先登入 微信公眾平臺 進入“公眾號設定”的“功能設定”裡填寫“JS介面安全域名”。
備註:登入後可在“開發者中心”檢視對應的介面許可權。
步驟二:引入JS檔案
步驟三:通過config介面注入許可權驗證配置
所有需要使用JS-SDK的頁面必須先注入配置資訊,否則將無法呼叫(同一個url僅需呼叫一次,對於變化url的SPA的web app可在每次url變化時進行呼叫)
1 wx.config({
2 debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
3 appId: '', // 必填,公眾號的唯一標識
4 timestamp: , // 必填,生成簽名的時間戳
5 nonceStr: '', // 必填,生成簽名的隨機串
6 signature: '',// 必填,簽名,見附錄1
7 jsApiList: [] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2
8 });
步驟四:通過ready介面處理成功驗證
1 wx.ready(function(){
2
3 // config資訊驗證後會執行ready方法,所有介面呼叫都必須在config介面獲得結果之後,config是一個客戶端的非同步操作,所以如果需要在頁面載入時就呼叫相關介面,則須把相關介面放在ready函式中呼叫來確保正確執行。對於使用者觸發時才呼叫的介面,則可以直接呼叫,不需要放在ready函式中。
4 });
步驟五:通過error介面處理失敗驗證
1 wx.error(function(res){
2
3 // config資訊驗證失敗會執行error函式,如簽名過期導致驗證失敗,具體錯誤資訊可以開啟config的debug模式檢視,也可以在返回的res引數中檢視,對於SPA可以在這裡更新簽名。
4
5 });
介面呼叫說明
所有介面通過wx物件(也可使用jWeixin物件)來呼叫,引數是一個物件,除了每個介面本身需要傳的引數之外,還有以下通用引數:
- success:介面呼叫成功時執行的回撥函式。
- fail:介面呼叫失敗時執行的回撥函式。
- complete:介面呼叫完成時執行的回撥函式,無論成功或失敗都會執行。
- cancel:使用者點選取消時的回撥函式,僅部分有使用者取消操作的api才會用到。
- trigger: 監聽Menu中的按鈕點選時觸發的方法,該方法僅支援Menu中的相關介面。
備註: 不要嘗試在trigger中使用ajax非同步請求修改本次分享的內容,因為客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回 。
以上幾個函式都帶有一個引數,型別為物件,其中除了每個介面本身返回的資料之外,還有一個通用屬性errMsg,其值格式如下:
- 呼叫成功時:"xxx:ok" ,其中xxx為呼叫的介面名
- 使用者取消時:"xxx:cancel",其中xxx為呼叫的介面名
- 呼叫失敗時:其值為具體錯誤資訊
三、開發及程式碼分析詳解(用的是CI框架,只要是MVC模式都可以)
1、先在伺服器端取到:公眾號的唯一標識appId、生成簽名的時間戳timestamp、生成簽名的隨機串nonceStr、簽名signature。
wx_upload.php
1 <?php
2class wx_upload extends xx_Controller {
3publicfunction __construct() {
4 parent::__construct();
5 }
6 7publicfunction wxUploadImg() {
8//在模板裡引入jssdk的js檔案 9$this->addResLink('http://res.wx.qq.com/open/js/jweixin-1.0.0.js');
10//取得:公眾號的唯一標識appId、生成簽名的時間戳timestamp、生成簽名的隨機串nonceStr、簽名signature這些值,並以json形式傳到模板頁面11$this->smartyData['wxJsApi'] = json_encode(array('signPackage' => $this->model->weixin->signPackage()));
12 }
圖片上傳控制器
WeixinModel.php
1 <?php
2class WxModel extends ModelBase{
3public$appId;
4public$appSecret;
5public$token;
6 7publicfunction __construct() {
8 parent::__construct();
9 10//稽核通過的移動應用所給的AppID和AppSecret 11$this->appId = 'wx0000000000000000';
12$this->appSecret = '00000000000000000000000000000';
13$this->token = '00000000';
14 }
15 16/**
17 * 獲取jssdk所需引數的所有值
18 * @return array
19*/ 20publicfunction signPackage() {
21$protocol = (!empty($_SERVER['HTTPS'] && $_SERVER['HTTPS'] == 'off' || $_SERVER['port'] == 443)) ? 'https://' : 'http://';
22//當前網頁的URL 23$url = "$protocol$_SERVER['host']$_SERVER['REQUEST_URI']";
24//生成簽名的時間戳 25$timestamp = time();
26//生成簽名的隨機串 27$nonceStr = $this->createNonceStr();
28//獲取公眾號用於呼叫微信JS介面的臨時票據 29$jsApiTicket = $this->getJsApiTicket();
30//對所有待簽名引數按照欄位名的ASCII 碼從小到大排序(字典序)後,
31 //使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字串$str。
32 //這裡需要注意的是所有引數名均為小寫字元 33$str = "jsapi_ticket=$jsApiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
34//對$str進行sha1簽名,得到signature: 35$signature = sha1($str);
36$signPackage = array(
37 "appId" => $this->AppId,
38 "nonceStr" => $nonceStr,
39 "timestamp" => $timestamp,
40 "url" => $url,
41 "signature" => $signature,
42 "rawString" => $string 43 );
44return$signPackage;
45 }
46 47/**
48 * 建立簽名的隨機字串
49 * @param int $length 字串長度
50 * @return string 隨機字串
51*/ 52privatefunction createNonceStr($length == 16) {
53$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
54$str = '';
55for ($i=0; $i < $length; $i++) {
56$str .= substr(mt_rand(0, strlen($chars)), 1);
57 }
58return$str;
59 }
60 61/**
62 * 獲取公眾號用於呼叫微信JS介面的臨時票據
63 * @return string
64*/ 65privatefunction getJsApiTicket() {
66//先檢視redis裡是否存了jsapi_ticket此值,假如有,就直接返回 67$jsApiTicket = $this->library->redisCache->get('weixin:ticket');
68if (!$jsApiTicket) {
69//先獲取access_token(公眾號的全域性唯一票據) 70$accessToken = $this->getApiToken();
71//通過access_token 採用http GET方式請求獲得jsapi_ticket 72$result = $this->callApi("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$accessToken&type=jsapi");
73//得到了jsapi_ticket 74$jsApiTicket = $result['ticket'];
75//將jsapi_ticket快取到redis裡面,下次就不用再請求去取了 76$expire = max(1, intval($result['expire']) - 60);
77$this->library->redisCache->set('weixin:ticket', $jsApiTicket, $expire);
78 }
79return$jsApiTicket;
80 }
81 82/**
83 * 獲取眾號的全域性唯一票據access_token
84 * @param boolean $forceRefresh 是否強制重新整理
85 * @return string 返回access_token
86*/ 87privatefunction getApiToken($forceRefresh = false) {
88//先檢視redis是否存了accessToken,如果有了,就不用再去微信server去請求了(提高效率) 89$accessToken = $this->library->redisCache->get('weixin:accessToken');
90//強制重新整理accessToken或者accessToken為空時就去請求accessToken 91if ($forceRefresh || empty($accessToken)) {
92//請求得到accessToken 93$result = $this->callApi("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}");
94$accessToken = $result['access_token'];
95$expire = max(1, intval($result['expire']) - 60);
96//將其存進redis裡面去 97$this->library->redisCache->set('weixin:accessToken', $accessToken, $expire);
98 }
99return$accessToken;
100 }
獲取到appId、nonceStr、timestamp、signature模型
這裡要補充一些 JS-SDK使用許可權簽名演算法 的思路和注意點(這裡我直接複製官網文件給大家看看)
jsapi_ticket
生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號用於呼叫微信JS介面的臨時票據。正常情況下, jsapi_ticket的有效期為7200秒 ,通過access_token來獲取。由於獲取jsapi_ticket的api呼叫次數非常有限,頻繁重新整理jsapi_ticket會導致api呼叫受限,影響自身業務, 開發者必須在自己的服務全域性快取jsapi_ticket 。
1、獲取access_token( 有效期7200秒,開發者必須在自己的服務全域性快取access_token )
2、用第一步拿到的access_token 採用http GET方式請求獲得jsapi_ticket( 有效期7200秒,開發者必須在自己的服務全域性快取jsapi_ticket )
成功返回如下JSON:
1 {
2 "errcode":0,
3