微信公众号-入坑指南(一)
微信公众号开发,没接触过的时候觉得挺高大上,自脱离大厂,入职中小公司后,技术几乎全靠自己一个人踩抗,当初入职公司的时候,第一个主任务中有一部分就涉及到了公众号开发,包括订阅,推送,学生扫码支付宿舍水电费,住宿费等等。由于从来没接触过微信开发,所以抱着无比激动的心情啃了一遍又一遍微信接口文档,不明就里。因为完全没有一点概念,首先要搞清楚订阅号,企业号,公众号三者之间的关系。区别还是挺大的,个人目前只能申请订阅号,微信提供的接口贼少,连个自定义菜单接口都么有,个人推推文章啥的凑合着用,要想尝试更多功能,只能是企业身份去注册公众号,当然有些功能还都是收费的,比如模板推送消息就要300元/年。其实网上很多教程代码给的都有坑,Copy下来很多都是自定义的类,又不提供全,很不利于新手的学习,新手最想的是什么,先来一个简单的,可以跑起来的程序,然后由浅及深的自我去认知,找个某系列教程, copy下来后 ,报红,一看是自定义类的锅,源码中又没有,真是坑,换一个教程,copy下来又是如此,反反复复几次,心态很容易就蹦,如果有接触过微信开发,或者能静下心来啃文档,这些都还好,当初我呢,时间很急,又从来没有接触过,身边更没有同事去请教,真是越慌越糟糕,最后一点一点的啃出来。只要程序能跑起来,心里大致有谱了,这个时间在去接触接口文档,看需求,加功能就得心应手了,万事开头难,古人诚不欺我也!
第一.搞微信第一个坑,要有一个外网,这里是在花生壳上注册一个域名,要保证域名解析正常,不正常的及时到官网找原因,或者直接提交工单,让后台人员处理,毕竟免费的壳域名不稳定,收费的顶级域名果然稍微好点(现在域名需要实名认证),在域名解析正常之后,开始设置内网映射。注意这里内网主机的端口号设置为80,没办法微信规定只对接80 或者443(https),之前可以转接端口号后来被封了只能老老实实用80。如下图所示:
第二,外网映射的问题搞定后,意味已经拥有了自己的外网域名网站,就可以着手开发网站,自动回复消息,这里新建一 MVC空项目,在引用中下载微信negut 包,主要盛派的 Senparc.Weixin.MP,Senparc.Weixin.MP.MVC 两个包,然后新建一控制器WeChat,方法如下,这是方法是用来验证订阅号中相关参数配置是否正确,需要登录微信公众平台在基本参数里面配置时 ,这里填写 url 的一定要为外网,并且指向地址一定要是这里新建的控制器 Wechat 保持一致
// GET: WeChat [HttpGet] [ActionName("Index")] public Task<ActionResult> Get(string signature, string timestamp, string nonce, string echostr) { return Task.Factory.StartNew(() => {
//申请订阅号token var token = ConfigHelper.ExitCache("Token"); if (CheckSignature.Check(signature, timestamp, nonce, token)) { //获取Token var acestoken = TokenHelper.IsExistAccess_Token(); return echostr; //返回随机字符串则表示验证通过 } else { return "failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, token) + "。" + "如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。"; } }).ContinueWith<ActionResult>(task => Content(task.Result)); }
填写一致后,微信公众平台里保存配置时,才会跳转到上面那个方法,检查好token,appId 等参数是否配对,有时候由于网络原因需要多点击几次,才会跳转到上面的方法中,调用微信接口时,需要提供一个token,而这个token 请求的次数对于订阅号而言是有限的,也就2000次,请求完了就没有了,所以一般这里,获取token的时候,我们判断一下token是否过期(2小时有效期),若未过期就不去请求最新的 token,避免浪费资源,这里处理方式为在配置文件中添加两个字段,一个保存 token,一个记录当前到期时间。完整代码如下:
public class TokenHelper { /// <summary> /// 根据当前日期 判断Access_Token 是否超期 如果超期返回新的Access_Token 否则返回之前的Access_Token /// </summary> /// <param name="datetime"></param> /// <returns></returns> public static string IsExistAccess_Token() { string token = string.Empty; DateTime youXRQ; // 读取XML文件中的数据,并显示出来 ,注意文件路径 string filepath = ConfigHelper.ExitCache("CurrentTokenPath"); XElement xml = XElement.Load(filepath); token = xml.Descendants("Access_Token").FirstOrDefault().Value.ToString(); youXRQ = Convert.ToDateTime(xml.Descendants("Access_YouXRQ").FirstOrDefault().Value.ToString()); //判断当前 token 是否过期 if (DateTime.Now > youXRQ) { DateTime _youxrq = DateTime.Now; Access_token mode = GetAccess_token(); xml.Descendants("Access_Token").FirstOrDefault().Value = mode.access_token; _youxrq = _youxrq.AddSeconds(int.Parse(mode.expires_in)); xml.Descendants("Access_YouXRQ").FirstOrDefault().Value= _youxrq.ToString(); xml.Save(filepath); token = mode.access_token; } return token; } /// <summary> /// 获取Access_token /// </summary> /// <returns></returns> private static Access_token GetAccess_token() { var appid = ConfigHelper.ExitCache("AppId"); var secret = ConfigHelper.ExitCache("AppSecret"); string strUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret; Access_token mode = new Access_token(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strUrl); //用GET形式请求指定的地址 req.Method = "GET"; using (WebResponse wr = req.GetResponse()) { StreamReader reader = new StreamReader(wr.GetResponseStream(), Encoding.UTF8); string content = reader.ReadToEnd(); reader.Close(); reader.Dispose(); //在这里对Access_token 赋值 Access_token token = new Access_token(); token = JsonHelper.ParseFromJson<Access_token>(content); mode.access_token = token.access_token; mode.expires_in = token.expires_in; } return mode; } }
其中类 Access_token 包含两个类型为字符串的成员字段 access_token(获取到的凭证),expires_in(凭证有效时间,秒),到这里算是将 微信公众号 和 所开发的程序关联起来。切记:微信公众平台中的白名单中需要添加开发电脑的内网ip,否则获取不到token,会提示当前往网络不在白名单内。