微信公众号裂变式营销代码实现,先讲下基础原理,先生成带有用户参数的二维码,然后用php自带的gd库处理,生成带有用户头像,昵称,参数二维码,营销信息的自定义图片,再将图片传入微信公众号临时素材,当其他用户扫描这个专属推荐码的时候,获取用户的昵称返回给推荐者,并存入数据库,以记录当前有多少人扫描了二维码。
技术难点:
1.gd库处理图片,以前没玩过gd库,gd库很难用,建议如果不懂gd库,可以直接尝试其他的php图像处理扩展。
2.生成用户参数二维码,参数二维码选择临时二维码,参数选择字符串参数,字符串是推荐者的openid,因为openid是唯一的,是用户的标识,当然你也可以自己为用户设置标识,而且效率更高。
3.判断关注事件,是否是通过参数二维码进来的,判断方法可查微信公众号开发文档的关注事件推送。
4.应用到的技术:PHP,curl扩展,gd扩展,mysqli,
话不多说,直接上代码,还有其他想了解的,直接留言。
第一段代码,yanzheng.php,用来接收微信端返回的信息的,如果自己有,请不要照抄,直接看关注事件部分以及自定义菜单,有注释。
<?php
/**
* wechat php test
*/
//define your token
// session_start();
//定义TOKEN秘钥
define("TOKEN", "weixin");
//实例化微信对象
$wechatObj = new wechatCallbackapiTest();
//验证成功后注释valid方法
// $wechatObj->valid();
//开启自动回复功能
$wechatObj->responseMsg();
//定义类文件
class wechatCallbackapiTest
{
//实现valid验证方法:实现对接微信公众平台
public function valid()
{
//接受随机字符串
$echoStr = $_GET["echostr"];
//valid signature , option
//进行用户数字签名验证
if($this->checkSignature()){
//如果成功,则返回接受到的随机字符串
echo $echoStr;
//退出
exit;
}
}
//定义自动回复功能
public function responseMsg()
{
//get post data, May be due to the different environments
//接受用户端发送过来的xml数据
$postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
//extract post data
//判断xml数据是否为空
if (!empty($postStr)){
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
//通过simplexml进行xml解析
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
//接受微信的手机端
$fromUsername = $postObj->FromUserName;
//微信公众平台
$toUsername = $postObj->ToUserName;
//接受用户发送的关键词
$keyword = trim($postObj->Content);
//1.接受用户消息类型
$msgType = $postObj -> MsgType;
//时间戳
$time = time();
//事件类型
$event = $postObj->Event;
//自定义菜单事件K值
$eventkey = $postObj->EventKey;
$ticket=$postObj->Ticket;
//文本发送模板
$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>";
//图片发送模板
$imageTpl = "<xml>
<ToUserName>< ![CDATA[%s] ]></ToUserName>
<FromUserName>< ![CDATA[%s] ]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType>< ![CDATA[%s] ]></MsgType>
<Image>
<MediaId>< ![CDATA[%s] ]></MediaId>
</Image>
</xml>
";
//关注事件
if($event=='subscribe') {
$msgType = "text";
$contentStr = "感谢关注德盛康大药房!
您可以\n
<a href='https://m.xxxx.com/ceshi.php'>在线购药</a>\n
<a href='https://m.xxxx.com/zixunyaoshi'>药品咨询</a>\n
<a href='https://m.xxxx.com/weixin/lxfs.html'>联系门店</a>";
$resultStr = sprintf($textTpl,$fromUsername,$toUsername,$time,$msgType,$contentStr);
echo $resultStr;
if(isset($eventkey)){
$canshu = substr($eventkey,8);
$data = array('canshu' =>$canshu,'openid'=>$fromUsername );
hurl("https://m.xxxxx.com/weixin/moban2.php",$data);
}
}
//扫描带参数的二维码的图片
// if($event=='subscribe' && isset($eventkey)){
// // $data = $eventkey;
// // hurl("https://m.39dsk.com/weixin/moban2.php",$data);
// // exit("success");
// $msgType = "text";
// $contentStr = substr($eventkey,8);
// $resultStr = sprintf($textTpl,$fromUsername,$toUsername,$time,$msgType,$contentStr);
// echo $resultStr;
// }
//自定义菜单事件
if ($event=='CLICK' && $msgType=='event') {
if ($eventkey == "jfhg") {
$contentStr = "您点击了积分换购,很抱歉,该功能未上线!";
$msgType = "text";
$resultStr = sprintf($textTpl,$fromUsername,$toUsername,$time,$msgType,$contentStr);
echo $resultStr;
}
if ($eventkey == "mfly") {
$data = $fromUsername;
$contentStr = "已生成您的专属推荐码,邀请10位好友扫描关注我们,可免费领取XXX,邀请码稍有延迟,如不能生成请再次点击免费领药";
$msgType = "text";
$resultStr = sprintf($textTpl,$fromUsername,$toUsername,$time,$msgType,$contentStr);
echo $resultStr;
hurl("https://m.xxxxx.com/weixin/weweima.php",$data);
}
}
//用户消息事件
if($msgType=='text'&&$keyword=="1"){
$msgType = "text";
$contentStr = "00";
$resultStr = sprintf($textTpl,$fromUsername,$toUsername,$time,$msgType,$contentStr);
echo $resultStr;
}
if ($msgType=='text'&&$keyword=="本期活动") {
// $msgType = "text";
// $contentStr = "22";
// $resultStr = sprintf($textTpl,$fromUsername,$toUsername,$time,$msgType,$contentStr);
// echo $resultStr;
include_once "kefujiekou2.php";
}
exit("success");
}
}
private function checkSignature()
{
// you must define TOKEN by yourself
//判断是否定义了TOKEN,如果没有就抛出一个异常
if (!defined("TOKEN")) {
throw new Exception('TOKEN is not defined!');
}
$signature = $_GET["signature"];//接受微信加密签名
$timestamp = $_GET["timestamp"];//接受时间戳
$nonce = $_GET["nonce"];//接受随机数
$token = TOKEN;//把TOKEN常量赋值给$token
//把相关参数组装成数组
$tmpArr = array($token, $timestamp, $nonce);
// use SORT_STRING rule
//排序
sort($tmpArr, SORT_STRING);
//把排序后的数组转换成字符串
$tmpStr = implode( $tmpArr );
//通过哈希算法加密
$tmpStr = sha1( $tmpStr );
//与加密签名进行对比
if( $tmpStr == $signature ){
//相同返回true
return true;
}else{
//不同返回false
return false;
}
}
}
function hurl($a,$data){
$th = curl_init();//初始化curl实例
curl_setopt($th,CURLOPT_URL,$a);
curl_setopt($th, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($th, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($th, CURLOPT_TIMEOUT, 1);
curl_setopt($th, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($th, CURLOPT_POST, 1);
curl_setopt($th, CURLOPT_POSTFIELDS, $data);
$zz = curl_exec($th);//执行curl
curl_close($th);//关闭curl
return $zz;
}
?>
第二段代码,erweima .php,主要是对图片进行处理,获取各种参数,只不过有图片保存到本地和上传到微信服务器,所以消耗时间过长,大家有什么好方法避免,欢迎交流。
<?php
header("Content-type:text/html;charset=utf-8");
$post = file_get_contents('php://input');//设置post消息可读
$fromUsername = $_POST[0];//接收yanzheng.php传来的信息,参加活动的用户ID
// print_r($_POST[0]);
include_once "access_token.php";//获取微信公众号的access_token,微信公众号为验证服务器的身份,access_token是必须的
$url0 = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$access_token."&openid=".$fromUsername."&lang=zh_CN";
$result0 = https_request($url0);
$a0 = json_decode($result0,true);//通过openid获取用户的头像和昵称
// echo $a0['nickname'] , $a0['headimgurl'];
$jsonmenu = '{"expire_seconds": 2592000, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str" : "'.$fromUsername.'"}}}';
$url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$access_token;
$result = https_request($url, $jsonmenu);//生成用户参数二维码的ticket,参数二维码需要用ticket换取,微信公众号规定,为什么这么规定,反正我是想不明白
$a = json_decode($result,true);
$b = UrlEncode($a['ticket']) ;//获取ticket
$url2 = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=".$b;
$result2 = https_request($url2); //参数二维码
// var_dump($result2);
//以下是GD库处理图片部分,不解释了,看GD库的文档吧
$bg = imagecreatefrompng("images/ceshi.png");
$img_info = getimagesize('images/ceshi.png');
$img_w = $img_info[0];
$img_h = $img_info[1];
$im = imagecreatetruecolor($img_w, $img_h);
$black = imagecolorallocate($im, 0, 0, 0);
$red = imagecolorallocate($im, 255, 0, 0);
imagecopy($im,$bg,0,0,0,0,$img_w,$img_h);
$font = "font/msyh.ttf";
$text = $a0['nickname'];
$text2 = '免费送药,免费咨询,快来和我一起体验吧';
imagettftext($im, 14, 0, 300, 970, $black, $font,$text);
imagettftext($im, 18, 0, 140, 1020, $red, $font,$text2);
$img2 = imagecreatefromstring($result2);//带有参数的二维码
imagecopyresized($im, $img2, 200, 470, 0, 0,320,320,430, 430);
$img3 = imagecreatefromjpeg($a0['headimgurl']);//用户头像图片
imagecopyresized($im, $img3, 300, 830, 0, 0,110,103,110, 103);
$img4 = imagecreatefrompng('images/touxiang.png');//二维码中心的头像,二维码被遮盖一小部分不影响识别,可以参考二维码原理
imagecopyresized($im, $img4, 320, 600, 0, 0,80,80,500, 500);
$img5 = imagecreatefrompng('images/yx.png');//圆角图片
imagecopyresized($im, $img5, 300, 830, 0, 0,110,110,110, 110);
header('Content-Type: image/png');
imagepng($im,'images/'.$fromUsername.'.png');
imagedestroy($im);
//GD库图片处理到此结束,将图片储存到了'images/'.$fromUsername.'.png'!
//以下是
$file = __DIR__."\images\\".$fromUsername.".png";//取出图片
// echo $file;
$obj = new CurlFile($file); //CurlFile,php高于5.5,上传文件必须要用CurlFile
$post['media'] = $obj;
$url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=".$access_token."&type=image";
$result = https_request($url,$post); //将图片信息上传至临时素材,获取素材ID
$zz = json_decode($result,true);
$data = '{
"touser":"'.$fromUsername.'",
"msgtype":"image",
"image":
{
"media_id":"'.$zz['media_id'].'"
}
}';
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token;
$result = https_request($url,$data); //利用客服接口,发送图片信息到用户
// var_dump($result);
function https_request($url,$data = null){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
?>
第三段代码,用户扫描了带参数的二维码,将事件通过模板消息的方式推送给推荐者,让他知道是谁扫描了该二维码
<?php
header("Content-type:text/html;charset=utf-8");
$post = file_get_contents('php://input');
$eventkey = $_POST['canshu'];//获取关注事件推送来的信息
$fromUsername = $_POST['openid'];
// $eventkey = "ou1RJxE7SYBEw4DBOBs8EBL0egZ0";
// $fromUsername = "ou1RJxJ0Y7yzT5H9_DG1jp0ybIy0";
if ($eventkey!=$fromUsername) {//判断不能自己扫自己,如果不加,那么用户将图片保存到本地,然后取消关注,扫自己的二维码关注是可行的。
include_once "access_token.php";//微信验证
$url0 = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$access_token."&openid=".$fromUsername."&lang=zh_CN";
$result0 = https_request($url0);
$a0 = json_decode($result0,true);
$name = $a0['nickname'];//获取扫描者的昵称
include_once "coom.php";//连接数据库,将事件存入数据库,以便判断有多少人扫描了二维码
mysqli_query($conn , "set names utf8");
$sql = "INSERT INTO biaoming ".
"(yqz,byqz) ".
"VALUES ".
"('$eventkey','$fromUsername')";
$sql2 = "SELECT *
FROM biaoming
where yqz = '$eventkey'";
$sql3 = "UPDATE biaoming
SET wancheng=1
WHERE yqz ='$eventkey'";
//biaoming = “表名”,yqz="推荐者的ID" ,byqz = "扫描者的ID"
mysqli_select_db( $conn, 'liuyanfankui');
$retval = mysqli_query( $conn, $sql );
$retval2 = mysqli_query( $conn, $sql2 );
$num = mysqli_num_rows($retval2);
$hsx = 10-$num;
if ($hsx<=0 ) {
$tt = "任务完成,请进入微信商城-->个人中心-->修改地址,填写收件信息,我们会尽快为您配送,如已填写,请忽略";
$retval3 = mysqli_query( $conn, $sql3 );
}else{
$tt = "邀请10位好友加入我们,就能获得德盛康大药房免费赠送的XXX,已邀请".$num."位,还差".$hsx."位";
}
if (!$retval) {
echo "插入失败";
}
mysqli_close($conn);
//以下发送模板消息,请查看微信公众号开发文档
$time = date("Y-m-d H:i:s");
$jsonmenu = ' {
"touser":"'.$eventkey.'",
"template_id":"模板素材ID",
"data":{
"first": {
"value":"'.$name.'通过您的二维码成为了我们的朋友!",
"color":"#173177"
},
"keyword1":{
"value":"免费领药",
"color":"#173177"
},
"keyword2": {
"value":"'.$time.'",
"color":"#173177"
},
"remark":{
"value":"'.$tt.'",
"color":"#ff0000"
}
}
}';
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token;
$result = https_request($url,$jsonmenu);
var_dump($result);
//以上为发送模板消息
}
function https_request($url,$data = null){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
?>
到此,功能基本开发完毕,但也有一些不完美的地方,最主要的是保存参数二维码到本地,然后上传参数二维码到微信服务器,这段代码耗时太长,欢迎学习交流。
有问题的,欢迎留言,本人原创