찾다
위챗 애플릿위챗 개발WeChat JS-SDK 이미지 인터페이스 개발

WeChat JS-SDK 이미지 인터페이스 개발

Mar 01, 2017 am 09:29 AM
위챗 개발

여기서는 WeChat JSSDK의 이미지 인터페이스를 사용하여 이미지 업로드 기능을 구현하도록 개발했습니다. 왜 이 인터페이스를 선택했나요? 첫째, 현재 프로젝트는 WeChat에서 열리는 웹페이지입니다. 결국에는 WeChat 자체의 성능이 향상됩니다. 둘째, 이 인터페이스를 사용하면 개발 효율성이 높아집니다. 중요한 점은 이미지를 압축할 수 있다는 점입니다. 예를 들어 2M 이미지를 사용하면 WeChat 이미지 업로드 인터페이스를 통해 이미지를 수백 K 크기로 압축할 수 있어 웹사이트 성능에 매우 도움이 됩니다.

1. 내 아이디어는 다음과 같습니다.

먼저 "사진 또는 휴대폰 앨범 인터페이스에서 사진 선택"을 호출합니다. -> 성공한 사진을 선택한 후 -> 인터페이스' -> 업로드가 성공한 후(즉, 이미지가 WeChat 서버에 업로드됨) -> "이미지 다운로드 인터페이스" 호출 -> 저장을 위해 이미지를 자체 서버에 다운로드합니다.

2. JSSDK 사용 단계

1. 개요

WeChat JS-SDK는 WeChat 웹 기반의 웹 개발자를 위해 WeChat 공개 플랫폼에서 제공됩니다. 개발 툴킷.

WeChat JS-SDK를 사용하면 웹 개발자는 WeChat을 사용하여 사진 촬영, 사진 선택, 음성 선택, 위치 등 휴대폰 시스템의 기능을 효율적으로 사용하는 동시에 WeChat을 직접 사용할 수 있습니다. 공유, 스캔, 쿠폰 등. 결제와 같은 WeChat의 고유한 기능은 WeChat 사용자에게 더 나은 웹 경험을 제공합니다.

2. 사용 단계

1단계: 도메인 이름 바인딩

먼저 WeChat 공개 플랫폼에 로그인하고 "공식 계정 설정"의 "기능 설정"으로 들어갑니다. "JS 인터페이스 보안" 도메인 이름을 입력합니다.

참고: 로그인 후 "개발자 센터"에서 해당 인터페이스 권한을 확인할 수 있습니다.

2단계: JS 파일 소개

JS 인터페이스를 호출해야 하는 페이지에 다음 JS 파일을 소개합니다(https 지원): http://res.wx.qq.com /open/js /jweixin-1.0.0.js

3단계: 구성 인터페이스를 통해 권한 확인 구성 주입

JS-SDK를 사용해야 하는 모든 페이지는 먼저 구성 정보를 주입해야 하며, 그렇지 않으면 호출되지 않습니다. (URL은 한 번만 호출하면 되고 URL이 변경될 때마다 URL을 변경하는 SPA 웹 앱을 호출할 수 있는 것과 같습니다.)

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

4단계: 다음을 통해 성공적인 확인을 처리합니다. 준비된 인터페이스

wx.ready(function(){

    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});

5단계: 오류 인터페이스를 통해 실패한 검증 처리

wx.error(function(res){

    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。

});

인터페이스 호출 지침

모든 인터페이스는 wx 개체를 통해 호출됩니다(jWeixin 개체도 사용할 수 있음). , 매개변수는 객체입니다. 단, 각 인터페이스 자체는 전달되어야 합니다. 매개변수 외에도 다음과 같은 일반 매개변수가 있습니다.

  1. success: 콜백 함수가 실행될 때 실행됩니다. 인터페이스 호출이 성공했습니다.

  2. fail: 인터페이스 호출이 실패했을 때 실행되는 콜백 함수입니다.

  3. 완료: 성공, 실패에 관계없이 인터페이스 호출이 완료되면 실행되는 콜백 함수입니다.

  4. cancel: 사용자가 취소를 클릭할 때의 콜백 함수는 사용자가 작업을 취소하는 경우에만 사용됩니다.

  5. trigger: 메뉴의 버튼을 클릭했을 때 실행되는 메서드입니다. 이 메서드는 메뉴의 관련 인터페이스만 지원합니다.

참고: 이 공유의 콘텐츠를 수정하기 위해 트리거에서 ajax 비동기 요청을 사용하지 마십시오. 클라이언트 공유 작업은 동기 작업이고 ajax를 사용하는 반환 패킷은 지금은 돌아올 수 없습니다.


위 함수에는 모두 객체 유형의 매개변수가 있습니다. 각 인터페이스 자체에서 반환되는 데이터 외에도 값 형식이 다음과 같은 일반 속성 errMsg도 있습니다.

    1. 호출이 성공한 경우: "xxx:ok", 여기서 xxx는 호출된 인터페이스 이름입니다.

    2. 사용자가 취소한 경우: "xxx: cancel" , 여기서 xxx는 호출된 인터페이스의 이름입니다.

    3. 호출이 실패하는 경우: 해당 값은 특정 오류 메시지입니다

 

3. 개발 및 코드 분석에 대한 자세한 설명(CI 프레임워크 사용, MVC 모드인 경우)

1. 먼저 서버측에서 획득: 고유 식별자 appId 공식 계정과 생성된 서명의 타임스탬프를 사용하여 서명된 임의 문자열 nonceStr 및 서명 서명을 생성합니다.

<?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');
        //取得:公众号的唯一标识appId、生成签名的时间戳timestamp、生成签名的随机串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();

            //审核通过的移动应用所给的AppID和AppSecret
            $this->appId = 'wx0000000000000000';
            $this->appSecret = '00000000000000000000000000000';
            $this->token = '00000000';
        }

        /**
         * 获取jssdk所需参数的所有值
         * @return array
         */
        public function signPackage() {
            $protocol = (!empty($_SERVER['HTTPS'] && $_SERVER['HTTPS'] == 'off' || $_SERVER['port'] == 443)) ? 'https://' : 'http://';
            //当前网页的URL
            $url = "$protocol$_SERVER['host']$_SERVER['REQUEST_URI']";
            //生成签名的时间戳
            $timestamp = time();
            //生成签名的随机串
            $nonceStr = $this->createNonceStr();
            //获取公众号用于调用微信JS接口的临时票据
            $jsApiTicket = $this->getJsApiTicket();
            //对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,
            //使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串$str。
            //这里需要注意的是所有参数名均为小写字符
            $str = "jsapi_ticket=$jsApiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
            //对$str进行sha1签名,得到signature:
            $signature = sha1($str);
            $signPackage = array(
                "appId"     => $this->AppId,
                "nonceStr"  => $nonceStr,
                "timestamp" => $timestamp,
                "url"       => $url,
                "signature" => $signature,
                "rawString" => $string
                );
            return $signPackage;
        }

        /**
         * 创建签名的随机字符串
         * @param  int $length 字符串长度
         * @return string      随机字符串
         */
        private function createNonceStr($length == 16) {
            $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            $str = '';
            for ($i=0; $i library->redisCache->get('weixin:ticket');
            if (!$jsApiTicket) {
                //先获取access_token(公众号的全局唯一票据)
                $accessToken = $this->getApiToken();
                //通过access_token 采用http GET方式请求获得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里面,下次就不用再请求去取了
                $expire = max(1, intval($result['expire']) - 60);
                $this->library->redisCache->set('weixin:ticket', $jsApiTicket, $expire);
            }
            return $jsApiTicket;
        }

        /**
         * 获取众号的全局唯一票据access_token
         * @param  boolean $forceRefresh 是否强制刷新
         * @return string                返回access_token
         */
        private function getApiToken($forceRefresh = false) {
            //先查看redis是否存了accessToken,如果有了,就不用再去微信server去请求了(提高效率)
            $accessToken = $this->library->redisCache->get('weixin:accessToken');
            //强制刷新accessToken或者accessToken为空时就去请求accessToken
            if ($forceRefresh || empty($accessToken)) {
                //请求得到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);
                //将其存进redis里面去
                $this->library->redisCache->set('weixin:accessToken', $accessToken, $expire);
            }
            return $accessToken;
        }

appId, nonceStr, 타임스탬프, 서명 모델 가져오기

다음은 JS-SDK에서 권한 서명 알고리즘 사용에 대한 몇 가지 아이디어와 참고 사항입니다( 여기서는 모두가 볼 수 있도록 공식 웹사이트 문서를 직접 복사합니다.)

jsapi_ticket

서명을 생성하기 전에 먼저 jsapi_ticket이 WeChat을 호출하기 위해 공용 계정에서 사용하는 임시 티켓이라는 점을 이해해야 합니다. 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을 전역적으로 캐시해야 합니다.

      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权限验证的签名了。

    

    签名算法

    签名生成规则如下:参与签名的字段包括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&timestamp=1414587457&url=http://www.php.cn/

    步骤2. 对string1进行sha1签名,得到signature:

      0f9de62fce790f9a083d5c99e95740ceb90c27ed

    注意事项

      1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

      2.签名用的url必须是调用JS接口页面的完整URL。

      3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

 

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

  uploadImg.tpl

<script>
        $(function(){
            $.util.wxMenuImage(&#39;{$wxJsApi|default:""}&#39;)
        });
</script>

   uploadImg.js

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

$.util.wxMenuImage = function(json) {
    if (json.length == 0) return; 
    //解析json变成js对象
    wxJsApi = JSON.parse(json);

    //通过config接口注入权限验证配置
    wx.config({
        debug: false,   //开启调试模式,调用的所有api的返回值会在客户端alert出来
        appId: wxJsApi.signPackage.appId,   //公众号的唯一标识
        timestamp: wxJsApi.signPackage.timestamp,   //生成签名的时间戳
        nonceStr: wxJsApi.signPackage.nonceStr, //生成签名的随机串
        signature: wxJsApi.signPackage.signature,   //签名
        jsApiList: ['chooseImage', 'uploadImage']   //需要使用的JS接口列表 这里我用了选择图片和上传图片接口
    });

    //通过ready接口处理成功验证,config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后
    wx.ready(function(){
        //得到上传图片按钮
        document.querySelector('#uploadImage').onclick = function() {
            var images = {localId:[],serverId:[]};
            //调用 拍照或从手机相册中选图接口
            wx.chooseImage({
                success: function(res) {
                    if (res.localIds.length != 1) {
                        alert('只能上传一张图片');
                        return;
                    }
                    //返回选定照片的本地ID列表
                    iamges.localId = res.localIds;
                    images.serverId = [];
                    //上传图片函数
                    function upload() {
                        //调用上传图片接口
                        wx.uploadImage({
                            localId: images.localId[0], // 需要上传的图片的本地ID,由chooseImage接口获得
                            isShowProcess: 1,   // 默认为1,显示进度提示
                            success: function(res) {
                                //返回图片的服务器端ID res.serverId,然后调用wxImgCallback函数进行下载图片操作
                                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) {
            //存储到服务器成功后的处理
            //
        }
    });
}

图片选择和图片上传接口调用

图片选择和图片上传接口调用

   

  3、图片上传完成后会返回一个serverId,然后通过这个来下载图片到本地服务器

  这里先补充下如何调用下载图片接口(我直接复制官方文档的说明了)

    公众号可调用本接口来获取多媒体文件。请注意,视频文件不支持下载,调用该接口需http协议。

    接口调用请求说明

    http请求方式: GET
     http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID

    参数说明

参数 是否必须 说明
access_token 调用接口凭证
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"

    错误情况下的返回JSON数据包示例如下(示例为无效媒体ID错误)::

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


 接下来看自己写的代码
 wx_upload.php
/*********************图片下载到本地服务器****************************************/
    //从微信服务器读取图片,然后下载到本地服务器
    public function upload($media_id) {
        //图片文件名
        $fileName = md5($this->wxId."/$media_id");
        //调用下载图片接口,返回路径
        $path = $this->weixin->wxDownImg($media_id, sys_get_temp_dir()."$fileName");
        if ($path != false) {
            //将图片的路径插入数据库去存储
            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')));
        }
        
    }

从微信服务器下载图片到本地存储

//从微信服务器端下载图片到本地服务器
        public function wxDownImg($media_id, $path) {
            //调用 多媒体文件下载接口
            $url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token={$this->model->weixin->_getApiToken()}&media_id=$media_id";
            //用curl请求,返回文件资源和curl句柄的信息
            $info = $this->curl_request($url);
            //文件类型
            $types = array('image/bmp'=>'.bmp', 'image/gif'=>'.gif', 'image/jpeg'=>'.jpg', 'image/png'=>'.png');
            //判断响应首部里的的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请求资源
         * @param  string $url 请求url
         * @return array 
         */
        private function curl_request($url = '') {
            if ($url == '') return;
            $ch = curl_init();
            //这里返回响应报文时,只要body的内容,其他的都不要
            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;
        }

从微信服务器下载图片到本地存储接口

  到这里,已经完成了:

    先调用“拍照或从手机相册选择图片接口”—>选择成功图片后—>调用“上传图片接口”—>上传成功后(也就是图片上传到了微信服务器上)—>调用“下载图片接口”—>将图片下载到自己的服务器存储。

  这一思路的实现。我们用到了微信的选择图片接口、上传图片接口和下载媒体资源接口。

  下面我附上这一接口开发的全部代码:

<?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');
        //取得:公众号的唯一标识appId、生成签名的时间戳timestamp、生成签名的随机串nonceStr、签名signature这些值,并以json形式传到模板页面
        $this->smartyData['wxJsApi'] = json_encode(array('signPackage' => $this->model->weixin->signPackage()));
    }

    /*********************图片下载到本地服务器****************************************/
    //从微信服务器读取图片,然后下载到本地服务器
    public function upload($media_id) {
        //图片文件名
        $fileName = md5($this->wxId."/$media_id");
        //调用下载图片接口,返回路径
        $path = $this->weixin->wxDownImg($media_id, sys_get_temp_dir()."$fileName");
        if ($path != false) {
            //将图片的路径插入数据库去存储
            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();

            //审核通过的移动应用所给的AppID和AppSecret
            $this->appId = 'wx0000000000000000';
            $this->appSecret = '00000000000000000000000000000';
            $this->token = '00000000';
        }

        /**
         * 获取jssdk所需参数的所有值
         * @return array
         */
        public function signPackage() {
            $protocol = (!empty($_SERVER['HTTPS'] && $_SERVER['HTTPS'] == 'off' || $_SERVER['port'] == 443)) ? 'https://' : 'http://';
            //当前网页的URL
            $url = "$protocol$_SERVER['host']$_SERVER['REQUEST_URI']";
            //生成签名的时间戳
            $timestamp = time();
            //生成签名的随机串
            $nonceStr = $this->createNonceStr();
            //获取公众号用于调用微信JS接口的临时票据
            $jsApiTicket = $this->getJsApiTicket();
            //对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,
            //使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串$str。
            //这里需要注意的是所有参数名均为小写字符
            $str = "jsapi_ticket=$jsApiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
            //对$str进行sha1签名,得到signature:
            $signature = sha1($str);
            $signPackage = array(
                "appId"     => $this->AppId,
                "nonceStr"  => $nonceStr,
                "timestamp" => $timestamp,
                "url"       => $url,
                "signature" => $signature,
                "rawString" => $string
                );
            return $signPackage;
        }

        /**
         * 创建签名的随机字符串
         * @param  int $length 字符串长度
         * @return string      随机字符串
         */
        private function createNonceStr($length == 16) {
            $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            $str = '';
            for ($i=0; $i library->redisCache->get('weixin:ticket');
            if (!$jsApiTicket) {
                //先获取access_token(公众号的全局唯一票据)
                $accessToken = $this->getApiToken();
                //通过access_token 采用http GET方式请求获得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里面,下次就不用再请求去取了
                $expire = max(1, intval($result['expire']) - 60);
                $this->library->redisCache->set('weixin:ticket', $jsApiTicket, $expire);
            }
            return $jsApiTicket;
        }

        /**
         * 获取众号的全局唯一票据access_token
         * @param  boolean $forceRefresh 是否强制刷新
         * @return string                返回access_token
         */
        private function getApiToken($forceRefresh = false) {
            //先查看redis是否存了accessToken,如果有了,就不用再去微信server去请求了(提高效率)
            $accessToken = $this->library->redisCache->get('weixin:accessToken');
            //强制刷新accessToken或者accessToken为空时就去请求accessToken
            if ($forceRefresh || empty($accessToken)) {
                //请求得到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);
                //将其存进redis里面去
                $this->library->redisCache->set('weixin:accessToken', $accessToken, $expire);
            }
            return $accessToken;
        }

        //从微信服务器端下载图片到本地服务器
        public function wxDownImg($media_id, $path) {
            //调用 多媒体文件下载接口
            $url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token={$this->model->weixin->_getApiToken()}&media_id=$media_id";
            //用curl请求,返回文件资源和curl句柄的信息
            $info = $this->curl_request($url);
            //文件类型
            $types = array('image/bmp'=>'.bmp', 'image/gif'=>'.gif', 'image/jpeg'=>'.jpg', 'image/png'=>'.png');
            //判断响应首部里的的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请求资源
         * @param  string $url 请求url
         * @return array 
         */
        private function curl_request($url = '') {
            if ($url == '') return;
            $ch = curl_init();
            //这里返回响应报文时,只要body的内容,其他的都不要
            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;
        }

    }


?>
    
        
    
    
        <button>点击上传图片</button>
        <script>
        $(function(){
            $.util.wxMenuImage(&#39;{$wxJsApi|default:""}&#39;)
        });
        </script>
    
if(typeof($util)=='undefined')$util={};

$.util.wxMenuImage = function(json) {
    if (json.length == 0) return; 
    //解析json变成js对象
    wxJsApi = JSON.parse(json);

    //通过config接口注入权限验证配置
    wx.config({
        debug: false,   //开启调试模式,调用的所有api的返回值会在客户端alert出来
        appId: wxJsApi.signPackage.appId,   //公众号的唯一标识
        timestamp: wxJsApi.signPackage.timestamp,   //生成签名的时间戳
        nonceStr: wxJsApi.signPackage.nonceStr, //生成签名的随机串
        signature: wxJsApi.signPackage.signature,   //签名
        jsApiList: ['chooseImage', 'uploadImage']   //需要使用的JS接口列表 这里我用了选择图片和上传图片接口
    });

    //通过ready接口处理成功验证,config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后
    wx.ready(function(){
        //得到上传图片按钮
        document.querySelector('#uploadImage').onclick = function() {
            var images = {localId:[],serverId:[]};
            //调用 拍照或从手机相册中选图接口
            wx.chooseImage({
                success: function(res) {
                    if (res.localIds.length != 1) {
                        alert('只能上传一张图片');
                        return;
                    }
                    //返回选定照片的本地ID列表
                    iamges.localId = res.localIds;
                    images.serverId = [];
                    //上传图片函数
                    function upload() {
                        //调用上传图片接口
                        wx.uploadImage({
                            localId: images.localId[0], // 需要上传的图片的本地ID,由chooseImage接口获得
                            isShowProcess: 1,   // 默认为1,显示进度提示
                            success: function(res) {
                                //返回图片的服务器端ID res.serverId,然后调用wxImgCallback函数进行下载图片操作
                                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) {
            //存储到服务器成功后的处理
            //
        }
    });
}

本次讲解就到此,这篇博文是给对微信接口开发有兴趣的朋友参考,如果你是高手,完全可以绕道。

 更多微信JS-SDK之图像接口开发相关文章请关注PHP中文网!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.