最近一个项目用到了微信小程序,并且需要通过微信服务号的模板消息发送消息提醒。之前一直采用的方式是在微信小程序中让用户输入用户名和密码来绑定账号,并且在服务号中再绑定一次系统用户来实现小程序和服务号的关联。由于需要绑定两次比较繁琐,所以这次想换一种方式,注册了一个微信开放平台,然后在开放平台中绑定服务号和小程序,这样就可以在小程序和服务号中通过获取unionid来实现关联。
小程序中获取unionid比较简单,在调用登陆接口时返回的参数中就已经携带了unionid,如果有需要我再单独写文章介绍。微信服务号中获取unionid也不难,通过openid就可以获取到,但最关键的是我想在用户关注公众号的同时就获取到用户的openid和unionid,这样用户就不用做过多的操作。在网上找了很多资料,也没找到C#相关的实现代码,花了半天时间研究,终于搞定,废话不多说,直接说过程。
第一步,代码实现
新建一个一般处理程序,在ProcessRequest中加入如下代码
try
{
string signature = HttpContext.Current.Request["signature"];
string echostr = HttpContext.Current.Request["echostr"];
string timeStamp = HttpContext.Current.Request["timeStamp"];
string nonce = HttpContext.Current.Request["nonce"];
if (context.Request.HttpMethod == "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 resultStr = Encoding.UTF8.GetString(xmlData);
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(resultStr);
XmlNode xRoot = xdoc.FirstChild;
string msgType = xRoot["MsgType"].InnerText.Trim().ToLower();
if (msgType == "event")//事件
{
string eventStr = xRoot["Event"].InnerText.Trim().ToLower();
string openId = xRoot["FromUserName"].InnerText.Trim();
if (eventStr == "subscribe")//关注
{
//获取token
string APPID = King.StringOper.getConfigValue("fwh_appid");
string APPSECRET = King.StringOper.getConfigValue("fwh_appSecret");
string tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APPID + "&secret=" + APPSECRET;
resultStr = King.StringOper.getJsonFromUrl(tokenUrl);
JObject jo = JObject.Parse(resultStr);
string access_token = jo["access_token"].ToString();
//获取unionid
string unionidUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_token + "&openid=" + openId + "&lang=zh_CN";
resultStr = King.StringOper.getJsonFromUrl(unionidUrl);
jo = JObject.Parse(resultStr);
string unionid = jo["unionid"].ToString();
context.Response.Write("感谢您的关注");
}
else if (eventStr == "unsubscribe")//取消关注
{
writeLog(openId + "取消关注微信号");
}
}
else
{
context.Response.Write("");//防止提示故障
}
}
else
{
//这里的Token令牌要与第三步服务器配置中的Token一致
string[] ArrTmp = { "Token令牌", timeStamp, nonce };
Array.Sort(ArrTmp);
string tmpStr = string.Join("", ArrTmp);
tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
tmpStr = tmpStr.ToLower();
if (tmpStr.Equals(signature))
{
HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;
HttpContext.Current.Response.Write(echostr);
}
}
}
catch (Exception ex)
{
context.Response.Write("");//防止提示故障
writeExceptionInfo(ex.ToString());
}
上面代码中做了请求方式的判断,如果是POST方式请求,则说明有消息过来了,如果是Get方式请求说明是微信公众平台配置时的验证。
由于微信服务器调用该接口时传递的参数是xml参数,因此需要通过XmlDocument对xml数据进行解析,参数格式如下:
代码下载地址:关注服务号时获取openid和unionid-小程序文档类资源-优快云下载
第二步,发布程序
将程序发布到iis或tomcat服务器,注意必须是80或443端口,这点微信有点不人性,为什么非得这两个端口,发布过程此处不详细说明。
第三步,微信公众平台配置
这一步比较关键,因为需要在线验证,所以要确保之前写的程序已经发布,在微信公众平台中登陆服务号,然后在基本配置页面启用“服务器配置”。服务器地址填写第一步中创建的一般处理程序的url,令牌(Token)自己填写,只需要跟代码中保持一致即可,消息加密解密密钥随机生成一个,因为我设置的是明文模式所以这里无所谓,如果设置的是加密模式,则需要在代码中对读取到的XML文档进行对应的解密操作。