微信公眾號裂變式營銷代碼實現,先講下基礎原理,先生成帶有用戶參數的二維碼,然后用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'); }
通過官方文檔 拿到二維碼圖片鏈接
$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; } //把二維碼合並到背景圖 }
大功告成。。。。。。。。。。。。。
總結:
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