用c#开发微信 (12) 微统计 - 阅读分享统计系统 2 业务逻辑实现
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读、分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问、好友分享消息访问等。本系统实现了手机网页阅读、分享与来源统计及手机网页在朋友圈的传播路径分析。
本系统使用最传统的三层架构。本文是微统计的第二篇,主要介绍如下内容:
1. 各实体具体业务实现
2. 获取分享记录
3. 获取访问来源
4. 识别访问者
5. 识别分享者
1. 各个实体具体业务实现
PageNavBll:
public class PageNavBll
{
public List<PageNavEntity> GetPageNavList()
{
var pageNavList = new PageNavDal().GetAll().OrderByDescending(p=>p.VisitTime).ToList();
PageNavEntity pageNavEntity = new PageNavEntity();
return pageNavList.Select(p => pageNavEntity.GetViewModel(p)).ToList();
}
public bool InsertPageNav(PageNavEntity entity)
{
return new PageNavDal().Insert(entity.GetDataEntity(entity));
}
}
PageShareBll:
public class PageShareBll
{
public List<PageShareEntity> GetPageShareList()
{
var psList = new PageShareDal().GetAll().OrderByDescending(p=>p.ShareTime).ToList();
PageShareEntity psEnt = new PageShareEntity();
return psList.Select(p => psEnt.GetViewModel(p)).ToList();
}
public bool InsertPageShare(PageShareEntity entity)
{
return new PageShareDal().Insert(entity.GetDataEntity(entity));
}
}
很简单就是查询和插入。
2. 获取分享记录
当用户点击了发送到朋友或发送到朋友圈时,可以利用微信JS接口来获取分享记录。详细的实现方法可参考《用c#开发微信 (10) JS-SDK 基本用法- 分享接口“发送到朋友”》。
然后调用上面的PageShareBll插入数据库。
3. 获取访问来源
1. 在微信内打开网页
2. 单击微信好友通过“发送给朋友”按钮分享的链接,这里会在链接后面加上 &from=SinbleMessage
3. 如果是朋友圈过来的链接,会在后面带上 &from=timeline
/// <summary>
/// 判断页面访问来源类型
/// </summary>
/// <returns></returns>
private static NavFrom GetNavFromType()
{
//网址中的参数集合
NameValueCollection parameters = System.Web.HttpContext.Current.Request.Params;
string fromStr = parameters["from"]; //发送给朋友、分享到朋友圈的链接会含有from参数
m_Log.Info("from: " + fromStr);
NavFrom fromType;
if (!Enum.TryParse<NavFrom>(fromStr, true, out fromType)) //通过判断from参数,识别页面访问是来自于发送给朋友的链接还是分享到朋友圈的链接
{
//获取HTTP访问头中的User-Agent参数的值
string agent = System.Web.HttpContext.Current.Request.Headers["User-Agent"];
if (agent.Contains(NavFrom.MicroMessenger.ToString())) //判断页面是否是在微信内置浏览器中打开
fromType = NavFrom.MicroMessenger;
else
fromType = NavFrom.Other;
}
return fromType;
}
4. 识别访问者
通过网页授权接口,可以方便地获取访问网页的微信个人用户的OpenId。要获取用户的OpenId,每次页面请求都需要执行微信公众平台“网页授权接口”的前二步,如果每次都请求访问这个接口,会影响性能,降低用户体验。因些这里用到了Cookie,第一次获取到OpenId后,把它保存到Cookie里。
首先,建立一个读写Cookie的类:
/// <summary>
/// 操作站内cookie的助手
/// </summary>
public class CookieHelper
{
/// <summary>
/// 写客户端cookie的名字
/// </summary>
public const string COOKIE_NAME = "awenhu";
#region 写COOKIE到客户端
/// <summary>
/// 登录后写COOKIE到客户端,代替session
/// </summary>
/// <param name="expires">过期时间,如果永不过期,设为DateTime.MaxValue,<para>如果不想写入客户端,浏览器关闭时即失效则设为DateTime.MinValue</para></param>
/// <param name="values">保存cookie信息</param>
public static void WriteLoginCookies(Dictionary<string, string> values, DateTime expires)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[COOKIE_NAME] ?? new HttpCookie(COOKIE_NAME);
if (expires != DateTime.MinValue)
cookie.Expires = expires;
foreach (var value in values)
{
cookie.Values[value.Key] = System.Web.HttpUtility.UrlEncode(value.Value);
}
HttpContext.Current.Response.Cookies.Add(cookie);
}
#endregion
#region cookie中获取信息
/// <summary>
/// cookie中获取信息;
/// </summary>
/// <returns></returns>
public static Dictionary<string, string> GetLoginCookies(string[] cookieKeys)
{
Dictionary<string, string> values = new Dictionary<string, string>();
HttpCookie cookie = HttpContext.Current.Request.Cookies[COOKIE_NAME];
if (cookie != null)
{
foreach (var cookieKey in cookieKeys)
{
string value = cookie.Values[cookieKey];
values.Add(cookieKey,
value == null ? null : System.Web.HttpUtility.UrlDecode(cookie.Values[cookieKey].Trim()).Replace("%5F", "_"));
}
}
else
{
foreach (var cookieKey in cookieKeys)
{
values.Add(cookieKey, null);
}
}
return values;
}
#endregion
#region 清除cookie
/// <summary>
/// 清除cookie
/// </summary>
public static void CleanLoginCookie(string[] keys)
{
HttpCookie ck = HttpContext.Current.Request.Cookies[COOKIE_NAME];
if (ck == null || ck.Values.Count == 0)
return;
foreach (var key in keys)
{
ck.Values[key] = "";
}
ck.Expires = DateTime.Now.AddDays(-1.0);
HttpContext.Current.Response.Cookies.Add(ck);
}
#endregion
}
以前《用c#开发微信(2)扫描二维码,用户授权后获取用户基本信息 (源码下载)》有过介绍怎么取OpenId,这里直接上代码:
/// <summary>
/// 获取访问者openId
/// </summary>
private string GetNavOpenId()
{
NameValueCollection parameters = System.Web.HttpContext.Current.Request.Params;
//获取链接中的openId
string navOpenId = parameters["u"];
#region 如果是从微信浏览器浏览,获取真实的微信OpenId
if (!string.IsNullOrEmpty(appID) && !string.IsNullOrEmpty(appSecret))
{
string accessSource = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"];
if (accessSource.Contains("MicroMessenger")) //如果是从微信打开页面
{
string[] cookieKeys = new[] { CookieHelper.COOKIE_NAME };
Dictionary<string, string> realIdCookie = CookieHelper.GetLoginCookies(cookieKeys); //获取保存在Cookie中的OpenId
//如果Cookie中不存在OpenId,或者链接中的openId与Cookie中的OpenId不一致,链接中的openId为分享者的OpenId,需要获取当前用户的真实OpenId
if (NeedGetReadOpenId(parameters, realIdCookie))
{
if (parameters["code"] == null)
{
// 先去获取code,并记录分享者
string snsapi_baseUrl = GoCodeUrl(navOpenId);
if (!string.IsNullOrEmpty(snsapi_baseUrl))
{
CookieHelper.CleanLoginCookie(cookieKeys);
//跳转到微信网页授权页面
System.Web.HttpContext.Current.Response.Redirect(snsapi_baseUrl, true);
System.Web.HttpContext.Current.Response.End();
return null;
}
}
else
{
m_Log.Info("code: " + parameters["code"].ToString());
OAuthAccessTokenResult tokenResult = GetRealOpenId(parameters["code"].ToString());
if (null != tokenResult && !string.IsNullOrEmpty(tokenResult.openid))
{
m_Log.Info("tokenResult.openid: " + tokenResult.openid);
navOpenId = tokenResult.openid;
// 获取到的当前访问者的OpenId保存到cookie里
CookieHelper.CleanLoginCookie(cookieKeys);
realIdCookie[CookieHelper.COOKIE_NAME] = tokenResult.openid;
CookieHelper.WriteLoginCookies(realIdCookie, DateTime.MinValue);
}
}
}
}
}
#endregion
return navOpenId;
}
/// <summary>
/// 如果Cookie中存在OpenId且链接中的openId与Cookie中的OpenId一致
/// 则不需要调用网页授权接口,链接中的openId即为当前访问者的真实OpenId
/// </summary>
/// <param name="parameters"></param>
/// <param name="realIdCookie"></param>
/// <returns></returns>
private bool NeedGetReadOpenId(NameValueCollection parameters, Dictionary<string, string> realIdCookie)
{
string referer = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_REFERER"];
string openId = null;
if (realIdCookie != null)
{
if (realIdCookie.ContainsKey(CookieHelper.COOKIE_NAME))
{
openId = realIdCookie[CookieHelper.COOKIE_NAME];
}
}
m_Log.Info("NeedGetReadOpenId openid: " + openId + " referer: " + referer + " u: " + parameters["u"].ToString());
if (!string.IsNullOrEmpty(referer) && openId == parameters["u"].ToString())
return false;
else
return true;
}
获取OpenId的二个步骤:
/// <summary>
/// 网页授权接口第一步
/// 跳转到获取code的url
/// </summary>
/// <param name="shareOpenId">当访问来源为朋友圈时的分享者微信openid</param>
private string GoCodeUrl(string shareOpenId)
{
string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri + "&s=" + shareOpenId; //添加分享者OpenId
return OAuthApi.GetAuthorizeUrl(appID, url, "STATE", OAuthScope.snsapi_base);
}
/// <summary>
/// 网页授权接口第二步
/// 解析code并获取当前访问者真正的openId
/// </summary>
/// <param name="parameters">url参数</param>
/// <returns>真正的openId</returns>
private OAuthAccessTokenResult GetRealOpenId(string code)
{
OAuthAccessTokenResult result = new OAuthAccessTokenResult();
try
{
result = OAuthApi.GetAccessToken(appID, appSecret, code);
}
catch (Exception ex)
{
m_Log.Error(ex.Message, ex);
}
return result;
}
5. 识别分享者
可以在页面网址中加上当前用户的OpenId,如果分享了页面,通过上面第4步获取到的当前访问者的OpenId跟网址中的不一样,那么网址中的OpenId即为分享者,记录完分享者后,再把网址中的OpenId替换为当前访问者的OpenId,以确保再次被分享后,同样能识别分享者。
未完待续!!!
用c#开发微信 (12) 微统计 - 阅读分享统计系统 2 业务逻辑实现的更多相关文章
- 用c#开发微信 (11) 微统计 - 阅读分享统计系统 1 基础架构搭建
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享 ...
- 用c#开发微信 (13) 微统计 - 阅读分享统计系统 3 UI设计及后台处理
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读. ...
- 用c#开发微信 (14) 微统计 - 阅读分享统计系统 4 部署测试 (最终效果图)
微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享 ...
- 用c#开发微信 (7) 微渠道 - 推广渠道管理系统 2 业务逻辑实现
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 上次介绍了 ...
- 用c#开发微信 (8) 微渠道 - 推广渠道管理系统 3 UI设计及后台处理
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 前面二篇& ...
- 用c#开发微信 (16) 微活动 2 刮刮卡
微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...
- 用c#开发微信 (9) 微渠道 - 推广渠道管理系统 4 部署测试 (最终效果图)
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 本文是微渠 ...
- 用c#开发微信 (6) 微渠道 - 推广渠道管理系统 1 基础架构搭建
我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 本系统使用 ...
- 用c#开发微信 (15) 微活动 1 大转盘
微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...
随机推荐
- linux C学习笔记03--单链表
单链表一直是程序员的基础,我也来复习下,下面是link.c中的代码,供main.c 调用,代码很简单,单链表的插入,删除,查找和遍历输出, #include <stdio.h> #incl ...
- Python list方法总结
1. 向列表的尾部添加一个新的元素 append(...) L.append(object) -- append object to end 1 2 3 4 >>> a = ['sa ...
- rtsp 协议 详细讲解
转载自:http://www.mikewootc.com/wiki/net/protocol/rtsp.html 目录: 概述 RTSP简介 协议特点 协议细节 典型的rtsp交互过程 RTSP消息格 ...
- wpf 自定义窗口,最大化时不覆盖任务栏
相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 WindowState="Maximized& ...
- C语言-------多文件编译
(1)前段时间,学长讲解宏的一些知识 也提起了那个多文件编译,同过看别人的博客,自己也懂了一些,现在来总结一下这个多文件编译,其实和java里面的那个class的调用好像有联系 其定义即可以理解成: ...
- xcode archive 一直是灰色的
把配置选择为device才能选build and archive的,模拟器的肯定不能build and anchive
- HDOJ 1512 几乎模板的左偏树
题目大意:有n个猴子.每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害.如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认 ...
- linux 下搭建 storm
搭建storm 需要搭建: 1.zookeeper 搭建 2.下载/安装 storm 的依赖包 zeromq, jzmq,python 2.storm 搭建 一.Zookeeper 安装 下载安装 ...
- vim global命令
global命令格式 : [range]global/{pattern}/{command} global命令在[range]指定的文本范围内(缺省为整个文件)查找{pattern},然后对匹配到的行 ...
- android studio小技巧
1. 为了防止乱码,请将 android studio 右下角编码设置成 UTF-8 2. Ctri + Q 查看api 3 Ctri + Shift +U 大小写互换 4 Ctrl + Alt + ...