[开源]微信在线信息模拟测试工具(基于Senparc.Weixin.MP开发)

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

  目前为止似乎还没有看到过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 Featured
100 {
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>

 

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

 

QQ:498977166

http://szw.cnblogs.com/
研究、探讨.NET开发
转载请注明出处和作者,谢谢!

 

微信开发深度解析:微信公众号、小程序高效开发秘籍
Senparc官方教程《微信开发深度解析:微信公众号、小程序高效开发秘籍》,耗时2年精心打造的微信开发权威教程,点击这里,购买正版

 

目录
相关文章
|
12天前
|
消息中间件 Java 数据库
【消息队列开发】 实现 VirtualHostTests 类——测试虚拟主机操作
【消息队列开发】 实现 VirtualHostTests 类——测试虚拟主机操作
|
12天前
|
消息中间件 存储 测试技术
【消息队列开发】 实现MemoryDataCenterTests类——测试管理内存数据
【消息队列开发】 实现MemoryDataCenterTests类——测试管理内存数据
|
2天前
|
小程序 前端开发 JavaScript
微信小程序|高校毕业生就业信息的设计与实现
微信小程序|高校毕业生就业信息的设计与实现
|
2天前
|
小程序 前端开发 JavaScript
微信小程序|机电公司管理信息系统的设计与实现
微信小程序|机电公司管理信息系统的设计与实现
|
9天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的外卖小程序的研究与开发的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的外卖小程序的研究与开发的详细设计和实现
12 0
|
10天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的智慧旅游平台开发微信小程序的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的智慧旅游平台开发微信小程序的详细设计和实现
29 8
|
10天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp微信小程序的小区租拼车管理信息系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的小区租拼车管理信息系统的详细设计和实现
10 0
|
12天前
|
NoSQL 关系型数据库 MySQL
软件测试之【基于开源商城系统fecmall功能测试项目实例】
软件测试之【基于开源商城系统fecmall功能测试项目实例】
20 0
软件测试之【基于开源商城系统fecmall功能测试项目实例】
|
12天前
|
测试技术 程序员 开发者
软件测试项目式学习一(认识软件生命周期与开发模型及软件质量)
软件测试项目式学习一(认识软件生命周期与开发模型及软件质量)
7 0
|
12天前
|
敏捷开发 测试技术
【软件测试】 开发模型和测试模型
【软件测试】 开发模型和测试模型