利用微信公众号提供的官方API上传图片获取永久图片素材!当图床用! - TANKING 创意开发者

利用微信公众号提供的官方API上传图片获取永久图片素材!当图床用!

2022-08-18 2994 阅读 php

需求


自己开发的小程序,例如社区类、电商类、新闻、博客等类型小程序,会需要储存很多图片,图片资源会给个人开发者带来很多成本,万一访问量大了,网站带宽、流量也会不堪重负,所以图片资源必然不合适储存在自己的服务器里面,而很多厂商提供的弹性储存也是按需付费的。


想法


微信公众平台提供了一个素材管理,里面可以上传图片、视频、音频等类型的素材,那么是否可以将图片素材上传上去,获取到url作为自己小程序项目的图片服务器呢?当然没问题!


根据开发文档的说法:永久图片素材新增后,将带有URL返回给开发者,开发者可以在腾讯系域名内使用(腾讯系域名外使用,图片将被屏蔽)。简单来说就是你只能在腾讯的平台使用这个图片素材URL,否则无法展示,因为有防盗链。


开发


根据微信公众平台开发文档提供的【新增永久素材】接口可知,分为以下几个步骤实现上传图片素材到微信服务器。


1. 获取access_token

2. 用新增永久素材接口进行上传素材

3. 获取到素材的永久URL


代码如下:


<?php

// 返回JSON
header("Content-type:application/json");
// 允许上传的图片后缀
$allowedExts = array("jpeg", "jpg", "png");
// 后缀名
if ($allowedExts[0] == 'jpeg') {
    $hzm = 'jpg';
}else{
    $hzm = $allowedExts[0];
}
// 获取选择的文件
$temp = explode(".", $_FILES["file"]["name"]);
// 获取文件后缀名
$extension = end($temp);

if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 10485760)
&& in_array($extension, $allowedExts)){
    if ($_FILES["file"]["error"] > 0){
        $result = array(
            'code' => 201,
            'msg' => '上传失败'.$_FILES["file"]["error"]
        );
    }else{
        // 重命名
           $new_file = date("Y-m-d")."-".rand(10000,99999).".".$hzm;
           // 上传到自己的服务器
        move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$new_file);
        // 获取真实地址
        $filepath = realpath(dirname(__FILE__));
        $upload_filepath = $filepath."/upload/".$new_file;
        // 上传到微信服务器
        $imgurl = upload_img($upload_filepath);
        // 验证上传结果
        if(strpos($imgurl,'http') !== false){

            // 上传成功
            $result = array(
                'code' => 200,
                'msg' => '上传成功',
                'url' => $imgurl
            );
            // 删除本地素材
            unlink($upload_filepath);
        }else{

            // 上传失败
            $result = array(
                'code' => 202,
                'msg' => '上传失败'
            );
        }
    }
}

// 获取access_token
function getToken(){
    // appid和secret
    $appid='填写你公众号的appid';
    $appsecret='填写你公众号的appsecret';
    // 读取access_token
    include './access_token.php';
    // 判断是否过期
    if (time() > $access_token['expires']){
        // 如果已经过期就得重新获取并缓存
        $access_token = array();
        $access_token['access_token'] = getNewToken($appid,$appsecret);
        $access_token['expires']=time()+7000;
        // 将数组写入php文件
        $arr = '<?php'.PHP_EOL.'$access_token = '.var_export($access_token,true).';'.PHP_EOL.'?>';
        $arrfile = fopen("./access_token.php","w");
        fwrite($arrfile,$arr);
        fclose($arrfile);
        // 返回当前的access_token
        return $access_token['access_token'];
    }else{
        // 如果没有过期就直接读取缓存文件
        return $access_token['access_token'];
    }
}
// 获取新的access_token
function getNewToken($appid,$appsecret){
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
    $access_token_Arr =  https_request($url);
    return $access_token_Arr['access_token'];
}
// curl请求函数
function https_request ($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $out = curl_exec($ch);
    curl_close($ch);
    return  json_decode($out,true);
}
// 上传图片素材到微信服务器
function upload_img($realpath){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.getToken().'&type=image');
    $data = array(
        'media' => new CURLFile($realpath)
    );
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $upimg = curl_exec($ch);
    return json_decode($upimg)->url;
    curl_close($ch);
}

// 返回JSON对象
echo json_encode($result,JSON_UNESCAPED_UNICODE);
?>

请求返回

{"media_id":"8IZhZUPXxsG_omeA5giO5By8VyHnjk7_oy0Co9jVWwxpgm-sqhx_Hkz_9rLVF9Ws","url":"http://mmbiz.qpic.cn/mmbiz_png/5zLSKyuEW2Kt5ZGZg7XUx05QyGOVFCpHqKic74qQP4gxzQJYXjwN4aGEiadtfUXax4fCXXV5ia1UnvSwdqxuqLCqA/0?wx_fmt=png","item":[]}


说明


1. 首先要将图片从客户端(小程序端)上传到你自己的服务器的upload目录

2. 然后调用新增永久素材接口从upload目录上传到微信的服务器

3. 需要配置公众号的appid和appsecret获取access_token

4. 新增永久素材接口需要传入access_token才可以调用

5. access_token才效期是2小时,每天最多获取2000次access_token,超过次数就获取不到,为了能够保证一直都能获取到新的token,不能每上传一次就获取一个新的access_token,量大的话一下子就把2000次用完了。access_token只要在2小时内都可以随便使用,所以需要进行缓存access_token。getToken()这个函数就是缓存access_token的步骤(如果access_token已经超过2小时就获取新的access_token并缓存到本地,如果access_token还没超过2小时直接读取本地缓存的access_token)

6. 获取access_token接口需要在公众号后台的安全中心配置白名单ip地址


注意

图片链接只能在腾讯域名的平台使用,在自建网站无法显示,本文主要将的是小程序调用永久图片素材,是可以用的!