最近在帮同事弄他商店的会员系统,牵扯到激活会员卡后自动将信息保存到系统数据库中的功能。这其中就需要对微信服务器那边发送的消息进行接收和处理。然后就需要在公众号基本配置里配置服务器设置并启动,于是他公众号里的自定义菜单也要在系统里实现,瞬间感觉亏大发了。

服务器地址需要指向你所实现的一个验证微信签名的方法。无论是哪种消息加解密方式,验证签名微信服务所使用的都是Get方式,到接收微信发送的消息的时候是POST过来的。下面方法中加解密的类可以在微信公众平台上的Demo下载到,不需要自己处理,直接拿来用即可。

注意,使用wxcpt.DectyptMsg()解密的时候,第一个参数“签名”填的不是随url中的signature里获取到的签名,而是消息签名msg_signature,明文方式里没有这个,但是安全模式有。

public void WXcheckSignature(){string sReqMsgSig;string echostr;string sReqTimeStamp;string encrypt_type;string sReqNonce;sReqMsgSig = HttpContext.Current.Request["signature"];echostr = HttpContext.Current.Request["echostr"];sReqTimeStamp = HttpContext.Current.Request["timeStamp"];sReqNonce = HttpContext.Current.Request["nonce"];encrypt_type = HttpContext.Current.Request["encrypt_type"];    //明文状态下没有这个的if (HttpContext.Current.Request.HttpMethod == "POST"){if (encrypt_type.ToLower() == "aes"){Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(m_sToken, m_sEncodingAESKey, m_sAppID);//获取加密的post消息Stream stream = System.Web.HttpContext.Current.Request.InputStream;stream.Position = 0;byte[] xmlData = new byte[stream.Length];stream.Read(xmlData, 0, xmlData.Length);string sReqData = Encoding.UTF8.GetString(xmlData);XmlDocument m_doc = new XmlDocument();m_doc.LoadXml(sReqData);XmlNode m_root = m_doc.FirstChild;string msgSignature = HttpContext.Current.Request["msg_signature"];string sMsg = "";  //解析之后的明文int ret = 0;ret = wxcpt.DecryptMsg(msgSignature, sReqTimeStamp, sReqNonce, sReqData, ref sMsg);if (ret != 0){System.Console.WriteLine("ERR: Decrypt fail, ret: " + ret);}else{EventInfoAnalysis(sMsg);}//string fromUser = root["FromUserName"].InnerText;}}else  //验证微信签名{string[] ArrTmp = { m_sToken, sReqTimeStamp, sReqNonce };Array.Sort(ArrTmp);     //字典排序string tmpStr = string.Join("", ArrTmp);tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");tmpStr = tmpStr.ToLower();if (tmpStr.Equals(sReqMsgSig)){HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;HttpContext.Current.Response.Write(echostr);}}}

在设置后保存时就会立刻开始验证了,所以要保证你所写的服务器地址能访问到。如果是自己电脑上测试,可以用“花生壳”什么的挂到外网上,不过花生壳是收费的。

<xml><ToUserName> < ![CDATA[gh_3fcea188bf78] ]></ToUserName><FromUserName>< ![CDATA[obLatjlaNQKb8FqOvt1M1x1lIBFE] ]></FromUserName><CreateTime>1432668700</CreateTime><MsgType>< ![CDATA[event] ]></MsgType><Event>< ![CDATA[submit_membercard_user_info] ]></Event><CardId>< ![CDATA[pbLatjtZ7v1BG_ZnTjbW85GYc_E8] ]></CardId><UserCardCode>< ![CDATA[018255396048] ]></UserCardCode>
</xml>

微信公众号开发文档-接收普通消息

上面这一段是接收到的明文消息,ToUserName指向你的服务,FromUserName则是用户的OpenId。

MsgType有几种类型,我这里只处理了“event”和“text”,因为实际需求里只针对菜单点击动作和文本消息自动回复这两个。回复的时候把接收到的xml消息处理后,将ToUserName和FromUserName换一下位置即可。

官方文档里面提到这个,所以一开始你不能确定是因为你的服务器地址写错了还是回复格式出错了,就回复空白HttpContext.Current.Response.Write("");如果你在公众号上发消息没有收到任何消息,也没有出现提示“该公众号提供的服务出现故障,请稍后再试”则证明你的地址是没有问题的。

下面的内容是我在官方文档下的demo里面的,因为我自己处理的忘记截图了。加密后接收的消息是这样的。

<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt>
</xml>

解密出来之后就类似下面这样(形式相同,我复制的可能是内容上毫不相干的)

<xml><ToUserName><![CDATA[mycreate]]></ToUserName><FromUserName><![CDATA[wx5823bf96d3bd56c7]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId>
</xml>

然后就需要解析xml的内容了,我看其他人的处理方式大多数是处理后以Map的形式来,但是C#里面明明有XmlDocument可以用,很奇怪。

回复文本、视频、语音等消息都是以xml的形式,其中视频一类的媒体消息需要你在公众号素材库里有相应的素材,你可以使用微信上的接口https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token= 你的access_token 获取到素材的msgId。

private void EventInfoAnalysis(string xmlStr){//从xml消息中获取解码用的值XmlDocument doc = new XmlDocument();doc.LoadXml(xmlStr);XmlNode root = doc.FirstChild;string msgType = root["MsgType"].InnerText;switch(msgType.ToLower()){case "event"://会员卡激活string eventType = root["Event"].InnerText;string userName = root["FromUserName"].InnerText;string fromName = root["ToUserName"].InnerText;switch(eventType){case "submit_membercard_user_info":string cardCode = root["UserCardCode"].InnerText;string cardId = root["CardId"].InnerText;string jsonResult = new MyHttpRequest().MExcute("GetMemberInfo", string.Format("cardId={0}&code={1}", cardId, cardCode));if (!string.IsNullOrEmpty(jsonResult)){MemCardAliveInfo info = TokenTicketUtil.JsonParseBeanData<MemCardAliveInfo>(jsonResult);if (info != null){memCardActive(info, "", "");}}break;case "VIEW"://介绍等连接 暂时不需要做什么break;case "CLICK":  //菜单点击事件string eventKey = root["EventKey"].InnerText;switch(eventKey){case "V1001_PHONE":ResponseToWeChat(userName,fromName, @"预约热线:******");break;case "V1001_VIDEO":    //视频ResponseVideoToWeChat(userName, fromName, "video", "********", "企业视频",@"同修仁德 济世养生
中华老字号 南京同仁堂 乐家药铺");break;case "V1001_MEM_CARD":  //尊享会员卡string xml0 = new MyHttpRequest().MExcute("sendMemCoups", string.Format("cardId={0}&userName={1}", "*****", userName));HttpContext.Current.Response.Write("");break;case "V1001_NEW_COUP":   //10元新会员优惠券string xml1 = new MyHttpRequest().MExcute("sendMemCoups", string.Format("cardId={0}&userName={1}", "****", userName));HttpContext.Current.Response.Write("");break;default:break;}break;}break;case "text":string content = root["Content"].InnerText;string name = root["FromUserName"].InnerText;string fName = root["ToUserName"].InnerText;ResponseToWeChat(name, fName, "感谢您的来访,自动回复功能正在完善中,暂无法为您提供此服务。");break;default:break;}}

回复的内容也是要以xml的形式来,按照文档上的要求来就行了,我把文本消息和视频消息回复的内容放上来。

/// <summary>/// 根据微信消息回应文本消息/// </summary>/// <param name="toUser"></param>/// <param name="replyText"></param>public string ResponseToWeChat(string toUser, string fromUser, string replyText){string result = "";Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(m_sToken, m_sEncodingAESKey, m_sAppID);string messageTime = MessageCreateTime();string sRespData = string.Format(@"<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{3}]]></Content></xml>", toUser, fromUser, messageTime, replyText);string sEncryptMsg = ""; //xml格式的密文int ret = wxcpt.EncryptMsg(sRespData, messageTime, GetRandomString(10, true, false, false, false, ""), ref sEncryptMsg);//System.Console.WriteLine("sEncryptMsg");//System.Console.WriteLine(sEncryptMsg);if (ret != 0){result = "{\"ERR\": Decrypt fail, ret: " + ret + "}";System.Console.WriteLine("ERR: Decrypt fail, ret: " + ret);}else {result = "{\"MSG\":" + sEncryptMsg + "}";}HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;HttpContext.Current.Response.Write(sEncryptMsg);return result;}
/// <summary>/// 根据微信消息回应视频信息/// </summary>/// <param name="toUser"></param>/// <param name="msgType"></param>/// <param name="mediaID"></param>private void ResponseVideoToWeChat(string toUser, string fromUser, string msgType, string mediaID, string title, string description){Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(m_sToken, m_sEncodingAESKey, m_sAppID);string messageTime = MessageCreateTime();string sRespData = string.Format(@"<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime><MsgType><![CDATA[{3}]]></MsgType><Video><MediaId><![CDATA[{4}]]></MediaId><Title><![CDATA[{5}]]></Title><Description><![CDATA[{6}]]></Description></Video></xml>", toUser, fromUser, messageTime, msgType, mediaID, title, description);string sEncryptMsg = ""; //xml格式的密文int ret = wxcpt.EncryptMsg(sRespData, messageTime, GetRandomString(10, true, false, false, false, ""), ref sEncryptMsg);//System.Console.WriteLine("sEncryptMsg");//System.Console.WriteLine(sEncryptMsg);if (ret != 0){System.Console.WriteLine("ERR: Decrypt fail, ret: " + ret);}HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;HttpContext.Current.Response.Write(sEncryptMsg);}

其中保险起见,加密用的timesmap要与写在xml回复消息里的CreateTime一致,不一致的话应该会出问题吧,我猜。。。wxcpt.EnctyptMsg()这个方法里面的第三个参数是一个随机字符串,由你自己设置,你可以自己编一套规则生成。到这里基本上就完成了,是不是很简单?

C#-微信公众号开发消息管理相关推荐

  1. 微信公众号-模板消息管理

    微信公众号-模板消息管理 通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通 ...

  2. 微信公众号开发--消息接收与回复

    在上篇文章中已经说明如何接入微信服务器,此篇直接接着上篇文章介绍公众号的消息接收与回复,可以结合上篇文章阅读本文,微信公众号开发–服务器接入. 微信公众号开发接口文档: https://mp.weix ...

  3. 该微信用户未开启“公众号安全助手”的消息接收功能,请先开启后再绑定,Java微信公众号开发消息推送公众号用户绑定问题 的解决办法

    问题概述 在进行微信公众号开发的时候遇到的这个问题,通过Web开发公众号的模板消息推送,在调试的过程中,需要进行开发者接口联调&调试,在调试之前需要将当前的公众号与用户的微信号进行绑定, 绑定 ...

  4. 微信公众号模板消息管理

    通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等.不支持广告等营销类消 ...

  5. 微信公众平台开发-消息管理-发送模板消息

    一.模板说明 模板消息是在特定服务场景中向粉丝发送的消息,例如:信用卡刷卡通知,商品购买成功通知.不同的模板有不同的风格,某些字段可以由你来填充自己的内容(同时设定颜色),从而形成自己的消息.微信公众 ...

  6. 微信公众号开发消息推送以及图文推送

    今天给大家分享的关注公众号自动推送图文消息,以及做一个超牛逼的机器人. 先看看效果. 发错图了...这是我昨天开发的一款机器人chu了会骂人啥都不会了.我今天将它词库进行了更新和升级,接入了http: ...

  7. 微信公众平台开发-消息管理-发送客服消息

    一.简介 当用户主动发消息给公众号的时候(包括发送信息.点击自定义菜单.订阅事件.扫描二维码事件.支付成功事件.用户维权),微信将会把消息数据推送给开发者,开发者在一段时间内(目前修改为48小时)可以 ...

  8. ASP.NET MVC5+EF6+EasyUI 后台管理系统(73)-微信公众平台开发-消息管理

    前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较多 思维导 ...

  9. 微信公众号开发的一些方法总结

    概述 微信公众号开发,其实就是微信使用者.微信公众号平台和自身服务器的http消息交互:在这一系列过程中,微信公众号平台充当了中介和转发作用(如图1所示).需要注意的是,微信公众号平台向自身服务器转发 ...

  10. C#开发微信门户及应用(27)-公众号模板消息管理

    原文:C#开发微信门户及应用(27)-公众号模板消息管理 通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中, ...

最新文章

  1. conflicts with existing, non-compatible bean definition of same name and class
  2. 第二阶段个人总结11
  3. 下列设备中 微型计算机系统必须具备的是,计算机应用基础题库
  4. python字符串功能_python字符串内置功能
  5. 「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)
  6. 中小企业CRM评测-用户交互_易客
  7. 《狂人日记》金句摘抄(一)
  8. golang 反射_Golang 会淘汰 Python 吗?
  9. ubuntu如何配置lxr
  10. Java多线程学习总结(5)——乐观锁和悲观锁的基本概念、实现方式(含实例)、适用场景及常见面试题
  11. linux+redhat+5下载地址,Redhat_Linux5下载地址集锦最终.docx
  12. python的pyaudio教程入门_Python音频操作工具PyAudio上手教程!
  13. DS18B20驱动编程
  14. Nature综述|整合组学分析护航健康,推动精准医学时代的到来!
  15. 先验概率与后验概率的区别(老迷惑了)
  16. 网络空间安全 渗透 攻防5(文件共享服务器)
  17. 怎么样可以在阿里云搭建个人网站及域名绑定介绍
  18. Python中的微型巨人-Flask
  19. c语言程序设计陈世清上海交通大学出版社,C语言程序设计
  20. 立创元件导入AD集成库的方法

热门文章

  1. ajax选项卡解析,ajax实现的选项卡
  2. Word页码从当前页自增
  3. krait和kryo_高通kryo架构还是arm吗
  4. 访问控制(相关概述)
  5. 1945-计算弹跳高度
  6. Git 修改提交者信息
  7. 滴滴分析专家8000字干货:数据如何驱动业务增长 ?
  8. linux将文件前面100行导出,linux中,使用cat、head、tail命令显示文件指定行
  9. Imbalance data——数据不平衡问题
  10. 2019ICPC徐州 H - Yuuki and a problem (动态(带修)主席树 + 区间Mex问题)