php實現自定義中間logo的微信小程序碼


小程序碼生成的時候是默認使用小程序后台設置的小程序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。

微信接口有時還會出現不穩定的時候,一定要做好異常處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM