公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)
背景:周末接到领导要求,实现一个功能,在公司绩效考核系统中,增加一个功能,每当同事点击任务需求,提交领导审核后,推送一条微信提示信息,
周六加班摸索了大半天,获得访问接口关键性凭证access_token,
周一一天时间拿到code,和openid,可以发送消息,
周二今天,进行各种优化,总算完成功能实现有图有真相
第一步:获取access_token,为能够成功获取关键是配置微信公众号里,开发者,基础配置信息,
public string GetAccess_Token()
{
string appid = "";
string appsecret = "";
//获取tokenstr
string token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
string result = GetWebContent(token_url);
//saveOpenID(result);
TokenAccess jsonObj = JsonConvert.DeserializeObject<TokenAccess>(result);
return jsonObj.access_token;
}
//优化,这个token有效期为两个小时,如果需要频繁发送推送,建议优化获取如下,
//记录获取时间,存到session当中,两个小时快结束前,进行重新获取,否则用存的
private string GetAccessToken()
{
double Now = GetTimeStamp(DateTime.Now);//获取一个Unix时间戳
if (Session["last"] != null)
{
last = Convert.ToDouble(Session["last"].ToString());
}
if (Now - last > 7000)
{
var result = new WXutil().GetAccess_Token();
try
{
token = result;
Session["last"] = Now;
Session["token"] = result;
return token;
}
catch (Exception)
{
return "err";
throw;
}
}
else
{
return Session["token"].ToString();
}
}
public double GetTimeStamp(DateTime d)
{
TimeSpan ts = d.ToUniversalTime() - new DateTime(1970, 1, 1);
return ts.TotalSeconds; //精确到毫秒
}
重点:白名单填写当前可允许访问的ip,(因为是跨域请求微信那边,相当于让对方设置你可以访问的)
点击IP白名单 后面设置,弹出如下弹窗
做完这一步很容易拿到token_token,
第二步:调用发送方法,除了有openid,还有一个关键信息templateid
这里先看拿到openid,即被发送消息的那个人标识,这个需要先拿到对方的验证code,
难点重点,难点重点,难点重点
配置完成如下:
获取code至关重要关键性一步:验证填写
这个页面是用来指定验证微信发过来凭证的,上面url里就写这个页面的路径
这个页面是用来指定验证微信发过来凭证的,上面url里就写这个页面的路径
这个页面是用来指定验证微信发过来凭证的,上面url里就写这个页面的路径
获取token,提交失败概率非常大,仔细检查,确认无误,多提交两次,
如果是后台发送请求方式,建议用文件记录相关信息,毕竟服务器端调试并不方便
protected void Page_Load(object sender, EventArgs e)
{
//处理微信验证服务请求,
//微信加密签名
string signature = Request["signature"];
//随机数
string nonce = Request["nonce"];
//时间戳
string timestamp = Request["timestamp"];
//凭据
string token = "fbjr";
string[] sort = { token, nonce, timestamp };
sort.Reverse();
string str = sort.ToString();
//理论来说,将以上三个参数,按照字典排序,进行拼接后,进行sha加密,和signature进行签名,
//这里为了省事,不做对比
//输出内容
string res = SHA1(str);
if (res==signature)
{
}
//echostr:6989564500401158062&signature:cf05c734fa61a6f806ed3082cd58b4318d34795e&nonce:17909316×tamp:1560752300
//echostr:7261461738163745518--signature:6cd95895a307b5bf8569de43d71e4d84e97c5316--nonce:992486027--timestamp:1560752806
string echostr = Request["echostr"];
//string test = "echostr:" + echostr + "--" + "signature:" + signature + "--" + "nonce:" + nonce + "--" + "timestamp:" + timestamp;
// string path = AppDomain.CurrentDomain.BaseDirectory + "weixin\\";
//StreamWriter mySw = new StreamWriter(path+"\\weixin.txt");//将文件流给写入器
//mySw.Write(Environment.NewLine+test + Environment.NewLine);
//mySw.Close();
Response.Write(echostr);
Response.End();
}
可以用二维码生成这个超链接,手机扫码进行授权,授权成功后这个页面,后面会跟一个code,进行获取openid
这个链接,是直接打开的,不能用ajax等其他方式,直接手机端访问,建议做成二维码超链接,
这个链接,是直接打开的,不能用ajax等其他方式,直接手机端访问,建议做成二维码超链接,
这个链接,是直接打开的,不能用ajax等其他方式,直接手机端访问,建议做成二维码超链接,
protected void Page_Load(object sender, EventArgs e)
{
string code=Request["code"];
string codeTest = wx.getCode();
string openId=wx.getopendid(code);
//openId = "ow5Qi5kaNCIrCXWBeDZr3ug5rLPY";//徐维
//openId="ow5Qi5n4Z5IiHINcg-0D2HDy1cAI";//邵然
//openId = "ow5Qi5rGdirLy88Qli7-W0HQPKTU";//张总
Response.Redirect("../Login.aspx?openid="+openId);
}
配置好域名,写好一个验证微信发送凭证的请求
public void SendMsgToWX(string openId){
//token = GetAccessToken();
string token = wx.GetAccess_Token();
string msg = "{\"touser\": \"" + openId + "\"," +
"\"template_id\": \"rztm1VcS2iXnJBN-A8V-WA4NiAa2SGnUBr8Z82nl3kc\", " +
"\"topcolor\": \"#FF0000\", " +
"\"data\": " +
"{\"first\": {\"value\": \"您好,您在绩效考核系统中,收到一条消息!\"}," +
"\"keyword1\": { \"value\": \"填写内容和模板相对应\"}," +
"\"keyword2\": { \"value\": \"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}," +
"\"keyword3\": { \"value\": \"填写内容和模板相对应\"}," +
"\"remark\": {\"value\": \"请尽快查看处理!\" }}}";
wx.saveOpenID("获取openid:" +openId);
string sendResult = wx.ModelMessageSend(msg, token);
//wx.saveOpenID(Environment.NewLine + "------------------" + DateTime.Now.ToLocalTime() + "---------------------");
wx.saveOpenID("发送结果返回消息:"+sendResult);
}
第三步:获取模板,在微信后台菜单 添加功能里,将这个功能拖动过来,
申请下来模板,填写模板号,接口号,即大工告成。
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using Newtonsoft.Json;
namespace WX
{
public class TokenAccess
{
public string access_token { get; set; }
public string expires_in { get; set; }
}
public class OpenID
{
public string access_token { get; set; }
public string expires_in { get; set; }
public string refresh_token { get; set; }
public string openid { get; set; }
public string scope { get; set; }
}
public class WXutil
{
// redirect_uri 回调地址
//scope=snsapi_base
//snsapi_base 发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的
//scope=snsapi_userinfo
//以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
//获取code,用来获取openid
//获取opendi
public String getCode()
{
string appid = "";
string secret = "";
string redirect_uri = Uri.EscapeUriString("http://jx.fbjr.cn/weixin/index.aspx");
String openid_url = "https://open.weixin.qq.com/connect/oauth2/authorize"
+ "?appid=APPID"
+ "&redirect_uri=REDIRECT_URI"
+ "&response_type=code"
+ "&scope=snsapi_base"
+ "&state=STATE"
+ "#wechat_redirect";
openid_url = openid_url.Replace("APPID", appid)
.Replace("AppSecret", secret).Replace("State", "1").Replace("REDIRECT_URI", redirect_uri);
string openid = GetWebContent(openid_url);
return openid;
}
public void saveOpenID(string openId)
{
string path = AppDomain.CurrentDomain.BaseDirectory + "weixin\\";
//StreamWriter sw = new StreamWriter(path + "\\weixin.txt");
//sw.Write(Environment.NewLine + test + Environment.NewLine);
//sw.Close();
FileStream fs = File.OpenWrite(path + "\\weixin.txt");
fs.Position = fs.Length;
Encoding encoder = Encoding.UTF8;
byte[] bytes = encoder.GetBytes(Environment.NewLine + openId + Environment.NewLine);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
}
//获取opendi
public String getopendid(String code)
{
string appid = "";
string secret = "";
String openid_url ="https://api.weixin.qq.com/sns/oauth2/access_token"
+ "?appid=AppId"
+ "&secret=AppSecret"
+ "&code=CODE"
+ "&grant_type=authorization_code";
openid_url = openid_url.Replace("AppId", appid)
.Replace("AppSecret", secret)
.Replace("CODE", code);
string result = GetWebContent(openid_url);
//saveOpenID(Environment.NewLine+"------------------"+DateTime.Now.ToLocalTime()+"---------------------");
saveOpenID("授权同意获取结果:"+result);
//saveOpenID(Environment.NewLine + "---------------------------------------" );
OpenID jsonObj = JsonConvert.DeserializeObject<OpenID>(result);
return jsonObj.openid;
//return openid;
}
//此获取基础token,即开发者公众号身份id
public string GetAccess_Token()
{
string appid = "";
string appsecret = "";
//获取tokenstr
string token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
string result = GetWebContent(token_url);
//saveOpenID(result);
TokenAccess jsonObj = JsonConvert.DeserializeObject<TokenAccess>(result);
return jsonObj.access_token;
}
public string ModelMessageSend(string data, string tc)
{
string url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + tc;
string result = HttpPost(url, data);
if (result.Contains("ok"))
{
return result;
}
else
{
return "消息推送失败,具体错误为:" + result;
}
}
public string HttpPost(string url, string postData)
{
byte[] data = Encoding.UTF8.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "Post";
request.ContentType = "application/json";
request.ContentLength = data.Length;
request.KeepAlive = true;
Stream stream = request.GetRequestStream();
stream.Write(data, 0, data.Length);
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = (HttpWebResponse)ex.Response;
}
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string content = reader.ReadToEnd();
request.Abort();
response.Close();
reader.Dispose();
stream.Close();
stream.Dispose();
return content;
}
public static string GetHtmlSource(string url, string encodestr)
{
Uri uri = new Uri(url);
System.GC.Collect();
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri);
myReq.UserAgent = "User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705";
myReq.Accept = "*/*";
myReq.KeepAlive = true;
myReq.Timeout = 5 * 60 * 1000;
myReq.Headers.Add("Accept-Language", "zh-cn,en-us;q=0.5");
System.Net.ServicePointManager.DefaultConnectionLimit = 50;
HttpWebResponse result = null;
string strHTML = "";
try
{
result = (HttpWebResponse)myReq.GetResponse();
}
catch (Exception ex)
{
// DebugForWinform(ex.ToString());
throw ex;
}
finally
{
Stream receviceStream = result.GetResponseStream();
if (result.ContentEncoding.ToLower().Contains("gzip"))
{
receviceStream = new GZipStream(receviceStream, CompressionMode.Decompress);
}
StreamReader readerOfStream = new StreamReader(receviceStream, System.Text.Encoding.GetEncoding(encodestr));
strHTML = readerOfStream.ReadToEnd();
readerOfStream.Close();
receviceStream.Close();
result.Close();
}
return strHTML;
}
public string GetWebContent(string uri)
{
string strResult = "";
try
{
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri);
myReq.Timeout = 3000;
myReq.Headers.Set("Pragma", "no-cache");
HttpWebResponse result = (HttpWebResponse)myReq.GetResponse();
Stream receviceStream = result.GetResponseStream();
Encoding encoding = Encoding.GetEncoding("UTF-8");
StreamReader sr = new StreamReader(receviceStream, encoding);
strResult = sr.ReadToEnd();
sr.Close();
result.Close();
receviceStream.Close();
}
catch (Exception)
{
//连接出错,请重试
throw;
}
return strResult;
}
}
}
以上是本文章全部内容,时间仓促,已经快下班了,有什么不清楚地方,欢迎留言交流,水平有限之处,也多包涵