前段时间搞推送来着,安卓方面用到了百度的推送服务,由于只是简单的用到安卓推送的通知功能,所以没用百度推荐的C# SDK,通过借鉴网上的各种资料和百度的API,费了老大劲终于折腾出来一段能用的代码(早知道这么纠结,直接用别人的了。。。强迫症伤不起啊)
2016-2-17在2.0基础上修改的3.0(百度巨坑,接口文档写的稀烂,文档上也不写明sign签名MD5需要小写,就为了这个问题我抓狂了3天)
最新3.0的
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";
///
/// 只简单实现单个设备通知功能
///
///
///
///
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);
}
}
///
/// 构建Data
///
///
///
///
///
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 dic = new Dictionary();
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());
}
///
/// 构建Sign
///
///
///
///
///
///
private static string StructSign(string httpMethod, string url, Dictionary 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原来要小写,接口文档里根本就没有说明。。。
}
}
///
/// 用到的扩展方法
///
public static class ExtendMethod
{
///
/// MD5加密
///
///
///
public static string MD5(this string str)
{
byte[] bs = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(str));
return BitConverter.ToString(bs).Replace("-", "");
}
///
/// url编码
///
///
///
public static string UrlEncode(this string str)
{
str = System.Web.HttpUtility.UrlEncode(str, Encoding.UTF8);
/*
* 不知道为什么微软要把空格编码为+,浏览器不认识啊
* 只能在这里手动替换下了
* */
return str.Replace("+", "%20");
}
}
以前2.0的
////// 百度推送 /// 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); } } /// /// 构建Sign /// /// /// /// /// /// 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)
////// MD5加密 /// /// /// public static string MD5(this string str) { byte[] bs = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(str)); return BitConverter.ToString(bs).Replace("-", ""); } /// /// url编码 /// /// /// public static string UrlEncode(this string str) { return System.Web.HttpUtility.UrlEncode(str, Encoding.UTF8); }