用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就行了。

下面是例子的源码:

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());

  这里我们需要先了解几个概念。

  1. APP_KEY:客户端在极光推送里的唯一标识符,相当于ID
  2. 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#入门啦。

有什么问题还请大家多多切磋。

时间: 2024-10-13 13:04:14

用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)的相关文章

Pubwin2009使用方法--服务端的安装

Pubwin2009使用方法 红字及红字目录下的内容表示是重要和必学的功能 软件安装环境及设定说明: 操作系统:WindowsXP SP3 Pubwin服务端版本:PubwinServer501.XXXXXXXXXX 控制台版本:PubwinConsole001.XXXXXXXXXXXX 注册号:124(也可以使用其他注册号) 注册口令:xxx 网吧名称:新浩艺网吧 服务端的安装 一. 检查和准备工作 操作系统最好不要安装带有防火墙的安全软件和IIS(互联网信息服务):如果电脑上已经安装有其他版

一小时精通SVN版本控制 之二 服务端的安装和配置

服务端的安装: 保持默认,单选框这里选择第一项,如果选择第二项就没有可视化界面了.复选框勾选上,否则不能用命令行. 这里选择标准版 standard Edition是免费的,下面的企业版是收费的. Location这里选择安装路径,repositores选择仓库路径也就是所有的文件和代码保存的位置,server port表示端口号,通过这个端口来与客户端通信,后面的复选框如果选中则是采用https协议,否则采用http协议,https协议在http协议的基础上加强了安全性,一般选中. 安装完成后

Zabbix 3.4.10 服务端的安装与设置

实验验目的:  Zabbix 3.x 服务端的安装 实验主机:  m01  (centos 7.4)  IP 10.0.0.61/172.16.1.61 1) 配置yum源, 并用wget命令把相关的软件包下载到本地, 然后再进行安装, 如下所示 #配置yum 源解决依赖的问题 [[email protected] /]# rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-

Dnscrypt_wrapper 服务端的安装与配置

之前我介绍了为了科学访问互联网其中非常重要的一环 DnsCrypt_Proxy,这其实是客户端.dnscrypt-proxy 安装好后会自带提供一些国外的公开的dnscrypt-wrapper服务,所以dnscrypt的服务端就是 dnscrypt-wrapper .dnscrypt提供了自主搭建dnscrypt-wrapper服务的程序以及教程. 我这里就来简要说一下 dnscrypt-wrapper 服务端的搭建用法. 前情提要: 服务端系统平台:CentOS 6 x86_64 dnscry

[Centos]openvpn 服务端的安装(easy-rsa3)

VPN在办公和fan墙领域有着广泛的应用,  我们小办公网最近可能会用到,先学学来着 vpn的server需要有公网ip,客户端可以在多种环境下使用 概念 PKI:Public Key Infrastructure 公钥基础设施 CA: Certificate Authority  pki的核心 https://github.com/OpenVPN/easy-rsa/tree/master/doc  这里有些简单的概念介绍 实验环境 虚拟机环境下 centos6.6 网卡 eth0 Link e

游戏服务端pomelo安装配置

一.安装环境 Linux Ubantu 二.安装需要的组件 1.安装nodejs 注:debian下nodejs没有相应的apt包,所以无法用apt-get安装,只能通过nodejs的源码包安装, 这里有比较全的其他系统环境下安装nodejs的方式https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager a.安装所需的组件,python g++ #apt-get install python g++ ma

SS_R服务端一键安装脚本

文章转自:https://xubiji.com/5680.html SS-R 是项目 SS 的增强版,用于方便地产生各种协议接口.实现为在原来的协议外套一层编码和解码接口,不但可以伪装成其它协议流量,还可以把原协议转换为其它协议进行兼容或完善,需要服务端与客户端配置相同的协议插件. 据了解,原版 SS-go 版基本来说已经阵亡(干扰严重),目前本人已在服务器安装 SSR,配合 SS-R 客户端使用新协议和混淆插件提升效果非常明显,速度快了好几倍.续笔记自媒体也对原脚本做了部分的修改,自用为主,考

XMPP(一)-openfire服务端的安装和搭建

XMPP全称:可扩展通讯和表示协议 简介:可扩展通讯和表示协议 (XMPP) 可用于服务类实时通讯.表示和需求响应服务中的XML数据元流式传输.XMPP以Jabber协议为基础,而Jabber是即时通讯中常用的开放式协议.XMPP is the IETF's formalization of the base XML streaming protocols for instant messaging and presence developed within the Jabber open-so

oracle客户端,服务端下载安装

下载的时候,千万别点错了:服务端,要两个文件都下 http://www.oracle.com/technetwork/database/enterprise-edition/downloads/112010-win64soft-094461.html 终于找到client端所在了,其实,如果无需特殊要求完全可以安装个客户端,就行了.