最近因为某些项目的原因,需要实现wappush的功能,本想偷懒在网上搜索一下,看有没有合适的内容,结果找不到一个合适的.只好自已动手来写一个. 看了一下pap协议的内容,其实也并不复杂,属于http协议的扩展,因此,使用.net的httpwebrequest类库便可以方便的实现pap
最近因为某些项目的原因,需要实现wappush的功能,本想偷懒在网上搜索一下,看有没有合适的内容,结果找不到一个合适的.只好自已动手来写一个.
看了一下pap协议的内容,其实也并不复杂,属于http协议的扩展,因此,使用.net的httpwebrequest类库便可以方便的实现pap的通讯层.剩下的工作便是pap协议内容的组合了,pap协议主要有四个方法及一个交互方法,分别是:
submit a push 提交一个push信息
cancel a push 取消一个push信息
query for status of a push 查询提交push信息的状态
query for wireless device capabilities 查询无线设备能力
如果需要接收ppg(推送代理网关)返回的发送结果通知消息,则需要提供一个回调地址,供ppg发送通知响应.pi(推送发起人)与ppg之间的关系如下图:
pi端与ppg之间使用pap协议通讯,ppg则调用空中协议传送到手机端.
上图则是pi发送一个wappush信息,pi与ppg之间的交互过程
pi发起一个推送请求
ppg返回一个接收响应包
ppg推送wappush到手机终端
手机终端响应接收结果
ppg推最终发送结果到pi端
pi端返回一个响应包到ppg,完成整个发送过程
对于cancel a push, query for status of a push , query for wireless device capabilities 这三种方式,都是pi与ppg之间的交互,即发起请求,得到响应的方式,因此,不作详细说明.
消息体格式
pap协议的消息体是采用多段的方式提交请求的,即content-type类型为multipart/related,到于具体的信息,可以参考rfc2387.整个pap协议包包括三种结构,分别为
控制实体(control entity):提供一些控制命令
内容实体(content entity):提供传送的内容信息
能力实体(capabilities entity):提供终端的支持的能力配置信息
除了推送消息需要使用到三种消息以外,其它请求方法都只使用到控制实体包。这三种类型的包都是mime类型格式,下面是一个请求包的具体格式
content-type: multipart/related; boundary=asdlfkjiurwghasf;
type=application/xml
--asdlfkjiurwghasf
content-type: application/xml
br /> http://www.wapforum.org/dtd/pap_2.0.dtd
[]>
..control for ppg..
--asdlfkjiurwghasf
content-type: text/vnd.wap.si
..service indication push message example..
--asdlfkjiurwghasf
content-type: application/xml
..assumed client capabilities..
--asdlfkjiurwghasf--
控制实体介绍
控制实体的定义如下
| push-response
| cancel-message
| cancel-response
| resultnotification-message
| resultnotification-response
| statusquery-message
| statusquery-response
| ccq-message
| ccq-response
| badmessage-response) >
product-name cdata #implied
>
它一共支持11种控制命令,这些命令都必须放在pap节点下面,如:
支持的11种控制命令分别如下:
push-message :pi -> ppg ,发起一个push请求
push-response :ppg -> pi,ppg对push请求的响应结果
cancel-message :pi->ppg,取消消息的请求
cancel-response :ppg -> pi,ppg对取消请求的响应结果
resultnotification-message :ppg->pi,结果提醒消息,由ppg调用通过push消息时提供的通知地址传送
resultnotification-response:pi->ppg,pi端对ppg的结果提醒消息的响应
statusquery-message :pi->ppg,状态查询消息,查询发送消息的当前状态
statusquery-response :ppg->pi,ppg对查询请求的响应结果
ccq-message :pi->ppg,发起一个终端能力查询请求
ccq-response :ppg->pi,ppg对终端能力查询的响应结果
badmessage-response:ppg->pi,ppg在接收到错误请求包的时候,返回的响应信息
push-message介绍
结构定义如下:
push-id cdata #required
replace-push-id cdata #implied
replace-method ( pending-only | all ) all
deliver-before-timestamp %datetime; #implied
deliver-after-timestamp %datetime; #implied
source-reference cdata #implied
ppg-notify-requested-to cdata #implied
progress-notes-requested ( true | false ) false
>
address-value cdata #required
>
priority ( high | medium | low ) medium
delivery-method ( confirmed | preferconfirmed
| unconfirmed | notspecified ) notspecified
network cdata #implied
network-required ( true | false ) false
bearer cdata #implied
bearer-required ( true | false ) false
>
push-message节点是推送一个消息的控制节点,它有多个属性,含义如下:
push-id:推送流水id,由pi端创建管理,需要全局唯一,返回响应包、通知包会根据此id来判断请求
replace-push-id:替换推送id,指被替换的旧pushid,多用于使用新的消息替换以提交却未发送的消息
replace-method:替换的方法,有pending-only和all两种选项可选,all表示替换旧消息的所有接收者,pending-only则表示替换有可能被取消的接收者
deliver-before-timestamp:发送终止时间,指超过指定的时间则不发送消息了,格式为标准的utc时间:yyyy-mm-ddthh:mm:ssz
deliver-after-timestamp:发送的开始时间,须在指定的时间才能开始发送,格式为标准的utc时间:yyyy-mm-ddthh:mm:ssz
source-reference:内容提供者的文本名称,ppg网关可能需要此参数判断pi的权限及能力
ppg-notify-requested-to:ppg发送结果响应请求的url地址
progress-notes-requested:是否在响应包中包括处理日志信息
address节点需要包括在push-message节点下,如果有多个接收人,则增加多个address节点即可,address-value是实际的接收地址,它可以是一个逻辑地址,具体的格式大致如下:
wappush=12345678/type=plmn@ppg.operator.com
quality-of-service节点也须要放在push-message节点下,它描述了当前消息的各种发送属性,如:优先级、使用网络、承载体等,不同的网络或许有不同的参数,请咨询相应的运营商。
具体的参数说明可以参考标准文档:wap-247
push-response介绍
push-id cdata #required
sender-address cdata #implied
sender-name cdata #implied
reply-time %datetime; #implied
>
push-response是pi提交push-message到ppg后,ppg返回的响应包结构,它有四个属性,如下:
push-id:相关的push-id
sender-address:发送者地址,一般是ppg的地址
sender-name:发送者名称,一般是ppg的名称
reply-time:应答时间,标准的utc时间
progress-note节点不多介绍,是属于处理日志节点
response-result节点包含了所发送消息的响应结果,其定义如下:
code cdata #required
desc cdata #implied
>
code是响应的结果,具体可参考标准文档的说明,desc则是相应的描述信息
对于其它几个请求结构相对简单,此处不再说明,参考标准文档即可。
http请求处理说明pap协议是基于http协议,因此,建立一个pap协议只需要发起一个http请求即可,截取一段发送代码如下:
code
//pap请求
httpwebrequest paprequest = (httpwebrequest)httpwebrequest.create(config.serviceurl);
paprequest.method = post;
paprequest.contenttype = multipart/related; type=application/xml;boundary= + irequest.boundary;
paprequest.headers.add(authorization, config.encpass);
byte[] papdata = rqeuestobj.getbytes(config.enc);
stream requeststream = paprequest.getrequeststream();
requeststream.write(papdata, 0, papdata.length);
requeststream.close();
httpwebresponse response = (httpwebresponse)paprequest.getresponse();
streamreader sr = new streamreader(response.getresponsestream(), config.enc);
ret = replacexml(sr.readtoend());
sr.close();
主要设置几个属性,分别为method、contenttype以及authorization,对于前两个不作说明,authorization则表示认证信息,有些ppg网关不需要认证信息,因此可以忽略这个属性。认证属性的值为base64编码的字串,格式为:base base64string
用户名和密码以这样的格式编写:username:password,然后对这个串进行编码,放在base 后面即可。表示基本的base64认证串。对于其它的代码就不多做解释了:)大家可以看源码。
关于源码:目前仅实现了pap协议的解析、生成等功能,未实现对数据发送的队列控制、流量控制等等,这些都需要进一步完善,如果各位有兴趣完善的话,希望也提交到项目里面咯:)
下载地址:http://paplib.codeplex.com/