PHP实现微信JS-SDK接口选择相册及拍照并上传的方法


Posted in PHP onDecember 05, 2016

本文实例讲述了PHP实现微信JS-SDK接口选择相册及拍照并上传的方法。分享给大家供大家参考,具体如下:

理解:微信上传接口是拍照,或者选择本地照片,上传到微信的服务器,获取到一个id,通过token与这个id获取到图片,保存到服务器即可。

效果图:

PHP实现微信JS-SDK接口选择相册及拍照并上传的方法

通过微信js接口,调用底层程序。
需要引入js文件,并进行配置。

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
wx.config({
  debug: false,
  appId: 'wxed7996e9ad58345d',
  timestamp: 1449717454,
  nonceStr: 'asdfasdfasdf',
  signature: 'b74fb4ab4790172d2ab7e58f0051a1523aaa4803',
  jsApiList: [
    'chooseImage',
    'uploadImage'
  ]
});

其中appId为微信公众平台id,timestamp为当前时间戳,nonceStr为随机字符串,signature为签名。

signature是最重要参数。需要通过很多步骤来获取。

首先获取access_token,能存活两小时,每天允许获取2000次。超过就不能获取了。

// 获取access_token 两小时有效
private function get_access_token(){
    $appid = C('oauth_config.appid');
    $appsecret = C('oauth_config.appsecret');
    $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;
    $rurl = file_get_contents($url);
    $rurl = json_decode($rurl,true);
    if(array_key_exists('errcode',$rurl)){
      return false;
    }else{
      $access_token = $rurl['access_token'];
      return $access_token;
    }
}

然后获取jsticket

// 获取jsticket 两小时有效
private function getjsticket(){ // 只允许本类调用,继承的都不可以调用,公开调用就更不可以了
    $access_token = $this->get_access_token();
    $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$access_token."&type=jsapi"; // 两小时有效
    $rurl = file_get_contents($url);
    $rurl = json_decode($rurl,true);
    if($rurl['errcode'] != 0){
      return false;
    }else{
      $jsticket = $rurl['ticket'];
      return $jsticket;
    }
}

然后获取signature,它是由多个参数拼接加密形成的,有实效性。

// 获取 signature
private function getsignature(){
    $noncestr = '';
    $jsapi_ticket = $this->getjsticket();
    $timestamp = time();
    $url = 'http://zhudianbao.diandodo.com/index.php?g=Opener&m=Merchant&a=open';
    $string1 = 'jsapi_ticket='.$jsapi_ticket.'&noncestr='.$noncestr.'×tamp='.$timestamp.'&url='.$url;
    $signature = sha1($string1);
    return $signature;
}

配置好之后,就可以使用了。我用了两个功能,一个是选择照片,一个是上传照片。

function chooseImage(obj){
  // 选择张片
  wx.chooseImage({
    count: 1, // 默认9
    sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
    sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
    success: function(res) {
      var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
      $(obj).attr('src', localIds);
      // 上传照片
      wx.uploadImage({
        localId: '' + localIds,
        isShowProgressTips: 1,
        success: function(res) {
          serverId = res.serverId;
          $(obj).next().val(serverId); // 把上传成功后获取的值附上
        }
      });
    }
  });
}

选择照片返回的localIds很有意思,可以用于上传使用,并且可以放在img的src属性中,展示图片。

上传成功后,获取一个serverId,通过这个id可以下载上传到微信服务器上的图片文件,把它保存到自己的服务器中。

// 获取图片地址
private function getmedia($access_token,$media_id,$foldername){
    $url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=".$access_token."&media_id=".$media_id;
    if (!file_exists("./Uploads/User_cert/".$foldername)) {
      mkdir("./Uploads/User_cert/".$foldername, 0777, true);
    }
    $targetName = './Uploads/User_cert/'.$foldername.'/'.date('YmdHis').rand(1000,9999).'.jpg';
    $ch = curl_init($url); // 初始化
    $fp = fopen($targetName, 'wb'); // 打开写入
    curl_setopt($ch, CURLOPT_FILE, $fp); // 设置输出文件的位置,值是一个资源类型
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_exec($ch);
    curl_close($ch);
    fclose($fp);
    return $targetName;
}

防止图片名称相同,加一个rand随机数,因为在同一秒钟可能会上传多张照片。

$targetName = './Uploads/User_cert/'.$foldername.'/'.date('YmdHis').rand(1000,9999).'.jpg';

这个serverId以表单的形式提交到服务器,然后对其进行写入文件,获取地址,并把地址保存到服务器中。

微信的js与jquery不冲突,可以共同使用。

附上牛逼的JSSDK类

<?php
class JSSDK {
 private $appId;
 private $appSecret;
 public function __construct($appId, $appSecret) {
  $this->appId = $appId;
  $this->appSecret = $appSecret;
 }
 public function getSignPackage() {
  $jsapiTicket = $this->getJsApiTicket();
  // 注意 URL 一定要动态获取,不能 hardcode.
  $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
  $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
  $timestamp = time();
  $nonceStr = $this->createNonceStr();
  // 这里参数的顺序要按照 key 值 ASCII 码升序排序
  $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
  $signature = sha1($string);
  $signPackage = array(
   "appId"   => $this->appId,
   "nonceStr" => $nonceStr,
   "timestamp" => $timestamp,
   "url"    => $url,
   "signature" => $signature,
   "rawString" => $string
  );
  return $signPackage; 
 }
 private function createNonceStr($length = 16) {
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  $str = "";
  for ($i = 0; $i < $length; $i++) {
   $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  }
  return $str;
 }
 private function getJsApiTicket() {
  // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
  $data = json_decode(file_get_contents("jsapi_ticket.json"));
  if ($data->expire_time < time()) {
   $accessToken = $this->getAccessToken();
   // 如果是企业号用以下 URL 获取 ticket
   // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
   $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
   $res = json_decode($this->httpGet($url));
   $ticket = $res->ticket;
   if ($ticket) {
    $data->expire_time = time() + 7000;
    $data->jsapi_ticket = $ticket;
    $fp = fopen("jsapi_ticket.json", "w");
    fwrite($fp, json_encode($data));
    fclose($fp);
   }
  } else {
   $ticket = $data->jsapi_ticket;
  }
  return $ticket;
 }
 private function getAccessToken() {
  // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
  $data = json_decode(file_get_contents("access_token.json"));
  if ($data->expire_time < time()) {
   // 如果是企业号用以下URL获取access_token
   // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
   $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
   $res = json_decode($this->httpGet($url));
   $access_token = $res->access_token;
   if ($access_token) {
    $data->expire_time = time() + 7000;
    $data->access_token = $access_token;
    $fp = fopen("access_token.json", "w");
    fwrite($fp, json_encode($data));
    fclose($fp);
   }
  } else {
   $access_token = $data->access_token;
  }
  return $access_token;
 }
 private function httpGet($url) {
  $curl = curl_init();
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_TIMEOUT, 500);
  // 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
  // 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
  curl_setopt($curl, CURLOPT_URL, $url);
  $res = curl_exec($curl);
  curl_close($curl);
  return $res;
 }
}

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php 文件状态缓存带来的问题
Dec 14 PHP
全世界最小的php网页木马一枚 附PHP木马的防范方法
Oct 09 PHP
DW中链接mysql数据库时,建立字符集中文出现乱码的解决方法
Mar 27 PHP
关于svn冲突的解决方法
Jun 21 PHP
学习php设计模式 php实现门面模式(Facade)
Dec 07 PHP
详解PHP的Yii框架中扩展的安装与使用
Apr 01 PHP
php文件上传后端处理小技巧
May 22 PHP
[原创]解决wincache不支持64位PHP5.5/5.6的问题(提供64位wincache下载)
Jun 22 PHP
PHP下的浮点运算不准的解决方法
Oct 27 PHP
php中遍历二维数组并以表格的形式输出的方法
Jan 03 PHP
利用php操作memcache缓存的基础方法示例
Aug 02 PHP
php实现支持中文的文件下载功能示例
Aug 30 PHP
thinkPHP js文件中U方法不被解析问题的解决方法
Dec 05 #PHP
thinkPHP中验证码的简单实现方法
Dec 05 #PHP
php获取当前月与上个月月初及月末时间戳的方法
Dec 05 #PHP
简述php环境搭建与配置
Dec 05 #PHP
php 变量引用与变量销毁机制详细介绍
Dec 05 #PHP
[原创]php实现 data url的图片生成与保存
Dec 04 #PHP
php 魔术常量详解及实例代码
Dec 04 #PHP
You might like
php调用Google translate_tts api实现代码
2013/08/07 PHP
PHP数据库链接类(PDO+Access)实例分享
2013/12/05 PHP
php中Array2xml类实现数组转化成XML实例
2014/12/08 PHP
PHP类的声明与实例化及构造方法与析构方法详解
2016/01/26 PHP
PHP简单实现冒泡排序的方法
2016/12/26 PHP
php实现微信分享朋友链接功能
2019/02/18 PHP
Javascript 不能释放内存.
2006/09/07 Javascript
javascript读取xml
2006/11/04 Javascript
理解JavaScript变量作用域更轻松
2009/10/25 Javascript
jquery实现图片左右间隔滚动特效(可自动播放)
2013/05/08 Javascript
js中的replace方法使用介绍
2013/10/28 Javascript
基于 Docker 开发 NodeJS 应用
2014/07/30 NodeJs
关于Javascript加载执行优化的研究报告
2014/12/16 Javascript
JavaScript结合AJAX_stream实现流式显示
2015/01/08 Javascript
Javascript原型链的原理详解
2016/01/05 Javascript
bootstrap-treeview自定义双击事件实现方法
2016/01/09 Javascript
文本框只能输入数字的实现方法(兼容IE火狐)
2016/06/25 Javascript
JS动态加载脚本并执行回调操作
2016/08/24 Javascript
JavaScript解析JSON数据示例
2019/07/16 Javascript
JavaScript实现鼠标移入随机变换颜色
2020/11/24 Javascript
python的正则表达式re模块的常用方法
2013/03/09 Python
Python中关于字符串对象的一些基础知识
2015/04/08 Python
Python的字典和列表的使用中一些需要注意的地方
2015/04/24 Python
Python Web程序搭建简单的Web服务器
2019/07/31 Python
解决Python spyder显示不全df列和行的问题
2020/04/20 Python
如何用python免费看美剧
2020/08/11 Python
简述synchronized和java.util.concurrent.locks.Lock的异同
2014/12/08 面试题
Java中的基本数据类型所占存储空间大小固定的吗
2012/02/15 面试题
个人授权委托书
2014/04/03 职场文书
大学教师师德师风演讲稿
2014/08/22 职场文书
教师岗位职责范本
2015/04/02 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
如何制定销售人员薪酬制度?
2019/07/09 职场文书
sql server删除前1000行数据的方法实例
2021/08/30 SQL Server
Jpa Specification如何实现and和or同时使用查询
2021/11/23 Java/Android
安装Windows Server 2012 R2企业版操作系统并设置好相关参数
2022/04/29 Servers