小程序碼生成的時候是默認使用小程序后台設置的小程序icon圖片的,但是在有些場景我們可能要替換成我們自己想要的icon。
下面先放代碼:
public function makeNewQrCodeAction()
{
//獲取用戶頭像並轉string
$avatarUrl = $this->_req->getQuery('avatarUrl', "");
if (!$avatarUrl) {
response::err_lack_param();
}
$avatar_file = file_get_contents($avatarUrl);
$logo = $this->changeAvatar($avatar_file);
//獲取小程序碼
$data['scene'] = $this->_req->getQuery('code', 1);
$data['width'] = (int)$this->_req->getQuery('width', 280);
$data['auto_color'] = $this->_req->getQuery('auto_color');
$data['line_color'] = $this->_req->getQuery('line_color'); //看了很多人說設置線條顏色失敗,我也嘗試了下,發現失敗可能存在這兩個原因其一:1、沒有設置auto_color的值為true;2、設置的顏色微信還不支持。我嘗試的rgb(255,0,0)是可以的,但是rgb(0,255,0)就不支持了。所以遇到設置線條顏色無效的可以先設置rgb(255,0,0)看看先
$data['is_hyaline'] = $this->_req->getQuery('is_hyaline'); //設置二維碼底色是否透明,默認false
$data['page'] = $this->_req->getQuery('path');
$wxModel = new \Hd\WxAuthModel();
$Qr_code = $wxModel->getShareCode($data); //生成小程序碼接口
// file_put_contents('/tmp/tmp_qr.png',$Qr_code); exit; //這里先看一下生成的小程序碼是否是自己設置的格式
//小程序碼與頭像進行拼接
$url = $this->makeOnePic($Qr_code, $logo);
response::result($url);
}
private function makeOnePic($qr_code, $logo) //二維碼與頭像組合
{
$qr_code = imagecreatefromstring($qr_code); //生成的二維碼底色為白色
//設置二維碼為透明底
imagesavealpha($qr_code, true); //這個設置一定要加上
$bg = imagecolorallocatealpha($qr_code, 255, 255, 255, 127); //拾取一個完全透明的顏色,最后一個參數127為全透明
imagefill($qr_code, 0, 0, $bg);
$icon = imagecreatefromstring($logo); //生成中間圓形logo (微信頭像獲取到的logo的大小為132px 132px)
$qr_width = imagesx($qr_code); //二維碼圖片寬度
// $qr_height = imagesy($qr_code); //二維碼圖片高度
$lg_width = imagesx($icon); //logo圖片寬度
$lg_height = imagesy($icon); //logo圖片高度
// var_dump($qr_width,$qr_height);
// var_dump($lg_width,$lg_height);
$qr_lg_width = $qr_width / 2.2;
$scale = $lg_width / $qr_lg_width;
$qr_lg_height = $lg_height / $scale;
$start_width = ($qr_width - $lg_width) / 2 + 2; //(獲取logo的左上方的位置:( 外部的正方形-logo的寬 ) / 2,我這邊存在1px的偏差 我就給+2啦)
// var_dump($scale,$qr_lg_height);
// var_dump($start_width);
imagecopyresampled($qr_code, $icon, $start_width, $start_width, 0, 0, $qr_lg_width, $qr_lg_height, $lg_width, $lg_height);
//傳回處理好的圖片url
// $qrcode = "/imgs/qrCode" . time() . ".png";
// $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
// $tmp_url = $protocol . $_SERVER['HTTP_HOST'] . $qrcode; //LCT這個需上線后除去
// response::result($tmp_url);
imagepng($qr_code); //保存
imagedestroy($qr_code);
imagedestroy($icon);
exit;
}
private function changeAvatar($avatar)
{
//處理用戶頭像為圓形icon
$avatar = imagecreatefromstring($avatar);
$w = imagesx($avatar);
$h = imagesy($avatar);
$w = min($w, $h);
$h = $w;
$img = imagecreatetruecolor($w, $h);
imagesavealpha($img, true);
$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($avatar, $x, $y);
if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
}
}
ob_start();
imagepng($img);
imagedestroy($img);
imagedestroy($avatar);
$contents = ob_get_contents(); 、、讀取緩存區的內容
ob_end_clean(); //清空緩存區
return $contents;
}
public function getShareCode($data) //生成小程序碼
{
$access_token = $this->getAccessToken(); //獲取access_token這個要設置token緩存,具體可以查看我的另一篇文章
$res_url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=$access_token";
header('content-type:image/png');
$data = json_encode($data);
$Qr_code = $this->http_request($res_url, $data);
return $Qr_code;
}
遇到的困難:
*之前將頭像圖片、處理成圓形頭像的圖片及最后的組合圖都先生成本地圖片,然后再處理,這樣就多了一個圖片存放的問題,在用戶很多的時候可能會產生很多不需要的圖。
*要求最終生成的二維碼為透明的底,一般來說是在生成二維碼的時候設置is_hyaline=true就可以了,但是我們這里再次對二維碼數據流進行再次生成,imagecreatefromstring()默認生成的為白色底,這樣就讓生成的透明底二維碼又帶了白色底。一直以為微信的is_hyaline配置無效。( T _ T )
存在的問題:
最后生成的二維碼中間的icon可能會出現位置不居中的問題。這個我這邊設置大小width大小為280左右的時候就大概能看。應該是算icon圖位置的時候沒有設好。這個有空要重新來一遍。
*** 突發bug: 未設置頭像的微信用戶 得到的二維碼為空白圖 (新申請的微信賬號一開始是無頭像的,哈哈哈這操作,我無知了~)
解決方式:
2019-03-22更新:
public function makeNewQrCodeAction()
{
//獲取用戶頭像並轉string
$avatarUrl = $this->_req->getQuery('avatarUrl', "");
// if (!$avatarUrl) {
// response::err_lack_param();
//}
if (!$avatarUrl) {
$avatarUrl = file_get_content(APP_PATH . "/public/imgs/default.png"); //這邊如果微信用戶沒有設置頭像,給一個默認的頭像,不然得到的二維碼是空白圖。
}
$avatar_file = file_get_contents($avatarUrl);
$logo = $this->changeAvatar($avatar_file);
//獲取小程序碼
$data['scene'] = $this->_req->getQuery('code', 1);
$data['width'] = (int)$this->_req->getQuery('width', 280);
$data['auto_color'] = $this->_req->getQuery('auto_color');
$data['line_color'] = $this->_req->getQuery('line_color'); //看了很多人說設置線條顏色失敗,我也嘗試了下,發現失敗可能存在這兩個原因其一:1、沒有設置auto_color的值為true;2、設置的顏色微信還不支持。我嘗試的rgb(255,0,0)是可以的,但是rgb(0,255,0)就不支持了。所以遇到設置線條顏色無效的可以先設置rgb(255,0,0)看看先
$data['is_hyaline'] = $this->_req->getQuery('is_hyaline'); //設置二維碼底色是否透明,默認false
$data['page'] = $this->_req->getQuery('path');
$wxModel = new \Hd\WxAuthModel();
$Qr_code = $wxModel->getShareCode($data); //生成小程序碼接口
// file_put_contents('/tmp/tmp_qr.png',$Qr_code); exit; //這里先看一下生成的小程序碼是否是自己設置的格式
//小程序碼與頭像進行拼接
$url = $this->makeOnePic($Qr_code, $logo);
response::result($url);
}
再次更新:
遇到的問題:組合得到的小程序碼有時會出現是空白。查看錯誤日志發現出現40001錯誤。
原因:開發環境的小程序appid和appsecret的賬號跟線上環境的賬號是一樣的,生成小程序碼請求到的token存在兩個不同的服務器。當某個環境的token被更新的時候,另一個環境的token雖然在緩存時間內,但是由於跟服務器的token不一致了,就會出現過期的現象。(這個真的得注意,一個小程序應該使用同一個token,保證拿到的token是最新的)
解決思路:
1、開發環境、測試環境及線上環境應該用不同的appid賬號,避免請求微信token的時候存在沖突;
2、多個環境的token存在同一個文件里,采用接口來獲取最新的token;同一個token過期會重新請求,所以能避免拿到過期token。
微信接口有時還會出現不穩定的時候,一定要做好異常處理。