This paper introduces the method of receiving event push and message discharging in the development of C # public number. Share to everyone for your reference. The specific analysis is as follows:
The server will not receive a response within 5 seconds to disconnect, and re-initiate the request with a total of three retries. In that case, the problem will come. There is a scenario where the user is interested in the account, gets the current user information, and writes the information to the database. Similar to the registration of a PC-side website. Perhaps because of this concern, the business logic that we need to deal with is more complex. If send points ah, write user log ah, assign user group AH. Wait a minute...... A series of logic needs to execute, or the network environment is more complex, can not guarantee 5 seconds to respond to the operation of the current user, if the operation is not completed, the server to our server to send a similar concern, we will again execute our logic, This can lead to duplicate data in the database (some children's shoes will say, I have to determine whether the current exists before inserting data, if there is no operation to perform the insert.) What I want to say is that I was thinking the same, but the real environment and our debugging environment still has a gap, until the discovery of the database has a lot of duplicate user information, I found the importance of the message to heavy. )。
There is a difference between a message's go-to-normal message and an event message. Ordinary messages use MsgId, while event messages use Fromusername + createtime. My train of thought is:
New class Basemsg, with three properties fromuser,msgflag,createtime. The code is as follows:
public class basemsg{//<summary>/// Sender ID//</summary> public string Fromuser {get; Set }//<summary>//The message indicates. For normal messages, when the event message is MsgId, the event is created for the time/// </summary> public string Msgflag {get; set;} <summary>/// time added to the queue//// </summary> public DateTime createtime {get; set;}}
Create a static list _queue, which is used to store the list of messages, and the type of the list is list<basemsg>.
Before processing the body of the message, first determine whether the list is instantiated, if not instantiated, or if the length of the list is greater than or equal to 50 (this can be customized, useful is the amount of concurrent messages), if it is greater than or equal to 50, the message is reserved for 20 seconds not responding (5 seconds retry, a total of 3 retries, It's 15 seconds, and it's safe to write for 20 seconds.
Gets the message type of the current message body and, based on _queue, determines whether the current message has been requested. If it is an event, save the Fromuser and the creation time. If the message is normal, save the Msgflag. Here's the code:
if (_queue = = null) {_queue = new list<basemsg> ();} else if (_queue. COUNT>=50) {_queue = _queue. Where (q = {return q.createtime.addseconds > DateTime.Now;}). ToList ();//Keep messages that are not responding within 20 seconds}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;}}
When the message already exists in the queue, the current message is not converted to the entity, and Null is returned directly, and when NULL is returned, no processing is done.
The following is the beginning of the event message. I'll talk about it in the next chapter. All messages inherit basemessage, and all event types contain an event property. Here to facilitate the invocation, the message
<summary>///Event Type enumeration//</summary>public enum event{///<summary>//Non-event type// </summary> NOEVENT,//<summary>//Subscription//</summary> SUBSCRIBE, <summary>//unsubscribe///</summary> unsubscribe,//<summary> Scan QR code with parameters///</summary> Scan,///<summary>///</summar Y> location,///<summary>//////</summary> click,//< ;summary>///LINK button///</summary> VIEW,///<summary>//Code push Event/ </summary> Scancode_push,///<summary>//Code push event and Popup "message received in" Prompt box///</summary > scancode_waitmsg,///<summary>//pop-up system photo Map///</summary> Pic_syspho To,///<summary>///pop-up photo or photo album///</summary> Pic_photo_or_album,///<summary>// Pop-up Photo gallery///</summary> Pic_weixin,///<summary>//pop-up geolocation selector///</sum Mary> Location_select,//<summary>//Templates message Push///</summary> TEMPLATES Endjobfinish}
Once the enumeration is defined, the message entity is defined.
Follow/Cancel Attention events
The XML packets are as follows:
<xml><tousername><! [cdata[touser]]></tousername><fromusername><! [cdata[fromuser]]></fromusername><createtime>123456789</createtime><msgtype><! [cdata[event]]></msgtype><event><! [cdata[subscribe]]></event></xml>
The corresponding entity:
<summary>///Subscribe/UNSUBSCRIBE events///</summary>public class subeventmessage:eventmessage{ private String _ Eventkey; <summary> ///Event key value, Qrscene_ as prefix, followed by the parameter value of the QR code (prefix is removed, can be used directly)/// </summary> public string Eventkey { get {return _eventkey;} set {_eventkey = value. Replace ("Qrscene_", "");} } <summary>///QR code Ticket, can be used to exchange QR code picture/// </summary> public string Ticket {get; set;}}
It is important to note that when the user scans the QR code with parameters, if the user does not pay attention to the current public number, the user concerned, will be in the message body with the Qrscene_ parameter, and Ticket, so here define two properties: Eventkey,ticket. When assigning a value to Eventkey, replace the qrscene_, because what we really need is the argument behind it.
Scan with parameter QR code event
When a user scans a two-D code with scene values, it is possible to push two kinds of events:
If the user has not yet paid attention to the public number, the user can focus on the public number, followed by the scene value attention event will be pushed to the developer.
If the user is already concerned about the public number, the scene value scan event is pushed to the developer. 、
The first one above has already been said, here is only the second kind.
Event push when the user is already concerned
The XML packages are as follows:
<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>
The corresponding entities are as follows:
<summary>///scan QR code entities with parameters///</summary>public class scaneventmessage:eventmessage{// < summary>/// Event key value, is a 32-bit unsigned integer, which is the QR code when creating the QR code scene_id/// </summary> public string Eventkey {get ; Set }///<summary>///QR code Ticket, can be used to exchange QR code picture/// </summary> public string Ticket {get; set;}}
Escalate geo-Location events
When the public number opens the location function, each time enters the public number session, the user agrees to escalate the geographical location, will escalate the geographical location in the entry, or after enters the reply every 5 seconds to report the geographical location, the public number may change the setting in the public platform backstage. When you escalate a geographic location, the escalation event is pushed to the URL that the developer fills in.
The XML packets are as follows:
<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>
The corresponding entities are as follows:
<summary>///Reporting Geo-location entities//</summary>public class locationeventmessage:eventmessage{// < Summary>///Geography latitude/// </summary> public string Latitude {get; set;} <summary>//location longitude/// </summary> public string longitude {get; set;} <summary>///Location accuracy/// </summary> public string Precision {get; set;}}
The events commonly used for custom menu events are: Click,view,scancode_puth,scancode_waitmsg,location_select. There are also three kinds of hair map event, because it is not commonly used, I did not think of the use of the scene, once again do not tell the story, interested in their own research, or to communicate with me.
The Click event pushes the XML packet:
<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>
The XML packet that the view event pushes is the same as the click Format, so defining a class is possible, as follows:
<summary>///common menu events, including click and view///</summary>public class normalmenueventmessage:eventmessage{ //<summary>/// Event key value, set jump URL/// </summary> public string Eventkey {get; set;}}
The XML packet for the Scancode event is as follows:
<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>
The corresponding entities are as follows:
<summary>///Menu Scan Event///</summary>public class scanmenueventmessage:eventmessage{// <summary >/// Event key value/// </summary> public string Eventkey {get; set;} <summary>// scan type. QRCode is the QR code, the other is the barcode/// </summary> public string ScanType {get; set;} <summary>///Scan results/// </summary> public string Scanresult {get; set;}}
At this point, the current commonly used event type message has been defined, in conjunction with the previous article, the XML packet into the object's full code as follows:
public class messagefactory{private static list<basemsg> _queue; public static Basemessage CreateMessage (string xml) {if (_queue = = null) {_q Ueue = new list<basemsg> (); } else if (_queue. COUNT>=50) {_queue = _queue. Where (q = {return q.createtime.addseconds > DateTime.Now;}). ToList ();//Keep messages that are not responding within 20 seconds} 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 = Fr Omusername, Msgflag = MsgId}); } else {return null; }} else {if (_queue. FirstOrDefault (M + = {return M.msgflag = = Createtime;}) = = null) {_queue. ADD (new basemsg {createtime = DateTime.Now, Fromuser = F Romusername, Msgflag = Createtime}); } else {return null; }} switch (type) {case MsgType.TEXT:return utils.convertobj<textmess Age> (XML); Case MsgType.IMAGE:return Utils.convertobj (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://Event Type {var EventType = (event) Enum.parse (typeof (Event), Xdoc. Element ("Event"). Value.toupper ()); Switch (eventtype) {case Event.CLICK:return UTILS.C Onvertobj<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); } }}
Hopefully this article will help you with C #-based development.