C#微信"號開辟之吸收事宜推送與新聞排重的辦法。本站提示廣大學習愛好者:(C#微信"號開辟之吸收事宜推送與新聞排重的辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是C#微信"號開辟之吸收事宜推送與新聞排重的辦法正文
本文實例講述了C#微信"號開辟之吸收事宜推送與新聞排重的辦法。分享給年夜家供年夜家參考。詳細剖析以下:
微佩服務器在5秒內收不到呼應會斷失落銜接,而且從新提議要求,總共重試三次。如許的話,成績就來了。有如許一個場景:當用戶存眷微信賬號時,獲得以後用戶信息,然後將信息寫到數據庫中。相似於pc端網站的注冊。能夠因為這個存眷事宜中,我們須要處置的營業邏輯比擬龐雜。如送積分啊,寫用戶日記啊,分派用戶組啊。等等……一系列的邏輯須要履行,或許收集情況比擬龐雜,沒法包管5秒內呼應以後用戶的操作,那假如當操作還沒有完成,微佩服務器又給我們的辦事器推送了一條雷同的存眷事宜,我們將再次履行我們的那些邏輯,如許就有能夠招致數據庫中湧現反復的數據(有的童鞋就會說了,我在拔出數據之前先斷定以後能否曾經存在了,假如存在了就不履行拔出的操作。我想說的是,我現在也是如許想的,但真實的運轉情況和我們的調試情況照樣有差距的,直到發明數據庫中有很多反復的用戶信息時,我才發明新聞去重的主要性。)。
新聞的去重通俗新聞和事宜新聞是有差別的。通俗新聞應用msgid,而事宜新聞應用FromUserName + CreateTime。我的思緒是:
新建類BaseMsg,有三個屬性分離是FromUser,MsgFlag,CreateTime。代碼以下:
public class BaseMsg
{
/// <summary>
/// 發送者標識
/// </summary>
public string FromUser { get; set; }
/// <summary>
/// 新聞表現。通俗新聞時,為msgid,事宜新聞時,為事宜的創立時光
/// </summary>
public string MsgFlag { get; set; }
/// <summary>
/// 添加到隊列的時光
/// </summary>
public DateTime CreateTime { get; set; }
}
創立個靜態列表_queue,用來存儲新聞列表,列表的類型是List<BaseMsg>.
在處置微信新聞體前,起首斷定列表能否實例化,假如沒有實例化則實例化,不然斷定列表的長度能否年夜於或等於50(這個可以自界說,用途就是微信並發的新聞量),假如年夜於或等於50,則保存20秒內未呼應的新聞(5秒重試一次,總共重試3次,就是15秒,保險起見這裡寫20秒)。
獲得以後新聞體的新聞類型,並依據_queue斷定以後新聞能否曾經要求了。假如是事宜則保留FromUser和創立時光。假如是通俗新聞則保留MsgFlag。上面是代碼:
if (_queue == null)
{
_queue = new List<BaseMsg>();
}
else if(_queue.Count>=50)
{
_queue = _queue.Where(q => { return q.CreateTime.AddSeconds(20) > DateTime.Now; }).ToList();//保存20秒內未呼應的新聞
}
XElement xdoc = XElement.Parse(xml);
var msgtype = xdoc.Element("MsgType").Value.ToUpper();
var FromUserName = xdoc.Element("FromUserName").Value;
var MsgId = xdoc.Element("MsgId").Value;
var CreateTime = xdoc.Element("CreateTime").Value;
MsgType type = (MsgType)Enum.Parse(typeof(MsgType), msgtype);
if (type!=MsgType.EVENT)
{
if (_queue.FirstOrDefault(m => { return m.MsgFlag == MsgId; }) == null)
{
_queue.Add(new BaseMsg
{
CreateTime = DateTime.Now,
FromUser = FromUserName,
MsgFlag = MsgId
});
}
else
{
return null;
}
}
else
{
if (_queue.FirstOrDefault(m => { return m.MsgFlag == CreateTime; }) == null)
{
_queue.Add(new BaseMsg
{
CreateTime = DateTime.Now,
FromUser = FromUserName,
MsgFlag = CreateTime
});
}
else
{
return null;
}
}
當新聞曾經存在隊列中時,則不轉換以後的新聞為實體了,直接前往null,挪用的時刻,當前往null時就不做任何處置。
上面開端講授事宜新聞。接上篇講。一切的新聞都繼續BaseMessage,而一切的事宜類型都包括一個Event的屬性。這裡為了便利挪用,將新聞
/// <summary>
/// 事宜類型列舉
/// </summary>
public enum Event
{
/// <summary>
/// 非事宜類型
/// </summary>
NOEVENT,
/// <summary>
/// 定閱
/// </summary>
SUBSCRIBE,
/// <summary>
/// 撤消定閱
/// </summary>
UNSUBSCRIBE,
/// <summary>
/// 掃描帶參數的二維碼
/// </summary>
SCAN,
/// <summary>
/// 地輿地位
/// </summary>
LOCATION,
/// <summary>
/// 單擊按鈕
/// </summary>
CLICK,
/// <summary>
/// 鏈接按鈕
/// </summary>
VIEW,
/// <summary>
/// 掃碼推事宜
/// </summary>
SCANCODE_PUSH,
/// <summary>
/// 掃碼推事宜且彈出“新聞吸收中”提醒框
/// </summary>
SCANCODE_WAITMSG,
/// <summary>
/// 彈出體系攝影發圖
/// </summary>
PIC_SYSPHOTO,
/// <summary>
/// 彈出攝影或許相冊發圖
/// </summary>
PIC_PHOTO_OR_ALBUM,
/// <summary>
/// 彈出微信相冊發圖器
/// </summary>
PIC_WEIXIN,
/// <summary>
/// 彈出地輿地位選擇器
/// </summary>
LOCATION_SELECT,
/// <summary>
/// 模板新聞推送
/// </summary>
TEMPLATESENDJOBFINISH
}
界說好列舉後,就是界說新聞實體了。
存眷/撤消存眷事宜
xml數據包以下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>
對應的實體:
/// <summary>
/// 定閱/撤消定閱事宜
/// </summary>
public class SubEventMessage : EventMessage
{
private string _eventkey;
/// <summary>
/// 事宜KEY值,qrscene_為前綴,前面為二維碼的參數值(已去失落前綴,可以直接應用)
/// </summary>
public string EventKey
{
get { return _eventkey; }
set { _eventkey = value.WordStr("qrscene_", ""); }
}
/// <summary>
/// 二維碼的ticket,可用來換取二維碼圖片
/// </summary>
public string Ticket { get; set; }
}
這裡須要留意的是,當用戶掃描帶參數的二維碼時,假如用戶沒有存眷以後"號,用戶存眷時,會在新聞體中帶上qrscene_參數,和Ticket,所以這裡界說了兩個屬性:EventKey,Ticket。當給EventKey賦值時,調換失落qrscene_,由於我們真正須要的就是前面的參數。
掃描帶參數二維碼事宜
用戶掃描帶場景值二維碼時,能夠推送一下兩種事宜:
假如用戶還未存眷"號,則用戶可以存眷"號,存眷後微信會將帶場景值存眷事宜推送給開辟者。
假如用戶曾經存眷"號,則微信會將帶場景值掃描事宜推送給開辟者。、
第一種下面曾經講了,這裡就只解釋下第二種。
用戶已存眷時的事宜推送
xml包以下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[SCAN]]></Event>
<EventKey><![CDATA[SCENE_VALUE]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>
對應的實體以下:
/// <summary>
/// 掃描帶參數的二維碼實體
/// </summary>
public class ScanEventMessage : EventMessage
{
/// <summary>
/// 事宜KEY值,是一個32位無符號整數,即創立二維碼時的二維碼scene_id
/// </summary>
public string EventKey { get; set; }
/// <summary>
/// 二維碼的ticket,可用來換取二維碼圖片
/// </summary>
public string Ticket { get; set; }
}
上報地輿地位事宜
當"號開啟上報地輿地位功效後,每次進入"號會話時,用戶贊成上報地輿地位後,都邑在進入時上報地輿地位,或在進入回話後每5秒上報一次地輿地位,"號可以再"平台的後台中修正設置。上報地輿地位時,微信會將上報地輿地位事宜推送到開辟者填寫的url。
xml數據包以下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[LOCATION]]></Event>
<Latitude>23.137466</Latitude>
<Longitude>113.352425</Longitude>
<Precision>119.385040</Precision>
</xml>
對應的實體以下:
/// <summary>
/// 上報地輿地位實體
/// </summary>
public class LocationEventMessage : EventMessage
{
/// <summary>
/// 地輿地位緯度
/// </summary>
public string Latitude { get; set; }
/// <summary>
/// 地輿地位經度
/// </summary>
public string Longitude { get; set; }
/// <summary>
/// 地輿地位精度
/// </summary>
public string Precision { get; set; }
}
自界說菜單事宜經常使用的事宜有:click,view,scancode_puth,scancode_waitmsg,location_select。別的還有三種發圖的事宜,因為其實不經常使用,筆者也沒想到應用場景,再次就紛歧一講述了,有興致的可以本身研討下,或許和我停止交換。
click事宜推送的xml數據包:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>
view事宜推送的xml數據包和click的格局是一樣的,所以界說一個類便可以了,以下:
/// <summary>
/// 通俗菜單事宜,包含click和view
/// </summary>
public class NormalMenuEventMessage : EventMessage
{
/// <summary>
/// 事宜KEY值,設置的跳轉URL
/// </summary>
public string EventKey { get; set; }
}
scancode事宜的xml數據包以下:
<xml><ToUserName><![CDATA[ToUserName]]></ToUserName>
<FromUserName><![CDATA[FromUserName]]></FromUserName>
<CreateTime>1419265698</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[scancode_push]]></Event>
<EventKey><![CDATA[EventKey]]></EventKey>
<ScanCodeInfo><ScanType><![CDATA[qrcode]]></ScanType>
<ScanResult><![CDATA[http://weixin.qq.com/r/JEy5oRLE0U_urVbC9xk2]]></ScanResult>
</ScanCodeInfo>
</xml>
對應的實體以下:
/// <summary>
/// 菜單掃描事宜
/// </summary>
public class ScanMenuEventMessage : EventMessage
{
/// <summary>
/// 事宜KEY值
/// </summary>
public string EventKey { get; set; }
/// <summary>
/// 掃碼類型。qrcode是二維碼,其他的是條碼
/// </summary>
public string ScanType { get; set; }
/// <summary>
/// 掃描成果
/// </summary>
public string ScanResult { get; set; }
}
至此,以後經常使用的事宜類型新聞都已界說終了,聯合上一篇所講的,將xml數據包轉換成對象的完全代碼以下:
public class MessageFactory
{
private static List<BaseMsg> _queue;
public static BaseMessage CreateMessage(string xml)
{
if (_queue == null)
{
_queue = new List<BaseMsg>();
}
else if(_queue.Count>=50)
{
_queue = _queue.Where(q => { return q.CreateTime.AddSeconds(20) > DateTime.Now; }).ToList();//保存20秒內未呼應的新聞
}
XElement xdoc = XElement.Parse(xml);
var msgtype = xdoc.Element("MsgType").Value.ToUpper();
var FromUserName = xdoc.Element("FromUserName").Value;
var MsgId = xdoc.Element("MsgId").Value;
var CreateTime = xdoc.Element("CreateTime").Value;
MsgType type = (MsgType)Enum.Parse(typeof(MsgType), msgtype);
if (type!=MsgType.EVENT)
{
if (_queue.FirstOrDefault(m => { return m.MsgFlag == MsgId; }) == null)
{
_queue.Add(new BaseMsg
{
CreateTime = DateTime.Now,
FromUser = FromUserName,
MsgFlag = MsgId
});
}
else
{
return null;
}
}
else
{
if (_queue.FirstOrDefault(m => { return m.MsgFlag == CreateTime; }) == null)
{
_queue.Add(new BaseMsg
{
CreateTime = DateTime.Now,
FromUser = FromUserName,
MsgFlag = CreateTime
});
}
else
{
return null;
}
}
switch (type)
{
case MsgType.TEXT: return Utils.ConvertObj<TextMessage>(xml);
case MsgType.IMAGE: return Utils.ConvertObj<ImgMessage>(xml);
case MsgType.VIDEO: return Utils.ConvertObj<VideoMessage>(xml);
case MsgType.VOICE: return Utils.ConvertObj<VoiceMessage>(xml);
case MsgType.LINK:
return Utils.ConvertObj<LinkMessage>(xml);
case MsgType.LOCATION:
return Utils.ConvertObj<LocationMessage>(xml);
case MsgType.EVENT://事宜類型
{
var eventtype = (Event)Enum.Parse(typeof(Event), xdoc.Element("Event").Value.ToUpper());
switch (eventtype)
{
case Event.CLICK:
return Utils.ConvertObj<NormalMenuEventMessage>(xml);
case Event.VIEW: return Utils.ConvertObj<NormalMenuEventMessage>(xml);
case Event.LOCATION: return Utils.ConvertObj<LocationEventMessage>(xml);
case Event.LOCATION_SELECT: return Utils.ConvertObj<LocationMenuEventMessage>(xml);
case Event.SCAN: return Utils.ConvertObj<ScanEventMessage>(xml);
case Event.SUBSCRIBE: return Utils.ConvertObj<SubEventMessage>(xml);
case Event.UNSUBSCRIBE: return Utils.ConvertObj<SubEventMessage>(xml);
case Event.SCANCODE_WAITMSG: return Utils.ConvertObj<ScanMenuEventMessage>(xml);
default:
return Utils.ConvertObj<EventMessage>(xml);
}
} break;
default:
return Utils.ConvertObj<BaseMessage>(xml);
}
}
}
願望本文所述對年夜家基於C#的微信開辟有所贊助。