项目需求:点餐系统因推广需要,需对每个产品设置分销提成奖励
项目思路:通过微信分享接口 jssdk ,将分享者的openid以参数形式放到分享链接中,用户点击,根据openid去分配上下级关系。
微信第三方分享sdk:已包含命名空间,解压放置extend 目录下,具体目录为:extend/org/wechat/Jssdk.php
链接: https://pan.baidu.com/s/1PRZJgFaYFmKP0LfFQi6sCQ 提取码: ce4h
skd说明:因为分享需要用到 access_token ,我对这个类库文件新增了第三个参数 token,每次调用直接传最新有效的 access_token 即可。
首先解决微信sdk分享问题:
第一步:头部引入需要引用的 sdk文件
//微信分享
use org\wechat\Jssdk;
第二步:获取 jssdk 分享需要用的全局调用参数 access_token
重点:此处的token 是全局调用凭据,但是跟登陆获取到的token是不一样的,这个有效期是7200秒,并且每天有调用次数限制,如果不对其进行存储,每次调用都重新生成的话很容易用完分配的额度,存储的方法有很多,tp 的 cache,写入文件,存到数据库均可,建议不要存到数据库,减少不必要的查询更有利于页面加载,此处我用的是cache 并在6000秒的时候就重新进行获取。
public function get_access_token(){
$appid = ''; //appid
$appserce = ''; //appserce
if(Cache::get("access_token")){
$access_token = Cache::get("access_token");
}else{
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appserce;
$res = $this->http_curl($url);
$access_token = $res['access_token'];
Cache::set("access_token",$access_token,6000);
}
return $access_token;
}
/*发送远程请求*/
public function http_curl($url,$type='get',$res='json',$arr=''){
//获取imooc
//1.初始化curl
$ch = curl_init();
//2.设置curl的参数
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($type == 'post') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
}
//3.采集
$output = curl_exec($ch);
//4.关闭
curl_close($ch);
if ($res == 'json') {
return json_decode($output,true);
}
}
第三步:在需要调用分享的页面控制器中生成分享必需的参数
public function share_info(){
$appid = ''; //appid
$appserce = ''; //appserce
$get_access_token = $this->get_access_token(); //获取token
$jssdkObj = new Jssdk($appid,$appserce,$get_access_token);
$res = $jssdkObj->getSignPackage();
$appId = $res['appId'];
$timestamp = $res['timestamp'];
$nonceStr = $res['nonceStr'];
$signature = $res['signature'];
$web_url = "http://".$_SERVER['HTTP_HOST'];
$sdk_array = [
'appId'=>$appId,
'timestamp'=>$timestamp,
'nonceStr'=>$nonceStr,
'signature'=>$signature,
];
//组装分享数组
$member_session = Session::get("member_info");
if(isset($member_session) && !empty($member_session)){
$share_link = $web_url.url("index/index/index",['openid'=>$member_session['openid']]);
}else{
$share_link = $web_url.url("index/index/index");
}
$share_array = [
'share_title' => '分享标题',
'share_link' => $share_link,
'share_desc' => '分享描述',
'share_imgUrl' => $web_url.'/uploads/share.png',
];
$this->assign("share_array",$share_array);
$this->assign("sdk_array",$sdk_array);
return $this->fetch();
}
第四步:在前端html页面进行分享配置
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
function wx_share(){
wx.config({
debug: false,
appId: "{$sdk_array['appId']}",
timestamp: "{$sdk_array['timestamp']}",
nonceStr: "{$sdk_array['nonceStr']}",
signature: "{$sdk_array['signature']}",
jsApiList: [
'onMenuShareTimeline', //朋友圈
'onMenuShareAppMessage',
'hideMenuItems'
]
});
wx.ready(function(){
//朋友圈
wx.onMenuShareTimeline({
title: "{$share_array.share_title}",
link: "{$share_array.share_link}",
desc: "{$share_array.share_desc}",
imgUrl: "{$share_array.share_imgUrl}",
trigger: function (res) {
},
success: function () {
layer.open({
content: '分享成功'
,skin: 'msg'
,time: 2
});
}
});
//分享给朋友
wx.onMenuShareAppMessage({
title: "{$share_array.share_title}",
link: "{$share_array.share_link}",
desc: "{$share_array.share_desc}",
imgUrl: "{$share_array.share_imgUrl}",
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
layer.open({
content: '分享成功'
,skin: 'msg'
,time: 2
});
}
});
});
}
</script>
<script type="text/javascript">
$(document).ready(function(){
wx_share();
});
</script>
这样就获取到带有分享者标示的分享链接,分享效果图:
接下来,分享出去点击后根据接收到的openid去判断绑定关系。
重点:用户点击后因为做的有授权登陆,首次进入会进行域名重定向跳转,所以在index方法就需要对获取到的openid参数进行session保存,否则等域名重定向回来就获取不到了。
public function index(){
$openid = input("openid");
if(isset($openid) && !empty($openid)){
Session::set("share_openid",$openid);
}
//微信授权登陆流程,具体可参照我的博客微信开发三:tp5授权登陆,登陆成功后会返回一个包含用户信息的数组,假设我回调后的操作在getUserOpentId方法中进行
$wxlogic = new Wxlogic();
$wxlogic->index();
}
public function getUserOpentId(){
$code = $_GET['code'];
/*
获取用户信息我的另外一篇有说明,不做赘述,假设授权登陆后获取到的信息我放到 $member_info 中,则根据获取到的用户信息去进行业务逻辑处理
*/
//获取到用户信息,则根据用户身份进行跳转
$member_check = Loader::model("member")->check_member($member_info);
$this->redirect("index/index/index_html");
}
/*会员登陆检测是否已存在等*/
public function check_member($member_info){
$check_member = $this->member_info($member_info['openid']);
if($check_member!=-1){
//说明会员已存在,则检查头像是否是最新头像
if($check_member['headimgurl'] != $member_info['headimgurl']){
$update_data = [
'headimgurl' => $member_info['headimgurl']
];
Db::name("member")->where('openid',$member_info['openid'])->update($update_data);
}
}else{
//说明是新会员,则插入数据,新会员需要判断是否绑定上级
if(Session::has("share_openid")){
//说明是通过分享链接进入的,则需要判断是否是本人
$share_openid = Session::get("share_openid");
if($share_openid != $member_info['openid']){
//非本人,进行账号绑定
$share_info = $this->member_info($share_openid);
$par_id = $share_info['member_id'];
}else{
$par_id = 0;
}
}else{
$par_id = 0;
}
$insert_data = [
'openid' => $member_info['openid'],
'par_id' => $par_id, //父id
'nickname' => $member_info['nickname'],
'headimgurl' => $member_info['headimgurl'],
'create_time' => time()
];
Db::name("member")->insert($insert_data);
$member_info = $this->member_info($member_info['openid']);
Session::set("member_info",$member_info);
}
}
/*会员信息*/
public function member_info($openid){
$member_info = Db::name("member")->where("openid",$openid)->find();
if(isset($member_info) && !empty($member_info)){
return $member_info;
}else{
return -1;
}
}
这样,就实现了通过微信分享进行上下级绑定操作。
核心注意点:
1,需要在微信公众平台设置安全域名和授权域名,ip需要添加到白名单中。
2,微信sdk分享效果中的图片需要是网络地址,图片尺寸300*300最佳,如果分享不成功,请在 js 设置debug 为true ,就可根据提示进行相关配置
3,判断上下级关系需要判断是否是新用户,是否是本人点击本人分享链接等操作。