zoukankan      html  css  js  c++  java
  • C#微信公众平台账号开发,从零到整,步骤详细。

    想到微信的火热,想到其他公司开发手游,如雷电,酷跑类的,都不是很火,但是弱智的“打飞机”和“天天酷跑”却是那么火热。于是乎,想做个微信营销的软件。
    首先想到的是手机连电脑wifi,用抓包工具抓微信的包,然后分析。奋斗2星期,基本一无所获,得到一个结论,腾讯的东西真的不好破解。就算千辛万苦破解一个,只要一更新,前面的努力全部白费。
    于是只能老老实实的去用官方提供的接口。也就是微信公众平台。
    C#开发公众平台,需要在官网mp.weixin.qq.com注册一个账号,审核通过后,就可以开始了。
    第一步
    点开高级功能,关闭弱智的编辑模式,打开高级的开发模式。
    第二部
    进入开发模式,填写接口配置信息。这里也是刚开始困扰我的地方。URL就是服务器地址,刚开始想用自己电脑做服务器,让微信服务器访问,但是我是在内网里,路由器权限也没有,无法端口映射到自己电脑,所以只好网上买了一个服务器空间,一年不到200的那种,空间只有100M,数据库50M。但是够用了。
    Token是验证用的令牌,随便填一个字符串,但是要记住。程序里也要用这个Token字符串来验证是否微信服务器发来请求。不然别人可以模拟请求,伪造信息。
    填好后,还不能通过验证,因为你没写代码。微信服务器访问你的时候,无法获取结果,自然不能通过验证。
    服务器地址填写后,微信服务器会提交get请求,访问你的URL并且带上4个参数。
    1,signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 
    2,timestamp 时间戳 
    3,nonce 随机数 
    4,echostr 随机字符串 
    他的signature加密方式为
    1. 将token、timestamp、nonce三个参数进行字典序排序2. 将三个参数字符串拼接成一个字符串进行sha1加密3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
    通过这些介绍,我们就可以开始在默认页面那里:比如Default.aspx.cs写page_load事件,获取4个参数,按加密算法,获得signature结果,再对比微信发过来的signature,相同,原样输出echostr。这样,就能通过微信服务器验证。以后每次收到消息后,微信就会发送消息到服务器,服务器经过处理后,就可以回复一定的内容给发送过来的那个人消息。

    下面详细介绍如何通过代码,来通过刚才的url接口配置。
    ASP.NET DEFAULT.ASPX页面的page_load事件里。
    首先获取四个参数。
    string signature = Request["signature"];
    string timestamp = Request["timestamp"];
    string nonce = Request["nonce"];
    string echostr = Request["echostr"];
    按照前面说的加密过程,获得加密结果。
    var arr = new[] { token, timestamp, nonce }.OrderBy(z => z).ToArray();
    var arrString = string.Join("", arr);
    var sha1 = System.Security.Cryptography.SHA1.Create();
    var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
    StringBuilder enText = new StringBuilder();
    foreach (var b in sha1Arr)
    {
    enText.AppendFormat("{0:x2}", b);
    }
    对比,
    if( enText.ToString() == signature )
    {
    Response.Output.Write(echostr);
    }
    这样,就完成了简单的一步验证。微信就能通过校验,以后所有信息都会发到你填写的这个url服务器上去了。
    校验完后,以后的消息都是post请求你的服务器。请求里包含一段xml数据。xml数据里包含了用户发过来的数据,和这个用户的openid.你获取了这些信息后,就可以发送自动回复的内容,发给这个openid的用户。

    只要某个用户发过来一个消息,微信服务器就会发送一个post请求到你填写的服务器url上,然后每次都会触发page_load事件。接收用户信息,和处理要回复的内容,都在page_load里。
    if (Request.HttpMethod == "POST")
    {
    string weixin = "";//获取xml数据
    weixin = PostInput();//自定义方法,获取xml数据
    if (!string.IsNullOrEmpty(weixin))
    {
    ResponseMsg(weixin);//根据获取的内容,自动回复一定的内容。
    }

    这样,我们的微信功能就完成了。教程到此结束。。。。。。是不可能的。
    先讲postinput方法,
    private string PostInput()/// 获取post请求数据
    {
    Stream s = System.Web.HttpContext.Current.Request.InputStream;
    byte[] b = new byte[s.Length];
    s.Read(b, 0, (int)s.Length);
    return Encoding.UTF8.GetString(b);
    }
    四行代码,就获取了xml数据。asp.net很少用,所以不知道有没有更好的方法。
    然后就是最重要的ResponseMsg方法了。上源码。
    private void ResponseMsg(string weixin)// 服务器响应微信请求
    {
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(weixin);//读取xml字符串
    XmlElement root = doc.DocumentElement;
    XmlNode MsgType = root.SelectSingleNode("MsgType");//获取收到的消息类型。文本(text),图片(image),语音等。
    string messageType = MsgType.InnerText;
    try
    {
    switch (messageType)
    {
    case "text":
    WriteContent(ResponseText.GetResponseMessage(weixin));
    break;
    case "image":

    break;
    case "voice":
    break;
    case "vedio":
    break;
    case "location":
    break;
    case "link":
    break;
    default:
    break;
    }
    Response.End();
    }
    catch (Exception)
    {

    }
    }
    其实前面讲的都不重要。重要的是分支语句,
    switch (messageType)
    {
    case "text":
    Response.Output.Write(ResponseText.GetResponseMessage(weixin));
    break;
    就是如果用户发过来的是文本请求,调用ResponseText.GetResponseMessage()方法。
    这个方法里,就是根据具体的文本关键字,经过处理,设置自动回复的内容。

    教程其实快结束了。
    只有一个自动回复的方法没讲。直接贴源码了。在代码里注释着讲。
    public static string GetResponseMessage(string weixin)
    {
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(weixin);//读取xml字符串
    XmlElement root = doc.DocumentElement;
    string message = "对不起,无法识别您发送的命令。请发送“帮助”来获取已经实现的功能。";
    string resxml = "";
    var model = new
    {
    ToUserName = root.SelectSingleNode("ToUserName").InnerText,//本公众账号
    FromUserName = root.SelectSingleNode("FromUserName").InnerText,//用户
    CreateTime = root.SelectSingleNode("CreateTime").InnerText,//创建时间
    Content = root.SelectSingleNode("Content").InnerText,//消息内容
    MsgId = root.SelectSingleNode("MsgId").InnerText//消息ID,64位整型
    };//获取xml数据里各个结点的内容。
    MySQL sql = new MySQL();//这里是我记录用户发送的内容到数据库的,不写也没事。
    string str_insert = "insert into ChatRecord values('" + model.FromUserName + "','" + model.Content + "','" + DateTime.Now.ToString().Substring(2) + "')";
    if (sql.ExecuteCommand(str_insert) < 0)//插入失败,记录日志
    {
    StreamWriter sw = new StreamWriter(HttpContext.Current.Request.PhysicalApplicationPath + "/Log/log.txt", true, Encoding.UTF8);
    sw.WriteLine(DateTime.Now.ToString().Substring(2) + ": 插入ChatRecord表失败[" + model.FromUserName + "----" + model.Content + "]");
    sw.Close();
    }
    //这里就是关键的设置自动回复的内容。回复的格式,要按照官方提供的来填写,也是一段xml数据。具体格式,注册了微信公众平台账号后,看API文档就有了。这里稍微简单的介绍一下。ToUserName,就是刚才发过来的那个用户的openid,fromusername一般就是我们的公众账号。CREATETIME就是一个整型时间,unix格式的,转成距离1970年1月1日0点0分有多少秒就行了。MsgType就是回复的类型。你可以回复图片,新闻链接,语音,视频,音乐等。这里我们是文本,所以是text。content就是自动回复的内容。funcflag不管,填写0.
    resxml += "<xml><ToUserName><![CDATA[" + model.FromUserName + "]]></ToUserName><FromUserName><![CDATA[";
    resxml += model.ToUserName + "]]></FromUserName><CreateTime>" + MyAPI.ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";
    ////////////////////////////////////已实现功能////////////////////已实现功能//////////////////////////////////////////////
    //这里如果对方发过来“帮助”,我们设置常量文本(暂时这么叫。。),自动回复给用户。
    if (model.Content == "帮助")
    {
    message = "目前实现功能有:" + CRLF + "1,帮助:获取发送命令菜单" + CRLF;
    message += "2,翻译功能。只要发送“翻译”+空格+需要翻译的内容,即可实现翻译功能。" + CRLF;
    message += "3,天气预报。发送 “天气”+空格+城市名 ,即可查询该城市6天内天气预报。如发送“天气 北京”。" + CRLF;
    }
    //这里。如果是“翻译+空格+词语”,我们就调用百度翻译API,获取翻译结果后,再发给用户。关于这些内容,就不在教程的范围里了。种类太多,毕竟你有可能要操作数据库,请求别的网站,等等各种各种的功能。发送“笑话”,“鬼故事”等等,查数据库也可以,请求别的网站也可以。这里实现方法就不在这个地方讲拉。我也不是很清楚。查了很多资料,才实现了翻译。
    else if (model.Content.Trim().StartsWith("翻译 "))
    {
    string str = model.Content.Trim().Substring(3);
    MyAPI api = new MyAPI();
    MyJSON json = new MyJSON();
    BaiDuFanYiResult obj = json.FromJson<BaiDuFanYiResult>(api.BaiduTanslate(str, "auto", "auto"));
    message = obj.trans_result[0].dst;
    }
    //这里是天气预报。用户发“天气+空格+城市”,
    else if (model.Content.Trim().StartsWith("天气 "))
    {
    string str = model.Content.Trim().Substring(3);
    MyAPI api = new MyAPI();
    MyJSON json = new MyJSON();
    string strjson = api.WeatherReport(str);
    if (strjson.Length < 10)
    {
    message = "对不起,找不到[" + str + "]的天气,请正确输入城市名字,如果城市确实存在,请发送“BUG 城市名”提交BUG";
    resxml += "<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[" + message + "]]></Content><FuncFlag>0</FuncFlag></xml>";
    return resxml;
    }
    RootObject report = json.FromJson<RootObject>(strjson);
    message = "今天: " + report.weatherinfo.temp1 + ", " + report.weatherinfo.weather1 + CRLF;
    message += "明天开始接下来5天天气预报如下:" + CRLF;
    message += report.weatherinfo.temp2 + ", " + report.weatherinfo.weather2 + CRLF;
    message += report.weatherinfo.temp3 + ", " + report.weatherinfo.weather3 + CRLF;
    message += report.weatherinfo.temp4 + ", " + report.weatherinfo.weather4 + CRLF;
    message += report.weatherinfo.temp5 + ", " + report.weatherinfo.weather5 + CRLF;
    message += report.weatherinfo.temp6 + ", " + report.weatherinfo.weather6 + CRLF;
    message += report.weatherinfo.index_d;
    }
    else if (model.Content.Trim().StartsWith(""))
    {

    }
    //这里本来是想写个在线的纯文字(可以带图片)的在线多人RPG游戏。。。暂时还没开始。。个人能力问题。
    else if (model.Content.Trim().StartsWith("游戏 "))
    {
    string gamename = model.Content.Trim().Substring(3);
    message = Game.GetBackground(gamename);
    }
    else
    {
    message = "对不起,无法识别您发送的命令。请发送“帮助”来获取已经实现的功能。";
    }
    resxml += "<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[" + message + "]]></Content><FuncFlag>0</FuncFlag></xml>";
    return resxml;//回复内容有了哦。基本实现了
    }
    还有其他更多的接口,比如发过来图片,语音,音乐,视频等等,还可以获取用户信息,用户地理位置,等等。这里应该又可以想出不少的功能。

     

  • 相关阅读:
    Verilog HDL设计进阶:有限状态机的设计原理及其代码风格_zt
    敏感信号与判断条件冲突引起的错误
    在Quartus II里查看综合器生成的原理图
    RGB与YCbCr颜色空间的互相转换公式
    YCbCr2转换成RGB的verilog解析_zt
    Verilog中函数与任务比较
    Verilog奇偶校验_zt
    8位数据的奇偶校验verilog程序_zt
    4个32位数的比较
    Latex排版工具的使用(一) 分类: Latex 2014-06-14 22:52 448人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/hs8888/p/5527197.html
Copyright © 2011-2022 走看看