用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#開發微信 系列匯總


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM