찾다
위챗 애플릿위챗 개발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으로 문의하세요.
PHP微信开发:如何实现消息加密解密PHP微信开发:如何实现消息加密解密May 13, 2023 am 11:40 AM

PHP是一种开源的脚本语言,广泛应用于Web开发和服务器端编程,尤其在微信开发中得到了广泛的应用。如今,越来越多的企业和开发者开始使用PHP进行微信开发,因为它成为了一款真正的易学易用的开发语言。在微信开发中,消息的加密和解密是一个非常重要的问题,因为它们涉及到数据的安全性。对于没有加密和解密方式的消息,黑客可以轻松获取到其中的数据,对用户造成威胁

PHP微信开发:如何实现客服聊天窗口管理PHP微信开发:如何实现客服聊天窗口管理May 13, 2023 pm 05:51 PM

微信是目前全球用户规模最大的社交平台之一,随着移动互联网的普及,越来越多的企业开始意识到微信营销的重要性。在进行微信营销时,客服服务是至关重要的一环。为了更好地管理客服聊天窗口,我们可以借助PHP语言进行微信开发。一、PHP微信开发简介PHP是一种开源的服务器端脚本语言,广泛运用于Web开发领域。结合微信公众平台提供的开发接口,我们可以使用PHP语言进行微信

PHP微信开发:如何实现用户标签管理PHP微信开发:如何实现用户标签管理May 13, 2023 pm 04:31 PM

在微信公众号开发中,用户标签管理是一个非常重要的功能,可以让开发者更好地了解和管理自己的用户。本篇文章将介绍如何使用PHP实现微信用户标签管理功能。一、获取微信用户openid在使用微信用户标签管理功能之前,我们首先需要获取用户的openid。在微信公众号开发中,通过用户授权的方式获取openid是比较常见的做法。在用户授权完成后,我们可以通过以下代码获取用

用PHP开发微信群发工具用PHP开发微信群发工具May 13, 2023 pm 05:00 PM

随着微信的普及,越来越多的企业开始将其作为营销工具。而微信群发功能,则是企业进行微信营销的重要手段之一。但是,如果只依靠手动发送,对于营销人员来说是一件极为费时费力的工作。所以,开发一款微信群发工具就显得尤为重要。本文将介绍如何使用PHP开发微信群发工具。一、准备工作开发微信群发工具,我们需要掌握以下几个技术点:PHP基础知识微信公众平台开发开发工具:Sub

如何使用PHP进行微信开发?如何使用PHP进行微信开发?May 21, 2023 am 08:37 AM

随着互联网和移动智能设备的发展,微信成为了社交和营销领域不可或缺的一部分。在这个越来越数字化的时代,如何使用PHP进行微信开发已经成为了很多开发者的关注点。本文主要介绍如何使用PHP进行微信开发的相关知识点,以及其中的一些技巧和注意事项。一、开发环境准备在进行微信开发之前,首先需要准备好相应的开发环境。具体来说,需要安装PHP的运行环境,以及微信公众平台提

PHP微信开发:如何实现群发消息发送记录PHP微信开发:如何实现群发消息发送记录May 13, 2023 pm 04:31 PM

随着微信成为了人们生活中越来越重要的一个通讯工具,其敏捷的消息传递功能迅速受到广大企业和个人的青睐。对于企业而言,将微信发展为一个营销平台已经成为趋势,而微信开发的重要性也逐渐凸显。在其中,群发功能更是被广泛使用,那么,作为PHP程序员,如何实现群发消息发送记录呢?下面将为大家简单介绍一下。1.了解微信公众号相关开发知识在了解如何实现群发消息发送记录之前,我

ThinkPHP6微信开发指南:快速搭建微信公众号应用ThinkPHP6微信开发指南:快速搭建微信公众号应用Aug 26, 2023 pm 11:55 PM

ThinkPHP6微信开发指南:快速搭建微信公众号应用引言:微信公众号作为一种重要的社交媒体平台,为个人和企业在市场推广、信息传播等方面提供了很大的机会。在这篇文章中,我们将介绍如何使用ThinkPHP6快速搭建一个微信公众号应用,并且提供一些常用的代码示例。环境准备在开始开发之前,我们首先需要准备好以下环境:PHP7以上版本ThinkPHP6框架微信公众号

PHP微信开发:如何实现语音识别PHP微信开发:如何实现语音识别May 13, 2023 pm 09:31 PM

随着移动互联网的普及,微信作为一款社交软件,越来越多的人开始使用,并且微信开放平台也给开发者带来了众多的机会。近年来,随着人工智能技术的发展,语音识别技术逐渐成为了移动端开发的热门技术之一。在微信开发中,如何实现语音识别成为很多开发者关注的问题。本文将介绍如何利用PHP开发微信应用实现语音识别功能。一、语音识别原理在介绍如何实现语音识别之前,我们先了解一下语

See all articles

핫 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 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

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

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구