微信公众号裂变式营销代码实现,PHP


 

  

 

微信公众号裂变式营销代码实现,先讲下基础原理,先生成带有用户参数的二维码,然后用php自带的gd库处理,生成带有用户头像,昵称,参数二维码,营销信息的自定义图片,再将图片传入微信公众号临时素材,当其他用户扫描这个专属推荐码的时候,获取用户的昵称返回给推荐者,并存入数据库,以记录当前有多少人扫描了二维码。

技术难点:

1.gd库处理图片,以前没玩过gd库,gd库很难用,建议如果不懂gd库,可以直接尝试其他的php图像处理扩展。

2.生成用户参数二维码,参数二维码选择临时二维码,参数选择字符串参数,字符串是推荐者的openid,因为openid是唯一的,是用户的标识,当然你也可以自己为用户设置标识,而且效率更高。

3.判断关注事件,是否是通过参数二维码进来的,判断方法可查微信公众号开发文档的关注事件推送。

4.应用到的技术:PHP,curl扩展,gd扩展,mysqli,

话不多说,直接上代码,还有其他想了解的,直接留言。

第一步: 生成一张二维码海报 

 

 

官方文档 :https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html

 

 本人具体代码:

// wechat 带参数自定义二维码生成
    /**
     * 创建二维码ticket
     * @param int|string $scene_id 自定义追踪id,临时二维码只能用数值型
     * @param int $type 0:临时二维码;1:数值型永久二维码(此时expire参数无效);2:字符串型永久二维码(此时expire参数无效)
     * @param int $expire 临时二维码有效期,最大为604800秒
     * @return array('ticket'=>'qrcode字串','expire_seconds'=>604800,'url'=>'二维码图片解析后的短连接地址')
     */
    public function getWxCode()
    {
        \Think\Log::write(print_r($_REQUEST,true));
        $scene_desc         = I('scene_desc'); // 二维码渠道标识
        $type               = I('type'); // 类型 (3 为 单图推送)
        $expire             = I('expire_seconds'); // 过期时间
        $title              = I('title'); // 标题 (或media_id)
        $description        = I('description'); // 描述
        $picture_url        = I('picture_url'); // 图文推送的图片链接
        $url                = I('url'); // 图文跳转的链接
        $qrcode_id          = I('qrcode_id'); // 二维码id(有则为编辑,没有则为新增)
        $lottery_id          = I('lottery_id',0); // 活动id
        $wetch_com_id          = I('wetch_com_id',1,"intval"); // 1猎芯  2芯片硬创
        $media_id_url          = I('media_id_url'); // 微信图片的url地址
        $qrcode_use          = I('qrcode_use',1,"intval"); // 二维码的用途 1 普通扫码  2 裂变

        if (!$scene_desc) return $this->apiReturn(140001, '自定义渠道标识 不可为空');
        if (!isset($type)) return $this->apiReturn(140002, '类型不可为空');
        if (strval($type) === '0') {
            if (!$expire) return $this->apiReturn(140003, '临时二维码有效期不可为空');
        }

        if ($qrcode_id) { // 编辑
            $scene_id = I('scene_id');
            if (!$scene_id) return $this->apiReturn(140001, '自定义追踪id 不可为空');
        } else { // 新增
            $scene_id = $_SERVER['REQUEST_TIME']; // 自定义追踪id
            // 0:临时二维码;1:数值型永久二维码(此时expire参数无效);2:字符串型永久二维码(此时expire参数无效);3:单图
            if (strval($type) === '0' && $qrcode_use == 2) {
                //如果是裂变的二维码  就必须是永久二维码
                $type = 2;
                $codeType = 2;
                $expire = '';
            }

            if (strval($type) !== '0') {
                $expire = '';
                if($qrcode_use == 2){
                    //裂变二维码
                    $scene_id = 'liebian_' . $scene_id; // 自定义追踪id
                }else{
                    $scene_id = 'liexin_' . $scene_id; // 自定义追踪id
                }
                $type = 2;
                $codeType = 2;
                $expire = '';
            }


            $codeType = $type;
            if (strval($type) === '3') {
                //单图
                $codeType = '2';
            }
            $wechatModel = wechatPublic(intval($wetch_com_id));

            // $codeType 0:临时二维码;1:数值型永久二维码(此时expire参数无效);2:字符串型永久二维码(此时expire参数无效)
            $res = $wechatModel->getQRCode($scene_id, $codeType, $expire);
            $ticket = $wechatModel->getQRUrl($res['ticket']);
            $qrurl = $wechatModel->getShortUrl($ticket); // 获取短连接
        }

        $addData['type'] = $type; //类型(永久,暂时)
        $addData['create_time'] = $_SERVER['REQUEST_TIME']; //创建时间
        $addData['expire_seconds'] = $expire; //有效期(秒)
        $addData['scene_desc'] = $scene_desc; // 渠道标识
        $addData['title'] = $title;
        $addData['description'] = $description;
        $addData['picture_url'] = $picture_url;
        $addData['url'] = $url;
        $addData['wetch_com_id'] = $wetch_com_id;
        $addData['media_id_url'] = $media_id_url;
        $addData['qrcode_use'] = $qrcode_use;
        $addData['lottery_id'] = intval($lottery_id);

        $WxQrConfigModel = D('WxQrConfig');
        try {
            if ($qrcode_id) { // 编辑
                $map['id'] = array('eq', $qrcode_id);
                $map['scene_id'] = array('eq', $scene_id);
                $WxQrConfigModel->where($map)->save($addData);
            } else { // 新增
                $addData['qrurl'] = $qrurl;
                $addData['qrurl_logo'] = $this->qrurl_logo($qrurl,$scene_id);
                $addData['count'] = 0; //渠道统计,每次关注后新增一次
                $addData['status'] = 1;
                $addData['scene_id'] = $scene_id; //渠道id,自定义(可以是字符串或数字)
                $res = $WxQrConfigModel->add($addData);
            }
        } catch(\Exception $e){

            \Think\Log::write($e->getMessage());
            echo $e->getMessage();
        }
        return $this->apiReturn(0, 'success');
    }
View Code

通过官方文档 拿到二维码图片链接

$wechatModel = wechatPublic(intval($wetch_com_id));

            // $codeType 0:临时二维码;1:数值型永久二维码(此时expire参数无效);2:字符串型永久二维码(此时expire参数无效)
            $res = $wechatModel->getQRCode($scene_id, $codeType, $expire);
            $ticket = $wechatModel->getQRUrl($res['ticket']);
            $qrurl = $wechatModel->getShortUrl($ticket); // 获取短连接

然后对二维码加水印  加上公司水印

 /*
     * weixin_erweima_logo
     */
    protected function qrurl_logo($QR,$scene_id){
        try{
            $logo='./public/img/weixin_erweima_logo.png';
            $im = @imagecreatetruecolor(430, 430);

            $QR = imagecreatefromstring(file_get_contents($QR));
            $logo = imagecreatefromstring(file_get_contents($logo));
            $QR_width = imagesx($QR);//二维码图片宽度 
            $QR_height = imagesy($QR);//二维码图片高度 
            $logo_width = imagesx($logo);//logo图片宽度 
            $logo_height = imagesy($logo);//logo图片高度 
            $logo_qr_width = $QR_width / 5;
            $scale = $logo_width/$logo_qr_width;
            $logo_qr_height = $logo_height/$scale;
            $from_width = ($QR_width - $logo_qr_width) / 2;
            //重新组合图片并调整大小
            $a = imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
            $dir = "./public/img/";
            $filename = $scene_id."_".time()."_qr.png";
            imagepng($QR, $dir.$filename);
            if(file_exists($dir.$filename)){
                //上传图片到oss
                $res = $this->upload($dir,$filename);
                @unlink($dir.$filename);
                if(!$res) throw new \Exception("生成logo失败");
                $res = \GuzzleHttp\json_decode($res,true);
                if($res['code'] == '200' && isset($res['data'][0])){
                    return $res['data'][0];
                }else{
                    throw new \Exception("生成logo失败");
                }
            }
        }catch(\Exception $e){
            @unlink($dir.$filename);
            return $QR;
        }
    }

此处是把二维码存到了公司的oss服务  大家可以随意存储 比如可以存储到自己服务器上也可以,上传到微信里面也是可以的

    protected function upload($dir,$filename){
        $k1 = time();
        $ch = curl_init(API_DOMAIN.'/oss/upload');
        $cfile = curl_file_create(realpath($dir.$filename),"image/png",realpath($dir.$filename));
        $data = [
            'source'=>1,
            'upload'=> $cfile,
            'is_rename'=>0,
            'set_dir'=>"wechat/",
            'k1'=>$k1,
            "k2"=>md5(md5($k1).C('SUPER_AUTH_KEY'))
        ];
        curl_setopt($ch, CURLOPT_POST,1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $res = curl_exec($ch);
        curl_close($ch);
        return $res ? $res : false;
    }

 

代码注释:

 

 

 

 

这些生成二维码的方法都是第三方的扩展包,可以自己百度 thinkphp   laravel  等都有相关的扩展包下载 没必要自己去手动写

至此  二维码海报生成了。。。。。。。。。。。。。。。。。。。。。

 

 

第二步骤,用户扫描二维码后,分享  裂变 拉取新用户关注 ,达到邀请人数后,发送奖品

首先打开微信公共账号基本设置

 

 

有个服务器地址地方,

    public function callbackxinychuang(){
        if(I('get.echostr')){//token验证
            echo I('get.echostr');exit();
        }
        try{
            $wechat = new Wechat(C('WX_PUBLIC_XinYChuang.token'), C('WX_PUBLIC_XinYChuang.appid'), C('WX_PUBLIC_XinYChuang.key'));
            //$wechat = new Wechat('weixin', 'wx0078c0d21d19e76b', ''); // 目前支付仅针对正式服务号
            $data = $wechat->request();
            \Think\Log::write(print_r($data,true));
            if($data && is_array($data)){
                file_put_contents('./data.json', json_encode($data));
                \Think\Log::write(print_r($data,true));
                $this->responseXinYChuang($wechat, $data);
            }
        } catch(\Exception $e){
            file_put_contents('./error.json', json_encode($e->getMessage()));
        }
    }

 

$this->responseXinYChuang($wechat, $data);是关键 ,主要是判断消息类型和事件类型


/**

* 消息类型常量

*/

const MSG_TYPE_TEXT = 'text';

const MSG_TYPE_IMAGE = 'image';

const MSG_TYPE_VOICE = 'voice';

const MSG_TYPE_VIDEO = 'video';

const MSG_TYPE_SHORTVIDEO = 'shortvideo';

const MSG_TYPE_LOCATION = 'location';

const MSG_TYPE_LINK = 'link';

const MSG_TYPE_MUSIC = 'music';

const MSG_TYPE_NEWS = 'news';

const MSG_TYPE_EVENT = 'event';



/**

* 事件类型常量

*/

const MSG_EVENT_SUBSCRIBE = 'subscribe';

const MSG_EVENT_UNSUBSCRIBE = 'unsubscribe';

const MSG_EVENT_SCAN = 'SCAN';

const MSG_EVENT_LOCATION = 'LOCATION';

const MSG_EVENT_CLICK = 'CLICK';

const MSG_EVENT_VIEW = 'VIEW';



responseXinYChuang方法代码片段:
switch ($data['MsgType']) {
            case Wechat::MSG_TYPE_EVENT:
                switch ($data['Event']) {
                    case Wechat::MSG_EVENT_SUBSCRIBE://关注事件
                        \Think\Log::write($data);
                        // 裂变二维码关注

                        if (isset($data['EventKey']) && $data['Event'] == 'subscribe' && strrpos($data['EventKey'],"qrscene_liebian") !== false){
                            $EventKey = str_replace("qrscene_", "", $data['EventKey']);
                            \Think\Log::write($EventKey);
                            $fromOpenid = "";
                            if(strrpos($EventKey,"_@_") === false){
                                $EventKey = $EventKey;
                            }else{
                                list($EventKey,$fromOpenid) = explode("_@_",$EventKey);
                            }

                            \Think\Log::write($EventKey);
                            $WxQrConfigModel = D('WxQrConfig');

                            $openid = $data['FromUserName']; //必须先赋值,不然获取不了值
                            $this->addScanCounts($EventKey, $openid); // 扫码统计处理

                            $this->addScanScribe($EventKey, $openid); // 扫码关注统计处理

                            $map = array();
                            $map['scene_id'] = $EventKey;
                            $WxQrConfigModel->where($map)->setInc('count');

                            $info = $WxQrConfigModel->where($map)->find();
                            \Think\Log::write(print_r($info,true));
                            if($info){
                                $this->liebian($info,$wechat,$data,$fromOpenid);
                            }

                        }


                        /**
                         * 普通二维码关注回复
                         */
                        if (isset($data['EventKey'])){
                            $EventKey = str_replace("qrscene_", "", $data['EventKey']);
                            $WxQrConfigModel = D('WxQrConfig');

                            $openid = $data['FromUserName']; //必须先赋值,不然获取不了值
                            $this->addScanCounts($EventKey, $openid); // 扫码统计处理

                            $this->addScanScribe($EventKey, $openid); // 扫码关注统计处理

                            $map = array();
                            $map['scene_id'] = $EventKey;
                            $WxQrConfigModel->where($map)->setInc('count');
                            //根据是否有首关元素
                            //replyText 文本
                            //replyNewsOnce 图文
                            $info = $WxQrConfigModel->where($map)->find();
                            if($info){
                                $title = $info['title'];
                                $description = $info['description'];
                                $url = $info['url'];
                                $picture_url = $info['picture_url'];
                                $info['tt'] = 1;
                                // $this->logger($info);
                                if ($info['type'] == '3') { // 单图输出
                                    $wechat->replyImage($title);die;
                                }
                                if ($info['url'] && $info['title'] && $info['description'] && $info['picture_url']) {
                                    $wechat->replyNewsOnce($title, $description, $url, $picture_url);die;
                                } else if ($description) {
                                    $wechat->replyText($description);die;
                                }
                            }

                        }



                        //首次关注推送信息
                        $wechat->replyText(C("WX_PUBLIC_XinYChuang.first_desc"));die;

                        //首次关注推送信息
                        $WxReplyModel = new \Wechat\Model\WxReplyModel('wx_keyword','lie_','MKTWX_DB_CONFIG');
                        $res = $WxReplyModel->where("status = 1 and toUserType=2")->field("type,content")->limit(1)->order("create_time desc")->find();
                        if($res  && !empty($res)){
                            $content  = json_decode($res['content'],true);
                            $this->autoReply($res['type'],$wechat,$content,$data);
                        }else{
                            $wechat->replyText('欢迎关注芯硬件创客');die;
                        }
                        die;

                        break;

当$data['MsgType'] ==    ‘’event‘   并且   $data['Event']  == “subscribe”  就是进入了首次关注事件:

此时我们的裂变需求可以在这个里面进行开发

if (isset($data['EventKey']) && $data['Event'] == 'subscribe' && strrpos($data['EventKey'],"qrscene_liebian") !== false){
                            $EventKey = str_replace("qrscene_", "", $data['EventKey']);
                            \Think\Log::write($EventKey);
                            $fromOpenid = "";
                            if(strrpos($EventKey,"_@_") === false){
                                $EventKey = $EventKey;
                            }else{
                                list($EventKey,$fromOpenid) = explode("_@_",$EventKey);
                            }

                            \Think\Log::write($EventKey);
                            $WxQrConfigModel = D('WxQrConfig');

                            $openid = $data['FromUserName']; //必须先赋值,不然获取不了值
                            $this->addScanCounts($EventKey, $openid); // 扫码统计处理

                            $this->addScanScribe($EventKey, $openid); // 扫码关注统计处理

                            $map = array();
                            $map['scene_id'] = $EventKey;
                            $WxQrConfigModel->where($map)->setInc('count');

                            $info = $WxQrConfigModel->where($map)->find();
                            \Think\Log::write(print_r($info,true));
                            if($info){
                                $this->liebian($info,$wechat,$data,$fromOpenid);
                            }

                        }

 

我们有一个后台用来管理二维码和关键词回复的

 

 

 

 

 

 你们没有也没关系,此处可以忽略。。。。。。

strrpos($data['EventKey'],"qrscene_liebian") !== false
主要关注这条判断,通过判断 EventKey 是不是你要做裂变拉取用户的 事件

然后开始重点了........................
看$this->liebian()方法


/**
     * @param $wechat
     * @param $data
     * 裂变
     * 第一次扫码 返回 {"ToUserName":"gh_c906f7a913dd","FromUserName":"o3We-wJWDFABO_ZXjmHbUdddNSc0","CreateTime":"1586403112","MsgType":"event","Event":"subscribe","EventKey":"qrscene_liexin_1586316369","Ticket":"gQEg8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAycERkU3RZdERlLTAxMDAwME0wNzEAAgRSRI1eAwQAAAAA"}
     * 分享后:
     *  {"ToUserName":"gh_c906f7a913dd","FromUserName":"o3We-wGVVAe-6h8z3D9akUhhZlxo","CreateTime":"1586403859","MsgType":"event","Event":"subscribe","EventKey":"qrscene_liexin_1586316369_@_o3We-wKekDrE2XkKCB7jYsiXKhhI","Ticket":"gQGp8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyZkRSWXRQdERlLTAxMDAwMDAwN3YAAgRrmI5eAwQAAAAA"}
     * $info    lie_wx_qr_config表信息
     * $wechat   对象
     * $resdata  关注二维码后 返回的信息
     * $fromOpenid  分享者的openid
     */
    public function liebian($info,$wechat,$resdata,$fromOpenid,$isShare=true){
        try{
            $description = $info['description'];


            //如果该用户已经扫描了该二维码  1从海报  2从他人  提示已经扫描过了二维码了

            if($fromOpenid){
                $where = sprintf(" wx_qr_config_id = %d  and (from_openid = '%s' or openid = '%s') ",intval($info["id"]),$fromOpenid,$resdata["FromUserName"]);
            }else{
                $where = sprintf(" wx_qr_config_id = %d  and (from_openid = '%s' or openid = '%s') ",intval($info["id"]),$resdata["FromUserName"],$resdata["FromUserName"]);
            }

            $isSaoMa = M("WxQrRelation")->where($where)->count("id");

            if($description){
                $msgType = "text";
                $textTpl = "<xml>
                              <ToUserName><![CDATA[%s]]></ToUserName>
                              <FromUserName><![CDATA[%s]]></FromUserName>
                              <CreateTime>%s</CreateTime>
                              <MsgType><![CDATA[%s]]></MsgType>
                              <Content><![CDATA[%s]]></Content>
                              <FuncFlag>0</FuncFlag>
                              </xml>";
                $description  =   htmlspecialchars_decode($description,ENT_QUOTES);
                $resultStr = sprintf($textTpl,$resdata["FromUserName"],$resdata["ToUserName"],time(),$msgType,$description);
                echo $resultStr;
            }


            $wechatModel = wechatPublic(intval($info["wetch_com_id"]));


            $this->liebianPushText($wechatModel,$resdata["FromUserName"],C("XINYINGCHUANG_LIEBIAN_CONFIG.liebianPushText"));


            if ($info['picture_url']) { // 推送新的分享二维码图片
                $this->liebianPushImage($wechatModel,$resdata["FromUserName"],$info);
            }


            //添加扫码记录

            if(!$isSaoMa){
                $insertQrRelation = M("WxQrRelation")->add([
                    "wx_qr_config_id" => $info["id"],
                    "scene_id" => $info["scene_id"],
                    "from_openid" => $fromOpenid ? $fromOpenid : "",
                    "openid" => $resdata["FromUserName"],
                    "create_time" => time(),
                ]);
            }




            //判断邀请是否成功 成功就推送消息
            //分享15个好友就可以提示分享者成功 拿到口令
            if(!$isSaoMa && $fromOpenid && $isShare){
                //发送口令 查询是否达到分享15个
                $hasFenXiangNums = M("WxQrRelation")->where(["from_openid"=>$fromOpenid,"wx_qr_config_id" => intval($info["id"])])->count();
                $pushNums = C("XINYINGCHUANG_LIEBIAN_CONFIG.PushNums");
                $cachePushFinishKey = $info["scene_id"].$fromOpenid;
                if($hasFenXiangNums >= intval($pushNums) && !S($cachePushFinishKey)){
                    //给分享者发送  任务完成的消息  领取奖品
                    $content = C("XINYINGCHUANG_LIEBIAN_CONFIG.fromOpenidFinishPush");
                    $this->liebianPushText($wechatModel,$fromOpenid,$content);
                    //小姐姐微信  领取奖品
                    $this->pushImage($wechatModel,$fromOpenid,C("XINYINGCHUANG_LIEBIAN_CONFIG.PushImagewxFriendsMedia_id"));
                    S($cachePushFinishKey,1,["expire"=>3600*24*7]);
                }


                $content = C("XINYINGCHUANG_LIEBIAN_CONFIG.toOpenidFinishPush");
                $this->liebianPushText($wechatModel,$resdata["FromUserName"],$content);
            }



        }catch(\Exception $e){
            \Think\Log::write($e->getMessage());
        }
    }

 

裂变需求一般是先推送两个文本消息,然后在推送一张海报,海报上要有用户的头像,昵称,和该事件的二维码

 

1,发送一条文本消息

$msgType = "text";
                $textTpl = "<xml>
                              <ToUserName><![CDATA[%s]]></ToUserName>
                              <FromUserName><![CDATA[%s]]></FromUserName>
                              <CreateTime>%s</CreateTime>
                              <MsgType><![CDATA[%s]]></MsgType>
                              <Content><![CDATA[%s]]></Content>
                              <FuncFlag>0</FuncFlag>
                              </xml>";
                $description  =   htmlspecialchars_decode($description,ENT_QUOTES);
                $resultStr = sprintf($textTpl,$resdata["FromUserName"],$resdata["ToUserName"],time(),$msgType,$description);
                echo $resultStr;

2,推送一条客服消息

$wechatModel = wechatPublic(intval($info["wetch_com_id"]));


            $this->liebianPushText($wechatModel,$resdata["FromUserName"],C("XINYINGCHUANG_LIEBIAN_CONFIG.liebianPushText"));
    /*
     * 裂变发送文本消息
     */
    protected function liebianPushText($wechatModel,$openid="",$content){
        try{
            $wechatModel = $wechatModel;
            $data["touser"] = $openid;
            $data["msgtype"] = "text";
            $data['text']["content"] = $content;
            $wechatModel->sendCustomMessage($data);
        }catch(\Exception $e){

        }
    }

 

$wechatModel->sendCustomMessage方法thinkphp第三方微信包  laravel  yii等都有相关的包可以下载 

3,发送海报 海报上要有用户昵称 图像 还有二维码 (重点介绍的)
$this->liebianPushImage($wechatModel,$resdata["FromUserName"],$info);


    /*
     * 裂变发送图片二维码推送消息
     */
    protected function liebianPushImage($wechatModel,$openid="",$info){
        try{
            //缓存发给用户的二维码key
            $cacheKey = $info["wx_qr_config_id"]."_".$info["scene_id"]."_".$openid."media_id";
            $wechatModel = $wechatModel;
            $data["touser"] = $openid;
            $data["msgtype"] = "image";
            if(!S($cacheKey)){
                $media_id = $this->getNewMediaId($wechatModel,$info["picture_url"],$openid,$info);
                S($cacheKey,$media_id,["expire"=>3600*24*7]);
            }else{
                $media_id = S($cacheKey);
            }
            $data['image']["media_id"] = $media_id;
            $wechatModel->sendCustomMessage($data);
        }catch(\Exception $e){

        }

    }

 

/*
     * params:$backgroundImage 背景图  $openid  $info后台二维码相关数据
     * 生成带参数的二维码
     * 背景图+二维码+用户昵称
     * 上传到微信
     * return  media_id
     */
    public function getNewMediaId($wechatModel,$backgroundImage,$openid,$info){
        try{

            $wechatModel = $wechatModel;
            $userinfo = $wechatModel->getUserInfo($openid);

            //获取带参数的二维码
            $wechatModel = $wechatModel;
            $scene_id = trim($info["scene_id"])."_@_".$openid;
            $res = $wechatModel->getQRCode($scene_id, 2, 3600*24*5);
            $QRUrl = $wechatModel->getQRUrl($res['ticket']);
            $erweima = $this->qrurl_logo($QRUrl,$scene_id);


            $logo='./public/img/weixin_erweima_logo.png';
            $im = @imagecreatetruecolor(430, 430);

            $originImage = imagecreatefromstring(file_get_contents($backgroundImage));


            $qrcodeImage = imagecreatefromstring(file_get_contents($erweima));

            $origin_width = imagesx($originImage);//原始背景图片宽度 
            $origin_height = imagesy($originImage);//原始背景图片高度 


            $qrcode_width = imagesx($qrcodeImage);//二维码图片宽度 
            $qrcode_height = imagesy($qrcodeImage);//二维码图片高度 


//            echo sprintf("%s,%s,%s,%s",$origin_width,$origin_height,$qrcode_width,$qrcode_height);
//            exit;


            $logo_qr_width = $origin_width / 2;
            $scale = $qrcode_width/$logo_qr_width;
            $logo_qr_height = $origin_height/$scale;



            $from_width = ($origin_width - 200) / 2;
            $from_height = ($origin_height/2+($origin_height/2-200)/2);
            //重新组合图片并调整大小
            // 目标图 源图 目标X坐标点 目标Y坐标点 源的X坐标点 源的Y坐标点 目标宽度 目标高度 源图宽度 源图高度
//            $a = imagecopyresampled($originImage, $qrcodeImage, $from_width, $from_height, 0, 0,200,200,$qrcode_width, $qrcode_height);
            imagecopyresampled($originImage, $qrcodeImage, 285,  1720, 0, 0,180,180,$qrcode_width, $qrcode_height);


            if($userinfo){
                if(isset($userinfo["nickname"]) && $userinfo["nickname"]){
                    $red = imagecolorallocate($im, 255, 255, 255);
                    $font = "./public/font/Droid Sans Fallback.ttf";
//                    $font = "./public/font/DroidSansChinese.ttf";
                    $content=  sprintf("%s,邀您一起免费参加~",$userinfo["nickname"]);
//                    list($post_0,,$post_2,,,,,) = imagettfbbox(24 , 0,$font, $content);
//                    imagettftext($originImage, 20, 0, ($origin_width-$post_2)/2+50, 40, $red, $font,$content);
                    imagettftext($originImage, 20, 0, 0, 40, $red, $font,$content);
                }

                if(isset($userinfo["headimgurl"]) && $userinfo["headimgurl"]){
//                    dump($userinfo["headimgurl"]);
//                    $user_touxiang  = $this->radius_img($userinfo["headimgurl"],60);
//                    $user_touxiang = $userinfo["headimgurl"];
//                    $usertouxiang = imagecreatefromstring(file_get_contents($user_touxiang));
//                    $touxiang_width = imagesx($usertouxiang);//二维码图片宽度 
//                    $touxiang_height = imagesy($usertouxiang);//二维码图片高度 
//                    imagecopyresampled($originImage, $usertouxiang, 300,  1000, 0, 0,100,100,$touxiang_width, $touxiang_height);
                }


            }

//            header('Content-type: image/jpeg');
            $filename = "./public/liebian_001_o3We-wJWDFABO_ZXjmHbUdddNSc0.jpg";
            imagejpeg($originImage,$filename,90); // 输出图象到浏览器或文件
            imagedestroy($originImage);
            $weData['media'] = '@' . $filename;
            $type = 'image';
            $res = $wechatModel->uploadForeverMedia($weData, $type);
            \Think\Log::write(print_r($res,true));
            if ($res && $res['url'] && $res['media_id']) {
                return $res['media_id'];
            }
            return false;
        }catch(\Exception $e){
            \Think\Log::write($e->getMessage());
           return false;
        }

        //把二维码合并到背景图




    }

 

代码主要做了些什么?

1,通过微信官方文档获取关注用户信息(openid 头像 昵称)

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId

 

 

2,先拿到海报的url地址,也就是我们所有的海报背景图($backgroundImage)

 

3,生成带参数的二维码(利用第三方扩展包生成的)

生成带参数二维码方法,官网有

https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html

 

 此处的二维码scene_id 记得和你刚开始生成的第一张  二维码相同哦 

我是用的 第一张分享出的二维码拼接open_id实现的 

然后首次关注里面我也巧妙的分割实现了获取EventKey的方法

$EventKey = str_replace("qrscene_", "", $data['EventKey']);
                            \Think\Log::write($EventKey);
                            $fromOpenid = "";
                            if(strrpos($EventKey,"_@_") === false){
                                $EventKey = $EventKey;
                            }else{
                                list($EventKey,$fromOpenid) = explode("_@_",$EventKey);
                            }

 

//获取带参数的二维码
            $wechatModel = $wechatModel;
            $scene_id = trim($info["scene_id"])."_@_".$openid;
            $res = $wechatModel->getQRCode($scene_id, 2, 3600*24*5);
            $QRUrl = $wechatModel->getQRUrl($res['ticket']);
            $erweima = $this->qrurl_logo($QRUrl,$scene_id);

 

到这里,海报背景有了,二维码也有了, 用户信息也有了,剩下的工作就是合成新的图片并上传到微信里面

1,先生成关联用户信息的带参数的二维码,然后可以把公司logo或者用户头像合成到一张新图片A上

A图片=   带参数(用户openid+scene_id)的二维码+logo(公司logo或者用户头像)

 

 

2,把A图片合并到海报背景图上面去

 

 

3,把用户昵称合并到海报上去

 

 

 

/*
     * params:$backgroundImage 背景图  $openid  $info后台二维码相关数据
     * 生成带参数的二维码
     * 背景图+二维码+用户昵称
     * 上传到微信
     * return  media_id
     */
    public function getNewMediaId($wechatModel,$backgroundImage,$openid,$info){
        try{

            $wechatModel = $wechatModel;
            $userinfo = $wechatModel->getUserInfo($openid);

            //获取带参数的二维码
            $wechatModel = $wechatModel;
            $scene_id = trim($info["scene_id"])."_@_".$openid;
            $res = $wechatModel->getQRCode($scene_id, 2, 3600*24*5);
            $QRUrl = $wechatModel->getQRUrl($res['ticket']);
            $erweima = $this->qrurl_logo($QRUrl,$scene_id);


            $logo='./public/img/weixin_erweima_logo.png';
            $im = @imagecreatetruecolor(430, 430);

            $originImage = imagecreatefromstring(file_get_contents($backgroundImage));


            $qrcodeImage = imagecreatefromstring(file_get_contents($erweima));

            $origin_width = imagesx($originImage);//原始背景图片宽度 
            $origin_height = imagesy($originImage);//原始背景图片高度 


            $qrcode_width = imagesx($qrcodeImage);//二维码图片宽度 
            $qrcode_height = imagesy($qrcodeImage);//二维码图片高度 


//            echo sprintf("%s,%s,%s,%s",$origin_width,$origin_height,$qrcode_width,$qrcode_height);
//            exit;


            $logo_qr_width = $origin_width / 2;
            $scale = $qrcode_width/$logo_qr_width;
            $logo_qr_height = $origin_height/$scale;



            $from_width = ($origin_width - 200) / 2;
            $from_height = ($origin_height/2+($origin_height/2-200)/2);
            //重新组合图片并调整大小
            // 目标图 源图 目标X坐标点 目标Y坐标点 源的X坐标点 源的Y坐标点 目标宽度 目标高度 源图宽度 源图高度
//            $a = imagecopyresampled($originImage, $qrcodeImage, $from_width, $from_height, 0, 0,200,200,$qrcode_width, $qrcode_height);
            imagecopyresampled($originImage, $qrcodeImage, 285,  1720, 0, 0,180,180,$qrcode_width, $qrcode_height);


            if($userinfo){
                if(isset($userinfo["nickname"]) && $userinfo["nickname"]){
                    $red = imagecolorallocate($im, 255, 255, 255);
                    $font = "./public/font/Droid Sans Fallback.ttf";
//                    $font = "./public/font/DroidSansChinese.ttf";
                    $content=  sprintf("%s,邀您一起免费参加~",$userinfo["nickname"]);
//                    list($post_0,,$post_2,,,,,) = imagettfbbox(24 , 0,$font, $content);
//                    imagettftext($originImage, 20, 0, ($origin_width-$post_2)/2+50, 40, $red, $font,$content);
                    imagettftext($originImage, 20, 0, 0, 40, $red, $font,$content);
                }

                if(isset($userinfo["headimgurl"]) && $userinfo["headimgurl"]){
//                    dump($userinfo["headimgurl"]);
//                    $user_touxiang  = $this->radius_img($userinfo["headimgurl"],60);
//                    $user_touxiang = $userinfo["headimgurl"];
//                    $usertouxiang = imagecreatefromstring(file_get_contents($user_touxiang));
//                    $touxiang_width = imagesx($usertouxiang);//二维码图片宽度 
//                    $touxiang_height = imagesy($usertouxiang);//二维码图片高度 
//                    imagecopyresampled($originImage, $usertouxiang, 300,  1000, 0, 0,100,100,$touxiang_width, $touxiang_height);
                }


            }

//            header('Content-type: image/jpeg');
            $filename = "./public/liebian_001_o3We-wJWDFABO_ZXjmHbUdddNSc0.jpg";
            imagejpeg($originImage,$filename,90); // 输出图象到浏览器或文件
            imagedestroy($originImage);
            $weData['media'] = '@' . $filename;
            $type = 'image';
            $res = $wechatModel->uploadForeverMedia($weData, $type);
            \Think\Log::write(print_r($res,true));
            if ($res && $res['url'] && $res['media_id']) {
                return $res['media_id'];
            }
            return false;
        }catch(\Exception $e){
            \Think\Log::write($e->getMessage());
           return false;
        }

        //把二维码合并到背景图




    }
View Code

 

大功告成。。。。。。。。。。。。。

 

 

 

总结:

1,先生成一个带参数的二维码比如(scene_id=liebian_001)分享出去 可以试试微信群也可以是做户外活动等等

2,用户扫描带参数二维码后

  通过关注事件,拿到用户相关信息 比如openid  eventkey

  eventkey ==  liebian_001

3,获取用户信息,拿到用户昵称 头像 openid 

4,通过scene_id=liebian_001     scene_id拼接上用户的openid生成一张和用户有关联的带参数的二维码

 

5,可以把用户头像或者logo合成到二维码上 居中显示


6,把新生成的和用户有关联的带参数的二维码 合并到   事先准备好的海报上  通过定位找到 x y坐标

 

 

7,把用户昵称合并到海报上

 

 

8,可以推送文本消息+客服消息 把你准备好的文字和图片 发给用户

 

9统计用户裂变数据

 

最终:

 

更多参考文献:

https://www.cnblogs.com/sunlong88/articles/12690454.html


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM