この記事の例では、C# WeChat パブリック アカウント開発におけるイベント プッシュの受信とメッセージの重複排除の方法について説明します。皆さんの参考に共有してください。具体的な分析は次のとおりです:
WeChat サーバーが 5 秒以内に応答を受信しない場合、接続を切断してリクエストを再開始し、合計 3 回再試行します。この場合、問題が発生します。このようなシナリオがあります。ユーザーが WeChat アカウントをフォローすると、現在のユーザー情報が取得され、その情報がデータベースに書き込まれます。 PCサイトでの登録と同様です。おそらくこの懸念のため、処理する必要があるビジネス ロジックは比較的複雑です。ポイントの送信、ユーザー ログの書き込み、ユーザー グループの割り当てなど。お待ちください... 一連のロジックを実行する必要があるか、ネットワーク環境が比較的複雑で、現在のユーザーの操作が 5 秒以内に応答されるという保証はありません。操作がまだ完了していない場合は、WeChat サーバーが応答します。同じアテンション イベントをサーバーにプッシュします。ロジックを再度実行します。これにより、データベース内にデータが重複する可能性があります (データを挿入する前に、まずデータが存在するかどうかを確認し、存在する場合は、何が言いたいかというと、最初はそう思っていましたが、実際の動作環境とデバッグ環境にはまだ大きな差があることに初めて気づきました。データベース内の重複したユーザー情報を調べて、メッセージの重複排除の重要性を発見しました。)
メッセージの重複排除と、通常のメッセージおよびイベント メッセージには違いがあります。通常のメッセージでは msgid が使用されますが、イベント メッセージでは FromUserName + CreateTime が使用されます。私のアイデアは次のとおりです。
FromUser、MsgFlag、CreateTime の 3 つの属性を持つ新しいクラス BaseMsg を作成します。コードは次のとおりです。
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; } }
メッセージ リストを保存するための静的な list_queue を作成します。リストのタイプは List
WeChat メッセージ本文を処理する前に、まずリストがインスタンス化されているかどうかを確認します。インスタンス化されていない場合は、インスタンス化します。それ以外の場合は、リストの長さが 50 以上であるかどうかを判断します (これはカスタマイズ可能で、WeChat の同時メッセージ量に使用されます)。50 以上の場合は、メッセージを保持します。 20 秒以内に応答がなかったもの (5 秒に 1 回再試行、合計 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; } }</basemsg>
メッセージがすでにキューに存在する場合、現在のメッセージはエンティティに変換されず、直接 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.Replace("qrscene_", ""); } } /// <summary> /// 二维码的ticket,可用来换取二维码图片 /// </summary> public string Ticket { get; set; } }
ここで注意すべき点は、ユーザーがパラメータ付きのQRコードをスキャンする際、ユーザーが現在の公式アカウントをフォローしていない場合、ユーザーは When に従い、qrscene_ パラメーターと Ticket がメッセージ本文に含まれるため、ここでは EventKey と Ticket の 2 つの属性が定義されています。 EventKey に値を割り当てるときは、qrscene_ を置き換えます。実際に必要なのは次のパラメーターであるためです。
パラメーターを使用して QR コード イベントをスキャンする
ユーザーがシーン値を使用して QR コードをスキャンすると、次の 2 つのイベントがプッシュされる場合があります:
ユーザーが公式アカウントをフォローしていない場合、ユーザーはフォローした後、公式アカウントをフォローできます。シーン値を含むイベントを開発者にプッシュします。
ユーザーが公式アカウントをフォローしている場合、WeChat はシーン値を含むスキャン イベントを開発者にプッシュします。 ,
最初のタイプについては上で説明しましたが、ここでは 2 番目のタイプについてのみ説明します。
ユーザーがフォローしたときのイベントプッシュ
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 秒ごとに報告されます。公式アカウントは設定を変更できます。公式プラットフォームの背景。地理的位置を報告する場合、WeChat は報告された地理的位置イベントを開発者が入力した 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 です。画像を投稿するための 3 つのイベントもあります。これらは一般的に使用されるものではないため、筆者は使用シナリオを考えていません。興味がある場合は、自分で勉強するか、私に連絡してください。 。
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><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# ベースの WeChat 開発の皆様のお役に立てれば幸いです。
C# WeChat パブリック アカウント開発におけるイベント プッシュの受信方法とメッセージの重複排除に関するその他の記事については、PHP 中国語 Web サイトに注目してください。

c#.netissuitableforenterprise-levelApplicationsとsystemduetoitsSystemdutyping、richlibraries、androbustperformance.

.NETでのC#のプログラミングプロセスには、次の手順が含まれます。1)C#コードの作成、2)中間言語(IL)にコンパイルし、3).NETランタイム(CLR)によって実行される。 .NETのC#の利点は、デスクトップアプリケーションからWebサービスまでのさまざまな開発シナリオに適した、最新の構文、強力なタイプシステム、および.NETフレームワークとの緊密な統合です。

C#は、Microsoftによって開発された最新のオブジェクト指向プログラミング言語であり、.NETフレームワークの一部として開発されています。 1.C#は、カプセル化、継承、多型を含むオブジェクト指向プログラミング(OOP)をサポートしています。 2。C#の非同期プログラミングは非同期を通じて実装され、適用応答性を向上させるためにキーワードを待ちます。 3. LINQを使用してデータ収集を簡潔に処理します。 4.一般的なエラーには、null参照の例外と、範囲外の例外インデックスが含まれます。デバッグスキルには、デバッガーと例外処理の使用が含まれます。 5.パフォーマンスの最適化には、StringBuilderの使用と、不必要な梱包とボクシングの回避が含まれます。

C#.NETアプリケーションのテスト戦略には、ユニットテスト、統合テスト、エンドツーエンドテストが含まれます。 1.単位テストにより、コードの最小ユニットがMSTEST、ヌニット、またはXUNITフレームワークを使用して独立して動作することを保証します。 2。統合テストでは、一般的に使用されるシミュレートされたデータと外部サービスを組み合わせた複数のユニットの機能を検証します。 3.エンドツーエンドのテストでは、ユーザーの完全な操作プロセスをシミュレートし、通常、セレンは自動テストに使用されます。

C#シニア開発者とのインタビューでは、非同期プログラミング、LINQ、.NETフレームワークの内部作業原則などのコア知識をマスターする必要があります。 1.非同期プログラミングは、非同期を通じて操作を簡素化し、アプリケーションの応答性を向上させるのを待ちます。 2.LinqはSQLスタイルでデータを操作し、パフォーマンスに注意を払います。 3.ネットフレームワークのCLRはメモリを管理し、ガベージコレクションに注意して使用する必要があります。

C#.NETインタビューの質問と回答には、基本的な知識、コアの概念、高度な使用が含まれます。 1)基本知識:C#は、Microsoftが開発したオブジェクト指向言語であり、主に.NETフレームワークで使用されています。 2)コアの概念:委任とイベントは動的な結合方法を可能にし、LINQは強力なクエリ関数を提供します。 3)高度な使用:非同期プログラミングは応答性を向上させ、式ツリーは動的コード構造に使用されます。

C#.NETは、その強力なエコシステムと豊富なサポートのため、マイクロサービスを構築するために人気のある選択肢です。 1)asp.netcoreを使用してRestfulapiを作成して、順序の作成とクエリを処理します。 2)GRPCを使用して、マイクロサービス間の効率的な通信を実現し、注文サービスを定義および実装します。 3)Dockerコンテナ化されたマイクロサービスを介して展開と管理を簡素化します。

C#および.NETのセキュリティベストプラクティスには、入力検証、出力エンコード、例外処理、認証と承認が含まれます。 1)正規表現または組み込みのメソッドを使用して入力を検証して、悪意のあるデータがシステムに入るのを防ぎます。 2)XSS攻撃を防ぐための出力エンコード、httputility.htmlencodeメソッドを使用します。 3)例外処理により、情報の漏れが回避され、エラーが記録されますが、詳細情報はユーザーに返されません。 4)ASP.Netidentityおよび請求に基づく許可を使用して、不正アクセスから申請を保護します。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

WebStorm Mac版
便利なJavaScript開発ツール

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

メモ帳++7.3.1
使いやすく無料のコードエディター
