逻辑分析:
1.首先准备小程序的APPID和SECRET,可在微信公众号中获取。以及准备好想要带进二维码里边的参数
2.logo上传:接受到上传的logo图片,先把图片画成圆形,然后获取到二维码后,把logo图片镶嵌到二维码上。
具体看代码演示:用到的重要方法看目录
public function recreateOp(){
if (request()->ispost() && request()->isAjax()) {
$logo = request()->file('file'); // 上传的logo
$width = input('width'); // 宽度
$shape = input('shape'); // 二维码形状
if($width < 280 || $width > 1280){
return json_encode(['status'=>ERROR,'msg'=>'宽度有误']);
}
if($shape != 1 && $shape != 2){
return json_encode(['status' => ERROR, 'msg' => '类型有误']);
}
$appid = "你自己的appid在微信公众号中查找";
$appsecret = "你的appsecret在微信公众号中查找";
$usertoken = "你需要带进二维码中的参数";
if (!$usertoken) {
return json_encode(['status' => ERROR, 'msg' => '信息有误']);
}
$Applet = new Applet(); // Applet() 类
if (!empty($logo)) {
$filename = uniqid('qrlogo_img_' . false);
$retImg = upload_files($logo, USER_QRLOGO_PATH, $filename); // 文件上传
if ($retImg['status'] == 9) {
$head_img = USER_QRLOGO_PATH.$retImg['msg'];
} else {
return json_encode(['status' => 'error', 'msg' => $retImg['msg']]);
}
$logo = $Applet->yuanImg($head_img); // 把上传的logo使用PHP自带的GD库画成圆形
@unlink($head_img); // 删除上传的logo图片
}
$Applet->creatCode($appid, $appsecret, $usertoken, $this->userinfo['uid'], $shape, $width,$logo);
return json_encode(['status' => SUCCESS, 'msg' => '二维码已重新生成','url'=>url('jieru')]);
}
}
/*
* 生成小程序接入专属二维码
* $appid 小程序appid
* $appsecret 小程序appsecret
* $usertoken 通行码
* $shape 二维码形状:1-菊花型,2-方形
* $width 二维码宽度
*/
public function creatCode($appid, $appsecret, $usertoken, $uid, $shape = 1, $width=280,$logo = '') {
//获取access_token
$access_token = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret";
$json = $this->httpRequest($access_token);
$token = json_decode($json, true);
$token = $token['access_token'];
// 构建请求二维码参数
switch ($shape) {
case 1: //菊花型
$qcode = "https://api.weixin.qq.com/wxa/getwxacode?access_token=$token"; //菊花二维码
break;
default: //方型
$qcode = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=$token"; // 方形二维码
break;
}
// 把需要带二维码中的参数组合发送给微信接口
$param = json_encode(array("path" => "pages/login/login?tongxingma=$usertoken", "width" => $width));
// $res 是获取到的二维码,可以将二维码存到数据库中
$res = $this->httpRequest($qcode, $param, "POST"); // 发送http请求换取带参数的二维码
if (!empty($logo)) {
$res = $this->qrcodeWithLogo($res,$logo,$shape); // 在二维码的中间区域镶嵌图片
}
//保存二维码图片
$file_name = time(). createStr(6) . ".png"; // 生成二维码图片名称
$path = ROOT_PATH . 'public/uploads/appLetCode/'. $usertoken.'/'; // 保存路径
$upload = $path . $file_name;
if (!file_exists($path)) mkdir($path, 0777, true);
file_put_contents($upload, $res);
//保存数据到数据库
$olddata = model('Applet')->where(['uid' => $uid])->field('numid,name')->find();
if(!$olddata){ //新增数据
$data = [
'uid' => $uid,
'name' => $file_name,
'width' => $width,
'shape' => $shape,
'addtime' => time(),
'status' => 9,
];
model('Applet')->allowField(true)->save($data);
}else{ //更新数据
if (file_exists($path . $olddata['name'])) {
@unlink($path . $olddata['name']);
}
$data = [
'numid' => $olddata['numid'],
'name' => $file_name,
'width' => $width,
'shape' => $shape,
'addtime' => time(),
'status' => 9,
];
model('Applet')->allowField(true)->isUpdate(true)->save($data);
}
return [
//转成base64
'base64_image' => "data:image/jpeg;base64," . base64_encode($res),
'upload' => $file_name,
];
}
//把请求发送到微信服务器换取二维码
private function httpRequest($url, $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 ($data != '') {
curl_setopt($curl, CURLOPT_POSTFIELDS, $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;
}
/**
* 剪切图片为圆形
* @param $picture 图片数据流 比如file_get_contents(imageurl)返回的东东
* @return 图片数据流
*/
public function yuanImg($picture) {
$picture = file_get_contents($picture);
$src_img = imagecreatefromstring($picture);
$w = imagesx($src_img);
$h = imagesy($src_img);
$w = min($w, $h);
$h = $w;
$img = imagecreatetruecolor($w, $h);
//这一句一定要有
imagesavealpha($img, true);
//拾取一个完全透明的颜色,最后一个参数127为全透明
$bg = imagecolorallocatealpha($img, 255, 255, 255, 127);
imagefill($img, 0, 0, $bg);
$r = $w / 2; //圆半径
$y_x = $r; //圆心X坐标
$y_y = $r; //圆心Y坐标
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$rgbColor = imagecolorat($src_img, $x, $y);
if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
}
}
/**
* 如果想要直接输出图片,应该先设header。header("Content-Type: image/png; charset=utf-8");
* 并且去掉缓存区函数
*/
//获取输出缓存,否则imagepng会把图片输出到浏览器
ob_start();
imagepng($img);
imagedestroy($img);
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
/**
* 在二维码的中间区域镶嵌图片
* @param $QR 二维码数据流。比如file_get_contents(imageurl)返回的东东,或者微信给返回的东东
* @param $logo 中间显示图片的数据流。比如file_get_contents(imageurl)返回的东东
* @return 返回图片数据流
*/
public function qrcodeWithLogo($QR, $logo,$shape) {
$QR = imagecreatefromstring($QR);
$logo = imagecreatefromstring($logo);
$QR_width = imagesx($QR);//二维码图片宽度
$QR_height = imagesy($QR);//二维码图片高度
$logo_width = imagesx($logo);//logo图片宽度
$logo_height = imagesy($logo);//logo图片高度
if ($shape == 1 ) {
$logo_qr_width = $QR_width / 2.2;//组合之后logo的宽度(占二维码的1/2.2)
} else {
$logo_qr_width = $QR_width / 4;//组合之后logo的宽度(占二维码的1/4)
}
$scale = $logo_width / $logo_qr_width;//logo的宽度缩放比(本身宽度/组合后的宽度)
$logo_qr_height = $logo_height / $scale;//组合之后logo的高度
$from_width = ($QR_width - $logo_qr_width) / 2;//组合之后logo左上角所在坐标点
/**
* 重新组合图片并调整大小
* imagecopyresampled() 将一幅图像(源图象)中的一块正方形区域拷贝到另一个图像中
*/
imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
/**
* 如果想要直接输出图片,应该先设header。header("Content-Type: image/png; charset=utf-8");
* 并且去掉缓存区函数
*/
//获取输出缓存,否则imagepng会把图片输出到浏览器
ob_start();
imagepng($QR);
imagedestroy($QR);
imagedestroy($logo);
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}