zoukankan      html  css  js  c++  java
  • [开源]微信在线信息模拟测试工具(基于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>

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

  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/szw/p/3888331.html
Copyright © 2011-2022 走看看