前言:微信吧!接触的人都会100%各种踩坑,就算同样东西去年做过,今年来一样踩坑,因为太多你稍微不记得一点点的细节就能让你研究N久。为此,我要把这个过程详细的记录下来。
一、开启消息接受
1.拿到企业corpId,应用的Token,EncodingAESKey
2.这界面先别关,拿到 Token,EncodingAESKey后,建个接口
鉴于公司系统的架构类型,我这里创建的是一个aspx文件,代码如下:
public partial class request_WxMsgApi : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//开启消息接受
if (Request.HttpMethod.ToUpper() == "GET")
{
string signature = HttpContext.Current.Request.QueryString["msg_signature"];
string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
string nonce = HttpContext.Current.Request.QueryString["nonce"];
string echostr = HttpContext.Current.Request.QueryString["echostr"];
string decryptEchoString = "";
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt("your token", "your EncodingAESKey", System.Configuration.ConfigurationManager.AppSettings["Corpid"]);
int ret = wxcpt.VerifyURL(signature, timestamp, nonce, echostr, ref decryptEchoString);
if (ret != 0)
{
//有错误的话记录日志
//WriteLogFile("ERR: VerifyURL fail, ret: " + ret);
}
HttpContext.Current.Response.Write(decryptEchoString);
HttpContext.Current.Response.End();
return;
}
}
}
注意:WXBizMsgCrypt类和Cryptography类,到微信官方下载即可:链接
3.写完代码,将文件更新到服务器,让这个 aspx文件能外网访问。然后再在
把这个aspx文件的链接填上去,若能正常返回,这里就会保存成功,若不能那就得再去补坑了....
二、接收消息
上面已经与微信那边打通了接口,接下来就是要正真接受消息了。开启消息是get请求,而正式使用接受消息则微信是post数据过来,所以 接口打通之后上面那些代码就没用了,因为数据传输模式和处理模式都不一样了。
我这里的接收消息,会把各种类型的文件存到数据库或者服务器,非文本的则存到服务器,放个路径到数据库
代码如下:
public partial class request_WxMsgApi : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
byte[] btHtml = Request.BinaryRead(Request.ContentLength);
string strHtml = System.Text.Encoding.Default.GetString(btHtml);
//接受消息
if (Request.HttpMethod.ToUpper() == "POST")
{
string token = "your token";//从配置文件获取Token
string encodingAESKey = "your EncodingAESKey";//从配置文件获取EncodingAESKey
string corpId = System.Configuration.ConfigurationManager.AppSettings["corpid"];//从配置文件获取corpId
string signature = HttpContext.Current.Request.QueryString["msg_signature"];
string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
string nonce = HttpContext.Current.Request.QueryString["nonce"];
string decryptEchoString = "";
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
int ret = wxcpt.DecryptMsg(signature, timestamp, nonce, strHtml, ref decryptEchoString);
if (ret == 0)
{
//WriteLogFile("ERR: VerifyURL fail, ret: " + ret);
if (!string.IsNullOrEmpty(decryptEchoString))
{
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(decryptEchoString);
XmlNode root = doc.FirstChild;
var msgType = root["MsgType"].InnerText;//voice(MediaId),video(MediaId),text(Content),image(PicUrl),
if (msgType == "voice" || msgType == "video" || msgType == "text" || msgType == "image")
{
var msgId = root["MsgId"].InnerText;
var fromuser = root["FromUserName"].InnerText;
var timesend = root["CreateTime"].InnerText;//时间戳
DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
long lTime = long.Parse(timesend + "0000000");
TimeSpan toNow = new TimeSpan(lTime);
var cTime = dtStart.Add(toNow);
var content = "";
switch (msgType)
{
case "voice":
content = root["MediaId"].InnerText;
break;
case "video":
content = root["MediaId"].InnerText;
break;
case "text":
content = root["Content"].InnerText;
break;
case "image":
content = root["PicUrl"].InnerText;
break;
default:
break;
}
string sql = "insert into T_CmpWxMsg([MsgId],[MsgType],[FromUser],[CreateTime],[Content]) values(@MsgId,@MsgType,@FromUser,@CreateTime,@Content)";
DataHelper.ExecuteNonQuery(sql, new System.Data.SqlClient.SqlParameter[]
{
new System.Data.SqlClient.SqlParameter("@MsgId", msgId),
new System.Data.SqlClient.SqlParameter("@MsgType", msgType),
new System.Data.SqlClient.SqlParameter("@FromUser", fromuser),
new System.Data.SqlClient.SqlParameter("@CreateTime", cTime),
new System.Data.SqlClient.SqlParameter("@Content", content)
}, conString);
//WriteLogFile("存入数据库成功" + cTime);
//异步任务-检索未下载的媒体文件
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
//WriteLogFile("异步任务开始");
try
{
//拉取媒体源文件
string sql_ = "select ID,Content,MsgType from T_CmpWxMsg WHERE ISNULL(MediaSavePath,'')='' and MsgType in ('voice','video')";
var mediaList = DataOperation.DataCenter.ExecuteReader(sql_, Base.ConString, new object[] { });
foreach (var item in mediaList)
{
string corpsecret = System.Configuration.ConfigurationManager.AppSettings["corpsecret"];//你的应用对应的secrect
string tocken = Base.GetCorpToken(corpsecret, corpId).Access_Token;//拿取tocken,注意有效时间,最好用缓存控制
string url = string.Format("https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token={0}&media_id={1}", tocken, item.Content);
string upfile = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"file\wxMaterial");
if (!System.IO.Directory.Exists(upfile))
System.IO.Directory.CreateDirectory(upfile);
string filePath = upfile + "\\" + item.Content + (item.MsgType == "voice" ? ".amr" : ".mp4");
WebClient client = new WebClient();
client.DownloadFile(url, filePath);
//更新存储的物理路径
string updatesql = "update T_CmpWxMsg set MediaSavePath = '" + (@"\file\wxMaterial\" + item.Content + (item.MsgType == "voice" ? ".amr" : ".mp4")) + "' where ID='" + item.ID + "'";
DataHelper.ExecuteNonQuery(updatesql, Base.ConString);
}
}
catch (Exception ex) {
//WriteLogFile("异步任务执行出错:" + ex.Message);
}
});
}
}
catch (Exception ex)
{
// WriteLogFile("程序异常:" + ex.Message);
}
finally
{
//WriteLogFile("解密消息内容:" + decryptEchoString);
HttpContext.Current.Response.Write(decryptEchoString);
HttpContext.Current.Response.End();
}
}
}
}
}
}
注意:这里用到的WXBizMsgCrypt类,在上面有提到可以到官方下载。
三、发送消息
string msg = "你好!点这里查看";
//按部门发送
//item = new { toparty = "438|439|471", msgtype = "text", agentid = "8", text = new { content = msg }, safe = "0" };
//按人发送
dynamic item = new { touser = "wanger|liuer", msgtype = "text", agentid = "你的应用对应的agentid", text = new { content = msg }, safe = "0" };
var body = Base.DataToJson(item);
var corpsecret = System.Configuration.ConfigurationManager.AppSettings["corpsecret"];
string tocken = Base.GetCorpToken(corpsecret).Access_Token;//获取token,注意有效时间,可用缓存控制
string url = string.Format("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={0}", tocken);
var result = Base.InfoPost(url, body);//post request 请求
JavaScriptSerializer js = new JavaScriptSerializer();
IDictionary obj = js.DeserializeObject(result) as IDictionary;
post请求代码
public static string InfoPost(string url, string body)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
request.Timeout = 30000;//30秒
request.Method = "POST";
byte[] payload = System.Text.Encoding.UTF8.GetBytes(body);
Stream writer = request.GetRequestStream();
writer.Write(payload, 0, payload.Length);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"));
var result = reader.ReadToEnd();
return result;
}
下次来写个支付的,自己写的看得懂点,不然每次才坑都要各种百度查资料
以上纯属个人独自研究成果,仅供参考,转载请注明出处