首页 > 代码库 > 微信在线信息模拟测试工具(基于Senparc.Weixin.MP)

微信在线信息模拟测试工具(基于Senparc.Weixin.MP)

  目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具。

  测试工具在线DEMO:http://weixin.senparc.com/SimulateTool

  Senparc.Weixin.MP是一个开源的微信SDK项目,地址:https://github.com/JeffreySu/WeiXinMPSDK (其中https://github.com/JeffreySu/WeiXinMPSDK/tree/master/Senparc.Weixin.MP.Sample 包含了本文所讲的所有源代码)

  也可以通过Nuget直接安装到项目中:https://www.nuget.org/packages/Senparc.Weixin.MP

  Senparc.Weixin.MP教程索引:http://www.cnblogs.com/szw/archive/2013/05/14/weixin-course-index.html

 

  下面大致解释一下源代码及工作原理:

一、界面

  

  界面分为4大区域:接口设置、发送参数、发送内容和接收内容

  其中接口设置用于提供类似微信公众账号后台的Url和Token的对接参数设置,指定目标服务器。

  在发送参数中,根据选择不同的消息类型,下面的参数选项会对应变化。

  发送内容显示的是提交参数之后,模拟发送到目标服务器的XML,这里摆脱了之前一些需要手动输入XML的麻烦。

  根据发送内容,在接收内容框中,显示目标服务器返回的实际内容。

二、服务器端代码

  由于使用了Senparc.Weixin.MP SDK,所有的XML生成、代理操作、XML流等操作都变得非常简单,一共只用了100多行代码就实现了XML生成及模拟发送、接收等2大块功能,这里为了让大家看得更明白,将所有代码都尽量平铺直叙,实际还可以有很多缩减或重用的地方(文件位于源代码/Senparc.Weixin.MP.Sample/Senparc.Weixin.MP.Sample/Controllers/SimulateToolController.cs):

using System;using System.IO;using System.Web.Mvc;using System.Xml.Linq;using Senparc.Weixin.MP.Agent;using Senparc.Weixin.MP.Entities;using Senparc.Weixin.MP.Helpers;namespace Senparc.Weixin.MP.Sample.Controllers{    public class SimulateToolController : BaseController    {        /// <summary>        /// 获取请求XML        /// </summary>        /// <returns></returns>        private XDocument GetrequestMessaageDoc(string url, string token, RequestMsgType requestType, Event? eventType)        {            RequestMessageBase requestMessaage = null;            switch (requestType)            {                case RequestMsgType.Text:                    requestMessaage = new RequestMessageText()                    {                        Content = Request.Form["Content"],                    };                    break;                case RequestMsgType.Location:                    requestMessaage = new RequestMessageLocation()                    {                        Label = Request.Form["Label"],                        Location_X = double.Parse(Request.Form["Location_X"]),                        Location_Y = double.Parse(Request.Form["Location_Y"]),                        Scale = int.Parse(Request.Form["Scale"])                    };                    break;                case RequestMsgType.Image:                    requestMessaage = new RequestMessageImage()                    {                        PicUrl = Request.Form["PicUrl"],                    };                    break;                case RequestMsgType.Voice:                    requestMessaage = new RequestMessageVoice()                    {                        Format = Request.Form["Format"],                        Recognition = Request.Form["Recognition"],                    };                    break;                case RequestMsgType.Video:                    requestMessaage = new RequestMessageVideo()                    {                        MsgId = long.Parse(Request.Form["MsgId"]),                        ThumbMediaId = Request.Form["ThumbMediaId"],                    };                    break;                //case RequestMsgType.Link:                //    break;                case RequestMsgType.Event:                    if (eventType.HasValue)                    {                        RequestMessageEventBase requestMessageEvent = null;                        switch (eventType.Value)                        {                            //case Event.ENTER:                            //    break;                            case Event.LOCATION:                                requestMessageEvent = new RequestMessageEvent_Location()                                {                                    Latitude = long.Parse(Request.Form["Event.Latitude"]),                                    Longitude = long.Parse(Request.Form["Event.Longitude"]),                                    Precision = double.Parse(Request.Form["Event.Precision"])                                };                                break;                            case Event.subscribe:                                requestMessageEvent = new RequestMessageEvent_Subscribe()                                {                                    EventKey = Request.Form["Event.EventKey"]                                };                                break;                            case Event.unsubscribe:                                requestMessageEvent = new RequestMessageEvent_Unsubscribe();                                  break;                            case Event.CLICK:                                requestMessageEvent = new RequestMessageEvent_Click()                                   {                                       EventKey = Request.Form["Event.EventKey"]                                   };                                break;                            case Event.scan:                                requestMessageEvent = new RequestMessageEvent_Scan()                                 {                                     EventKey = Request.Form["Event.EventKey"],                                     Ticket = Request.Form["Event.Ticket"]                                 }; break;                            case Event.VIEW:                                requestMessageEvent = new RequestMessageEvent_View()                                 {                                     EventKey = Request.Form["Event.EventKey"]                                 }; break;                            case Event.MASSSENDJOBFINISH:                                requestMessageEvent = new RequestMessageEvent_MassSendJobFinish()                                {                                    FromUserName = "mphelper",//系统指定                                    ErrorCount = int.Parse(Request.Form["Event.ErrorCount"]),                                    FilterCount = int.Parse(Request.Form["Event.FilterCount"]),                                    SendCount = int.Parse(Request.Form["Event.SendCount"]),                                    Status = Request.Form["Event.Status"],                                    TotalCount = int.Parse(Request.Form["Event.TotalCount"])                                }; break;                            default:                                throw new ArgumentOutOfRangeException("eventType");                        }                        requestMessaage = requestMessageEvent;                    }                    else                    {                        throw new ArgumentOutOfRangeException("eventType");                    }                    break;                default:                    throw new ArgumentOutOfRangeException("requestType");            }            requestMessaage.CreateTime = DateTime.Now;            requestMessaage.FromUserName = requestMessaage.FromUserName ?? "FromUserName(OpenId)";//用于区别不同的请求用户            requestMessaage.ToUserName = "ToUserName";            return requestMessaage.ConvertEntityToXml();        }        /// <summary>        /// 默认页面        /// </summary>        /// <returns></returns>        public ActionResult Index()        {            ViewData["Token"] = WeixinController.Token;            return View();        }        /// <summary>        /// 模拟发送并返回结果        /// </summary>        /// <returns></returns>        [HttpPost]        public ActionResult Index(string url, string token, RequestMsgType requestType, Event? eventType)        {            using (MemoryStream ms = new MemoryStream())            {                var requestMessaageDoc = GetrequestMessaageDoc(url, token, requestType, eventType);                requestMessaageDoc.Save(ms);                ms.Seek(0, SeekOrigin.Begin);                var responseMessageXml = MessageAgent.RequestXml(null, url, token, requestMessaageDoc.ToString());                return Content(responseMessageXml);            }        }        /// <summary>        /// 返回模拟发送的XML        /// </summary>        /// <returns></returns>        [HttpPost]        public ActionResult GetRequestMessageXml(string url, string token, RequestMsgType requestType, Event? eventType)        {            var requestMessaageDoc = GetrequestMessaageDoc(url, token, requestType, eventType);            return Content(requestMessaageDoc.ToString());        }    }}

  

三、View代码

  下面是MVC中View(razor)的代码(200行左右,文件位于源代码/Senparc.Weixin.MP.Sample/Senparc.Weixin.MP.Sample/Views/SimulateTool/Index.cshtml):

  1 @{  2     ViewBag.Title = "微信消息模拟测试工具";  3     Layout = "~/Views/Shared/_Layout.cshtml";  4   5     var nonce = "JeffreySu";  6     var timestamp = DateTime.Now.Ticks.ToString();  7     var echostr = DateTime.Now.Ticks.ToString();  8     var token = ViewData["Token"] as string;  9 } 10 @section HeaderContent 11 { 12     <style> 13         .param { 14             display: none; 15         } 16  17         .messageXmlArea { 18             width: 100%; 19         } 20  21             .messageXmlArea textarea { 22                 width: 100%; 23                 height: 200px; 24             } 25  26         .paramAreaLeft { 27             float: left; 28             width: 45%; 29             margin-right: 6%; 30         } 31  32         .paramArearight { 33             width: 45%; 34             float: left; 35         } 36  37         #requestType, #eventType { 38             padding: 5px; 39         } 40     </style> 41     <script> 42         $(function () { 43             $(#requestType).change(checkRequestType); 44             $(#eventType).change(checkEventType); 45             checkRequestType(); 46             checkEventType(); 47         }); 48  49         function checkRequestType() { 50             var requestType = $(#requestType).val(); 51             var paramId = param + requestType; 52             $(div[id^=param]).hide(); 53             $(# + paramId).show(); 54         } 55  56         function checkEventType() { 57             var requestType = $(#eventType).val(); 58             var eventId = event + requestType; 59             $(div[id^=event]).hide(); 60             $(# + eventId).show(); 61         } 62  63         function sendMessage() { 64             var url = $(#Url).val(); 65             var token = $(#Token).val(); 66             var requestType = $(#requestType).val(); 67             var eventType = $(#eventType).val(); 68             var param = { url: url, token: token, requestType: requestType }; 69             var paramId = param + requestType; 70             var eventId = event + eventType; 71             //设置参数 72             if (requestType != Event) { 73                 $.each($(# + paramId).find(input), function (i, item) { 74                     param[$(item).attr(name)] = $(item).val(); 75                 }); 76             } else { 77                 param.eventType = eventType; 78                 $.each($(# + eventId).find(input), function (i, item) { 79                     param[$(item).attr(name)] = $(item).val(); 80                 }); 81             } 82  83             var txtResponseMessageXML = $(#responseMessageXML); 84             var txtRequestMessageXML = $(#requestMessageXML); 85  86             txtResponseMessageXML.html(载入中...); 87             txtRequestMessageXML.html(载入中...); 88  89             $.post(@Url.Action("Index"), param, function (result) { 90                 txtResponseMessageXML.html(result); 91             }); 92  93             $.post(@Url.Action("GetRequestMessageXml"), param, function (result) { 94                 txtRequestMessageXML.html(result); 95             }); 96         } 97     </script> 98 } 99 @section Featured100 {101 102 }103 <section class="content-wrapper main-content clear-fix">104     <h1>消息模拟工具</h1>105     <div class="clear-fix"></div>106     <div id="simulateTool">107         <div class="paramAreaLeft">108             <h3>接口设置</h3>109             <div>110                 URL:@Html.TextBox("Url", Url.Action("Index", "Weixin", null, "http", Request.Url.Host))<br />111                 Token:@Html.TextBox("Token", token)112             </div>113             <h3>发送参数</h3>114             <div>115                 类型:<select id="requestType">116                     <option value="Text">文本</option>117                     <option value="Location">地理位置</option>118                     <option value="Image">图片</option>119                     <option value="Voice">语音</option>120                     <option value="Video">视频</option>121                     @*<option value="Link">连接信息</option>*@122                     <option value="Event">事件推送</option>123                 </select>124             </div>125             <div>126                 参数:127                 <div id="paramText" class="param">128                     Content:<input name="Content" />129                 </div>130                 <div id="paramLocation" class="param">131                     Label:<input name="Label" /><br />132                     Location_X:<input name="Location_X" type="number" value="0" /><br />133                     Location_Y:<input name="Location_Y" type="number" value="0" /><br />134                     Scale:<input name="Scale" type="number" value="0" step="1" /><br />135                 </div>136                 <div id="paramImage" class="param">137                     PicUrl:<input name="PicUrl" /><br />138                 </div>139                 <div id="paramVoice" class="param">140                     Format:<input name="Format" value="arm" /><br />141                     Recognition:<input name="Recognition" /><br />142                 </div>143                 <div id="paramVideo" class="param">144                     MsgId:<input name="MsgId" type="number" value="@DateTime.Now.Ticks" step="1" /><br />145                     ThumbMediaId:<input name="ThumbMediaId" /><br />146                 </div>147                 @*<div id="paramLink" class="param"></div>*@148                 <div id="paramEvent" class="param">149                     事件类型:<select id="eventType">150                         @*<option value="ENTER">进入会话</option>*@151                         <option value="LOCATION">地理位置</option>152                         <option value="subscribe">订阅</option>153                         <option value="unsubscribe">取消订阅</option>154                         <option value="CLICK">自定义菜单点击事件</option>155                         <option value="scan">二维码扫描</option>156                         <option value="VIEW">URL跳转</option>157                         <option value="MASSSENDJOBFINISH">事件推送群发结果</option>158                     </select>159                     @*<div id="eventENTER" class="param"></div>*@160                     <div id="eventLOCATION" class="param">161                         Latitude:<input name="Event.Latitude" type="number" value="0"/><br />162                         Longitude:<input name="Event.Longitude" type="number" value="0"/><br />163                         Precision:<input name="Event.Precision" type="number" value="0"/><br />164                     </div>165                     <div id="eventsubscribe" class="param">166                         EventKey:<input name="Event.EventKey" /><br />167                     </div>168                     <div id="eventunsubscribe" class="param"></div>169                     <div id="eventCLICK" class="param">170                         EventKey:<input name="Event.EventKey" /><br />171                     </div>172                     <div id="eventscan" class="param">173                         EventKey:<input name="Event.EventKey" /><br />174                         Ticket:<input name="Event.Ticket" /><br />175                     </div>176                     <div id="eventVIEW" class="param">177                         EventKey:<input name="Event.EventKey" value="http://" /><br />178                     </div>179                     <div id="eventMASSSENDJOBFINISH" class="param">180                         ErrorCount:<input name="Event.ErrorCount" type="number" value="0"/><br />181                         FilterCount:<input name="Event.FilterCount" type="number" value="0"/><br />182                         SendCount:<input name="Event.SendCount" type="number" value="0"/><br />183                         Status:<input name="Event.Status"/><br />184                         TotalCount:<input name="Event.TotalCount" type="number" value="0"/><br />185                     </div>186                 </div>187                 <div>188                     <input type="button" value="提交" onclick="sendMessage()" />189                 </div>190             </div>191         </div>192         <div class="paramArearight">193 194             <div class="messageXmlArea">195                 <h3>发送内容(根据参数自动生成)</h3>196                 <textarea id="requestMessageXML" readonly="readonly"></textarea>197             </div>198             <div class="messageXmlArea">199                 <h3>接收内容</h3>200                 <textarea id="responseMessageXML"></textarea>201             </div>202         </div>203     </div>204 </section>

 

  因为代码已经足够简单,所以不再一一详解,如果有任何问题可以在评论里面讨论,欢迎提各种建议!