這次公司要我們做一個功能,就是當用戶成功注冊以后,他登錄以后要收到消息,當然這個消息是安裝了我們的手機APP應用的手機咯。
極光推送的網站的網址是:https://www.jpush.cn/
極光推送的官方API以及幫助文檔都在這里:http://docs.jpush.cn/display/dev/Index
其中服務端的接口以及示例代碼都在這里:http://docs.jpush.cn/display/dev/Server-SDKs
大家有興趣的可以看看,因為這次我做的不是客戶端APP,所以一筆帶過啦,就跟大家介紹一下C#端的吧。
首先我們下載一下極光推送的C#例子吧,如下圖。
然后例子里面有詳細的介紹,注釋什么的。
極光推送的NET.FRAMEWORK的版本號是4.0的,所以如果我們的網站如果是2.0的,那么就要把極光推送的代碼集成到WebService里面,然后從要用的時候直接調用這個WebService就行了。
下面是例子的源碼:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; using cn.jpush.api; using cn.jpush.api.push; using cn.jpush.api.report; using cn.jpush.api.common; using cn.jpush.api.util; namespace JpushApiClientExample { class JPushApiExample { public class ExtralClass { public String sound = "ssss"; public String menu="button"; } static void Main(string[] args) { Console.WriteLine("************"); Console.WriteLine("*****開始發送******"); //String result; String app_key = "_"; String master_secret = "_"; //int sendno = 9; HashSet<DeviceEnum> set = new HashSet<DeviceEnum>(); set.Add(DeviceEnum.Android); set.Add(DeviceEnum.IOS); JPushClient client = new JPushClient(app_key, master_secret, 0, set, true); MessageResult result = null; NotificationParams notifyParams = new NotificationParams(); CustomMessageParams customParams = new CustomMessageParams(); //notifyParams. //傳入json字符串 String extras = null; extras = "{\"ios\":{\"badge\":88, \"sound\":\"happy\"}}"; //extras中有中文請用HttpUtility.UrlEncode編碼 //System.Web.HttpUtility.UrlEncode(notificationContent, Encoding.UTF8); Console.WriteLine("*****發送帶tag通知******"); /** *發送類型 *APP_KEY 通知 *TAG TAG *ALIAS ALIAS *REGISTRATION_ID REGISTRATION_ID */ notifyParams.ReceiverType = ReceiverTypeEnum.APP_KEY; notifyParams.SendNo = 256; //notifyParams.OverrideMsgId = "1"; result = client.sendNotification("酷派tag111111", notifyParams, extras); Console.WriteLine("sendNotification by tag:**返回狀態:" + result.getErrorCode().ToString() + " **返回信息:" + result.getErrorMessage() + " **Send No.:" + result.getSendNo() + " msg_id:" + result.getMessageId() + " 頻率次數:" + result.getRateLimitQuota() + " 可用頻率:" + result.getRateLimitRemaining() + " 重置時間:" + result.getRateLimitReset()); Console.WriteLine("*****發送帶tag消息******"); //customParams.addPlatform(DeviceEnum.Android); customParams.ReceiverType = ReceiverTypeEnum.TAG; customParams.ReceiverValue = "tag_api"; customParams.SendNo = 256; result = client.sendCustomMessage("send custom mess by tag", "tag notify content", customParams, extras); Console.WriteLine("sendCustomMessage:**返回狀態:" + result.getErrorCode().ToString() + " **返回信息:" + result.getErrorMessage() + " **Send No.:" + result.getSendNo() + " msg_id:" + result.getMessageId() + " 頻率次數:" + result.getRateLimitQuota() + " 可用頻率:" + result.getRateLimitRemaining() + " 重置時間:" + result.getRateLimitReset()); Console.WriteLine(); String msg_ids = "1613113584,1229760629,1174658841,1174658641"; ReceivedResult receivedResult = client.getReceivedApi(msg_ids); Console.WriteLine("Report Result:"); foreach(ReceivedResult.Received re in receivedResult.ReceivedList) { Console.WriteLine("getReceivedApi************msgid=" + re.msg_id+ " ***andriod received="+re.android_received+" ***ios received="+re.ios_apns_sent); } Console.WriteLine(); } public class IOSExtras { public int badge = 888; public String sound = "happy"; } } }
然后我們還是來結合例子一步一步走吧。
首先是發送通知:
Console.WriteLine("************"); Console.WriteLine("*****開始發送******"); //String result; String app_key = "_"; String master_secret = "_"; //int sendno = 9; HashSet<DeviceEnum> set = new HashSet<DeviceEnum>(); set.Add(DeviceEnum.Android); set.Add(DeviceEnum.IOS); JPushClient client = new JPushClient(app_key, master_secret, 0, set, true); MessageResult result = null; NotificationParams notifyParams = new NotificationParams(); CustomMessageParams customParams = new CustomMessageParams(); //notifyParams. //傳入json字符串 String extras = null; extras = "{\"ios\":{\"badge\":88, \"sound\":\"happy\"}}"; //extras中有中文請用HttpUtility.UrlEncode編碼 //System.Web.HttpUtility.UrlEncode(notificationContent, Encoding.UTF8); Console.WriteLine("*****發送帶tag通知******"); /** *發送類型 *APP_KEY 通知 *TAG TAG *ALIAS ALIAS *REGISTRATION_ID REGISTRATION_ID */ notifyParams.ReceiverType = ReceiverTypeEnum.APP_KEY; notifyParams.SendNo = 256; //notifyParams.OverrideMsgId = "1"; result = client.sendNotification("酷派tag111111", notifyParams, extras); Console.WriteLine("sendNotification by tag:**返回狀態:" + result.getErrorCode().ToString() + " **返回信息:" + result.getErrorMessage() + " **Send No.:" + result.getSendNo() + " msg_id:" + result.getMessageId() + " 頻率次數:" + result.getRateLimitQuota() + " 可用頻率:" + result.getRateLimitRemaining() + " 重置時間:" + result.getRateLimitReset());
這里我們需要先了解幾個概念。
- APP_KEY:客戶端在極光推送里的唯一標識符,相當於ID
- Master_Secret:客戶端在極光推送的唯一標識符的密碼。
這個是我自己總結的,無非就是我們在極光推送ISP里的一個相當於對於APP應用的一個唯一進入憑證。
極光推送C#版本的SDK目前支持Android和IOS系統,因為上面的代碼是發送通知,而通知應該是對所有安裝了APP的人開放,所以應該選擇APP_KEY。
大家是不是對JpushClient這個類有些疑惑呢,下面就帶大家來解析這個類。
public class JPushClient { private PushClient _pushClient; /// <summary> /// 帶兩個參數的構造函數,該狀態下,ApnsProduction默認為true /// </summary> /// <param name="app_key">Portal上產生的app_key</param> /// <param name="masterSecret">你的API MasterSecret</param> public JPushClient(String app_key, String masterSecret) { HashSet<DeviceEnum> devices = new HashSet<DeviceEnum>(); devices.Add(DeviceEnum.IOS); devices.Add(DeviceEnum.Android); _pushClient = new PushClient(masterSecret, app_key, MessageParams.NO_TIME_TO_LIVE, null, true); _reportClient = new ReportClient(app_key, masterSecret); } /// <summary> /// 發送通知 /// </summary> /// <param name="notificationContent">通知內容</param> /// <param name="notifyParams"></param> /// <param name="extras"></param> /// <returns></returns> public MessageResult sendNotification(String notificationContent, NotificationParams notifyParams, String extras) { return _pushClient.sendNotification(notificationContent, notifyParams, extras); } }
看來上面其實就是帶入了幾個參數,其核心是PushClient,磨刀不誤砍柴工,我們來看看PushClient這個類。
internal class PushClient:BaseHttpClient { private const String HOST_NAME_SSL = "https://api.jpush.cn"; private const String HOST_NAME = "http://api.jpush.cn:8800"; private const String PUSH_PATH = "/v2/push"; private String appKey; private String masterSecret; private bool enableSSL = false; private long timeToLive; private bool apnsProduction = false; private HashSet<DeviceEnum> devices = new HashSet<DeviceEnum>(); public MessageResult sendNotification(String notificationContent, NotificationParams notParams, String extras) { if ( !string.IsNullOrEmpty(extras) ) { notParams.NotyfyMsgContent.n_extras = extras; } notParams.NotyfyMsgContent.n_content = System.Web.HttpUtility.UrlEncode(notificationContent, Encoding.UTF8); //notParams.NotyfyMsgContent.n_content = notificationContent; return sendMessage(notParams, MsgTypeEnum.NOTIFICATIFY); } private MessageResult sendPush(MessageParams msgParams, MsgTypeEnum msgType) { String url = enableSSL ? HOST_NAME_SSL : HOST_NAME; url += PUSH_PATH; String pamrams = prase(msgParams, msgType); //Console.WriteLine("begin post"); ResponseResult result = sendPost(url, null, pamrams); //Console.WriteLine("end post"); MessageResult messResult = new MessageResult(); if (result.responseCode == System.Net.HttpStatusCode.OK) { //Console.WriteLine("responseContent===" + result.responseContent); messResult = (MessageResult)JsonTool.JsonToObject(result.responseContent, messResult); String content = result.responseContent; } messResult.ResponseResult = result; return messResult; } }
從上面看來,這個地方有2個重點,一個是極光推送給我們的接口地址,這個非常重要,
另一個就是SendPush方法,下面的Parse方法轉換成極光推送認識的字符串也是相當的重要的。
private String prase(MessageParams message, MsgTypeEnum msgType) { StringBuilder sb = new StringBuilder(); sb.Append(message.SendNo).Append((int)message.ReceiverType).Append(message.ReceiverValue).Append(message.MasterSecret); String verificationCode = sb.ToString(); //Console.WriteLine(verificationCode); verificationCode = Md5.getMD5Hash(verificationCode); sb.Clear(); message.setMsgContent(); String receiverVallue = System.Web.HttpUtility.UrlEncode(message.ReceiverValue, Encoding.UTF8); sb.Append("sendno=").Append(message.SendNo).Append("&app_key=").Append(message.AppKey).Append("&receiver_type=").Append((int)message.ReceiverType) .Append("&receiver_value=").Append(receiverVallue).Append("&verification_code=").Append(verificationCode) .Append("&msg_type=").Append((int)msgType).Append("&msg_content=").Append(message.MsgContent).Append("&platform=").Append(message.getPlatform()) .Append("&apns_production=").Append(message.ApnsProduction); if(message.TimeToLive >= 0) { sb.Append("&time_to_live=").Append(message.TimeToLive); } if(message.OverrideMsgId != null) { sb.Append("&override_msg_id=").Append(message.OverrideMsgId); } Console.WriteLine(sb.ToString()); //Debug.Print(sb.ToString()); return sb.ToString(); } }
上面的調用方法其實極光推送里面也寫到了:http://docs.jpush.cn/display/dev/Push+API+v2
其實很明白了,上面的就是我們一開始帶進來的參數了,至於msgid,我猜想應該是極光推送給我們自動生成的一個自增長的ID,當然這個肯定是服務端生成的。
總結一下上面的一切的一切,其實無非就是方法之間的嵌套調用,真正的重點是調用到的最終的極光推送的URL的那個接口。相當於我們只是傳參數吧。
不過我猜想應該是極光推送的保密性,不然哪里會這么調用呢,直接傳個URL不就得了。偷笑~~
下面我們再來討論一下給單個用戶推消息,比如:有一個注冊用戶,他的文章需要審核才能發布,然后管理員審核了他的文章,當管理員審核通過的那么一瞬間,就應該給這個安裝了APP的用戶發送一條消息,提示這個用戶應該取發布文章了。這個就是向單個人去推的思路。
因為公司這次的項目只用到了ALIAS(別名),就想當於每個在手機上登錄的用戶,都邦定了一個別名,這個別名是唯一的,但是卻是區別於用戶名的,只要這個用戶邦定了這個別名,即使他的APP保持了登錄狀態(沒有注銷),那么他在任何時刻都可以接受到服務端SDK給這個用戶推送到的消息。如下圖。
這個別名是怎么產生的呢,因為我在webservice里面給了手機端一個登錄接口,這個登錄接口的形參里有別名,當然了,我是通過用戶名去尋找別名了,下面是代碼 ,最后返回的是一個JSON的字符串
//用戶登錄 [WebMethod(Description = "用戶登錄,帶入參數,用戶名,密碼以及數據庫的類型", EnableSession = true)] public string LoginUser(string username, string password,string alias) { JavaScriptSerializer ser = new JavaScriptSerializer(); SysBaseTag sys = new SysBaseTag(); sys.data = new List<object>(); try { //輸入查詢用戶的SQL,查詢2張表,一張用戶表,一張用戶詳細信息表。 string sql = "select a.*,b.* from t_sys_user a,t_sys_userinfo b where a.id='" + username + "' and a.password='" + password + "' and a.id=b.userid"; //查詢出結果 DataSet dbSet = DBHelperSQL.Query(sql, DBHelperSQL.GetDBString(), 2); if (dbSet != null && dbSet.Tables[0].Rows.Count > 0) { sys.message = "成功"; sys.result = true; Users userInfo = new Users(); foreach (DataRow Row in dbSet.Tables[0].Rows) { userInfo.ID = Row["ID"].ToString(); userInfo.Phone = Row["Phone"].ToString(); userInfo.Name = Row["name"].ToString(); userInfo.Email = Row["email"].ToString(); userInfo.QQ = Row["qq"].ToString(); userInfo.CompanyName = Row["companyname"].ToString(); userInfo.ComapnyType = Row["companytype"].ToString(); userInfo.CompanyAddress = Row["companyaddress"].ToString(); userInfo.Website = Row["website"].ToString(); userInfo.Introduce = Row["introduce"].ToString(); userInfo.Products = Row["products"].ToString(); userInfo.Reward = Row["reward"].ToString(); } sys.data.Add(userInfo); sys.count = 1; //臨時:插入別名 string sql_ins = "update t_sys_user set alias='" + alias + "' where id='" + username + "'"; int a=DBHelperSQL.ExecuteSQL(sql_ins,DBHelperSQL.GetDBString(),2); } else { sys.message = "失敗"; sys.result = false; sys.count = 0; } } catch (System.Exception e) { sys.message = e.Message; sys.result = false; sys.count = 0; } return ser.Serialize(sys); }
因為客戶需要,我還做了一個表,專門存放手機消息的發送記錄,如果成功推送消息,那么就往這張表里插入一條記錄。
下面是JSON的示例,大家看看就好。
總之大家要明白,ALIAS是唯一的,不同於用戶名的,我們判斷的是這個人對應的手機APP的ALIAS(唯一性),而不是關心她的用戶名。
基本上原理就這樣,然后的話我們需要建立一個WEBSERVICE,ASMX文件,然后把這個ASMX文件部署到網上去。
比如我們調用這個WebService的地址是http://xxx.com/test.asmx,基本上就這個原理了。通過后台傳參數給WEBSERVICE。
//發布文章的時候同時發送短信。 public void PublishToMobile(string []ids) { cs.Common.Web.BasePage bp = new cs.Common.Web.BasePage(); string ids_=""; //最終得到的字符串 for (int i = 0; i < ids.Length; i++) { ids_ += ",'" + ids[i]+"'"; } ids_ = ids_.Substring(1); DataSet set = bp.DataManager.Fill("select * from cms_core_content where id in(" + ids_ + ")"); string title = ""; //標題 string content = ""; //內容 string publishDate = ""; //發布時間 foreach (DataRow Row in set.Tables[0].Rows) { title = Row["title"].ToString(); content = Row["Text"].ToString(); publishDate = Row["publishdate"].ToString(); string wsUrl = BL.AppContext.AppSettings["MobileWs"]; string rs = (string)BL.WebHelper.InvokeWebService(wsUrl, "GetMsg_ArticlePublish", new object[] { publishDate, title, content }); }
上面的是一段示例代碼,其中的InvokeWebService方法就是調用Webservie的方法了,第一參數是調用的URL,第二個是方法名,第三個是參數。
基本上好像沒什么說的了吧,反正一個是群發,一個是向某一個用戶發,而用戶因為邦定了別名,所以可以通過這個別名向指定的用戶進行發送消息,
下一次有空的話把微信那一塊的說一下,就是微信C#入門啦。
有什么問題還請大家多多切磋。