\r\n????????點(diǎn)擊上傳圖片<\/button>\r\n????????
	






亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
  步驟四:透過ready介面處理成功驗(yàn)證
  步驟五:透過error介面處理失敗驗(yàn)證
  介面呼叫說明
首頁 微信小程式 微信開發(fā) 微信JS-SDK之影像介面開發(fā)

微信JS-SDK之影像介面開發(fā)

Mar 01, 2017 am 09:29 AM
微信開發(fā)

  我這裡借助微信JSSDK的圖像介面對(duì)其進(jìn)行開發(fā)實(shí)現(xiàn)圖片上傳的功能,為何我選擇此介面?第一,目前的專案是在微信中打開的網(wǎng)頁,利用此接口,性能肯定是好一點(diǎn)的啦,畢竟是微信自己的東西;第二,用此接口,開發(fā)效率更高嘛;第三,最重要的一點(diǎn),就是它能對(duì)圖片進(jìn)行壓縮,假如一張2M的圖片,透過微信圖片上傳介面可以將圖片壓縮成幾百K的大小,這對(duì)網(wǎng)站的效能是很有幫助的。

  一、我的想法是:

先呼叫「拍照或從手機(jī)相簿選擇圖片介面」—>選擇成功圖片後—>呼叫「上傳圖片介面」—>上傳成功後(也就是圖片上傳到了微信伺服器上)—>呼叫「下載圖片介面」—>將圖片下載到自己的伺服器儲(chǔ)存。

?

  二、JSSDK的使用步驟

  1、概述

  微信JS-SDK是微信公眾平臺(tái)為網(wǎng)頁開發(fā)者提供的基於微信內(nèi)的網(wǎng)頁開發(fā)工具包。

  透過使用微信JS-SDK,網(wǎng)頁開發(fā)者可藉助微信高效地使用拍照、選圖、語音、位置等手機(jī)系統(tǒng)的能力,同時(shí)可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,提供微信使用者更優(yōu)質(zhì)的網(wǎng)頁體驗(yàn)。

  2、使用步驟

  步驟一:綁定網(wǎng)域名稱

  先登入微信公眾平臺(tái)進(jìn)入「公眾號(hào)設(shè)定」的「功能設(shè)定」內(nèi)填寫「JS介面安全域名」。

  備註:登入後可在「開發(fā)者中心」查看對(duì)應(yīng)的介面權(quán)限。

  步驟二:引入JS檔案

  在需要呼叫JS介面的頁面引入如下JS文件,(支援https):http://res.wx.qq.com/open/js /jweixin-1.0.0.js

  步驟三:透過config介面注入權(quán)限驗(yàn)證設(shè)定

  所有需要使用JS-SDK的頁面必須先註入設(shè)定訊息,否則將無法呼叫(同一個(gè)url只需呼叫一次,對(duì)於變化url的SPA的web app可在每次url變化時(shí)進(jìn)行呼叫)

wx.config({
????debug:?true,?//?開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會(huì)通過log打出,僅在pc端時(shí)才會(huì)打印。
????appId:?'',?//?必填,公眾號(hào)的唯一標(biāo)識(shí)
????timestamp:?,?//?必填,生成簽名的時(shí)間戳
????nonceStr:?'',?//?必填,生成簽名的隨機(jī)串
????signature:?'',//?必填,簽名,見附錄1
????jsApiList:?[]?//?必填,需要使用的JS接口列表,所有JS接口列表見附錄2
});

  步驟四:透過ready介面處理成功驗(yàn)證

wx.ready(function(){

????//?config信息驗(yàn)證后會(huì)執(zhí)行ready方法,所有接口調(diào)用都必須在config接口獲得結(jié)果之后,config是一個(gè)客戶端的異步操作,所以如果需要在頁面加載時(shí)就調(diào)用相關(guān)接口,則須把相關(guān)接口放在ready函數(shù)中調(diào)用來確保正確執(zhí)行。對(duì)于用戶觸發(fā)時(shí)才調(diào)用的接口,則可以直接調(diào)用,不需要放在ready函數(shù)中。
});

  步驟五:透過error介面處理失敗驗(yàn)證

wx.error(function(res){

????//?config信息驗(yàn)證失敗會(huì)執(zhí)行error函數(shù),如簽名過期導(dǎo)致驗(yàn)證失敗,具體錯(cuò)誤信息可以打開config的debug模式查看,也可以在返回的res參數(shù)中查看,對(duì)于SPA可以在這里更新簽名。

});

  介面呼叫說明

  所有介面透過wx物件(也可使用jWeixin物件)來調(diào)用,參數(shù)是一個(gè)對(duì)象,除了每個(gè)介面本身需要傳的參數(shù)之外,還有以下通用參數(shù):

  1. success:介面呼叫成功時(shí)執(zhí)行的回呼函數(shù)。

  2. fail:介面呼叫失敗時(shí)執(zhí)行的回呼函數(shù)。

  3. complete:在介面呼叫完成時(shí)執(zhí)行的回呼函數(shù),無論成功或失敗都會(huì)執(zhí)行。

  4. cancel:使用者點(diǎn)擊取消時(shí)的回呼函數(shù),只有部分有使用者取消操作的api才會(huì)用到。

  5. trigger: 監(jiān)聽Menu中的按鈕點(diǎn)擊時(shí)觸發(fā)的方法,該方法僅支援Menu中的相關(guān)介面。

  備註:不要嘗試在trigger中使用ajax非同步要求修改本次分享的內(nèi)容,因?yàn)榭蛻舳朔窒聿僮魇且粋€(gè)同步操作,這時(shí)候使用ajax的回包會(huì)還沒有返回。


  以上幾個(gè)函數(shù)都帶有一個(gè)參數(shù),類型為對(duì)象,其中除了每個(gè)接口本身返回的資料之外,還有一個(gè)通用屬性errMsg,其值格式如下:

    1. 呼叫成功時(shí):"xxx:ok" ,其中xxx為呼叫的介面名稱

    2. 使用者取消時(shí):"xxx:cancel" ,其中xxx為呼叫的介面名稱

    3. 呼叫失敗時(shí):其值為具體錯(cuò)誤訊息

##  

#  三、開發(fā)及程式碼分析詳解(用的是CI框架,只要是MVC模式都可以)

  1、先在伺服器端取到:公眾號(hào)碼的唯一識(shí)別appId、產(chǎn)生簽章的時(shí)間戳timestamp 、產(chǎn)生簽名的隨機(jī)串nonceStr、簽名signature。

<?php
class wx_upload extends xx_Controller {
    public function __construct() {
        parent::__construct();
    }
 
    public function wxUploadImg() {
        //在模板里引入jssdk的js文件
        $this->addResLink('http://res.wx.qq.com/open/js/jweixin-1.0.0.js');
????????//取得:公眾號(hào)的唯一標(biāo)識(shí)appId、生成簽名的時(shí)間戳timestamp、生成簽名的隨機(jī)串nonceStr、簽名signature這些值,并以json形式傳到模板頁面
????????$this->smartyData['wxJsApi']?=?json_encode(array('signPackage'?=>?$this->model->weixin->signPackage()));
????}
###圖片上傳控制器###
<?php
    class WxModel extends ModelBase{
        public $appId;
        public $appSecret;
        public $token;

        public function __construct() {
            parent::__construct();

            //審核通過的移動(dòng)應(yīng)用所給的AppID和AppSecret
            $this->appId?=?'wx0000000000000000';
????????????$this->appSecret?=?'00000000000000000000000000000';
????????????$this->token?=?'00000000';
????????}

????????/**
?????????*?獲取jssdk所需參數(shù)的所有值
?????????*?@return?array
?????????*/
????????public?function?signPackage()?{
????????????$protocol?=?(!empty($_SERVER['HTTPS']?&&?$_SERVER['HTTPS']?==?'off'?||?$_SERVER['port']?==?443))???'https://'?:?'http://';
????????????//當(dāng)前網(wǎng)頁的URL
????????????$url?=?"$protocol$_SERVER['host']$_SERVER['REQUEST_URI']";
????????????//生成簽名的時(shí)間戳
????????????$timestamp?=?time();
????????????//生成簽名的隨機(jī)串
????????????$nonceStr?=?$this->createNonceStr();
????????????//獲取公眾號(hào)用于調(diào)用微信JS接口的臨時(shí)票據(jù)
????????????$jsApiTicket?=?$this->getJsApiTicket();
????????????//對(duì)所有待簽名參數(shù)按照字段名的ASCII?碼從小到大排序(字典序)后,
????????????//使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串$str。
????????????//這里需要注意的是所有參數(shù)名均為小寫字符
????????????$str?=?"jsapi_ticket=$jsApiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
????????????//對(duì)$str進(jìn)行sha1簽名,得到signature:
????????????$signature?=?sha1($str);
????????????$signPackage?=?array(
????????????????"appId"?????=>?$this->AppId,
????????????????"nonceStr"??=>?$nonceStr,
????????????????"timestamp"?=>?$timestamp,
????????????????"url"???????=>?$url,
????????????????"signature"?=>?$signature,
????????????????"rawString"?=>?$string
????????????????);
????????????return?$signPackage;
????????}

????????/**
?????????*?創(chuàng)建簽名的隨機(jī)字符串
?????????*?@param??int?$length?字符串長(zhǎng)度
?????????*?@return?string??????隨機(jī)字符串
?????????*/
????????private?function?createNonceStr($length?==?16)?{
????????????$chars?=?'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
????????????$str?=?'';
????????????for?($i=0;?$i?< $length; $i++) { 
                $str .= substr(mt_rand(0, strlen($chars)), 1);
            }
            return $str;
        }

        /**
         * 獲取公眾號(hào)用于調(diào)用微信JS接口的臨時(shí)票據(jù)
         * @return string 
         */
        private function getJsApiTicket() {
            //先查看redis里是否存了jsapi_ticket此值,假如有,就直接返回
            $jsApiTicket = $this->library->redisCache->get('weixin:ticket');
????????????if?(!$jsApiTicket)?{
????????????????//先獲取access_token(公眾號(hào)的全局唯一票據(jù))
????????????????$accessToken?=?$this->getApiToken();
????????????????//通過access_token?采用http?GET方式請(qǐng)求獲得jsapi_ticket
????????????????$result?=?$this->callApi("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$accessToken&type=jsapi");
????????????????//得到了jsapi_ticket
????????????????$jsApiTicket?=?$result['ticket'];
????????????????//將jsapi_ticket緩存到redis里面,下次就不用再請(qǐng)求去取了
????????????????$expire?=?max(1,?intval($result['expire'])?-?60);
????????????????$this->library->redisCache->set('weixin:ticket',?$jsApiTicket,?$expire);
????????????}
????????????return?$jsApiTicket;
????????}

????????/**
?????????*?獲取眾號(hào)的全局唯一票據(jù)access_token
?????????*?@param??boolean?$forceRefresh?是否強(qiáng)制刷新
?????????*?@return?string????????????????返回access_token
?????????*/
????????private?function?getApiToken($forceRefresh?=?false)?{
????????????//先查看redis是否存了accessToken,如果有了,就不用再去微信server去請(qǐng)求了(提高效率)
????????????$accessToken?=?$this->library->redisCache->get('weixin:accessToken');
????????????//強(qiáng)制刷新accessToken或者accessToken為空時(shí)就去請(qǐng)求accessToken
????????????if?($forceRefresh?||?empty($accessToken))?{
????????????????//請(qǐng)求得到accessToken
????????????????$result?=?$this->callApi("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}");
????????????????$accessToken?=?$result['access_token'];
????????????????$expire?=?max(1,?intval($result['expire'])?-?60);
????????????????//將其存進(jìn)redis里面去
????????????????$this->library->redisCache->set('weixin:accessToken',?$accessToken,?$expire);
????????????}
????????????return?$accessToken;
????????}
###取得到appId、nonceStr、timestamp、signature模型######  這裡要補(bǔ)充一些JS-SDK使用權(quán)限簽章演算法的想法與注意點(diǎn)(這裡我直接複製官網(wǎng)文件給大家看看)######    jsapi_ticket######    生成簽章之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號(hào)碼用於使用微信的簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號(hào)碼用於使用微信正常情況下,jsapi_ticket的有效期限為7,200秒,透過access_token來取得。由於取得jsapi_ticket的api呼叫次數(shù)非常有限,頻繁刷新jsapi_ticket會(huì)導(dǎo)致api呼叫受限,影響自身業(yè)務(wù),開發(fā)者必須在自己的服務(wù)全域快取jsapi_ticket?。 ######    1、獲取access_token(有效期7200秒,開發(fā)者必須在自己的服務(wù)全域快取access_token)######    2、用第一步拿到的access_token 採(cǎi)用http GET方式請(qǐng)求(jsapi_ticket有效期限7200秒,開發(fā)者必須在自己的服務(wù)全域快取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
}

    獲得jsapi_ticket之后,就可以生成JS-SDK權(quán)限驗(yàn)證的簽名了。

    

    簽名算法

    簽名生成規(guī)則如下:參與簽名的字段包括noncestr(隨機(jī)字符串), 有效的jsapi_ticket, timestamp(時(shí)間戳), url(當(dāng)前網(wǎng)頁的URL,不包含#及其后面部分) 。對(duì)所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串string1。這里需要注意的是所有參數(shù)名均為小寫字符。對(duì)string1作sha1加密,字段名和字段值都采用原始值,不進(jìn)行URL 轉(zhuǎn)義。
    即signature=sha1(string1)。 示例:


    • noncestr=Wm3WZYTPz0wzccnW

    • jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg

    • timestamp=1414587457

    • url=http://mp.weixin.qq.com?params=value

    步驟1. 對(duì)所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串string1:

      jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://ipnx.cn/

    步驟2. 對(duì)string1進(jìn)行sha1簽名,得到signature:

      0f9de62fce790f9a083d5c99e95740ceb90c27ed

    注意事項(xiàng)

      1.簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。

      2.簽名用的url必須是調(diào)用JS接口頁面的完整URL。

      3.出于安全考慮,開發(fā)者必須在服務(wù)器端實(shí)現(xiàn)簽名的邏輯。

?

?  2、取到我們所需要的值后,就在js文件里面開始使用了

  uploadImg.tpl

<script>
????????$(function(){
????????????$.util.wxMenuImage('{$wxJsApi|default:""}')
????????});
</script>

?  uploadImg.js

if(typeof($util)=='undefined')$util={};

$.util.wxMenuImage?=?function(json)?{
????if?(json.length?==?0)?return;?
????//解析json變成js對(duì)象
????wxJsApi?=?JSON.parse(json);

????//通過config接口注入權(quán)限驗(yàn)證配置
????wx.config({
????????debug:?false,???//開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來
????????appId:?wxJsApi.signPackage.appId,???//公眾號(hào)的唯一標(biāo)識(shí)
????????timestamp:?wxJsApi.signPackage.timestamp,???//生成簽名的時(shí)間戳
????????nonceStr:?wxJsApi.signPackage.nonceStr,?//生成簽名的隨機(jī)串
????????signature:?wxJsApi.signPackage.signature,???//簽名
????????jsApiList:?['chooseImage',?'uploadImage']???//需要使用的JS接口列表?這里我用了選擇圖片和上傳圖片接口
????});

????//通過ready接口處理成功驗(yàn)證,config信息驗(yàn)證后會(huì)執(zhí)行ready方法,所有接口調(diào)用都必須在config接口獲得結(jié)果之后
????wx.ready(function(){
????????//得到上傳圖片按鈕
????????document.querySelector('#uploadImage').onclick?=?function()?{
????????????var?images?=?{localId:[],serverId:[]};
????????????//調(diào)用?拍照或從手機(jī)相冊(cè)中選圖接口
????????????wx.chooseImage({
????????????????success:?function(res)?{
????????????????????if?(res.localIds.length?!=?1)?{
????????????????????????alert('只能上傳一張圖片');
????????????????????????return;
????????????????????}
????????????????????//返回選定照片的本地ID列表
????????????????????iamges.localId?=?res.localIds;
????????????????????images.serverId?=?[];
????????????????????//上傳圖片函數(shù)
????????????????????function?upload()?{
????????????????????????//調(diào)用上傳圖片接口
????????????????????????wx.uploadImage({
????????????????????????????localId:?images.localId[0],?//?需要上傳的圖片的本地ID,由chooseImage接口獲得
????????????????????????????isShowProcess:?1,???//?默認(rèn)為1,顯示進(jìn)度提示
????????????????????????????success:?function(res)?{
????????????????????????????????//返回圖片的服務(wù)器端ID?res.serverId,然后調(diào)用wxImgCallback函數(shù)進(jìn)行下載圖片操作
????????????????????????????????wxImgCallback(res.serverId);
????????????????????????????},
????????????????????????????fail:?function(res)?{
????????????????????????????????alert('上傳失敗');
????????????????????????????}
????????????????????????});
????????????????????}
????????????????????upload();
????????????????}
????????????});
????????}
????});
}


function?wxImgCallback(serverId)?{
????//將serverId傳給wx_upload.php的upload方法
????var?url?=?'wx_upload/upload/'+serverId;
????$.getJSON(url,?function(data){
????????if?(data.code?==?0)?{
????????????alert(data.msg);
????????}?else?if?(data.code?==?1)?{
????????????//存儲(chǔ)到服務(wù)器成功后的處理
????????????//
????????}
????});
}

圖片選擇和圖片上傳接口調(diào)用

圖片選擇和圖片上傳接口調(diào)用

?  

  3、圖片上傳完成后會(huì)返回一個(gè)serverId,然后通過這個(gè)來下載圖片到本地服務(wù)器

  這里先補(bǔ)充下如何調(diào)用下載圖片接口(我直接復(fù)制官方文檔的說明了)

    公眾號(hào)可調(diào)用本接口來獲取多媒體文件。請(qǐng)注意,視頻文件不支持下載,調(diào)用該接口需http協(xié)議。

    接口調(diào)用請(qǐng)求說明

    http請(qǐng)求方式:?GET
     http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID

    參數(shù)說明

參數(shù) 是否必須 說明
access_token 調(diào)用接口憑證
media_id 媒體文件ID

    返回說明

    正確情況下的返回HTTP頭如下:

      HTTP/1.1?200?OK
      Connection:?close
      Content-Type:?image/jpeg?
      Content-disposition:?attachment;?filename="MEDIA_ID.jpg"
      Date:?Sun,?06?Jan?2013?10:20:18?GMT
      Cache-Control:?no-cache,?must-revalidate
      Content-Length:?339721
      curl?-G?"http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"

    錯(cuò)誤情況下的返回JSON數(shù)據(jù)包示例如下(示例為無效媒體ID錯(cuò)誤)::

      {"errcode":40007,"errmsg":"invalid?media_id"}


 接下來看自己寫的代碼
 wx_upload.php
/*********************圖片下載到本地服務(wù)器****************************************/
????//從微信服務(wù)器讀取圖片,然后下載到本地服務(wù)器
????public?function?upload($media_id)?{
????????//圖片文件名
????????$fileName?=?md5($this->wxId."/$media_id");
????????//調(diào)用下載圖片接口,返回路徑
????????$path?=?$this->weixin->wxDownImg($media_id,?sys_get_temp_dir()."$fileName");
????????if?($path?!=?false)?{
????????????//將圖片的路徑插入數(shù)據(jù)庫(kù)去存儲(chǔ)
????????????if?($this->model->weixin->updateByWxid($this->wxId,?array('img_path'=>$path)))?{
????????????????$this->output->_display(json_encode(
????????????????????array(
????????????????????????????'code'=>1,
????????????????????????????'msg'=>'上傳成功',
????????????????????????????'fileUrl'?=>$path;
????????????????????????)
????????????????));
????????????}?else?{
????????????????$this->output->_display(json_encode2(array('code'=>0,'msg'?=>?'上傳失敗','err'=>'1')));
????????????}
????????}?else?{
????????????$this->output->_display(json_encode2(array('code'=>0,'msg'?=>?'上傳失敗','err'=>'2')));
????????}
????????
????}

從微信服務(wù)器下載圖片到本地存儲(chǔ)

//從微信服務(wù)器端下載圖片到本地服務(wù)器
????????public?function?wxDownImg($media_id,?$path)?{
????????????//調(diào)用?多媒體文件下載接口
????????????$url?=?"https://api.weixin.qq.com/cgi-bin/media/get?access_token={$this->model->weixin->_getApiToken()}&media_id=$media_id";
????????????//用curl請(qǐng)求,返回文件資源和curl句柄的信息
????????????$info?=?$this->curl_request($url);
????????????//文件類型
????????????$types?=?array('image/bmp'=>'.bmp',?'image/gif'=>'.gif',?'image/jpeg'=>'.jpg',?'image/png'=>'.png');
????????????//判斷響應(yīng)首部里的的content-type的值是否是這四種圖片類型
????????????if?(isset($types[$info['header']['content_type']]))?{
????????????????//文件的uri
????????????????$path?=?$path.$types[$info['header']['content_type']];
????????????}?else?{
????????????????return?false;
????????????}

????????????//將資源寫入文件里
????????????if?($this->saveFile($path,?$info['body']))?{
????????????????//將文件保存在本地目錄
????????????????$imgPath?=?rtrim(base_url(),?'/').'/img'.date('Ymd').'/'.md5($this->controller->wxId.$media_id).$types[$info['header'['content_type']]];
????????????????if?(!is_dir($imgPath))?{
????????????????????if(mkdir($imgPath))?{
????????????????????????if?(false?!==?rename($path,?$imgPath)?{
????????????????????????????return?$imgPath;
????????????????????????}
????????????????????}
????????????????}
????????????????return?$path;
????????????}

????????????return?false;

????????}

????????/**
?????????*?curl請(qǐng)求資源
?????????*?@param??string?$url?請(qǐng)求url
?????????*?@return?array?
?????????*/
????????private?function?curl_request($url?=?'')?{
????????????if?($url?==?'')?return;
????????????$ch?=?curl_init();
????????????//這里返回響應(yīng)報(bào)文時(shí),只要body的內(nèi)容,其他的都不要
????????????curl_setopt($ch,?CURLOPT_HEADER,?0);
????????????curl_setopt($ch,?CURLOPT_NOBODY,?0);
????????????curl_setopt($ch,?CURLOPT_SSL_VERIFYPEER,?false);
????????????curl_setopt($ch,?CURLOPT_SSL_VERIFYHOST,?false);
????????????curl_setopt($ch,?CURLOPT_RETURNTRANSFER,?1);
????????????$package?=?curl_exec($ch);
????????????//獲取curl連接句柄的信息
????????????$httpInfo?=?curl_getinfo($ch);
????????????curl_close($ch);

????????????$info?=?array_merge(array($package),?array($httpInfo));

????????????return?$info;

????????}

????????/**
?????????*?將資源寫入文件
?????????*?@param??string?資源uri
?????????*?@param??source?資源
?????????*?@return?boolean?
?????????*/
????????private?function?saveFile($path,?$fileContent)?{
????????????$fp?=?fopen($path,?'w');
????????????if?(false?!==?$localFile)?{
????????????????if?(false?!==?fwrite($fp,?$fileContent))?{
????????????????????fclose($fp);
????????????????????return?true;
????????????????}
????????????}
????????????return?false;
????????}

從微信服務(wù)器下載圖片到本地存儲(chǔ)接口

  到這里,已經(jīng)完成了:

    先調(diào)用“拍照或從手機(jī)相冊(cè)選擇圖片接口”—>選擇成功圖片后—>調(diào)用“上傳圖片接口”—>上傳成功后(也就是圖片上傳到了微信服務(wù)器上)—>調(diào)用“下載圖片接口”—>將圖片下載到自己的服務(wù)器存儲(chǔ)。

  這一思路的實(shí)現(xiàn)。我們用到了微信的選擇圖片接口、上傳圖片接口和下載媒體資源接口。

  下面我附上這一接口開發(fā)的全部代碼:

<?php
class wx_upload extends xx_Controller {
    public function __construct() {
        parent::__construct();
    }
 
    public function wxUploadImg() {
        //在模板里引入jssdk的js文件
        $this->addResLink('http://res.wx.qq.com/open/js/jweixin-1.0.0.js');
????????//取得:公眾號(hào)的唯一標(biāo)識(shí)appId、生成簽名的時(shí)間戳timestamp、生成簽名的隨機(jī)串nonceStr、簽名signature這些值,并以json形式傳到模板頁面
????????$this->smartyData['wxJsApi']?=?json_encode(array('signPackage'?=>?$this->model->weixin->signPackage()));
????}

????/*********************圖片下載到本地服務(wù)器****************************************/
????//從微信服務(wù)器讀取圖片,然后下載到本地服務(wù)器
????public?function?upload($media_id)?{
????????//圖片文件名
????????$fileName?=?md5($this->wxId."/$media_id");
????????//調(diào)用下載圖片接口,返回路徑
????????$path?=?$this->weixin->wxDownImg($media_id,?sys_get_temp_dir()."$fileName");
????????if?($path?!=?false)?{
????????????//將圖片的路徑插入數(shù)據(jù)庫(kù)去存儲(chǔ)
????????????if?($this->model->weixin->updateByWxid($this->wxId,?array('img_path'=>$path)))?{
????????????????$this->output->_display(json_encode(
????????????????????array(
????????????????????????????'code'=>1,
????????????????????????????'msg'=>'上傳成功',
????????????????????????????'fileUrl'?=>$path;
????????????????????????)
????????????????));
????????????}?else?{
????????????????$this->output->_display(json_encode2(array('code'=>0,'msg'?=>?'上傳失敗','err'=>'1')));
????????????}
????????}?else?{
????????????$this->output->_display(json_encode2(array('code'=>0,'msg'?=>?'上傳失敗','err'=>'2')));
????????}
????????
????}
}



?>
<?php
    class WxModel extends ModelBase{
        public $appId;
        public $appSecret;
        public $token;

        public function __construct() {
            parent::__construct();

            //審核通過的移動(dòng)應(yīng)用所給的AppID和AppSecret
            $this->appId?=?'wx0000000000000000';
????????????$this->appSecret?=?'00000000000000000000000000000';
????????????$this->token?=?'00000000';
????????}

????????/**
?????????*?獲取jssdk所需參數(shù)的所有值
?????????*?@return?array
?????????*/
????????public?function?signPackage()?{
????????????$protocol?=?(!empty($_SERVER['HTTPS']?&&?$_SERVER['HTTPS']?==?'off'?||?$_SERVER['port']?==?443))???'https://'?:?'http://';
????????????//當(dāng)前網(wǎng)頁的URL
????????????$url?=?"$protocol$_SERVER['host']$_SERVER['REQUEST_URI']";
????????????//生成簽名的時(shí)間戳
????????????$timestamp?=?time();
????????????//生成簽名的隨機(jī)串
????????????$nonceStr?=?$this->createNonceStr();
????????????//獲取公眾號(hào)用于調(diào)用微信JS接口的臨時(shí)票據(jù)
????????????$jsApiTicket?=?$this->getJsApiTicket();
????????????//對(duì)所有待簽名參數(shù)按照字段名的ASCII?碼從小到大排序(字典序)后,
????????????//使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串$str。
????????????//這里需要注意的是所有參數(shù)名均為小寫字符
????????????$str?=?"jsapi_ticket=$jsApiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
????????????//對(duì)$str進(jìn)行sha1簽名,得到signature:
????????????$signature?=?sha1($str);
????????????$signPackage?=?array(
????????????????"appId"?????=>?$this->AppId,
????????????????"nonceStr"??=>?$nonceStr,
????????????????"timestamp"?=>?$timestamp,
????????????????"url"???????=>?$url,
????????????????"signature"?=>?$signature,
????????????????"rawString"?=>?$string
????????????????);
????????????return?$signPackage;
????????}

????????/**
?????????*?創(chuàng)建簽名的隨機(jī)字符串
?????????*?@param??int?$length?字符串長(zhǎng)度
?????????*?@return?string??????隨機(jī)字符串
?????????*/
????????private?function?createNonceStr($length?==?16)?{
????????????$chars?=?'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
????????????$str?=?'';
????????????for?($i=0;?$i?< $length; $i++) { 
                $str .= substr(mt_rand(0, strlen($chars)), 1);
            }
            return $str;
        }

        /**
         * 獲取公眾號(hào)用于調(diào)用微信JS接口的臨時(shí)票據(jù)
         * @return string 
         */
        private function getJsApiTicket() {
            //先查看redis里是否存了jsapi_ticket此值,假如有,就直接返回
            $jsApiTicket = $this->library->redisCache->get('weixin:ticket');
????????????if?(!$jsApiTicket)?{
????????????????//先獲取access_token(公眾號(hào)的全局唯一票據(jù))
????????????????$accessToken?=?$this->getApiToken();
????????????????//通過access_token?采用http?GET方式請(qǐng)求獲得jsapi_ticket
????????????????$result?=?$this->callApi("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$accessToken&type=jsapi");
????????????????//得到了jsapi_ticket
????????????????$jsApiTicket?=?$result['ticket'];
????????????????//將jsapi_ticket緩存到redis里面,下次就不用再請(qǐng)求去取了
????????????????$expire?=?max(1,?intval($result['expire'])?-?60);
????????????????$this->library->redisCache->set('weixin:ticket',?$jsApiTicket,?$expire);
????????????}
????????????return?$jsApiTicket;
????????}

????????/**
?????????*?獲取眾號(hào)的全局唯一票據(jù)access_token
?????????*?@param??boolean?$forceRefresh?是否強(qiáng)制刷新
?????????*?@return?string????????????????返回access_token
?????????*/
????????private?function?getApiToken($forceRefresh?=?false)?{
????????????//先查看redis是否存了accessToken,如果有了,就不用再去微信server去請(qǐng)求了(提高效率)
????????????$accessToken?=?$this->library->redisCache->get('weixin:accessToken');
????????????//強(qiáng)制刷新accessToken或者accessToken為空時(shí)就去請(qǐng)求accessToken
????????????if?($forceRefresh?||?empty($accessToken))?{
????????????????//請(qǐng)求得到accessToken
????????????????$result?=?$this->callApi("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}");
????????????????$accessToken?=?$result['access_token'];
????????????????$expire?=?max(1,?intval($result['expire'])?-?60);
????????????????//將其存進(jìn)redis里面去
????????????????$this->library->redisCache->set('weixin:accessToken',?$accessToken,?$expire);
????????????}
????????????return?$accessToken;
????????}

????????//從微信服務(wù)器端下載圖片到本地服務(wù)器
????????public?function?wxDownImg($media_id,?$path)?{
????????????//調(diào)用?多媒體文件下載接口
????????????$url?=?"https://api.weixin.qq.com/cgi-bin/media/get?access_token={$this->model->weixin->_getApiToken()}&media_id=$media_id";
????????????//用curl請(qǐng)求,返回文件資源和curl句柄的信息
????????????$info?=?$this->curl_request($url);
????????????//文件類型
????????????$types?=?array('image/bmp'=>'.bmp',?'image/gif'=>'.gif',?'image/jpeg'=>'.jpg',?'image/png'=>'.png');
????????????//判斷響應(yīng)首部里的的content-type的值是否是這四種圖片類型
????????????if?(isset($types[$info['header']['content_type']]))?{
????????????????//文件的uri
????????????????$path?=?$path.$types[$info['header']['content_type']];
????????????}?else?{
????????????????return?false;
????????????}

????????????//將資源寫入文件里
????????????if?($this->saveFile($path,?$info['body']))?{
????????????????//將文件保存在本地目錄
????????????????$imgPath?=?rtrim(base_url(),?'/').'/img'.date('Ymd').'/'.md5($this->controller->wxId.$media_id).$types[$info['header'['content_type']]];
????????????????if?(!is_dir($imgPath))?{
????????????????????if(mkdir($imgPath))?{
????????????????????????if?(false?!==?rename($path,?$imgPath)?{
????????????????????????????return?$imgPath;
????????????????????????}
????????????????????}
????????????????}
????????????????return?$path;
????????????}

????????????return?false;

????????}

????????/**
?????????*?curl請(qǐng)求資源
?????????*?@param??string?$url?請(qǐng)求url
?????????*?@return?array?
?????????*/
????????private?function?curl_request($url?=?'')?{
????????????if?($url?==?'')?return;
????????????$ch?=?curl_init();
????????????//這里返回響應(yīng)報(bào)文時(shí),只要body的內(nèi)容,其他的都不要
????????????curl_setopt($ch,?CURLOPT_HEADER,?0);
????????????curl_setopt($ch,?CURLOPT_NOBODY,?0);
????????????curl_setopt($ch,?CURLOPT_SSL_VERIFYPEER,?false);
????????????curl_setopt($ch,?CURLOPT_SSL_VERIFYHOST,?false);
????????????curl_setopt($ch,?CURLOPT_RETURNTRANSFER,?1);
????????????$package?=?curl_exec($ch);
????????????//獲取curl連接句柄的信息
????????????$httpInfo?=?curl_getinfo($ch);
????????????curl_close($ch);

????????????$info?=?array_merge(array($package),?array($httpInfo));

????????????return?$info;

????????}

????????/**
?????????*?將資源寫入文件
?????????*?@param??string?資源uri
?????????*?@param??source?資源
?????????*?@return?boolean?
?????????*/
????????private?function?saveFile($path,?$fileContent)?{
????????????$fp?=?fopen($path,?'w');
????????????if?(false?!==?$localFile)?{
????????????????if?(false?!==?fwrite($fp,?$fileContent))?{
????????????????????fclose($fp);
????????????????????return?true;
????????????????}
????????????}
????????????return?false;
????????}

????}


?>
<html>
????<head>
????????
????</head>
????<body>
????????<button id="uploadImage">點(diǎn)擊上傳圖片</button>
????????<script>
????????$(function(){
????????????$.util.wxMenuImage('{$wxJsApi|default:""}')
????????});
????????</script>
????</body>
</html>
if(typeof($util)=='undefined')$util={};

$.util.wxMenuImage?=?function(json)?{
????if?(json.length?==?0)?return;?
????//解析json變成js對(duì)象
????wxJsApi?=?JSON.parse(json);

????//通過config接口注入權(quán)限驗(yàn)證配置
????wx.config({
????????debug:?false,???//開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來
????????appId:?wxJsApi.signPackage.appId,???//公眾號(hào)的唯一標(biāo)識(shí)
????????timestamp:?wxJsApi.signPackage.timestamp,???//生成簽名的時(shí)間戳
????????nonceStr:?wxJsApi.signPackage.nonceStr,?//生成簽名的隨機(jī)串
????????signature:?wxJsApi.signPackage.signature,???//簽名
????????jsApiList:?['chooseImage',?'uploadImage']???//需要使用的JS接口列表?這里我用了選擇圖片和上傳圖片接口
????});

????//通過ready接口處理成功驗(yàn)證,config信息驗(yàn)證后會(huì)執(zhí)行ready方法,所有接口調(diào)用都必須在config接口獲得結(jié)果之后
????wx.ready(function(){
????????//得到上傳圖片按鈕
????????document.querySelector('#uploadImage').onclick?=?function()?{
????????????var?images?=?{localId:[],serverId:[]};
????????????//調(diào)用?拍照或從手機(jī)相冊(cè)中選圖接口
????????????wx.chooseImage({
????????????????success:?function(res)?{
????????????????????if?(res.localIds.length?!=?1)?{
????????????????????????alert('只能上傳一張圖片');
????????????????????????return;
????????????????????}
????????????????????//返回選定照片的本地ID列表
????????????????????iamges.localId?=?res.localIds;
????????????????????images.serverId?=?[];
????????????????????//上傳圖片函數(shù)
????????????????????function?upload()?{
????????????????????????//調(diào)用上傳圖片接口
????????????????????????wx.uploadImage({
????????????????????????????localId:?images.localId[0],?//?需要上傳的圖片的本地ID,由chooseImage接口獲得
????????????????????????????isShowProcess:?1,???//?默認(rèn)為1,顯示進(jìn)度提示
????????????????????????????success:?function(res)?{
????????????????????????????????//返回圖片的服務(wù)器端ID?res.serverId,然后調(diào)用wxImgCallback函數(shù)進(jìn)行下載圖片操作
????????????????????????????????wxImgCallback(res.serverId);
????????????????????????????},
????????????????????????????fail:?function(res)?{
????????????????????????????????alert('上傳失敗');
????????????????????????????}
????????????????????????});
????????????????????}
????????????????????upload();
????????????????}
????????????});
????????}
????});
}


function?wxImgCallback(serverId)?{
????//將serverId傳給wx_upload.php的upload方法
????var?url?=?'wx_upload/upload/'+serverId;
????$.getJSON(url,?function(data){
????????if?(data.code?==?0)?{
????????????alert(data.msg);
????????}?else?if?(data.code?==?1)?{
????????????//存儲(chǔ)到服務(wù)器成功后的處理
????????????//
????????}
????});
}

本次講解就到此,這篇博文是給對(duì)微信接口開發(fā)有興趣的朋友參考,如果你是高手,完全可以繞道。

?更多微信JS-SDK之圖像接口開發(fā)相關(guān)文章請(qǐng)關(guān)注PHP中文網(wǎng)!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
PHP微信開發(fā):如何實(shí)作訊息加密解密 PHP微信開發(fā):如何實(shí)作訊息加密解密 May 13, 2023 am 11:40 AM

PHP是一種開源的腳本語言,廣泛應(yīng)用於網(wǎng)頁開發(fā)和伺服器端編程,尤其在微信開發(fā)中得到了廣泛的應(yīng)用。如今,越來越多的企業(yè)和開發(fā)者開始使用PHP進(jìn)行微信開發(fā),因?yàn)樗蔀榱苏嬲囊讓W(xué)易用的開發(fā)語言。在微信開發(fā)中,訊息的加密和解密是一個(gè)非常重要的問題,因?yàn)樗鼈兩婕百Y料的安全性。對(duì)於沒有加密和解密方式的消息,駭客可以輕鬆取得其中的數(shù)據(jù),對(duì)用戶造成威脅

PHP微信開發(fā):如何實(shí)現(xiàn)投票功能 PHP微信開發(fā):如何實(shí)現(xiàn)投票功能 May 14, 2023 am 11:21 AM

在微信公眾號(hào)開發(fā)中,投票功能經(jīng)常被運(yùn)用。投票功能是讓使用者快速參與互動(dòng)的好方式,也是舉辦活動(dòng)和調(diào)查意見的重要工具。本文將為您介紹如何使用PHP實(shí)作微信投票功能。在取得微信公眾號(hào)授權(quán)首先,你需要取得微信公眾號(hào)的授權(quán)。在微信公眾平臺(tái)上,你需要設(shè)定微信公眾號(hào)碼的api地址、官方帳號(hào)和公眾號(hào)碼對(duì)應(yīng)的token。在我們使用PHP語言開發(fā)的過程中,我們需要使用微信官方提供的PH

用PHP開發(fā)微信群發(fā)工具 用PHP開發(fā)微信群發(fā)工具 May 13, 2023 pm 05:00 PM

隨著微信的普及,越來越多的企業(yè)開始將其作為行銷工具。而微信群發(fā)功能,則是企業(yè)進(jìn)行微信行銷的重要手段之一。但是,如果只依靠手動(dòng)發(fā)送,對(duì)於行銷人員來說是一件極為費(fèi)時(shí)費(fèi)力的工作。所以,開發(fā)一款微信群發(fā)工具就顯得格外重要。本文將介紹如何使用PHP開發(fā)微信群發(fā)工具。一、準(zhǔn)備工作開發(fā)微信群發(fā)工具,我們需要掌握以下幾個(gè)技術(shù)點(diǎn):PHP基礎(chǔ)知識(shí)微信公眾平臺(tái)開發(fā)開發(fā)工具:Sub

PHP微信開發(fā):如何實(shí)現(xiàn)客服聊天視窗管理 PHP微信開發(fā):如何實(shí)現(xiàn)客服聊天視窗管理 May 13, 2023 pm 05:51 PM

微信是目前全球用戶規(guī)模最大的社群平臺(tái)之一,隨著行動(dòng)網(wǎng)路的普及,越來越多的企業(yè)開始意識(shí)到微信行銷的重要性。在進(jìn)行微信行銷時(shí),客服服務(wù)是至關(guān)重要的一環(huán)。為了更好地管理客服聊天窗口,我們可以藉助PHP語言進(jìn)行微信開發(fā)。一、PHP微信開發(fā)簡(jiǎn)介PHP是一種開源的伺服器端腳本語言,廣泛用於Web開發(fā)領(lǐng)域。結(jié)合微信公眾平臺(tái)提供的開發(fā)接口,我們可以使用PHP語言進(jìn)行微信

PHP微信開發(fā):如何實(shí)現(xiàn)使用者標(biāo)籤管理 PHP微信開發(fā):如何實(shí)現(xiàn)使用者標(biāo)籤管理 May 13, 2023 pm 04:31 PM

在微信公眾號(hào)開發(fā)中,使用者標(biāo)籤管理是一個(gè)非常重要的功能,可以讓開發(fā)者更了解和管理自己的使用者。本篇文章將介紹如何使用PHP實(shí)作微信使用者標(biāo)籤管理功能。一、取得微信用戶openid在使用微信用戶標(biāo)籤管理功能之前,我們首先需要取得用戶的openid。在微信公眾號(hào)開發(fā)中,透過使用者授權(quán)的方式取得openid是比較常見的做法。在使用者授權(quán)完成後,我們可以透過以下程式碼取得用

PHP微信開發(fā):如何實(shí)作群發(fā)訊息傳送記錄 PHP微信開發(fā):如何實(shí)作群發(fā)訊息傳送記錄 May 13, 2023 pm 04:31 PM

隨著微信成為了人們生活中越來越重要的通訊工具,其敏捷的訊息傳遞功能迅速受到廣大企業(yè)和個(gè)人的青睞。對(duì)企業(yè)而言,將微信發(fā)展為一個(gè)行銷平臺(tái)已經(jīng)成為趨勢(shì),而微信開發(fā)的重要性也逐漸凸顯。在其中,群發(fā)功能更是被廣泛使用,那麼,作為PHP程式設(shè)計(jì)師,如何實(shí)現(xiàn)群發(fā)訊息發(fā)送記錄呢?以下將為大家簡(jiǎn)單介紹一下。 1.了解微信公眾號(hào)相關(guān)開發(fā)知識(shí)在了解如何實(shí)現(xiàn)群發(fā)訊息發(fā)送記錄之前,我

使用PHP實(shí)現(xiàn)微信公眾號(hào)開發(fā)的步驟 使用PHP實(shí)現(xiàn)微信公眾號(hào)開發(fā)的步驟 Jun 27, 2023 pm 12:26 PM

如何使用PHP實(shí)現(xiàn)微信公眾號(hào)開發(fā)微信公眾號(hào)已經(jīng)成為了許多企業(yè)推廣和互動(dòng)的重要管道,而PHP作為常用的Web語言,也可以用來進(jìn)行微信公眾號(hào)的開發(fā)。本文將介紹使用PHP實(shí)現(xiàn)微信公眾號(hào)開發(fā)的具體步驟。第一步:取得微信公眾號(hào)的開發(fā)者帳號(hào)在開始微信公眾號(hào)開發(fā)之前,需要先去申請(qǐng)一個(gè)微信公眾號(hào)的開發(fā)者帳號(hào)。具體的註冊(cè)流程可參考微信公眾平臺(tái)的官方網(wǎng)

如何使用PHP進(jìn)行微信開發(fā)? 如何使用PHP進(jìn)行微信開發(fā)? May 21, 2023 am 08:37 AM

隨著網(wǎng)路和行動(dòng)智慧型裝置的發(fā)展,微信成為了社交和行銷領(lǐng)域不可或缺的一部分。在這個(gè)越來越數(shù)位化的時(shí)代,如何使用PHP進(jìn)行微信開發(fā)已經(jīng)成為了許多開發(fā)者的關(guān)注點(diǎn)。本文主要介紹如何使用PHP進(jìn)行微信發(fā)展的相關(guān)知識(shí)點(diǎn),以及其中的一些技巧和注意事項(xiàng)。一、開發(fā)環(huán)境準(zhǔn)備在進(jìn)行微信開發(fā)之前,首先需要準(zhǔn)備好對(duì)應(yīng)的開發(fā)環(huán)境。具體來說,需要安裝PHP的運(yùn)作環(huán)境,以及微信公眾平臺(tái)提

See all articles