用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)
这次公司要我们做一个功能,就是当用户成功注册以后,他登录以后要收到消息,当然这个消息是安装了我们的手机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就行了。
下面是例子的源码:

然后我们还是来结合例子一步一步走吧。
首先是发送通知:
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 | 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这个类有些疑惑呢,下面就带大家来解析这个类。
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 | 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这个类。
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 | 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方法转换成极光推送认识的字符串也是相当的重要的。
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 | 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的字符串
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 | //用户登录 [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。
上面的是一段示例代码,其中的InvokeWebService方法就是调用Webservie的方法了,第一参数是调用的URL,第二个是方法名,第三个是参数。
基本上好像没什么说的了吧,反正一个是群发,一个是向某一个用户发,而用户因为邦定了别名,所以可以通过这个别名向指定的用户进行发送消息,
下一次有空的话把微信那一块的说一下,就是微信C#入门啦。
有什么问题还请大家多多切磋。
__EOF__
作 者:ღKawaii
出 处:https://www.cnblogs.com/kmsfan/p/4033361.html
关于博主:一个普通的小码农,为了梦想奋斗
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!

出处:http://www.cnblogs.com/kmsfan
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
欢迎大家加入KMSFan之家,以及访问我的优酷空间!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?