微信小程序生成官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html
流程分析:
1.第一步调用微信官放获取 access_token(不用管为什么,去获取就行,后面必须要用)
(大概逻辑:获取完access_token,存redis,小程序官方定的过期时间是2小时,存的时候注意过期时间的单位是分还是秒)
public static function getWxAccessToken() { $app_id = config('wechat.mini_program.default.app_id'); $app_secret = config('wechat.mini_program.default.secret'); if (!$app_id || !$app_secret) { return [false, '获取小程序配置失败!']; } if (Cache::get('access_token_' . $app_id)) { return [true, Cache::get('access_token_' . $app_id)]; } else { $third_api = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $app_id . "&secret=" . $app_secret; $result = getHttpContent($third_api, 'GET'); $json = json_decode($result, true); if (!isset($json['access_token']) && !$json['access_token']) { return [false, '获取access_token失败']; } $access_token = $json['access_token']; Cache::put('access_token_' . $app_id, $access_token, 120); return [true, $access_token]; } }
2.拿到token ,GET方式curl请求微信的生成二维码图片的api
//这个api有限制30万次 $url= "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=" .$access_token; //这个api没有次数限制 $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" . $access_token;3.这里以第一个api为例,下面是示范代码,我自己完整实现过放心使用, (第二个没次数限制的api 传参方式不一样,请看官方文档)
$post_data = json_encode(array("path"=>"pages/index/index?spread_code=$spread_code","width"=> 150)); $data = WechatService::httpRequest($url, $post_data,'POST'); //自己建个服务类,把下面方法放到服务类里面静态去调用 public static function httpRequest($url, $post_data='', $method='GET'){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($curl, CURLOPT_AUTOREFERER, 1); if($method=='POST') { curl_setopt($curl, CURLOPT_POST, 1); if ($post_data != '') { curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); } } curl_setopt($curl, CURLOPT_TIMEOUT, 30); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($curl); curl_close($curl); return $result; }通过打印可以发现,微信返回并不是图片链接,而是二进制流
需要对上面的返回结果进行如下处理:
$result = WechatService::data_uri($data, 'image/jpeg'); /* 二进制转图片image/png*/ public static function data_uri($contents, $mime) { $base64 = base64_encode($contents); return ('data:' . $mime . ';base64,' . $base64); }得到完整的二进制流图片地址,调用自己封装的二进制图片上传到oss方法
$res = OssService::base64ToOss($result); public static function base64ToOss($base64){ // OSS处理 $result = OssService::base64Upload($base64);//这个方法下面提供的有,根据代码封装位置是否静态调用,里面逻辑是先将二进制流上传到服务器本地,再通过下面的代码上传到oss,若成功上传到oss就删除刚才本地图片 if ($result['code'] != 200) { return ['code' => $result['code'], 'msg' => $result['msg']]; } $fileResult = &$result['data']; $filePath = $fileResult['path'] . $fileResult['name']; $ossFileName = implode('/', ['upload/image', date('Ymd'), $fileResult['name']]); try { $config = config('services.oss'); //实例化对象 将配置传入 $ossClient = new OssClient($config['access_key'], $config['secret_key'], $config['endpoint']); $result = $ossClient->uploadFile($config['bucket'], $ossFileName, $filePath); $arr = [ 'oss_url' => $result['info']['url'], //上传资源地址 'relative_path' => $ossFileName //数据库保存名称(相对路径) ]; } catch (OssException $e) { return ['code' => 400, 'msg' => $e->getMessage()]; } finally { unlink($filePath); } return ['code' => 200, 'info' => $arr]; }public static function base64Upload($base64, $path = '') { $data = explode(',', $base64); unset($base64); if (count($data) !== 2) { return ['code' => 400, 'msg' => '文件格式错误']; } if (preg_match('/^(data:\s*image\/(\w+);base64)/', $data[0], $result)) { $type = $result[2]; if (!in_array($type, array('jpeg', 'jpg', 'gif', 'bmp', 'png'))) { return ['code' => 400, 'msg' => '文件格式不在允许范围内']; } $image_name = md5(uniqid()) . '.' . $result[2]; $image_path = "./upload/image/"; $image_file = $image_path . $image_name; if (!file_exists($image_path)) { mkdir($image_path, 0777, true); } //服务器文件存储路径 try { if (file_put_contents($image_file, base64_decode($data[1]))) { return ['code' => 200, 'msg' => '成功', 'data' => ['name' => $image_name, 'path' => $image_path]]; } else { return ['code' => 400, 'msg' => '文件保存失败']; } } catch (\Exception $e) { return ['code' => 400, 'msg' => $e->getMessage()]; } } return ['code' => 400, 'msg' => '文件格式错误']; }