溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

微信JS-SDK之圖像接口開發(fā)的示例分析

發(fā)布時(shí)間:2021-09-10 10:17:45 來(lái)源:億速云 閱讀:121 作者:小新 欄目:移動(dòng)開發(fā)

這篇文章主要為大家展示了“微信JS-SDK之圖像接口開發(fā)的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“微信JS-SDK之圖像接口開發(fā)的示例分析”這篇文章吧。

  一、我的思路是:

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

  二、JSSDK的使用步驟

  1、概述 

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

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

  2、使用步驟

  步驟一:綁定域名

  先登錄微信公眾平臺(tái)進(jìn)入“公眾號(hào)設(shè)置”的“功能設(shè)置”里填寫“JS接口安全域名”。

  備注:登錄后可在“開發(fā)者中心”查看對(duì)應(yīng)的接口權(quán)限。

  步驟二:引入JS文件

  在需要調(diào)用JS接口的頁(yè)面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js

  步驟三:通過(guò)config接口注入權(quán)限驗(yàn)證配置

  所有需要使用JS-SDK的頁(yè)面必須先注入配置信息,否則將無(wú)法調(diào)用(同一個(gè)url僅需調(diào)用一次,對(duì)于變化url的SPA的web app可在每次url變化時(shí)進(jìn)行調(diào)用)

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

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

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

});

  接口調(diào)用說(shuō)明

  所有接口通過(guò)wx對(duì)象(也可使用jWeixin對(duì)象)來(lái)調(diào)用,參數(shù)是一個(gè)對(duì)象,除了每個(gè)接口本身需要傳的參數(shù)之外,還有以下通用參數(shù):

  1. success:接口調(diào)用成功時(shí)執(zhí)行的回調(diào)函數(shù)。

  2. fail:接口調(diào)用失敗時(shí)執(zhí)行的回調(diào)函數(shù)。

  3. complete:接口調(diào)用完成時(shí)執(zhí)行的回調(diào)函數(shù),無(wú)論成功或失敗都會(huì)執(zhí)行。

  4. cancel:用戶點(diǎn)擊取消時(shí)的回調(diào)函數(shù),僅部分有用戶取消操作的api才會(huì)用到。

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

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


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

    1. 調(diào)用成功時(shí):"xxx:ok" ,其中xxx為調(diào)用的接口名

    2. 用戶取消時(shí):"xxx:cancel",其中xxx為調(diào)用的接口名

    3. 調(diào)用失敗時(shí):其值為具體錯(cuò)誤信息

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

  1、先在服務(wù)器端取到:公眾號(hào)的唯一標(biāo)識(shí)appId、生成簽名的時(shí)間戳timestamp、生成簽名的隨機(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形式傳到模板頁(yè)面
        $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();

            //審核通過(guò)的移動(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)頁(yè)的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();
                //通過(guò)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)(這里我直接復(fù)制官網(wǎng)文檔給大家看看)

    jsapi_ticket

    生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號(hào)用于調(diào)用微信JS接口的臨時(shí)票據(jù)。正常情況下,jsapi_ticket的有效期為7200秒,通過(guò)access_token來(lái)獲取。由于獲取jsapi_ticket的api調(diào)用次數(shù)非常有限,頻繁刷新jsapi_ticket會(huì)導(dǎo)致api調(diào)用受限,影響自身業(yè)務(wù),開發(fā)者必須在自己的服務(wù)全局緩存jsapi_ticket 。

    1、獲取access_token(有效期7200秒,開發(fā)者必須在自己的服務(wù)全局緩存access_token)

    2、用第一步拿到的access_token 采用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)頁(yè)的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://www.php.cn/

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

      0f9de62fce790f9a083d5c99e95740ceb90c27ed

    注意事項(xiàng)

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

      2.簽名用的url必須是調(diào)用JS接口頁(yè)面的完整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);

    //通過(guò)config接口注入權(quán)限驗(yàn)證配置
    wx.config({
        debug: false,   //開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái)
        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接口列表 這里我用了選擇圖片和上傳圖片接口
    });

    //通過(guò)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,然后通過(guò)這個(gè)來(lái)下載圖片到本地服務(wù)器

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

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

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

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

    參數(shù)說(shuō)明

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

    返回說(shuō)明

    正確情況下的返回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ù)包示例如下(示例為無(wú)效媒體ID錯(cuò)誤)::

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


 接下來(lái)看自己寫的代碼
 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://cache.yisu.com/upload/information/20201208/260/13216', '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形式傳到模板頁(yè)面
        $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();

            //審核通過(guò)的移動(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)頁(yè)的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();
                //通過(guò)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://cache.yisu.com/upload/information/20201208/260/13216', '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);

    //通過(guò)config接口注入權(quán)限驗(yàn)證配置
    wx.config({
        debug: false,   //開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái)
        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接口列表 這里我用了選擇圖片和上傳圖片接口
    });

    //通過(guò)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ù)器成功后的處理
            //
        }
    });
}

以上是“微信JS-SDK之圖像接口開發(fā)的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI