如何利用微信小程序生成小程序码实现分销功能

    小程序申请配置之类的就不多做赘述了,今天主要介绍一下实现分销的核心内容。

     该功能的核心地方就在于,使用微信小程序生成小程序码。而该小程序码中就是带有用户标识参数的,接下来一起来揭开生成带参小程序码的面纱吧。

      具体代码如下:

public function getWxAcCode()
    {
        $wx = new WxAction();
        $token = $wx->getAccessToken();//获取accesstoken

        //整理post请求参数
        $post_data = [
            'scene' => '用户id',//场景值 可以理解成用户标识 但是存在限制(文档中有说明)
            'page' => '页面路径 path',//小程序的页面路径 特别注意该路径要与小程序内定义的路径一致测试时不要添加否则会生成不了 最最重要的是路径之前不要有斜杠/ 直接以pages开头否则会提示41030
            'is_hyaline' => true //生成的小程序码图片背景是否为透明的
        ];
        $data = json_encode($post_data, true);

        //请求地址
        $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$token;
        
        $accode = $wx->sendPost($url,$data);//获取小程序二维码 返回的就是图片流信息
        $img = $this->cutPictureCircular('微信头像地址');//获取圆形头像流信息
        $qrcode = $this->mergeImages($accode,$img);//加上头像的小程序码图片流信息
        $qrcode = imagecreatefromstring($qrcode);

        // 读取背景图的信息
        $tmp = file_get_contents('./bg.png');
        $bg = imagecreatefromstring($tmp);

        // 将小程序码合并到海报图上
        imagecopyresampled($bg, $qrcode, 225, 630, 0, 0, 285, 285, imagesx($qrcode), imagesy($qrcode));

        header("Content-Type: image/png; charset=utf-8"); // 设置header头
        imagealphablending($bg, false); // (很重要)不合并颜色,直接用 PNG 图像颜色替换,包括透明色;
        imagesavealpha($bg, true);  // (很重要)设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息;
        imagepng($bg); // 保存图片为png
        imagedestroy($qrcode); // 清除画布资源
        imagedestroy($bg); // 清除画布资源
        die;
    }

/**
     * 将图片裁剪成圆形
     */
    private function cutPictureCircular($img)
    {
        // 获取图片流信息
        $info = file_get_contents($img);
        $src_img = imagecreatefromstring($info);
        $w = imagesx($src_img);
        $h = imagesy($src_img);
        $w = min($w, $h);
        $h = $w;
        $img = imagecreatetruecolor($w, $h);
        imagealphablending($img, false); // 设定图像的混色模式
        imagesavealpha($img, true); // 这一句一定要有(设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息)
        $bg = imagecolorallocatealpha($img, 255, 255, 255, 127); // 拾取一个完全透明的颜色,最后一个参数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();
        imagealphablending($img, false); // (很重要)不合并颜色,直接用 PNG 图像颜色替换,包括透明色;
        imagesavealpha($img, true);  // (很重要)设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息;
        imagepng($img);
        imagedestroy($img);
        $contents = ob_get_contents();
        ob_end_clean();
        return $contents;
    }

    /**
     * 合成图片
     */
    private function mergeImages($code,$img)
    {
        $code = imagecreatefromstring($code);
        $img = imagecreatefromstring($img);

        $QR_width = imagesx($code); // 二维码图片宽度
        $QR_height = imagesy($code); // 二维码图片高度
        $logo_width = imagesx($img); // logo图片宽度
        $logo_height = imagesy($img); // logo图片高度
        $logo_qr_width = $QR_width / 2.2; // 组合之后logo的宽度(占二维码的1/2.2)
        $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($code, $img, $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();
        imagealphablending($code, false); // (很重要)不合并颜色,直接用 PNG 图像颜色替换,包括透明色;
        imagesavealpha($code, true);  // (很重要)设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息;
        imagepng($code);
        imagedestroy($code);
        imagedestroy($img);
        $contents = ob_get_contents();
        ob_end_clean();
        return $contents;
    }

     获取accesstoken方法代码如下:

class wxAction extends Controller
{
    /**
     * 获取access_token
     */
    public function getAccessToken()
    {
        // 获取redis存储key
        $cash_key = config('redisKey')['access_token'];

        // 获取redis连接
        $redis = RedisConnect::getRedis();
        // 获取token
        $token = $redis->get($cash_key);
        // 判断是否存在 不存在或过期 获取最新的token
        if (empty($token)) {
            // 读取配置中的appid和secret
            $appid = config('appid');
            $secret = config('secret');

            $obj = file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret);
            $arr = json_decode($obj,true);
            $token = $arr['access_token'];
            
            // 存入redis并设置过期时间
            $redis->set($cash_key,$token,7000);
        }
        return $token;
    }
}

    上述代码实现了生成带有头像的小程序码的海报图,结果如下:

    微信小程序生成小程序码相关文档

    前端只需要在扫码进入的那个页面的onLoad方法中,获取小程序码中的场景值,在用户注册时传给后端就可以了。而后端需要做的就是将新用户与分享用户之间做一个关系绑定的处理剩下的就是根据实际的业务逻辑来做处理的事情了。小程序中获取小程序码的参数代码如下:

onLoad: function (options) {
  console.log(options.scene);
}