• [开源]微信在线信息模拟测试工具(基于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 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>

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

  • 相关阅读:
    C#写的操作系统
    FPS游戏:实现狙击子弹加速
    内表的一些操作例子(工作区赋值使用了新语法)
    SAP MM模块相关透明表收集
    简单的ALV显示例子
    拼接和前导零用法
    LOOP AT GROUP语法练习
    RFC函数的初步使用同步
    excel保存时出现“请注意,您的文档的部分内容可能包含了文档检查器无法删除的个人信息”
    Abap内表
  • 原文地址:https://www.cnblogs.com/szw/p/3888331.html
Copyright © 2020-2023  润新知