zoukankan      html  css  js  c++  java
  • 用c#开发微信 (12) 微统计

    微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读、分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问、好友分享消息访问等。本系统实现了手机网页阅读、分享与来源统计及手机网页在朋友圈的传播路径分析。

    本系统使用最传统的三层架构。本文是微统计的第二篇,主要介绍如下内容:

    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#开发微信 系列汇总

  • 相关阅读:
    java se 转到ee小结
    objective c基本知识
    2013_11_14:递归算法(2)—全排列
    2013_11_13:递归算法(1)
    2013_11_13:关于 new 和delelte 的使用
    c++调试问题
    模式匹配BM算法介绍与实现
    一个n数组求和问题
    机试题
    算法题目
  • 原文地址:https://www.cnblogs.com/fengwenit/p/4550835.html
Copyright © 2011-2022 走看看