C# 简单的百度推送代码
前段时间搞推送来着,安卓方面用到了百度的推送服务,由于只是简单的用到安卓推送的通知功能,所以没用百度推荐的C# SDK,通过借鉴网上的各种资料和百度的API,费了老大劲终于折腾出来一段能用的代码(早知道这么纠结,直接用别人的了。。。强迫症伤不起啊)
2016-2-17在2.0基础上修改的3.0(百度巨坑,接口文档写的稀烂,文档上也不写明sign签名MD5需要小写,就为了这个问题我抓狂了3天)
最新3.0的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | public class BaiduPush { private const string url = "http://api.tuisong.baidu.com/rest/3.0/push/single_device" ; private const string apikey = "XXXXXXXXXXXXXXXXXX" ; private const string secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXX" ; /// <summary> /// 只简单实现单个设备通知功能 /// </summary> /// <param name="channel_id"></param> /// <param name="msg"></param> /// <param name="type"></param> public static void Send( string channel_id, string msg, string type) { WebClient webClient = new WebClient(); webClient.Headers.Add( "Content-Type" , "application/x-www-form-urlencoded;charset=utf-8" ); webClient.Headers.Add( "User-Agent" , "BCCS_SDK/3.0 (Darwin; Darwin Kernel Version 14.0.0: Fri Sep 19 00:26:44 PDT 2014; root:xnu-2782.1.97~2/RELEASE_X86_64; x86_64) PHP/5.6.3 (Baidu Push Server SDK V3.0.0 and so on..) cli/Unknown ZEND/2.6.0" ); try { byte [] response = webClient.UploadData(url, "POST" , StructData(channel_id, msg, type)); var ss = Encoding.UTF8.GetString(response, 0, response.Length); } catch (WebException ex) { Stream stream = ex.Response.GetResponseStream(); byte [] bs = new byte [1024]; int index = 0; int b; while ((b = stream.ReadByte()) > 0) { bs[index++] = ( byte )b; } stream.Close(); var ss = Encoding.UTF8.GetString(bs, 0, index); } } /// <summary> /// 构建Data /// </summary> /// <param name="token"></param> /// <param name="msg"></param> /// <param name="type"></param> /// <returns></returns> private static byte [] StructData( string channel_id, string msg, string type) { DateTime utcNow = DateTime.UtcNow; DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0); uint timestamp = ( uint )(utcNow - epoch).TotalSeconds; uint expires = ( uint )(utcNow.AddDays(1) - epoch).TotalSeconds; //一天后过期 Dictionary< string , string > dic = new Dictionary< string , string >(); dic.Add( "apikey" , apikey); dic.Add( "timestamp" , timestamp.ToString()); dic.Add( "expires" , expires.ToString()); dic.Add( "device_type" , "3" ); //3:android 4:iOS dic.Add( "channel_id" , channel_id); dic.Add( "msg_type" , "1" ); //取值如下:0:消息;1:通知。默认为0 dic.Add( "msg" , "{\"title\":\"hello\",\"description\":\"" + msg + "\",\"custom_content\":{\"ClassName\":\"igs.android.healthsleep.MainActivity\",\"PushMessageType\":" + type + "}}" ); dic.Add( "sign" , StructSign( "POST" , url, dic, secret_key)); StringBuilder sb = new StringBuilder(); foreach ( var d in dic) { sb.Append(d.Key + "=" + d.Value + "&" ); } sb.Remove(sb.Length - 1, 1); return Encoding.UTF8.GetBytes(sb.ToString()); } /// <summary> /// 构建Sign /// </summary> /// <param name="httpMethod"></param> /// <param name="url"></param> /// <param name="dic"></param> /// <param name="secret_key"></param> /// <returns></returns> private static string StructSign( string httpMethod, string url, Dictionary< string , string > dic, string secret_key) { //按key正序 dic = dic.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value); StringBuilder sb = new StringBuilder(); //构建键值对 foreach ( var d in dic) { sb.Append(d.Key + "=" + d.Value); } string sign = httpMethod + url + sb + secret_key; //url编码 sign = sign.UrlEncode(); //将编码后替换的字符大写,这地方是个坑。。。文档里根本没说明 char [] cs = new char [sign.Length]; for ( int i = 0; i < sign.Length; i++) { cs[i] = sign[i]; if (sign[i] == '%' ) { cs[++i] = Convert.ToChar(sign[i].ToString().ToUpper()); cs[++i] = Convert.ToChar(sign[i].ToString().ToUpper()); } } //MD5加密 return new string (cs).MD5().ToLower(); //巨坑,sign原来要小写,接口文档里根本就没有说明。。。 } } /// <summary> /// 用到的扩展方法 /// </summary> public static class ExtendMethod { /// <summary> /// MD5加密 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string MD5( this string str) { byte [] bs = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(str)); return BitConverter.ToString(bs).Replace( "-" , "" ); } /// <summary> /// url编码 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string UrlEncode( this string str) { str = System.Web.HttpUtility.UrlEncode(str, Encoding.UTF8); /* * 不知道为什么微软要把空格编码为+,浏览器不认识啊 * 只能在这里手动替换下了 * */ return str.Replace( "+" , "%20" ); } } |
以前2.0的
/// <summary> /// 百度推送 /// </summary> public class BaiduPush { private const string method = "push_msg"; private const string url = "https://channel.api.duapp.com/rest/2.0/channel/channel"; private const string apikey = "xxxxxxxxxxxxxxxxx"; private const string secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"; public static string Push(string user_id, string title, string description, string msg_keys) { DateTime utcNow = DateTime.UtcNow; DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0); uint timestamp = (uint)(utcNow - epoch).TotalSeconds; uint expires = (uint)(utcNow.AddDays(1) - epoch).TotalSeconds; //一天后过期 Dictionary<string, string> dic = new Dictionary<string, string>(); dic.Add("method", method); dic.Add("apikey", apikey); dic.Add("timestamp", timestamp.ToString()); dic.Add("expires", expires.ToString()); dic.Add("push_type", "1"); //单播 dic.Add("device_type", "3"); //Andriod设备 dic.Add("user_id", user_id); dic.Add("message_type", "1"); //只发通知 dic.Add("messages", "{\"title\":\"" + title + "\",\"description\":\"" + description + "\"}"); dic.Add("msg_keys", msg_keys); //消息标识 相同消息标识的消息会自动覆盖。只支持android。 dic.Add("sign", StructSign("POST", url, dic, secret_key)); StringBuilder sb = new StringBuilder(); foreach (var d in dic) { sb.Append(d.Key + "=" + d.Value + "&"); } sb.Remove(sb.Length - 1, 1); byte[] data = Encoding.UTF8.GetBytes(sb.ToString()); WebClient webClient = new WebClient(); try { webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可 byte[] response = webClient.UploadData(url, "POST", data); return Encoding.UTF8.GetString(response); } catch (WebException ex) { Stream stream = ex.Response.GetResponseStream(); byte[] bs = new byte[256]; int i = 0; int b; while ((b = stream.ReadByte()) > 0) { bs[i++] = (byte)b; } stream.Close(); return Encoding.UTF8.GetString(bs, 0, i); } } /// <summary> /// 构建Sign /// </summary> /// <param name="httpMethod"></param> /// <param name="url"></param> /// <param name="dic"></param> /// <param name="secret_key"></param> /// <returns></returns> private static string StructSign(string httpMethod, string url, Dictionary<string, string> dic, string secret_key) { //按key正序 dic = dic.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value); StringBuilder sb = new StringBuilder(); //构建键值对 foreach (var d in dic) { sb.Append(d.Key + "=" + d.Value); } string sign = httpMethod + url + sb + secret_key; //url编码 sign = sign.UrlEncode(); //将编码后替换的字符大写,这地方是个坑。。。 char[] cs = new char[sign.Length]; for (int i = 0; i < sign.Length; i++) { cs[i] = sign[i]; if (sign[i] == '%') { cs[++i] = Convert.ToChar(sign[i].ToString().ToUpper()); cs[++i] = Convert.ToChar(sign[i].ToString().ToUpper()); } } //MD5加密 return new string(cs).MD5(); } }
外加两个扩展方法
System.Web.HttpUtility.UrlEncode需要添加引用System.Web (.net framework 4.0 client profile下面找不到System.Web请切换到.net framework 4.0)
/// <summary> /// MD5加密 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string MD5(this string str) { byte[] bs = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(str)); return BitConverter.ToString(bs).Replace("-", ""); } /// <summary> /// url编码 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string UrlEncode(this string str) { return System.Web.HttpUtility.UrlEncode(str, Encoding.UTF8); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)