zoukankan      html  css  js  c++  java
  • 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 HdWxAuthModel();
            $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 HdWxAuthModel();
        $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。

    微信接口有时还会出现不稳定的时候,一定要做好异常处理。
  • 相关阅读:
    Docker容器启动时初始化Mysql数据库
    使用Buildpacks高效构建Docker镜像
    Mybatis 强大的结果集映射器resultMap
    Java 集合排序策略接口 Comparator
    Spring MVC 函数式编程进阶
    换一种方式编写 Spring MVC 接口
    【asp.net core 系列】6 实战之 一个项目的完整结构
    【asp.net core 系列】5 布局页和静态资源
    【asp.net core 系列】4. 更高更强的路由
    【Java Spring Cloud 实战之路】- 使用Nacos和网关中心的创建
  • 原文地址:https://www.cnblogs.com/xinxinmifan/p/weixinlogo.html
Copyright © 2011-2022 走看看