SlideShare ist ein Scribd-Unternehmen logo
1 von 159
Downloaden Sie, um offline zu lesen
浙江电信移动业务接入实践




浙江电信移动业务接入实践




   浙江电信互联网与信息事业部
         林路
       21-51
        000-3




                   1
浙江电信移动业务接入实践


                                                                             目录

一. ISAG 接入篇 ............................................................................................................................................... 4
    1. ISAG 简介 .......................................................................................................................................... 4
    1.1 ISAG 在电信网络里面的位置 ........................................................................................................... 6
    1.2 ISAG 与 WEB SERVICE 技术 ........................................................................................................... 6
    1.3 开发环境搭建...................................................................................................................................... 7
         1.3.1 安装 JDK ................................................................................................................................. 7
         1.3.2 下载安装 ECLIPSE .................................................................................................................. 7
         1.3.3 安装 WTP 模块 ....................................................................................................................... 8
         1.3.4 安装 Tomcat ............................................................................................................................. 9
         1.3.5 ISAG 接口相关通用参数及说明........................................................................................... 10
    2. SMS...................................................................................................................................................... 13
         2.1 短信接口开发环境搭建 ............................................................................................................ 13
         2.2 SendSMS 短信发送接口开发 ................................................................................................... 19
         2.3 SendSMS 短信上行,回执接口开发 ....................................................................................... 39
    3. WAP PUSH .......................................................................................................................................... 46
         3.1 WAP PUSH 简介 .................................................................................................................... 46
         3.2 WAP PUSH 网络结构和业务实现 ........................................................................................ 46
         3.3 WAP PUSH 是什么?WAP PUSH 不是什么? .................................................................... 48
         3.4 WAP Push 接口开发环境搭建 .................................................................................................. 49
         3.5 WAP Push 发送接口开发 .......................................................................................................... 53
         3.6 WAP Push 状态报告接口开发 ................................................................................................. 58
    4.    彩信................................................................................................................................................. 61
         4.1 彩信的构成................................................................................................................................ 61
         4.2 彩信在电信网络里面的网络结构 ........................................................................................... 62
         4.3 彩信开发接口开发环境搭建 ................................................................................................... 63
         彩信发送接口开发.......................................................................................................................... 69
         45彩信上行.................................................................................................................................. 81
          .
         5.1 TcpMon 使用 ............................................................................................................................. 94
         5.2 Web Services Explorer ............................................................................................................... 98
    附录一: SendSms 短信发送接口报文数据: ..................................................................................... 100
         1.1 请求(SP 发起):...................................................................................................................... 100
         2.2 应答(ISAG 应答) ............................................................................................................... 101
    附录二: WAP PUSH 发送报文数据: ................................................................................................ 102
         1.1 请求(SP 发起):...................................................................................................................... 102
         2.2 应答(ISAG 应答) ............................................................................................................... 103
    附录三: SendMessage 彩信发送接口报文数据: .............................................................................. 104
         1.1 请求(SP 发起):...................................................................................................................... 104
         1.2 ISAG 响应 ............................................................................................................................... 106
二. 与 ISMP 接口实现 ................................................................................................................................. 107
    1.ISMP 简介 .......................................................................................................................................... 107
    1.1 与 ISMP 相关的术语 ...................................................................................................................... 107
    2.业务流程............................................................................................................................................. 109

                                                                                                                                                                 2
浙江电信移动业务接入实践


        2.1 点播业务流程.......................................................................................................................... 109
        2.2 包月业务流程.......................................................................................................................... 110
   3. ISMP 接口开发环境搭建 ................................................................................................................. 111
   4. 订购关系同步 orderRelationUpdateNotify 方法实现 ..................................................................... 117
   5. 管理信息同步 notifyManagementInfo 方法实现 ............................................................................ 122
   6. 服务使用通知接口 serviceConsumeNotify 方法实现 .................................................................... 124
   7.反向取消接口 spWithdrawSubscription 接口实现 ........................................................................... 126
   8. 程序部署........................................................................................................................................... 129
   9. 接口测试........................................................................................................................................... 131
三.WAP 业务开发 ...................................................................................................................................... 135
   1 WAP 业务简介 ................................................................................................................................... 135
        1.1 WAP 业务的网络结构 ............................................................................................................ 136
        1.2 WAP 业务实现原理 ................................................................................................................ 137
   2 点播实现............................................................................................................................................ 140
   3 包月实现............................................................................................................................................ 142
   4. WAP 1.0 还是 WAP 2.0 ..................................................................................................................... 144
   5.UA 适配 .............................................................................................................................................. 145
   6.WAP 业务测试 .................................................................................................................................. 147
四. 短信网关 SMGP 接入篇 ........................................................................................................................ 150
   1. 短信网关接口协议 SMGP 概述 ...................................................................................................... 150
   2. SMGP 封包结构................................................................................................................................ 151
   3. SMGP 相关术语解释 ........................................................................................................................ 154
   4. 封包拼装和解析............................................................................................................................... 155
        4.1 登录请求相关封包:Login,Login_Resp ................................................................................ 156
        4.2 发送短信相关封包:Submit,Submit_Resp ............................................................................ 158
        4.3 上行短信相关封包:Deliver,Deliver_Resp ......................................................................... 158
        4.4 退出请求相关封包:Exit,Exit_Resp..................................................................................... 158
        4.5 TLV 字段封装 ...................................................................................................................... 158
五. 关于本文档............................................................................................................................................. 159




                                                                                                                                                           3
浙江电信移动业务接入实践




一. ISAG 接入篇

1.   ISAG 简介

 关于 IA 是啥,我们直接看下百度百科上的说明,这个很好诠释了什么是 IA:
     SG                              SG
 IA 综合业务接入网关,英文全称为 Itgae SrieAcs Gtwy
  SG                nertd evc ces aea。

 中国电信的综合业务接入网关(IA)将为应用提供符合国际标准的 Pra X. 接口,并对该接
                SG               aly 20

口作了适当增强,为应用提供更为丰富的业务能力,采用开放的综合业务接入架构的 IA 具有以下
                                       SG

优点:

 1 采用了统一的符合国际标准的接口,业务可以多网移植或跨网运行。基于这种业务接入架构,
  .

一个应用可以使用来自多种网络(H、PT、3 和 SP等)
               PS SN G   I  的能力,形成融合的业务应用。

 2 采用统一的业务接入、安全认证及控制机制,与 IM 平台有机地结合起来,便于业务的统一
  .                       SP

管理、统一计费,有效保护电信核心网络资源及运营商的利益;

 3 由于 PRA X是基于 XL的开放接口,
  .    ALY      M      不依赖于任何专门的电信协议,这使得数量巨大的 IT

业软件开发者也可以开发电信业务,真正实现电信增值业务与 Itre 业务的融合;
                             nent

 4 由于采用了标准的、简单的开放接口,使得业务开发周期缩短,开发成本降低;
  .

 5 简化了组合业务的开发及计费工作;
  .

 6 运营商可以非常灵活地对业务接入平台所提供的业务能力进行组合,为应用提供组合的业务能
  .

力,进一步简化组合业务的开发。

 IA 是移动业务网络中实现业务统一接入和服务质量监控的功能实体。
  SG                             使运营商能够开放电信网络

资源,并控制对网络资源的使用;为 C/P
                  PS 屏蔽底层网络技术复杂性,提供统一业务开发环境,降低

业务开发门槛;为用户提供融合业务,丰富业务形式,有利于开发企业应用,拓展企业用户市场。

 IA 在业务网络中主要功能为:
  SG

 IA 屏蔽了底层网络的复杂性,实现对移动数据、移动语音、PS
  SG                          H 业务的业务能力高度抽象,封装

成开放、统一、标准应用开发接口提供给 C/P
                    PS,支持电信自营增值业务、第三方 C/P
                                       PS 增值业务及

企业应用的接入;为 C/P
           PS 提供统一的增值应用集成开发和测试环境;协同 IM 完成业务应用过程
                                     SP

中认证、鉴权、计费和管理等功能;实现组合业务计费;对业务流进行质量监控和内容安全控制。



                                              4
浙江电信移动业务接入实践



 以上已经很好的诠释了什么是 IA,
                SG在移动业务接入的初期,业务的承载模式基本上
以短信为主,S 如需接入运营商的平台,应根据运营商短信网关的接口协议:CP(
       P                            MP中国
移动) GP
   ,SI(中国联通) MP
            ,SG(中国电信)直接接入短信网关,同时与短信管理平台
实现订购关系同步计费等接口。这些协议从某种意义上是平台的私有接口。
 而现有的移动增值业务已经不仅仅是短信。如果 SP需要接入彩信业务,需要与彩信
接入网关实现 M7
       M 协议;如果需要接入 WP UH
                    A PS 业务需要与 PGPS 代理网关)
                                P(UH     实现 PP
                                             A
协议;如果需要实现定位业务,还需要与运营商的定位系统进行对接。我们可以看到的
是,这些接口的实现方式完全不同,这给 S 接入增值业务带来了很大的难度和困惑。
                    P
  为了解决这个问题,各运营商希望能够屏蔽各个接口的私有协议,而采用标准的协
议进行统一接入。而 SA的盛行,使得 WBSRIE成为统一接入最好的承载模式。而
           O       E EVC
19 年一个由 65 家通信和 IT 领域的公司共同参与的非盈利性 组织,
 99                                  提出了 Pra/S
                                          alyOA
应用程序接口规范,并且发布了多个版本,其中包括:

  1 Pra 5-20..1
   ) aly  0541
  2 Pra 4-20..
   ) aly  0538
  3 Pra XWbSrie Seiiain Vrin20-20.
   ) aly  e evcs pcfcto, eso .  053
  4 Pra XWbSrie Seiiain Vrin101-20.
   ) aly  e evcs pcfcto, eso ..  046
  5 Pra XWbSrie Seiiain Vrin10 -20.
   ) aly e evcs pcfcto, eso ..   034

  而中国电信选取了 Pra X e Srie Seiiain Vrin . 作为了 IA
            aly Wb evcs pcfcto, eso 20      SG
的标准规范。




                                             5
浙江电信移动业务接入实践



1.1 ISAG 在电信网络里面的位置




  紫色箭头为 SP 需要实现的接口,在整个体系中,SP 与 ISAG 通过不同的 Web Services 接口实现
短信,彩信,WAP 的业务接入,ISAG 将收到的 Web Service 请求转换成各引擎相应的接口,与短信
网关采用 SMGP 协议,与 PPG 采用 PAP 协议,与彩信中心实现 MM7 协议,与定位系统采用 MLP 协
议。同时 SP 还需要与 ISMP 实现接口,实现订购关系的同步。
  通过上图可以看出,由于 ISAG 的引入,SP 侧只需要按照规范实现 Web Services 接口即可,而不
需要再跟具体的协议比如 SMGP,PAP,MM7 打交道。


1.2 ISAG 与 WEB SERVICE 技术

  这里不再详细讲解什么是 WBSRIE
               E EVC,如果你对 WBSRIE
                           E EVC 缺乏了解,可以参考
相应的书籍或者拜 Gol 为老师。
          oge
  简单对象访问协议(OP是 WBSRIE承载的协议,这里需要说明的你的程序与
           SA)  E EVC
IA 进行交互的时候需要设置 SA HAE 进行相关鉴权信息的传送,而某些接口(比
 SG             OP EDR
如彩信)还需要你的 WBSRIE
           E EVC 程序支持附件。
  目前 AI
      XS是目前应用最广的 WBSRIE的引擎,对于上述的两项都能够很好的支
                  E EVC
持,所以以下涉及到开发的例子我们会使用它作为我们开发的引擎。简单说下 AI, XS
                                    XS AI
是 Aah Etnil Itrcin ytm
   pce xesbe neato Sse 的英文缩写,意为:阿帕奇可扩展交互系统。
                                                          6
浙江电信移动业务接入实践



他是 AAH 基金会的一个开源项目,Ai 本质上就是一个 SA 引擎,提供创建服务器
    PCE           xs          OP
端、客户端和网关 SA 操作的基本框架。Ai 目前版本是为 Jv 编写的。
          OP         xs        aa
 当然同样 ELPE
       CIS 是目前最广泛应用的 JV 开发工具。 Elpe
                      AA       cis 最初是由 IM
                                         B 公司
开发的替代商业软件 Vsa AefrJv 的下一代 IE
           iul g o aa      D 开发环境,20 年 1 月贡献给
                                   01   1
开源社区,现在它由非营利软件供应商联盟 Elpe基金会(ElpeFudto)管
                     cis     cis onain
理。
 整个教程将会以 JV 作为开发语言,以 Elpe
          AA          cis 作为开发工具,AI 作为 SA 引擎
                                  XS    OP
进行讲解如何进行 IA 的接口开发。如果你习惯使用微软的.E 进行开发;非常抱歉,
          SG                 NT
本人虽然不是反微软的斗士,但是对于微软的东西有种天生的莫名的排斥,虽然我的笔
记本也安装着 Wnos
        idw 操作系统,但是对于微软的开发工具一窍不通。




1.3 开发环境搭建

1.3.1 安装 JDK

 需要使用 JV
       AA开发,必然需要安装 JK目前 JK常用的版本有 13 .、15以及
                    D,   D        .、14 .
16 13 14
 .。 . 和 . 版本目前已经很少使用,至于 15
                         . 还是 16
                               . 需要你根据你服务器上的 JP
                                              S
引擎的 jv 版本进行匹配安装。
     aa
 JK
  D 的下载地址:ht:/aasncm
           tp/jv.u.o



1.3.2 下载安装 ECLIPSE

 Elpe可以在 ht:/w.cis.r 上下载,elpe因为不仅仅是一个 JV
  cis     tp/wwelpeog     cis          AA
开发工具,所以他有多个版本,我们需要下载的是 ElpeIEfrJv E Dvlpr
                        cis D o aa E eeoes
版本,如果下载的是企业版,因为其自带了 WP模块,忽略下面步骤 143安装 WP模
                     T           ..    T
块。
 当然你也可以选择 ElpeIEfrJv Dvlpr 版本,如果选择该版本需要根
           cis D o aa eeoes
据 143
   .. 安装 WP
         T 模块。

                                             7
浙江电信移动业务接入实践



 Elpe
  cis 下载以后解压缩到某一目录,然后运行 elpeee
                         cis.x 即可。


1.3.3 安装 WTP 模块

 注:如果选择安装了 ElpeIEfrJv E Dvlpr 版本,忽略该步骤。
            cis D o aa E eeoes
 WP 是 Wb Tos Pafr
  T    e ol ltom的缩写,顾名思义是 Wb工具包,其官方网站是
                           e
ht:/w.cis.r/etos,同样他跟 Elpe
 tp/wwelpeogwbol/      cis 一样是个 Fe 的软件。
                                 re
 先安装好 elpeIEfrjv,
       cis D o aa运行 Elpe然后菜单选择 hl-IsalNw
                     cis,       ep>ntl e
Sfwr, Wr Wt 输入:
 otae在 ok ih
 ht:/onodelpeogwbol/pae/
 tp/dwla.cis.r/etosudts




 选中上述项目以后,点击 Nx。稍等片刻就会完成 WP
              et          T 模块的安装。




                                          8
浙江电信移动业务接入实践



1.3.4 安装 Tomcat

 由于接口需要建立一个 Wb Srie进行发送结果的接受,需要开发相应的 Wb
             e evc                    e
Srie evr
 evc Sre 程序,另外与 IM 的订购关系同步也需要开发相应的服务端软件,我们
                 SP
需要一个能够运行 WbSrie Wb
          e evc 的 e 服务器,Tma 是目前常用的 Jp
                         oct        s 服务器,当然
你可以其他的 JP
        S 引擎,比如 RsnWbpee
                 ei,eShr 等,考虑到 Tma 是免费的,
                                oct     容易获得,
所以我们下面的例子都会以 Tma 为例。
              oct
  Tma 的官方网站是:ht:/octaah.r/
   oct        tp/tma.pceog,你可以到网站上下载 55
                                      . 或者
60
 . 版本。 如果你下载的是 Zp
               i 方式,安装与 Elpe
                         cis 类似,解压缩到某个目录下即可,
当然你也可以选择 WnosSrieIsalr
          idw evc ntle 的文件包,下载后直接安装。
  安装以后,在 tma 的安装目录有如下目录。
          oct




  其中:
     目录 bn tma 的运行目录,运行该目录下的 satpbt即可启动 Tma
         i 是 oct              tru.a      oct
     目录 wbps
         eap 是应用程序部署的目录,程序完成开发以后需要将文件部署到该目录
下。
 其他目录的作用请参考相关资料,这里不再详述。



                                            9
浙江电信移动业务接入实践



1.3.5 ISAG 接口相关通用参数及说明

     在讲解具体的 ISAG 接口前,我们需要将 ISAG 的接口进行相关概要的说明。

     在与 ISAG 进行交互的时候,Web Service 相关的程序都需要设置 SOAP HEADER,负责接口间鉴权

的实现。

  SOAP HEADER 需要包含以下参数:

参数名                    类型          描述

spid                   String      SP 编号,这个编号是 8 位,比如浙江电信接入

                                   的应该是 121XXXXXXX 这样的数字,其中 12

                                   表示浙江,第三位的 1 表示 CDMA 的 SP

spPassword             String      SP 密码(MD5 加密)

                                   MD5 加密算法如下:

                                   SP 密码=SPID+密钥+时间戳

                                   密钥部分由 ISMP 分配,你在申请业务能力的

                                   时候填写的密钥。

                                   时间戳, SP 端生成,
                                       由       格式:MMDDHHMMSS,

                                   月日时分秒

timeStamp              String      时间戳, SP 端生成,
                                       由       格式:MMDDHHMMSS,

                                   月日时分秒,要与上面加密用的密钥一致。

productId              String      产品编号

SAN                    String      业务接入码,可选

transactionId          String      业务流水号;可选

transEnd               EndReason   交易技术标识,用户组和业务。可选

linkID                 String      事务关联 ID,用户点播业务

OA                     anyURI      业务订购地址。群发时不填

FA                     anyURI      付费地址。可选

Multi-cast Messaging   Boolean     True:群发

                                   False:非群发

                                   缺省为 false


                                                                 10
浙江电信移动业务接入实践




 程序中还会用到 anyURI 的类型,如果该类型标识用户号码的时候需要加上”tel:”,以说
明是电话号码,比如 18905718888 这个号码,anyURI 表示应该为 tel:+8618905718888。


  另外用到的 MD5 加密,加密完成后需要转换成 16 进制表示的字串,我们需要增加一
个加密的类,代码如下:

package cn.com.chinatelecom.util;
import java.security.*;
public class MD5 {


     private final static String[] hexDigits = {
             "0", "1", "2", "3", "4", "5", "6", "7",
             "8", "9", "a", "b", "c", "d", "e", "f"};
     /**
      * 转换字节数组为16进制字串
      * @param b 字节数组
      * @return 16进制字串
      */
     public static String byteArrayToHexString(byte[] b) {
         StringBuffer resultSb = new StringBuffer();
         for (int i = 0; i < b.length; i++) {
             resultSb.append(byteToHexString(b[i]));
         }
         return resultSb.toString();
     }
     private static String byteToHexString(byte b) {
         int n = b;
         if (n < 0)
             n = 256 + n;
         int d1 = n / 16;
         int d2 = n % 16;
         return hexDigits[d1] + hexDigits[d2];
     }
     public static String compile(String origin) {
         String resultString = null;


         try {
             resultString=new String(origin);
             MessageDigest md = MessageDigest.getInstance("MD5");



                                                                    11
浙江电信移动业务接入实践


resultString=byteArrayToHexString(md.digest(resultString.getBytes()));
           }
           catch (Exception ex) {


           }
           return resultString;
       }
   }



  这样的话我们就可以使用 MD5.compile(“SPID”+”密钥”+”时间戳”) 进行 spPassword 的数
据生成。




                                                                         12
浙江电信移动业务接入实践




2. SMS

   特别说明:目前短信业务接入有两种模式,一种是 IM+
                           SP短信网关,短信接入采用 SG
                                          MP
30
 . 协议;一种是 IM+SG
           SPIA 方式接入,短信的接入采用 Wb evc。
                              e Srie 目前由于浙江 IA
                                             SG
的能力有限,所以浙江电信的短信业务是采用 IM+
                      SP短信网关方式,该方式不在这里讲述。
     因为短信也是 IA
             SG的一个接入的一个基本功能,而且相对 WPPS
                                  A UH和彩信接口比
较简单,接口与彩信和 WPPS
            A UH相近,理解 IA
                       SG短信接入的接口协议也有利于了解整
个 IA 的接口协议。所以这里还是就 IA 接入短信业务进行讲解。
   SG               SG




2.1 短信接口开发环境搭建

   与 IA 相关的短信接口,需要实现 3
      SG              个接口:

接口名称                    接口方法                         作用       谁是服务器端
SendSMS                 sendSms                      发送短信
                        sendSmsLogo                  发送图标
                        sendSmsRingtone              发送铃声     ISAG
                        getSmsDeliverStatus          查询发送状态
SmsNotifactionService   notifySmsReception           接受上行消息   SP 端程序
                        notifySmsDeliveryReception   接收状态报告


   需要注意接口谁作为服务器端,谁作为客户端。这个开发的时候有很大的区别。


1)新建项目
如下图,新建一个项目,项目选择类型为:DnmcWbPoet 我们这里将这个项目
                    yai e rjc,
命名为 ss可以根据自己喜好确定)
     m(          。




                                                                       13
浙江电信移动业务接入实践




               14
浙江电信移动业务接入实践




我本机上安装的是 tma 55所以我在 Tre rnie
          oct .,     agt utm 选择了它。


点击确认以后,我们会在 PoetEpoe 看到如下目录。
             rjc xlrr




2)导入 WD
      SL
                                     15
浙江电信移动业务接入实践



与短信接入相关的 wd 文件有如下:
          sl
与 IA 接口相关的 wd
  SG        sl
 cc_m_ye__.s
  tcsstps21xd
 cc_m_edsrie21wd
  tcsssn_evc__.sl
 cc_m_editrae21wd
  tcsssn_nefc__.sl
 cc_m_eev_evc__.sl
  tcssrciesrie21wd
 cc_m_eev_nefc__.sl
  tcssrcieitrae21wd
 cc_m_oiiainsrie21wd
  tcssntfcto_evc__.sl
 cc_m_oiiainitrae21wd
  tcssntfcto_nefc__.sl
 cc_omntps21xd
  tccmo_ye__.s
 cc_omnfut__.sl
  tccmo_als20wd
与 IM 相关的 wd
  SP      sl
 ImSEgn.sl
  sppniewd


为了区分其他程序的文件,我们为 wd
                 sl新建一个目录,在 ss的项目按右键选择
                             m
Nw>odr
 e-Fle,我们将这个目录起名为 wd。
                   sl




选中 wd 目录,按右键选择 Ipr。
    sl          mot




                                     16
浙江电信移动业务接入实践




在 Import 的对话框选择 General->File System




找到你本机上 WSDL 的存放目录

                                              17
浙江电信移动业务接入实践




选择我们需要的 WSDL 文件,然后点击 Finish,至此我们需要的 wsdl 文件就已经导入进
来。可能部分开发人员习惯新建一个 Web Service,然后指定相应的 wsdl 文件进行生成,
但由于 ISAG 的接口协议由多个描述文件构成,如果这样的方式很容易导致 Web Service
生成的时候提示语法不对,或者缺少相应描述文件。




                                                18
浙江电信移动业务接入实践




2.2 SendSMS 短信发送接口开发

  短信发送的接口过程中,SP 侧的软件是作为 Web Service Client,而 ISAG 作为 Server,
所以我们这里需要生成发送接口的客户端软件。
  方法非常简单,选中 wsdl 目录下的 cc_m_edsrie21wd 文件,按右键
                      tcsssn_evc__.sl
 选择 WbSrie-Gnrt Cin。
     e evcs>eeae let




完成以后我们会看到 Java Resources:src 目录下有如下文件:




其中 SendSmsServiceLocator 就是我们需要发送短信的客户端软件。
                                                          19
浙江电信移动业务接入实践




我们再写个软件来测试下,新建一个 SendSmsTest 的类


代码如下:

import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.Date;


import javax.xml.rpc.ServiceException;
import javax.xml.soap.SOAPException;


import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.types.URI.MalformedURIException;


import cn.com.chinatelecom.util.MD5;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference;
import
cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsBindingStub;
import
cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsServiceLocator;
import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms;


public class SendSmsTest {


   public static void main(String[] args) {


         String webserviceUrl = "isag接口地址,非wsdl地址";
         String SPID = "SPID"; // SPID
         String Token = "密钥"; // 密钥
         String DestNum = "tel:+86153XXXXXXXX"; // 发送号码
         String ProductID = "21位的产品编号,1开头"; // 产品编号
         String ServiceID = "21位的业务编号,2开头"; // 业务编号
         String TimeStamp = dateString(); // 当前时间
         String senderName = "10620000"; // 短信主叫号码,在浙江ISAG实际无效,ISAG会读
取业务部署时候的接入号
         String message = "测试短信"; // 短信内容



                                                                              20
浙江电信移动业务接入实践


      SOAPHeaderElement SoapHeader = new SOAPHeaderElement(
              "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1",
              "RequestSOAPHeader");


      try {


          /* 初始化Web Service Client */
          SendSmsServiceLocator ssl = new SendSmsServiceLocator();
          SendSms sendSms = ssl.getSendSms(new java.net.URL(webserviceUrl));


          /* 设置SOAP Header */
          SoapHeader.addChildElement("spId").addTextNode(SPID); // SpID
          SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp);
          SoapHeader.addChildElement("spPassword").addTextNode(
                 MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5加
密
          SoapHeader.addChildElement("productId").addTextNode(ProductID);
          SoapHeader.addChildElement("OA").addTextNode(DestNum);
          SoapHeader.addChildElement("FA").addTextNode(DestNum);
          SoapHeader.addChildElement("multicastMessaging").addTextNode(
                 "false"); // 是否群发
          ((SendSmsBindingStub) sendSms).setHeader(SoapHeader); // 添加SOAP头


          /* 设置被叫号码 */
          org.apache.axis.types.URI[] addresses = new
org.apache.axis.types.URI[1];
          addresses[0] = new org.apache.axis.types.URI(DestNum);


          /* 设置ChargingInformation */
          ChargingInformation charging = new ChargingInformation();
          charging.setDescription("gm");// 描述
          charging.setAmount(new BigDecimal(1));// 扣费数目
          charging.setCode(ServiceID);// 业务代码
          charging.setCurrency("0");


          /* 设置SimpleReference */
          SimpleReference receiptRequest = new SimpleReference();
          receiptRequest.setCorrelator("1001559"); // 序号自己随机增加
          receiptRequest.setInterfaceName("SmsNotificationService");
          receiptRequest.setEndpoint(new org.apache.axis.types.URI(
                 "http://开头的接收短信状态报告的webserivce地址,后续章节会讲"));


          /* 发送短信 */
          String result = sendSms.sendSms(addresses, senderName, charging,

                                                                             21
浙江电信移动业务接入实践


                     message, receiptRequest);


            System.out.println("result:" + result);


            }catch
(cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) {
            //鉴权失败
            System.out.println("MessageId:" + e.getMessageId());
            System.out.println("Text:" + e.getText());
            String[] variables = e.getVariables();
            for (int i = 0; i < variables.length; i++) {
                System.out.println("Variable:" + variables[i]);
            }
    } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException e)
{


            System.out.println("MessageId:" + e.getMessageId());
            System.out.println("Text:" + e.getText());
            String[] variables = e.getVariables();
            for (int i = 0; i < variables.length; i++) {
                System.out.println("Variable:" + variables[i]);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (SOAPException e) {
            e.printStackTrace();
        } catch (MalformedURIException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }


    }


    private static String dateString() {
        SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
        return sdf.format(new Date());
    }
}




                                                                            22
浙江电信移动业务接入实践



注:红色部分请根据问题提示替换成你的实际数据。


我们来解释下这个程序,首先我们看下:

1)初始化 SendSmsServiceLocator

   a)类:SendSmsServiceLocator 说明:

   他有如下方法:

public SendSmsServiceLocator()
  说明:构造函数

public SendSmsServiceLocator(org.apache.axis.EngineConfiguration config)
  说 明 : 构 造 函 数 可 以 通 过 设 置 EngineConfiguration 的 方 式 , 构 造 一 个
SendSmsServiceLocator

public SendSmsServiceLocator(java.lang.String wsdlLoc, javax.xml.namespace.QName
sName) throws javax.xml.rpc.ServiceException
  说明:构造函数,可以通过设置 wsdl 地址和 QName 来构造 Client

public java.lang.String getSendSmsAddress()
  说明:返回 SendSms 的接口地址

public java.lang.String getSendSmsWSDDServiceName()
  说明:返回服务名称,这里固定返回 SendSms

public void setSendSmsWSDDServiceName(java.lang.String name)
  说明:设置服务名称

public           cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms
getSendSms() throws javax.xml.rpc.ServiceException
  说明:返回发送短信接口方法。可以通过该方法得到一个实际可以发送短信的类
SendSms

public           cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms
getSendSms(java.net.URL portAddress) throws javax.xml.rpc.ServiceException
  说明:返回发送短信接口方法。可以通过该方法得到一个实际可以发送短信的类
SendSms

public void setSendSmsEndpointAddress(java.lang.String address)
  说明:设置服务器端 WebService 地址


                                                                                 23
浙江电信移动业务接入实践


public java.rmi.Remote getPort(Class serviceEndpointInterface)
  说明:返回 Webservice 端口

public javax.xml.namespace.QName getServiceName()
  说明:返回 QName 方式表示的服务名称

 public java.util.Iterator getPorts()
  说明:返回端口

public void setEndpointAddress(java.lang.String portName, java.lang.String address)
throws javax.xml.rpc.ServiceException
  说明:设置请求地址

public      void      setEndpointAddress(javax.xml.namespace.QName       portName,
java.lang.String address)
  说明:通过 QName 方式设置请求地址


b)类:SendSmsServiceLocator 使用

  我们需要初始化一个SendSmsServiceLocator类,直接通过构造函数 public

SendSmsServiceLocator() 构建,代码如下:



SendSmsServiceLocator ssl = new SendSmsServiceLocator();



由于提供给SP开发的WSDL文件里面,设定的WebService地址是:
http://localhost:9080/SendSmsService/services/SendSms

所以需要根据实际请求地址设定WebService的调用地址,代码如下 :

        String webserviceUrl = "isag接口地址(非wsdl地址)";
           SendSms sendSms = ssl.getSendSms(new
java.net.URL(webserviceUrl));


当然你可以直接修改SendSmsServiceLocator.java里面的代码:


          private java.lang.String SendSms_address =
          "http://localhost:9080/SendSmsService/services/SendSms";


                                                                                 24
浙江电信移动业务接入实践



修改为

           private java.lang.String SendSms_address = " isag接口地址(非

           wsdl地址)";


         考虑到程序的通用性,建议在初始化服务的时候设置Web Service地址,而不是

直接修改SendSmsServiceLocator.java程序。


2)类 SendSMS 的使用

  通过上述初始化,我们得到一个 SendSMS对象,他是我们发送短信实际需要的类,他
有如下方法:
public java.lang.String sendSms(
   org.apache.axis.types.URI[] addresses,
   java.lang.String senderName,
   cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging,
   java.lang.String message,
   cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest
)
  throws java.rmi.RemoteException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException;
说明:
org.apache.axis.types.URI[] addresses:接受方地址,由于这里是 URI 表示的,addresses 应
该为 new URI(“tel:+86 手机号码”)
String    senderName:String 类型,说明发送源地址号码
ChargingInformation charging:计费类型
String message:消息内容
SimpleReference receiptRequest:接口回调地址,也就是该短信的状态报告返回地址。

public java.lang.String sendSmsLogo(
org.apache.axis.types.URI[] addresses,
java.lang.String senderName,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging,
byte[] image,
cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest
                                                                                 25
浙江电信移动业务接入实践


)
throws
  java.rmi.RemoteException,
  cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException,
  cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException;
说明:
org.apache.axis.types.URI[] addresses:接受方地址,由于这里是 URI 表示的,addresses 应
该为 new URI(“tel:+86 手机号码”)
String   senderName:String 类型,说明发送源地址号码
ChargingInformation charging:计费类型
String message:消息内容
byte[] image:图片数据
cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat:短信格式
SimpleReference receiptRequest:接口回调地址,也就是该短信的状态报告返回地址。

public java.lang.String sendSmsRingtone(
org.apache.axis.types.URI[] addresses,
java.lang.String senderName,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging,
java.lang.String ringtone,
cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest
)
  throws
   java.rmi.RemoteException,
   cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException,
   cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException;
说明:
org.apache.axis.types.URI[] addresses:接受方地址,由于这里是 URI 表示的,addresses 应
该为 new URI(“tel:+86 手机号码”)
String   senderName:String 类型,说明发送源地址号码
ChargingInformation charging:计费类型
String message:消息内容
java.lang.String ringtone,:铃声数据
cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat:短信格式


                                                                                 26
浙江电信移动业务接入实践



SimpleReference receiptRequest:接口回调地址,也就是该短信的状态报告返回地址。



public cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.DeliveryInformation[]
getSmsDeliveryStatus(
java.lang.String requestIdentifier
) throws
  java.rmi.RemoteException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException;
    说明:查询消息发送状态,requestIdentifier 为发送消息时候返回的字串。


   我们这里需要调用的是 SendSms 方法

           String DestNum = "tel:+86153XXXXXXXX"; // 发送号码
           String ServiceID = "21位的业务编号,2开头"; // 业务编号


           /* 设置被叫号码 */
              org.apache.axis.types.URI[] addresses = new
    org.apache.axis.types.URI[1];
               addresses[0] = new org.apache.axis.types.URI(DestNum);


               /* 设置ChargingInformation */
               ChargingInformation charging = new ChargingInformation();
               charging.setDescription("gm");// 描述
               charging.setAmount(new BigDecimal(1));// 扣费数目
               charging.setCode(ServiceID);// 业务代码
               charging.setCurrency("0");


               /* 设置SimpleReference */
               SimpleReference receiptRequest = new SimpleReference();
               receiptRequest.setCorrelator("1001559"); // 序号自己随机增加
               receiptRequest.setInterfaceName("SmsNotificationService");
               receiptRequest.setEndpoint(new org.apache.axis.types.URI(
                       "http://开头的接收短信状态报告的webserivce地址,后续章节会讲"));


               /* 发送短信 */
               String result = sendSms.sendSms(addresses, senderName, charging,
                       message, receiptRequest);


               System.out.println("result:" + result);



                                                                            27
浙江电信移动业务接入实践




  调用 sendSms 的方法以后,系统会返回一个短信表示字串叫做 RequestIdentifier,这个
为长度为 32 位的数字,类似在短信网关里面 MessageID,用以识别短信,如果后续查询短
信状态报告的时候都需要通过此参数进行查询。比如 19120004a924d2c021b1,前面 191200
前面 6 为表示 isag 的设备号,后面一位 0 预留,4a924d2c021b1 由设备厂商内部编码。




3)设置 SOAP HEADER
   正如 1.4.5 我们提到与 ISAG 交互的时候,需要传送 SOAPHeader 以作验证用。
  SOAPHeader 在 AXIS 里面有一个对象:SOAPHeaderElement 对应:
  相关文档可以查询:
  http://ws.apache.org/axis/java/apiDocs/org/apache/axis/message/SOAPHeaderElement.html


  我们看下 SOAPHeaderElement 的定义:

    public class SOAPHeaderElement
    extends MessageElement
    implements SOAPHeaderElement
    A simple header element abstraction. Extends MessageElement with header-specific
    stuff like mustUnderstand, actor, and a 'processed' flag.

  它是 MessageElement 的扩展类,用于定义 SOAP HEADER


  其构造函数有如下方法:
    SOAPHeaderElement 构造函数

    SOAPHeaderElement(Name nm)
                            ae
    SOAPHeaderElement(QName qae
                             nm)

    SOAPHeaderElement(QName qae jv.agOjc vle
                             nm, aaln.bet au)

    SOAPHeaderElement(aaln.tig nmsae
                      jv.agSrn  aepc,
    jv.agSrn lclat
     aaln.tig oaPr)

    SOAPHeaderElement(aaln.tig nmsae
                      jv.agSrn  aepc,
    jv.agSrn lclat jv.agOjc vle
     aaln.tig oaPr, aaln.bet au)

                                                                                     28
浙江电信移动业务接入实践



    SOAPHeaderElement(aaln.tig nmsae
                      jv.agSrn  aepc,
    jv.agSrn lclat
     aaln.tig oaPr,                                        jv.agSrn pei,
                                                            aaln.tig rfx
    ogxlsxAtiue atiue,DeserializationContext
     r.m.a.trbts trbts                                                cnet
                                                                       otx)


参考文档《中国电信综合业务接入网关_ISAG_开放接口协议 01-总册 RC V1.0.0》7.2
SOAP Header 的定义,我们可以定义如下 soap header:

   SOAPHeaderElement SoapHeader = new SOAPHeaderElement(
      "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1",
            "RequestSOAPHeader");




如何在 SOAP Header 设置参数名和参数的值,我们看下 SOAPHeaderElement 的父类 MessageElement,

其增加参数的方法为:addChildElement

    返回值           方法
    SOAPElement   addChildElement(Name childName)

                            add the child element

    SOAPElement   addChildElement(SOAPElement element)

                  The added child must be an instance of MessageElement rather than an

                  abitrary SOAPElement otherwise a (wrapped) ClassCastException will be

                  thrown.

    SOAPElement   addChildElement(java.lang.String localName)

                            add a child element in the message element's own namespace

    SOAPElement   addChildElement(java.lang.String       localName,   java.lang.String

                  prefixName)

                  add a child element

    SOAPElement   java.lang.String childPrefix, java.lang.String uri)

                  add a child element




通过 MessageElement 的 addChildElement 方法我们可以增加一个 SOAP Header


                                                                                    29
浙江电信移动业务接入实践



的 一 个 参 数 , 我 们 的 参 数 比 较 简 单 , 都 为 String 字 段 , 所 以 可 以 直 接 使 用

addChildElement(java.lang.String localName)方法进行参数的增加。

addChildElement 其返回值为 SOAPElement,所以我们可以直接通过 SOAPElement

设置相应的值,我们继续看下 SOAPElement ,他有

SOAPElement           adetoejv.agSrn tx)
                        dTxNd(aaln.tig et
                            Creates a new Tx object initialized with the given Srn and adds it to
                                           et                                   tig
                      this SAEeet
                            OPlmn object.


由于与 ISAG 涉及到的参数都是 String 类型,所以我们可以通过方法:

//增加SPID
SoapHeader.addChildElement("spId").addTextNode("12100000");


可以通过上述这样的方法来设置 spId(注意字母的大小写),其他同理。

整个代码如下:

              /* 设置SOAP Header */
              SoapHeader.addChildElement("spId").addTextNode(SPID); // SpID
              SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp);
              SoapHeader.addChildElement("spPassword").addTextNode(
                    MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5
加密
              SoapHeader.addChildElement("productId").addTextNode(ProductID);
              SoapHeader.addChildElement("OA").addTextNode(DestNum);
              SoapHeader.addChildElement("FA").addTextNode(DestNum);
              SoapHeader.addChildElement("multicastMessaging").addTextNode(
                    "false"); // 是否群发




绑定 SOAP HEADER

   我们构建好 SOAP Header 以后需要将 Soap header 与服务请求进行绑定,代码如

下:



                                                                                               30
浙江电信移动业务接入实践


((SendSmsBindingStub) sendSms).setHeader(SoapHeader);




4)抛出异常处理

在 SendSms 类的使用介绍中,我们知道 SendSms 方法会抛出 3 个异常:

        java.rmi.RemoteException

        cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException

        cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException



     java.rmi.RemoteException 是 Java 远程调用产生的异常,产生这个异常的原因很多这里不再详述。

     PolicyException,ServiceException 这两个异常是 ISAG 服务端程序抛出的,具体异常查看规范《中

国电信综合业务网关_ISAG_开发接口协议 01-总册》查询。这两个异常都会返回 Messsage Id,以说明

错误的类别;会返回 Text 是错误的描述;还会返回 Variables 数组说明错误的具体错误原因。

     因为这个两个错误很容易发生,比如用户订购关系不存在会抛出 ServiceException;比如你没有接

口权限会抛出 PolicyException。为了程序能够正常处理,我们需要对这两个异常做特殊处理。代码如

下:
            catch
(cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) {
            //鉴权失败
            System.out.println("MessageId:" + e.getMessageId());
            System.out.println("Text:" + e.getText());
            String[] variables = e.getVariables();
            for (int i = 0; i < variables.length; i++) {
                System.out.println("Variable:" + variables[i]);
            }
     } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException
e) {


            System.out.println("MessageId:" + e.getMessageId());
            System.out.println("Text:" + e.getText());
            String[] variables = e.getVariables();
            for (int i = 0; i < variables.length; i++) {
                System.out.println("Variable:" + variables[i]);
            }
        }

                                                                            31
浙江电信移动业务接入实践




5)查询短信状态

查询短信状态有多种方式,这个章节只讨论如何通过SendSms接口的getSmsDeliverStatus方式来实现,

在开始的例子中的main方法的结束前增加如下几行。

代码如下:
          //等待10秒以后再查询
          try {
              Thread.sleep(10000);
          } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          DeliveryInformation[] delvierinfo = sendSms
                 .getSmsDeliveryStatus(result);


          for (int i = 0; i < delvierinfo.length; i++) {
              System.out.println("发送号码:" + delvierinfo[i].getAddress());
              System.out
                     .println("发送状态:" +
delvierinfo[i].getDeliveryStatus());
          }



6)封装短信发送

SendSmsTest.java演示了如何发送短信,但是如果每个程序都这样调用的过于繁琐。我们需要把短信方

法封装成一个方便使用的类。

类:cn.com.chinatelecom.sms.SMS
package cn.com.chinatelecom.sms;


import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Date;


import javax.xml.rpc.ServiceException;


import org.apache.axis.message.SOAPHeaderElement;


import cn.com.chinatelecom.sms.bean.Result;

                                                                       32
浙江电信移动业务接入实践


import cn.com.chinatelecom.util.MD5;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference;
import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms;
import
cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsBindingStub;
import
cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsServiceLocator;


public class SMS {
   private java.lang.String SendSms_address =
"http://localhost:9080/SendSmsService/services/SendSms";
   private String SPID = "";
   private String Token = "";
   private SendSmsServiceLocator ssl;
   private SendSms sendSms;
   private String receiptRequestUrl = "";
   private String receiptRequestInterfaceName = "notifySmsDeliveryReception";
   private ChargingInformation chargingInformation = new ChargingInformation();


   public SMS(String spid, String token, String ws_address,
            String receiptrequestUrl) throws MalformedURLException,
            ServiceException {
         this.SendSms_address = ws_address;
         this.ssl = new SendSmsServiceLocator();
         this.receiptRequestUrl = receiptrequestUrl;
         this.sendSms = ssl.getSendSms(new java.net.URL(this.SendSms_address));
         this.SPID = spid;
         this.Token = token;
         this.chargingInformation.setDescription("Free");
         this.chargingInformation.setAmount(new BigDecimal(1));// 扣费数目
         this.chargingInformation.setCurrency("0");
   }


   public void SetChargingInformation(ChargingInformation charginginformation){
         //设置计费规则
         this.chargingInformation=charginginformation;
   }


   public Result SendSms(String sendnum, String destnum, String message,
            String productid, String serviceid) {
         String[] destnumarray = new String[1];
         destnumarray[0] = destnum;
         return SendSms(sendnum, destnumarray, message, productid, serviceid);

                                                                              33
浙江电信移动业务接入实践




    }


    public Result SendSms(String sendnum, String[] destnum, String message,
           String productid, String serviceid) {


        try {
           // 设置SoapHeader
           SOAPHeaderElement SoapHeader = new SOAPHeaderElement(
                   "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1",
                   "RequestSOAPHeader");
           String TimeStamp = dateString();
           SoapHeader.addChildElement("spId").addTextNode(this.SPID); // SpID
           SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp);
           SoapHeader.addChildElement("spPassword").addTextNode(
                   MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5加
密
           SoapHeader.addChildElement("productId").addTextNode(productid);
           if (destnum.length == 1) {
                SoapHeader.addChildElement("OA").addTextNode(
                      FormatMsisdn(destnum[0]));
                SoapHeader.addChildElement("FA").addTextNode(
                      FormatMsisdn(destnum[0]));
                SoapHeader.addChildElement("multicastMessaging").addTextNode(
                      "false"); // 是否群发
           } else {
                SoapHeader.addChildElement("multicastMessaging").addTextNode(
                      "true"); // 是否群发
           }


           ((SendSmsBindingStub) this.sendSms).setHeader(SoapHeader); // 添加
SOAP头


           /* 设置被叫号码 */
           org.apache.axis.types.URI[] addresses = new
org.apache.axis.types.URI[destnum.length];
           for (int i = 0; i < destnum.length; i++) {


                destnum[i] = FormatMsisdn(destnum[i]);


                addresses[i] = new org.apache.axis.types.URI(destnum[i]);
           }


           /* 设置ChargingInformation */

                                                                                34
浙江电信移动业务接入实践


           this.chargingInformation.setCode(serviceid);// 业务代码


           /* 设置SimpleReference */
           SimpleReference receiptRequest = new SimpleReference();
           String Correlator = getCorrelator();
          receiptRequest.setCorrelator(Correlator); // 序号自己随机增加
   receiptRequest.setInterfaceName(this.receiptRequestInterfaceName);
           receiptRequest.setEndpoint(new org.apache.axis.types.URI(
                 this.receiptRequestUrl));


           Result result = new Result();
           result.RequestIdentifier = this.sendSms.sendSms(addresses, sendnum,
                 this.chargingInformation, message, receiptRequest);
           result.Correlator=Correlator;
           return result;


       } catch
(cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) {
           // 鉴权失败
           Result result = new Result();
           result.MessageId = e.getMessageId();
           result.Text = e.getText();
           result.Variables = e.getVariables();
           return result;


       } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException
e) {
           // 规则健权失败
           Result result = new Result();
           result.MessageId = e.getMessageId();
           result.Text = e.getText();
           result.Variables = e.getVariables();
           return result;
       } catch (Exception e) {
           // 其他错误
           e.printStackTrace();
           Result result = new Result();
           result.MessageId = "-1";
           result.Text = "Unkonw error";
           result.Variables = new String[1];
           result.Variables[0] = "Unkonw error";
           return result;
       }



                                                                            35
浙江电信移动业务接入实践


    }


    private static String FormatMsisdn(String msisdn) {
        msisdn = msisdn.toLowerCase();
        if ((msisdn.indexOf("+86") < 0) && (msisdn.indexOf("tel:") != 0)
               && (msisdn.length() == 11)) {
            // 不带+86,不带tel:的手机号码
            return "tel:+86" + msisdn;
        }
        if ((msisdn.indexOf("86") == 0) && (msisdn.indexOf("tel:") != 0)
               && (msisdn.length() == 13)) {
            // 带86,不带+号,不带tel:的手机号码
            return "tel:+" + msisdn;
        }
        return msisdn;
    }


    private static String getCorrelator() {
        SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
        return sdf.format(new Date());
    }


    private static String dateString() {
        SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
        return sdf.format(new Date());
    }
}




为了方便返回数据,还需要构建一个类cn.com.chinatelecom.sms.bean.Result:


package cn.com.chinatelecom.sms.bean;


public class Result {
    public String RequestIdentifier=null;
    public String Correlator="";
    public String MessageId="";
    public String Text="";
    public String[] Variables;
}




                                                                           36
浙江电信移动业务接入实践




另外加密用的的cn.com.chinatelecom.util.MD5
package cn.com.chinatelecom.util;


import java.security.*;


public class MD5 {


     private final static String[] hexDigits = {
             "0", "1", "2", "3", "4", "5", "6", "7",
             "8", "9", "a", "b", "c", "d", "e", "f"};
     /**
      * 转换字节数组为16进制字串
      * @param b 字节数组
      * @return 16进制字串
      */
     public static String byteArrayToHexString(byte[] b) {
         StringBuffer resultSb = new StringBuffer();
         for (int i = 0; i < b.length; i++) {
             resultSb.append(byteToHexString(b[i]));
         }
         return resultSb.toString();
     }
     private static String byteToHexString(byte b) {
         int n = b;
         if (n < 0)
             n = 256 + n;
         int d1 = n / 16;
         int d2 = n % 16;
         return hexDigits[d1] + hexDigits[d2];
     }
     public static String compile(String origin) {
         String resultString = null;


         try {
             resultString=new String(origin);
             MessageDigest md = MessageDigest.getInstance("MD5");


resultString=byteArrayToHexString(md.digest(resultString.getBytes()));
         }
         catch (Exception ex) {


         }
                                                                         37
浙江电信移动业务接入实践


           return resultString;
       }
   }



生成这3个类以后,我们可以非常方便的使用这个接口:

cn.com.chinatelecom.sms.SMS

方法                                               说明
public SMS(String spid, String token, String
                                                 SMS构造函数,参数分别为:SPID,密钥,发
ws_address,
              String receiptrequestUrl) throws   送短信服务器端地址,发送短信回执地址
MalformedURLException,



public void                                      设置计费规则,可选

SetChargingInformation(ChargingInformation

charginginformation)

public Result SendSms(String sendnum, String     发送单条短信。参数为:发送号码,目的号
destnum, String message,
                                                 码,消息内容,产品编号,服务编号
              String productid, String
                                                 返回值为:Result。
serviceid)
                                                 其中Result.RequestIdentifier不为null值,表

                                                 示短信已经提交给网关,如果为null,表示

                                                 提交失败
public Result SendSms(String sendnum,
                                                 群发短信。参数为:发送号码,目的号码数
String[] destnum, String message,
                                                 组,消息内容,产品编号,服务编号。返回
              String productid, String
                                                 值为:Result。
serviceid)
                                                 其中Result.RequestIdentifier不为null值,表

                                                 示短信已经提交给网关,如果为null,表示

                                                 提交失败



我们可以测试下上述这个类,代码如下:
           SMS sms=new SMS("spid","linlu","ISAG接口地址","短信回执接口地址");


           Result result = sms.SendSms("主叫号码", "用户号码", "短信内容", "产品编号", "

                                                                                  38
浙江电信移动业务接入实践


服务编号");


      if (result.RequestIdentifier!=null){
          System.out.println("短信发送成功!");
          System.out.println("RequestIdentifier:"+result.RequestIdentifier);
          System.out.println("Correlator:"+result.Correlator);
      }else {
          System.out.println("短信发送失败!");
          System.out.println("MessageId:"+result.MessageId);
          System.out.println("Text:"+result.Text);
      }

注:红色部分替换成实际数据




2.3 SendSMS 短信上行,回执接口开发

短信上行的接口需要SP端作为服务器端,并实现SmsNotification接口,其中方法
notifySmsReception方法实现短信上行接受,notifySmsDeliveryReception实现短信回执接
收。
方法同样,找到我们先前导入的wsdl文件:ctcc_sms_notification_service_2_1.wsdl
按右键,选择Web Services->Generate Java bean skeleton




在出现的界面里面,选择Finish按钮即可:




                                                                          39
浙江电信移动业务接入实践




Eclipse会自动生成如下文件:




                                   40
浙江电信移动业务接入实践




获取SoapHeader:
   由于在点播业务中,我们还需要换取LinkID,在下发的时候需要带上LinkID,由于
LinkID存在于服务器的请求的SoapHeader中,我们还需要获取SoapHeader相应的数值。
   代码如下:
NotifySOAPHeader.java

package cn.com.chinatelecom.ws;


import java.util.Iterator;


import javax.xml.soap.SOAPElement;


import org.apache.axis.AxisFault;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPHeaderElement;


public class NotifySOAPHeader {
   private String spRevId = "";
   private String spRevpassword = "";
   private String spId = "";
   private String SAN = "";
   private String linkId = "";


   public String getSpRevId() {
       return spRevId;
   }


   public NotifySOAPHeader(SOAPEnvelope envelope) {


       try {
          SOAPHeaderElement soapHeaderElement = envelope.getHeaderByName(
                  "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1",
                  "NotifySOAPHeader");
          Iterator iterator = soapHeaderElement.getChildElements();
          while (iterator.hasNext()) {
               SOAPElement element = (SOAPElement) iterator.next();
               String elementName = element.getElementName().getLocalName();
               if (elementName.equals("spRevId")) {
                  this.spRevId = element.getValue();
               } else if (elementName.equals("spRevpassword")) {
                  this.spRevpassword = element.getValue();

                                                                               41
浙江电信移动业务接入实践


            } else if (elementName.equals("spId")) {
                 this.spId = element.getValue();
            } else if (elementName.equals("SAN")) {
                 this.SAN = element.getValue();
            } else if (elementName.equals("linkId")) {
                 this.linkId = element.getValue();
            }
        }
    } catch (AxisFault e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


}


public void setSpRevId(String spRevId) {
    this.spRevId = spRevId;
}


public String getSpRevpassword() {
    return spRevpassword;
}


public void setSpRevpassword(String spRevpassword) {
    this.spRevpassword = spRevpassword;
}


public String getSpId() {
    return spId;
}


public void setSpId(String spId) {
    this.spId = spId;
}


public String getSAN() {
    return SAN;
}


public void setSAN(String sAN) {
    SAN = sAN;
}


public String getLinkId() {

                                                         42
浙江电信移动业务接入实践


        return linkId;
    }


    public void setLinkId(String linkId) {
        this.linkId = linkId;
    }


}



说明:public NotifySOAPHeader(SOAPEnvelope envelope)是该类的构造函数,通过传入
SOAPEnvelope,程序从SOAPEnvelope分析出需要用到的SoapHeader里面的具体数值。 其中
SOAPEnvelope可以在WebService的具体实现代码里面:XXXXXXImpl.java里面通过以下代码获取:
// 获取soapheader
         NotifySOAPHeader notifySOAPHeader = new NotifySOAPHeader(
                  MessageContext.getCurrentContext().getRequestMessage()
                         .getSOAPEnvelope());
           System.out.println("LinkId:"+notifySOAPHeader.getLinkId());
           System.out.println("SAN:"+notifySOAPHeader.getSAN());
           System.out.println("SpId:"+notifySOAPHeader.getSpId());
           System.out.println("RevId:"+notifySOAPHeader.getSpRevId());
    System.out.println("SpRevpassword:"+notifySOAPHeader.getSpRevpassword());




其中SmsNotificationBindingImpl.java是我们需要继续增加处理逻辑的文件。


package cn.com.chinatelecom.www.wsdl.ctcc.sms.notification.v2_1.service;


import java.io.FileWriter;
import java.io.IOException;
import cn.com.chinatelecom.ws.NotifySOAPHeader;
public class SmsNotificationBindingImpl implements
cn.com.chinatelecom.www.wsdl.ctcc.sms.notification.v2_1._interface.SmsNotification{
    public void notifySmsReception(java.lang.String registrationIdentifier,
cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsMessage message) throws
java.rmi.RemoteException {


        // 获取soapheader
            NotifySOAPHeader notifySOAPHeader = new NotifySOAPHeader(
                   MessageContext.getCurrentContext().getRequestMessage()
                          .getSOAPEnvelope());


                                                                              43
浙江电信移动业务接入实践


                 System.out.println("LinkId:"+notifySOAPHeader.getLinkId());
                 System.out.println("SAN:"+notifySOAPHeader.getSAN());
                 System.out.println("SpId:"+notifySOAPHeader.getSpId());
                 System.out.println("RevId:"+notifySOAPHeader.getSpRevId());
           System.out.println("SpRevpassword:"+notifySOAPHeader.getSpRevpassword());


        try {
                 FileWriter fw=new FileWriter("c:sms.log",true);
                 fw.write("registrationIdentifier:"+registrationIdentifier + "rn");
                 fw.write("Sender:"+message.getSenderAddress()+ "rn");
                 fw.write("Message:"+message.getMessage()+ "rn");
                 fw.write("LinkId:"+notifySOAPHeader.getLinkId()+ "rn");
                 fw.close();
           } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
           }


    }


    public void notifySmsDeliveryReceipt(java.lang.String correlator,
cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.DeliveryInformation deliveryStatus)
throws java.rmi.RemoteException {




         try {
                 FileWriter fw = new FileWriter("c:deliver.log",true);
                 fw.write("correlator:"+correlator + "rn");
                 fw.write("Address:"+deliveryStatus.getAddress()+ "rn");
                 fw.write("DeliveryStatus:"+deliveryStatus.getDeliveryStatus()+ "rn");
                 fw.close();
           } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
           }



    }


}



    绿底部分会在自动生成代码基础上增加的代码,作用是将短信上行写到文件
                                                                                 44
浙江电信移动业务接入实践



c:sms.log,状态报告写在:c: deliver.log。当然实际的程序远比这个复杂,或者入库或者
触发相应的程序。


  代码完成后,由于接收上行消息和接收状态报告是Web Service服务端程序,需要部署
到Web服务器上;因此需要生成war文件,方法如下,选中sms项目,按右键选择
Export->WAR file,生成的文件拷贝到Tomcat安装目录的webapps目录下,tomcat会自动部
署该文件。




                                                        45
浙江电信移动业务接入实践




3. WAP PUSH

3.1    WAP PUSH 简介

      WP
       A 业务发展初期基本上采用的是 PL 的方式,
                        UL    也就是说你需要访问某个 WP
                                           A 网站,
那么需要打开 WP浏览器,并且输入网址比如:ht:/a.ntmb,访问中国电信
        A              tp/wpve.oi
的 WP
  A 门户网站。由于手机输入网址不方便,而且用户并非无时无刻连接在 WP
                                    A 网站上,
所以鉴于这样的原因,OA
           M 提出了 WPPS 的概念。其主要思想是通过某种特殊短信,
                  A UH
来触发用户使用某种 WP
           A 业务。

       A PS 目前主要分成两种,一种 Service Indication 方式(简称 SI) 通过短
      WP UH                                         ,

信方式 PS 相关 WP
     UH   A 网址以及简要的说明,至于用户是否访问这个网址,需要用户点击
确认。当然手机厂家对于 SI方式的 WPPS
                   A UH展示方式不一样,显示的界面有很大的区
别,所以那个按钮可能叫确认也有可能叫转向。这个也就是窄义上的 WPPS,也是本
                                A UH
章节讲解的 WPPS。
       A UH

      另外一种 WP UH
            A PS 类型叫 Service Loading(简称 SL),通过短信 Ps 一个网
                                                  uh

址,手机主动联网并且下载该文件并且保存,最终以某种形式展示给用户。SL的种类非
常多,最典型的就是彩信,当用户手机收到 S 消息以后,
                     L     自动到彩信中心下载彩信内容,
中间不需要用户干预;当然还有一些 OA
                  T 下载,某些 Ps Mi 也采用类似 S 的方式,
                           uh al       L
这里不再详述。




3.2    WAP PUSH 网络结构和业务实现


      我们看下目前 WPPS 网络的结构:
              A UH



                                                      46
浙江电信移动业务接入实践




  在电信网内一个正常的 WbPs(I下发如上图蓝绿色箭头表示。整个 PS 的实
              e uhS)                UH
现从 SP发起,并经过 IA,uh代理网关(PG
             SGPs      P)以及短信中心,最后以一种特殊短信
的方式下发给用户。其具体流程和接口协议如下:
  1 S 使用 IA 的 WbSrie
   . P    SG   e evc 接口提交 S。
                           I
  2 IA 将 S Wb evc 提交的数据,分装成 XL
   . SG P e Srie             M 文件,并通过 PP
                                       A 协议(Ps
                                             uh
    Acs Pooo)协议,将 S 消息提交给 Ps 代理网关(PG。
     ces rtcl      I      uh       P)
  3 PG收到 S
   . P    I消息以后,将 SI消息按照 Ps-S
                          uhWP协议,把 XL文件压缩成
                                    M
    WXLWPBnr XL一种 S 的压缩方式)
     BM(A iay M,   I      变成一条或者多条短信,提交给短
    信中心。
  4 短信中心下发这条或者这组特殊短信到用户的手机。
   .


  当然如果不通过 IA 接入,理论上可以直接通过 PP协议接入 PG代理网关,但
           SG              A     P
协议相对于 WbSrie
       e evc 协议要复杂一些。
  在 GM
     S 的网络中,当然还存在一种特殊的方式,S 侧直接将 S 根据 WXL
                          P      I    BM 的方式
进行压缩成一条或者多条短信,直接通过短信网关,由短信网关提交给短信中心,从而
实现 WPPS 的下发,如上图棕色部分箭头。需要说明的是 CM 网络里面的 WPPS
    A UH                      DA       A UH
封装与 GM
     S 存在相当大的差异,如果你通过 GM
                      S 方式封装的 WP UH用户实际收到的短
                               A PS,
信很有可能是一段乱码。虽然我查询了 TAEA67A以及 OA
                   I-I-3-,   M 相关的 WP
                                    A 的协议,具
体地址:ht:/w.pnoielineogTcnclwpne.sx
     tp/wwoemblalac.r/ehia/aidxap,并未找到直


                                             47
浙江电信移动业务接入实践



接通过短信网关下发实际有效的 WPPS。比较靠谱的消息是:CM
                A UH          DA网络里面是通过
Tlsried
 eeevcI 来区分普通的短信还是 WPPS 亦或彩信,而 WPPS 和彩信都需要设
                    A UH        A UH
置 Tlsried 602
   eeevcI 为 50,可惜的是 Tlsried
                     eeevcI 并不是 SP 协议能够传输的,需
                                 MP
要短信中心对于不同的短信实体进行强制设置,也意味着你无法通过 SG 协议发送 WP
                                MP      A
PS。当然如果您研究出来在 CM 的网络里面如何通过短信网关发送 WPPS,
 UH            DA                 A UH欢迎您
发邮件到我的邮箱:dwlh@mi.o。
          oelzgalcm




3.3    WAP PUSH 是什么?WAP PUSH 不是什么?

      在您开发 WpPs 应用的时候,我觉得有必要跟你说明白“WPPS 是什么?WP
            a uh                   A UH     A
PS 不是什么?” 这个问题。
 UH
      首先 WpPs 并不是所有的手机都支持,虽然它本身属于 OA
          a uh                     M 标准协议的一部分,
我手头上的 CoPdD8
       ola 1 就不支持,当有个 Ps 送达手机的时候,屏幕会一亮,然后就
                      uh
无下文了。
      其次 Wp uh
          a Ps 在终端上显示有很大的差别,WnosMbl 的系统显示相对比较正
                             idw oie
常,而 CoPdN0
     ola 90一条 Ps
               uh跟一条文字后面跟着网站地址的普通短信显示上没本质
的区别。
      再次 Wp uh
          a Ps 无法显示主叫号码,在多普达 S0C
                              90 显示的主叫号码为:未验证用户,
而三星的 i2 显示为系统管理员。这估计也是为什么一度 GM
      39                     S 网络的手机收到大量的垃
圾 WpPs 短信的一个原因,因为用户都不知道谁发的。
  a uh
      还有需要说明的是,在某些情况下,一条 WPPS 和一条文字加网站链接构成的普
                          A UH
通的短信在用户的体验上没特别的差别,因为部分手机会自动识别普通短信中带了
ht:/
 tp/开头的地址,用户点击这个地址也会自动关联相应的浏览器,唯一的区别 WP
                                      A
Ps 用户点击的时候肯定会通过 CWP
 uh              TA 方式连接,而普通短信里面的地址有可能用户连
接的 CWP
    TA,也有可能连接的是 CNT
                 TE。
      当然 WPPS 跟普通短信还有一个很大的区别是,用户至少直接拿终端(不通过直
          A UH
接控制通讯模块)是无法发送 WPPS 的,也意味着无法转发 WPPS,
               A UH            A UH这对于某些安
全级别要求较高的业务由于不能转发而不容易泄密,比如可以 ps 你一个通过加密生成
                             uh
的 Ul Ul
  r 串, r 串里面含有免登录数据,由于无法转发,用户泄漏数据的可能性大大降低。
                                              48
浙江电信移动业务接入实践




3.4 WAP Push 接口开发环境搭建

  为了完成 WPPs 开发,我们需要实现以下接口:
        A uh
接口名称                  接口方法                             作用            谁是服务器端
SendMessage           SendMessage                      发送 Wap Push
                      getMessageDeliverStatus          查询发送状态        ISAG
MessageNotification   notifyMessageDeliveryReception   接收状态报告        SP


   你会发现 WpPs
         a uh远比短信接口要少,很大的原因是在用户不通过某种特殊途径是
无法直接在终端上发送 WpPs 上行的,所以他的 Msaeoiiain
            a uh          esgNtfcto 里面就没有接
受上行的接口。
   1)      新建项目
   因为接受状态报告需要 S 端作为服务器端,所以我们同样需要新建一个 Dnmc e
               P                      yai Wb
Poet
 rjc。
   选择 Fl-Nw>yai WbPoet
       ie>e-Dnmc e rjc




   在弹出的确认窗口我这里起名叫 Wpuh你也可以起其他的项目名称
                   aPs,




                                                                              49
浙江电信移动业务接入实践




点击 Fns,
    iih一个项目就新建成功。
2)   导入 WD 文件
        SL
  开发 WPPs 需要用到的 WD 文件如下:
      A uh       SL
     与 IA 接口相关的 wd
        SG       sl
      cc_a_uhntfcto_nefc__.sl
       tcwpps_oiiainitrae10wd
      cc_a_uhntfcto_evc__.sl
       tcwpps_oiiainsrie10wd
      cc_a_uhsn_nefc__.sl
       tcwpps_editrae10wd
      cc_a_uhsn_evc__.sl
       tcwpps_edsrie10wd
      cc_a_uhtps10xd
       tcwpps_ye__.s
      cc_omntps21xd
       tccmo_ye__.s
      cc_omnfut__.sl
       tccmo_als20wd
     与 IM 相关的 wd
        SP     sl
      ImSEgn.sl(
       sppniewd 该接口实现不在这个章节讨论)



                                   50
浙江电信移动业务接入实践



a同样我们为了不与其他程序混在一块,为 WD
 )                   SL文件新建一个目录 wd,
                                 sl用户导入
wd 文件。
 sl




b选择建立的 wd 目录,按右键选择 Ipr
 )      sl          mot




c选择 Fl Sse
 )   ie ytm




                                      51
浙江电信移动业务接入实践




d选中我们需要的 WD 文件:
 )        SL




                             52
浙江电信移动业务接入实践




 导入完成后我们应该看到 PoetEpoe 有如下文件
              rjc xlrr




3.5 WAP Push 发送接口开发

 Wap Push 发送的接口过程中,SP 侧的软件是作为 Web Service Client,而 ISAG 作为
Server,所以我们这里需要生成发送接口的客户端软件。
  方法非常简单,选中 wsdl 目录下的 cc_a_uhsn_evc__.sl
                       tcwpps_edsrie10wd 文件,
 按右键选择 WbSrie-Gnrt Cin。
        e evcs>eeae let
                                                        53
浙江电信移动业务接入实践




生成以后,系统会多了如下代码:




其中:SendMessageServiceLocator.java 就是我们需要的客户端程序。

我们编写个测试代码:
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.Date;


import javax.xml.rpc.ServiceException;
import javax.xml.soap.SOAPException;


import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.types.URI.MalformedURIException;


import cn.com.chinatelecom.util.MD5;

                                                          54
浙江电信移动业务接入实践


import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation;
import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference;


import cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.MessagePriority;
import cn.com.chinatelecom.www.wsdl.ctcc.wap_push.send.v1_0._interface.SendMessage;
import
cn.com.chinatelecom.www.wsdl.ctcc.wap_push.send.v1_0.service.SendMessageBindingStub;
import
cn.com.chinatelecom.www.wsdl.ctcc.wap_push.send.v1_0.service.SendMessageServiceLocator;



public class SendWapPush {
   public static void main(String[] args) {


         String webserviceUrl = "ISAG WAP Push地址(非WSDL地址)";
         String SPID = "SPID"; // SPID
         String Token = "密码"; // 密钥
         String DestNum = "tel:+8615305711873"; // 发送号码
         String ProductID = "112000000000000004112"; // 产品编号
         String ServiceID = "212000000000000002488"; // 业务编号
         String TimeStamp = dateString(); // 当前时间
         String senderName = "10620068"; // WAP Push主叫号码,在浙江ISAG实际无效,ISAG会读取业
务部署时候的接入号
    String targetURL="http://wap.189.cn";
         String subject ="189邮箱";



         SOAPHeaderElement SoapHeader = new SOAPHeaderElement(
                 "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1",
                 "RequestSOAPHeader");


         try {


            /* 初始化WebService Client */
            SendMessageServiceLocator ssl = new SendMessageServiceLocator();
            SendMessage sendMessage = ssl.getSendMessage(new java.net.URL(webserviceUrl));


            /* 设置SOAP Header */
            SoapHeader.addChildElement("spId").addTextNode(SPID); // SpID
            SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp);
            SoapHeader.addChildElement("spPassword").addTextNode(
                   MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5加密
            SoapHeader.addChildElement("productId").addTextNode(ProductID);
            SoapHeader.addChildElement("OA").addTextNode(DestNum);

                                                                               55
浙江电信移动业务接入实践


          SoapHeader.addChildElement("FA").addTextNode(DestNum);
          SoapHeader.addChildElement("multicastMessaging").addTextNode(
                 "false"); // 是否群发
          ((SendMessageBindingStub) sendMessage).setHeader(SoapHeader); // 添加SOAP头


          /* 设置被叫号码 */
          org.apache.axis.types.URI[] addresses = new org.apache.axis.types.URI[1];
          addresses[0] = new org.apache.axis.types.URI(DestNum);


          /* 设置ChargingInformation */
          ChargingInformation charging = new ChargingInformation();
          charging.setDescription("gm");// 描述
          charging.setAmount(new BigDecimal(1));// 扣费数目
          charging.setCode(ServiceID);// 业务代码
          charging.setCurrency("0");


          /* 设置SimpleReference */
          SimpleReference receiptRequest = new SimpleReference();
          receiptRequest.setCorrelator("1001559"); // 序号自己随机增加
          receiptRequest.setInterfaceName("notifyMessageDeliveryReception");
          receiptRequest.setEndpoint(new org.apache.axis.types.URI(


   "http://202.101.166.196:8080/WebPush/services/notifyMessageDeliveryReception"));


          /* 发送WAP PUSH */
          String result = sendMessage.sendMessage(addresses, new
org.apache.axis.types.URI(targetURL), senderName, subject, MessagePriority.Normal,
charging, receiptRequest);


          System.out.println("result:" + result);




      } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) {
          // 鉴权失败
          System.out.println("MessageId:" + e.getMessageId());
          System.out.println("Text:" + e.getText());
          String[] variables = e.getVariables();
          for (int i = 0; i < variables.length; i++) {
              System.out.println("Variable:" + variables[i]);
          }


      } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException e) {



                                                                           56
浙江电信移动业务接入实践


            System.out.println("MessageId:" + e.getMessageId());
            System.out.println("Text:" + e.getText());
            String[] variables = e.getVariables();
            for (int i = 0; i < variables.length; i++) {
                System.out.println("Variable:" + variables[i]);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (SOAPException e) {
            e.printStackTrace();
        } catch (MalformedURIException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }


    }


    private static String dateString() {
        SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
        return sdf.format(new Date());
    }
}



注:红色部分替换成自己相应的数据。

关于 SOAP Header 的设置请查看短信章节里面的说明,设置完全一样。

类似短信方式我们需要初始化一个 SendMessage 的 Client,获得一个 SendMessage 的对象

            /* 初始化WebService Client */
            SendMessageServiceLocator ssl = new SendMessageServiceLocator();
            SendMessage sendMessage = ssl.getSendMessage(new
java.net.URL(webserviceUrl));



其中 SendMessage 有如下方法:
public java.lang.String sendMessage(
org.apache.axis.types.URI[] addresses, //用户号码
org.apache.axis.types.URI targetURL,     //WAP PUSH地址
java.lang.String senderAddress, //发送方地址
                                                                               57
浙江电信移动业务接入实践


java.lang.String subject, //WAP PUSH标题
cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.MessagePriority priority,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest
) throws java.rmi.RemoteException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException;
说明:这是实际发送 WAP Push 的方法,多数参数与发送短信类似。

其中 targetURL 表示推送给用户的 Web 地址

   subject 表示 wap push 的标题,也就是 wap push 的正文

同样该函数还会返回一个 String 字段表示的 requestIdentifier 用以说明这条 Wap Push 的标识


public cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.DeliveryInformation[]
getMessageDeliveryStatus(java.lang.String requestIdentifier) throws
java.rmi.RemoteException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException,
cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException;
说明:发送结果查询


3.6 WAP Push 状态报告接口开发

   Wap Push 状态报告接收接口 ,SP 侧的软件是作为 Web Service Server,而 ISAG 作为
Client,所以我们这里需要生成发送接口的服务器端软件。
    方法非常简单,选中 wsdl 目录下的 cc_a_uhntfcto_evc__.sl
                        tcwpps_oiiainsrie10wd
 文件,按右键选择 WbSrie-Gnrt Jv ba seeo。
           e evcs>eeae aa en kltn




 生成以后,在 Poet xlr 项目的 Jv Rsucssc
         rjc Epoe     aa eore:r 分项里面会看到如下文件:




                                                                                 58
浙江电信移动业务接入实践




MessageNotificationBindingImpl.java 是我们需要完成的代码。代码如下:
package cn.com.chinatelecom.www.wsdl.ctcc.wap_push.notification.v1_0.service;


import java.io.FileWriter;
import java.io.IOException;


public class MessageNotificationBindingImpl
implements
cn.com.chinatelecom.www.wsdl.ctcc.wap_push.notification.v1_0._interface.MessageNotification
{
    public void notifyMessageDeliveryReceipt(
             java.lang.String correlator,
             cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.DeliveryInformation
deliveryStatus)
             throws java.rmi.RemoteException {
        try {
             FileWriter fw = new FileWriter("c:wappushdeliver.log");
             fw.write("correlator:" + correlator);
             fw.write("Address:" + deliveryStatus.getAddress());
             fw.write("DeliveryStatus:" + deliveryStatus.getStatus());
             fw.close();
        } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
        }


    }


}


    绿底部分会在自动生成代码基础上增加的代码,作用是将短信上行写到文件
c:sms.log,状态报告写在:c: wappushdeliver.log。当然实际的程序远比这个复杂,或者
入库或者触发相应的程序。
    代码完成后,由于接收上行消息和接收状态报告是Web Service服务端程序,需要部署
到Web服务器上;因此需要生成war文件,方法如下,选中wappush项目,按右键选择
                                                                             59
浙江电信移动业务接入实践



Export->WAR file,生成的文件拷贝到Tomcat安装目录的webapps目录下,tomcat会自动部
署该文件。




  以上是WAP Push的开发文档,相关报文数据可以参考附件二。




                                                        60
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513
浙江电信移动业务接入实践20100513

Weitere ähnliche Inhalte

Was ist angesagt?

102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授
102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授
102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授文化大學
 
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.033120160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331liu sheng
 
Gps Guide L3
Gps Guide L3Gps Guide L3
Gps Guide L3Nasir
 
J Boss+J Bpm+J Pdl用户开发手册 3.2.3
J Boss+J Bpm+J Pdl用户开发手册 3.2.3J Boss+J Bpm+J Pdl用户开发手册 3.2.3
J Boss+J Bpm+J Pdl用户开发手册 3.2.3yiditushe
 
20150211支付清算协会分布式架构研究与设计参考 v1.0.0211
20150211支付清算协会分布式架构研究与设计参考 v1.0.021120150211支付清算协会分布式架构研究与设计参考 v1.0.0211
20150211支付清算协会分布式架构研究与设计参考 v1.0.0211liu sheng
 
20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc
20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc
20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.docliu sheng
 
20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版
20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版
20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版liu sheng
 
2006 年中国博客调查报告
2006 年中国博客调查报告2006 年中国博客调查报告
2006 年中国博客调查报告sugeladi
 
Think php3.0 完全开发手册
Think php3.0 完全开发手册Think php3.0 完全开发手册
Think php3.0 完全开发手册qianhuazhu
 
商业之星使用手册
商业之星使用手册商业之星使用手册
商业之星使用手册guest165649
 
Moodle種子師資培訓課程講義(2009v1)
Moodle種子師資培訓課程講義(2009v1)Moodle種子師資培訓課程講義(2009v1)
Moodle種子師資培訓課程講義(2009v1)Jainan O
 
Cloudsnetworking
CloudsnetworkingCloudsnetworking
Cloudsnetworkingdrewz lin
 
证券基金求职大礼包
证券基金求职大礼包证券基金求职大礼包
证券基金求职大礼包airy6548
 
Spring从入门到精通
Spring从入门到精通Spring从入门到精通
Spring从入门到精通yiditushe
 
程式人雜誌 -- 2013 年 1 月 (創刊號)
程式人雜誌 -- 2013 年 1 月 (創刊號)程式人雜誌 -- 2013 年 1 月 (創刊號)
程式人雜誌 -- 2013 年 1 月 (創刊號)鍾誠 陳鍾誠
 
深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)colderboy17
 
2013 非營利組織《科技為善》趨勢統整電子書
2013 非營利組織《科技為善》趨勢統整電子書2013 非營利組織《科技為善》趨勢統整電子書
2013 非營利組織《科技為善》趨勢統整電子書開拓文教基金會
 

Was ist angesagt? (20)

102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授
102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授
102年產業人才投資計畫作業手冊(101.9.13)1 詹翔霖教授
 
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.033120160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331
 
2010年中国中小企业网络营销使用状况调查报告
2010年中国中小企业网络营销使用状况调查报告2010年中国中小企业网络营销使用状况调查报告
2010年中国中小企业网络营销使用状况调查报告
 
Gps Guide L3
Gps Guide L3Gps Guide L3
Gps Guide L3
 
J Boss+J Bpm+J Pdl用户开发手册 3.2.3
J Boss+J Bpm+J Pdl用户开发手册 3.2.3J Boss+J Bpm+J Pdl用户开发手册 3.2.3
J Boss+J Bpm+J Pdl用户开发手册 3.2.3
 
20150211支付清算协会分布式架构研究与设计参考 v1.0.0211
20150211支付清算协会分布式架构研究与设计参考 v1.0.021120150211支付清算协会分布式架构研究与设计参考 v1.0.0211
20150211支付清算协会分布式架构研究与设计参考 v1.0.0211
 
20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc
20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc
20141204支付清算行业分布式系统架构设计研究报告(草案)联动优势刘胜.doc
 
微積分
微積分微積分
微積分
 
20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版
20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版
20150820支付清算协会分布式架构研究与设计参考 v2.0820正式版
 
Dwz user-guide
Dwz user-guideDwz user-guide
Dwz user-guide
 
2006 年中国博客调查报告
2006 年中国博客调查报告2006 年中国博客调查报告
2006 年中国博客调查报告
 
Think php3.0 完全开发手册
Think php3.0 完全开发手册Think php3.0 完全开发手册
Think php3.0 完全开发手册
 
商业之星使用手册
商业之星使用手册商业之星使用手册
商业之星使用手册
 
Moodle種子師資培訓課程講義(2009v1)
Moodle種子師資培訓課程講義(2009v1)Moodle種子師資培訓課程講義(2009v1)
Moodle種子師資培訓課程講義(2009v1)
 
Cloudsnetworking
CloudsnetworkingCloudsnetworking
Cloudsnetworking
 
证券基金求职大礼包
证券基金求职大礼包证券基金求职大礼包
证券基金求职大礼包
 
Spring从入门到精通
Spring从入门到精通Spring从入门到精通
Spring从入门到精通
 
程式人雜誌 -- 2013 年 1 月 (創刊號)
程式人雜誌 -- 2013 年 1 月 (創刊號)程式人雜誌 -- 2013 年 1 月 (創刊號)
程式人雜誌 -- 2013 年 1 月 (創刊號)
 
深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)
 
2013 非營利組織《科技為善》趨勢統整電子書
2013 非營利組織《科技為善》趨勢統整電子書2013 非營利組織《科技為善》趨勢統整電子書
2013 非營利組織《科技為善》趨勢統整電子書
 

Ähnlich wie 浙江电信移动业务接入实践20100513

深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护colderboy17
 
Mongo db实战
Mongo db实战Mongo db实战
Mongo db实战Roger Xia
 
条码公司调查取样2010 1 30
条码公司调查取样2010 1 30条码公司调查取样2010 1 30
条码公司调查取样2010 1 30changeself
 
中国移动互联网发展状况调查报告
中国移动互联网发展状况调查报告中国移动互联网发展状况调查报告
中国移动互联网发展状况调查报告bihaizhou
 
51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册poker mr
 
飞机订票系统详细规格说明书
飞机订票系统详细规格说明书飞机订票系统详细规格说明书
飞机订票系统详细规格说明书yiditushe
 
Back track中文指南v9
Back track中文指南v9 Back track中文指南v9
Back track中文指南v9 o0tao
 
行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授
行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授
行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授文化大學
 
創業補助 創業天使計畫-詹翔霖顧問
創業補助 創業天使計畫-詹翔霖顧問創業補助 創業天使計畫-詹翔霖顧問
創業補助 創業天使計畫-詹翔霖顧問文化大學
 
Biee 入门讲座
Biee 入门讲座Biee 入门讲座
Biee 入门讲座Hero Art
 
971230建築能源管理(bems)節能手冊
971230建築能源管理(bems)節能手冊971230建築能源管理(bems)節能手冊
971230建築能源管理(bems)節能手冊jbcinvest
 
BMI商業模式創新研析報告
BMI商業模式創新研析報告BMI商業模式創新研析報告
BMI商業模式創新研析報告基欽 劉
 
Pl sql developer7.0用户指南
Pl sql developer7.0用户指南Pl sql developer7.0用户指南
Pl sql developer7.0用户指南irons_zhou
 
Memcached
MemcachedMemcached
Memcachedfeizone
 
Memcached
MemcachedMemcached
Memcachednowise
 
Memcached全面剖析
Memcached全面剖析Memcached全面剖析
Memcached全面剖析chen vivian
 
Lucene 原理与代码分析完整版
Lucene 原理与代码分析完整版Lucene 原理与代码分析完整版
Lucene 原理与代码分析完整版山城 碧海
 
創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師
創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師
創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師文化大學
 

Ähnlich wie 浙江电信移动业务接入实践20100513 (20)

深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护
 
Mongo db实战
Mongo db实战Mongo db实战
Mongo db实战
 
条码公司调查取样2010 1 30
条码公司调查取样2010 1 30条码公司调查取样2010 1 30
条码公司调查取样2010 1 30
 
中国移动互联网发展状况调查报告
中国移动互联网发展状况调查报告中国移动互联网发展状况调查报告
中国移动互联网发展状况调查报告
 
51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册
 
飞机订票系统详细规格说明书
飞机订票系统详细规格说明书飞机订票系统详细规格说明书
飞机订票系统详细规格说明书
 
Back track中文指南v9
Back track中文指南v9 Back track中文指南v9
Back track中文指南v9
 
行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授
行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授
行政院國家發展基金創業天使計畫申請須知完整版(含附件) -詹翔霖教授
 
創業補助 創業天使計畫-詹翔霖顧問
創業補助 創業天使計畫-詹翔霖顧問創業補助 創業天使計畫-詹翔霖顧問
創業補助 創業天使計畫-詹翔霖顧問
 
Biee 入门讲座
Biee 入门讲座Biee 入门讲座
Biee 入门讲座
 
971230建築能源管理(bems)節能手冊
971230建築能源管理(bems)節能手冊971230建築能源管理(bems)節能手冊
971230建築能源管理(bems)節能手冊
 
BMI商業模式創新研析報告
BMI商業模式創新研析報告BMI商業模式創新研析報告
BMI商業模式創新研析報告
 
Pl sql developer7.0用户指南
Pl sql developer7.0用户指南Pl sql developer7.0用户指南
Pl sql developer7.0用户指南
 
Memcached
MemcachedMemcached
Memcached
 
Memcached
MemcachedMemcached
Memcached
 
Memcached
MemcachedMemcached
Memcached
 
Memcached全面剖析
Memcached全面剖析Memcached全面剖析
Memcached全面剖析
 
Lucene 原理与代码分析完整版
Lucene 原理与代码分析完整版Lucene 原理与代码分析完整版
Lucene 原理与代码分析完整版
 
創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師
創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師
創新創業 大學校院創業實戰模擬習平臺-詹翔霖老師
 
Direct show
Direct showDirect show
Direct show
 

Mehr von Bob Huang

Gsm 03-42 v300
Gsm 03-42 v300Gsm 03-42 v300
Gsm 03-42 v300Bob Huang
 
Oracle 经验操作
Oracle 经验操作Oracle 经验操作
Oracle 经验操作Bob Huang
 
Cap信令原理
Cap信令原理Cap信令原理
Cap信令原理Bob Huang
 
Gsm智能网原理
Gsm智能网原理Gsm智能网原理
Gsm智能网原理Bob Huang
 
移动智能应答业务
移动智能应答业务移动智能应答业务
移动智能应答业务Bob Huang
 
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01Bob Huang
 
高性能网站建设指南
高性能网站建设指南高性能网站建设指南
高性能网站建设指南Bob Huang
 
百度排名优化方法及注意事项
百度排名优化方法及注意事项百度排名优化方法及注意事项
百度排名优化方法及注意事项Bob Huang
 
Random 101214055524-phpapp01
Random 101214055524-phpapp01Random 101214055524-phpapp01
Random 101214055524-phpapp01Bob Huang
 
Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01Bob Huang
 
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01Bob Huang
 
201001 100208094620-phpapp01
201001 100208094620-phpapp01201001 100208094620-phpapp01
201001 100208094620-phpapp01Bob Huang
 
Mysql gdb-101022041146-phpapp01
Mysql gdb-101022041146-phpapp01Mysql gdb-101022041146-phpapp01
Mysql gdb-101022041146-phpapp01Bob Huang
 

Mehr von Bob Huang (15)

Gsm 03-42 v300
Gsm 03-42 v300Gsm 03-42 v300
Gsm 03-42 v300
 
Gsm 04.08
Gsm 04.08Gsm 04.08
Gsm 04.08
 
Oracle 经验操作
Oracle 经验操作Oracle 经验操作
Oracle 经验操作
 
Vpmn业务
Vpmn业务Vpmn业务
Vpmn业务
 
Cap信令原理
Cap信令原理Cap信令原理
Cap信令原理
 
Gsm智能网原理
Gsm智能网原理Gsm智能网原理
Gsm智能网原理
 
移动智能应答业务
移动智能应答业务移动智能应答业务
移动智能应答业务
 
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
 
高性能网站建设指南
高性能网站建设指南高性能网站建设指南
高性能网站建设指南
 
百度排名优化方法及注意事项
百度排名优化方法及注意事项百度排名优化方法及注意事项
百度排名优化方法及注意事项
 
Random 101214055524-phpapp01
Random 101214055524-phpapp01Random 101214055524-phpapp01
Random 101214055524-phpapp01
 
Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01
 
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
Introduction to-taobao-cdn-at-linuxfb-v0-2-100620101417-phpapp01
 
201001 100208094620-phpapp01
201001 100208094620-phpapp01201001 100208094620-phpapp01
201001 100208094620-phpapp01
 
Mysql gdb-101022041146-phpapp01
Mysql gdb-101022041146-phpapp01Mysql gdb-101022041146-phpapp01
Mysql gdb-101022041146-phpapp01
 

浙江电信移动业务接入实践20100513

  • 1. 浙江电信移动业务接入实践 浙江电信移动业务接入实践 浙江电信互联网与信息事业部 林路 21-51 000-3 1
  • 2. 浙江电信移动业务接入实践 目录 一. ISAG 接入篇 ............................................................................................................................................... 4 1. ISAG 简介 .......................................................................................................................................... 4 1.1 ISAG 在电信网络里面的位置 ........................................................................................................... 6 1.2 ISAG 与 WEB SERVICE 技术 ........................................................................................................... 6 1.3 开发环境搭建...................................................................................................................................... 7 1.3.1 安装 JDK ................................................................................................................................. 7 1.3.2 下载安装 ECLIPSE .................................................................................................................. 7 1.3.3 安装 WTP 模块 ....................................................................................................................... 8 1.3.4 安装 Tomcat ............................................................................................................................. 9 1.3.5 ISAG 接口相关通用参数及说明........................................................................................... 10 2. SMS...................................................................................................................................................... 13 2.1 短信接口开发环境搭建 ............................................................................................................ 13 2.2 SendSMS 短信发送接口开发 ................................................................................................... 19 2.3 SendSMS 短信上行,回执接口开发 ....................................................................................... 39 3. WAP PUSH .......................................................................................................................................... 46 3.1 WAP PUSH 简介 .................................................................................................................... 46 3.2 WAP PUSH 网络结构和业务实现 ........................................................................................ 46 3.3 WAP PUSH 是什么?WAP PUSH 不是什么? .................................................................... 48 3.4 WAP Push 接口开发环境搭建 .................................................................................................. 49 3.5 WAP Push 发送接口开发 .......................................................................................................... 53 3.6 WAP Push 状态报告接口开发 ................................................................................................. 58 4. 彩信................................................................................................................................................. 61 4.1 彩信的构成................................................................................................................................ 61 4.2 彩信在电信网络里面的网络结构 ........................................................................................... 62 4.3 彩信开发接口开发环境搭建 ................................................................................................... 63 彩信发送接口开发.......................................................................................................................... 69 45彩信上行.................................................................................................................................. 81 . 5.1 TcpMon 使用 ............................................................................................................................. 94 5.2 Web Services Explorer ............................................................................................................... 98 附录一: SendSms 短信发送接口报文数据: ..................................................................................... 100 1.1 请求(SP 发起):...................................................................................................................... 100 2.2 应答(ISAG 应答) ............................................................................................................... 101 附录二: WAP PUSH 发送报文数据: ................................................................................................ 102 1.1 请求(SP 发起):...................................................................................................................... 102 2.2 应答(ISAG 应答) ............................................................................................................... 103 附录三: SendMessage 彩信发送接口报文数据: .............................................................................. 104 1.1 请求(SP 发起):...................................................................................................................... 104 1.2 ISAG 响应 ............................................................................................................................... 106 二. 与 ISMP 接口实现 ................................................................................................................................. 107 1.ISMP 简介 .......................................................................................................................................... 107 1.1 与 ISMP 相关的术语 ...................................................................................................................... 107 2.业务流程............................................................................................................................................. 109 2
  • 3. 浙江电信移动业务接入实践 2.1 点播业务流程.......................................................................................................................... 109 2.2 包月业务流程.......................................................................................................................... 110 3. ISMP 接口开发环境搭建 ................................................................................................................. 111 4. 订购关系同步 orderRelationUpdateNotify 方法实现 ..................................................................... 117 5. 管理信息同步 notifyManagementInfo 方法实现 ............................................................................ 122 6. 服务使用通知接口 serviceConsumeNotify 方法实现 .................................................................... 124 7.反向取消接口 spWithdrawSubscription 接口实现 ........................................................................... 126 8. 程序部署........................................................................................................................................... 129 9. 接口测试........................................................................................................................................... 131 三.WAP 业务开发 ...................................................................................................................................... 135 1 WAP 业务简介 ................................................................................................................................... 135 1.1 WAP 业务的网络结构 ............................................................................................................ 136 1.2 WAP 业务实现原理 ................................................................................................................ 137 2 点播实现............................................................................................................................................ 140 3 包月实现............................................................................................................................................ 142 4. WAP 1.0 还是 WAP 2.0 ..................................................................................................................... 144 5.UA 适配 .............................................................................................................................................. 145 6.WAP 业务测试 .................................................................................................................................. 147 四. 短信网关 SMGP 接入篇 ........................................................................................................................ 150 1. 短信网关接口协议 SMGP 概述 ...................................................................................................... 150 2. SMGP 封包结构................................................................................................................................ 151 3. SMGP 相关术语解释 ........................................................................................................................ 154 4. 封包拼装和解析............................................................................................................................... 155 4.1 登录请求相关封包:Login,Login_Resp ................................................................................ 156 4.2 发送短信相关封包:Submit,Submit_Resp ............................................................................ 158 4.3 上行短信相关封包:Deliver,Deliver_Resp ......................................................................... 158 4.4 退出请求相关封包:Exit,Exit_Resp..................................................................................... 158 4.5 TLV 字段封装 ...................................................................................................................... 158 五. 关于本文档............................................................................................................................................. 159 3
  • 4. 浙江电信移动业务接入实践 一. ISAG 接入篇 1. ISAG 简介 关于 IA 是啥,我们直接看下百度百科上的说明,这个很好诠释了什么是 IA: SG SG IA 综合业务接入网关,英文全称为 Itgae SrieAcs Gtwy SG nertd evc ces aea。 中国电信的综合业务接入网关(IA)将为应用提供符合国际标准的 Pra X. 接口,并对该接 SG aly 20 口作了适当增强,为应用提供更为丰富的业务能力,采用开放的综合业务接入架构的 IA 具有以下 SG 优点: 1 采用了统一的符合国际标准的接口,业务可以多网移植或跨网运行。基于这种业务接入架构, . 一个应用可以使用来自多种网络(H、PT、3 和 SP等) PS SN G I 的能力,形成融合的业务应用。 2 采用统一的业务接入、安全认证及控制机制,与 IM 平台有机地结合起来,便于业务的统一 . SP 管理、统一计费,有效保护电信核心网络资源及运营商的利益; 3 由于 PRA X是基于 XL的开放接口, . ALY M 不依赖于任何专门的电信协议,这使得数量巨大的 IT 业软件开发者也可以开发电信业务,真正实现电信增值业务与 Itre 业务的融合; nent 4 由于采用了标准的、简单的开放接口,使得业务开发周期缩短,开发成本降低; . 5 简化了组合业务的开发及计费工作; . 6 运营商可以非常灵活地对业务接入平台所提供的业务能力进行组合,为应用提供组合的业务能 . 力,进一步简化组合业务的开发。 IA 是移动业务网络中实现业务统一接入和服务质量监控的功能实体。 SG 使运营商能够开放电信网络 资源,并控制对网络资源的使用;为 C/P PS 屏蔽底层网络技术复杂性,提供统一业务开发环境,降低 业务开发门槛;为用户提供融合业务,丰富业务形式,有利于开发企业应用,拓展企业用户市场。 IA 在业务网络中主要功能为: SG IA 屏蔽了底层网络的复杂性,实现对移动数据、移动语音、PS SG H 业务的业务能力高度抽象,封装 成开放、统一、标准应用开发接口提供给 C/P PS,支持电信自营增值业务、第三方 C/P PS 增值业务及 企业应用的接入;为 C/P PS 提供统一的增值应用集成开发和测试环境;协同 IM 完成业务应用过程 SP 中认证、鉴权、计费和管理等功能;实现组合业务计费;对业务流进行质量监控和内容安全控制。 4
  • 5. 浙江电信移动业务接入实践 以上已经很好的诠释了什么是 IA, SG在移动业务接入的初期,业务的承载模式基本上 以短信为主,S 如需接入运营商的平台,应根据运营商短信网关的接口协议:CP( P MP中国 移动) GP ,SI(中国联通) MP ,SG(中国电信)直接接入短信网关,同时与短信管理平台 实现订购关系同步计费等接口。这些协议从某种意义上是平台的私有接口。 而现有的移动增值业务已经不仅仅是短信。如果 SP需要接入彩信业务,需要与彩信 接入网关实现 M7 M 协议;如果需要接入 WP UH A PS 业务需要与 PGPS 代理网关) P(UH 实现 PP A 协议;如果需要实现定位业务,还需要与运营商的定位系统进行对接。我们可以看到的 是,这些接口的实现方式完全不同,这给 S 接入增值业务带来了很大的难度和困惑。 P 为了解决这个问题,各运营商希望能够屏蔽各个接口的私有协议,而采用标准的协 议进行统一接入。而 SA的盛行,使得 WBSRIE成为统一接入最好的承载模式。而 O E EVC 19 年一个由 65 家通信和 IT 领域的公司共同参与的非盈利性 组织, 99 提出了 Pra/S alyOA 应用程序接口规范,并且发布了多个版本,其中包括: 1 Pra 5-20..1 ) aly 0541 2 Pra 4-20.. ) aly 0538 3 Pra XWbSrie Seiiain Vrin20-20. ) aly e evcs pcfcto, eso . 053 4 Pra XWbSrie Seiiain Vrin101-20. ) aly e evcs pcfcto, eso .. 046 5 Pra XWbSrie Seiiain Vrin10 -20. ) aly e evcs pcfcto, eso .. 034 而中国电信选取了 Pra X e Srie Seiiain Vrin . 作为了 IA aly Wb evcs pcfcto, eso 20 SG 的标准规范。 5
  • 6. 浙江电信移动业务接入实践 1.1 ISAG 在电信网络里面的位置 紫色箭头为 SP 需要实现的接口,在整个体系中,SP 与 ISAG 通过不同的 Web Services 接口实现 短信,彩信,WAP 的业务接入,ISAG 将收到的 Web Service 请求转换成各引擎相应的接口,与短信 网关采用 SMGP 协议,与 PPG 采用 PAP 协议,与彩信中心实现 MM7 协议,与定位系统采用 MLP 协 议。同时 SP 还需要与 ISMP 实现接口,实现订购关系的同步。 通过上图可以看出,由于 ISAG 的引入,SP 侧只需要按照规范实现 Web Services 接口即可,而不 需要再跟具体的协议比如 SMGP,PAP,MM7 打交道。 1.2 ISAG 与 WEB SERVICE 技术 这里不再详细讲解什么是 WBSRIE E EVC,如果你对 WBSRIE E EVC 缺乏了解,可以参考 相应的书籍或者拜 Gol 为老师。 oge 简单对象访问协议(OP是 WBSRIE承载的协议,这里需要说明的你的程序与 SA) E EVC IA 进行交互的时候需要设置 SA HAE 进行相关鉴权信息的传送,而某些接口(比 SG OP EDR 如彩信)还需要你的 WBSRIE E EVC 程序支持附件。 目前 AI XS是目前应用最广的 WBSRIE的引擎,对于上述的两项都能够很好的支 E EVC 持,所以以下涉及到开发的例子我们会使用它作为我们开发的引擎。简单说下 AI, XS XS AI 是 Aah Etnil Itrcin ytm pce xesbe neato Sse 的英文缩写,意为:阿帕奇可扩展交互系统。 6
  • 7. 浙江电信移动业务接入实践 他是 AAH 基金会的一个开源项目,Ai 本质上就是一个 SA 引擎,提供创建服务器 PCE xs OP 端、客户端和网关 SA 操作的基本框架。Ai 目前版本是为 Jv 编写的。 OP xs aa 当然同样 ELPE CIS 是目前最广泛应用的 JV 开发工具。 Elpe AA cis 最初是由 IM B 公司 开发的替代商业软件 Vsa AefrJv 的下一代 IE iul g o aa D 开发环境,20 年 1 月贡献给 01 1 开源社区,现在它由非营利软件供应商联盟 Elpe基金会(ElpeFudto)管 cis cis onain 理。 整个教程将会以 JV 作为开发语言,以 Elpe AA cis 作为开发工具,AI 作为 SA 引擎 XS OP 进行讲解如何进行 IA 的接口开发。如果你习惯使用微软的.E 进行开发;非常抱歉, SG NT 本人虽然不是反微软的斗士,但是对于微软的东西有种天生的莫名的排斥,虽然我的笔 记本也安装着 Wnos idw 操作系统,但是对于微软的开发工具一窍不通。 1.3 开发环境搭建 1.3.1 安装 JDK 需要使用 JV AA开发,必然需要安装 JK目前 JK常用的版本有 13 .、15以及 D, D .、14 . 16 13 14 .。 . 和 . 版本目前已经很少使用,至于 15 . 还是 16 . 需要你根据你服务器上的 JP S 引擎的 jv 版本进行匹配安装。 aa JK D 的下载地址:ht:/aasncm tp/jv.u.o 1.3.2 下载安装 ECLIPSE Elpe可以在 ht:/w.cis.r 上下载,elpe因为不仅仅是一个 JV cis tp/wwelpeog cis AA 开发工具,所以他有多个版本,我们需要下载的是 ElpeIEfrJv E Dvlpr cis D o aa E eeoes 版本,如果下载的是企业版,因为其自带了 WP模块,忽略下面步骤 143安装 WP模 T .. T 块。 当然你也可以选择 ElpeIEfrJv Dvlpr 版本,如果选择该版本需要根 cis D o aa eeoes 据 143 .. 安装 WP T 模块。 7
  • 8. 浙江电信移动业务接入实践 Elpe cis 下载以后解压缩到某一目录,然后运行 elpeee cis.x 即可。 1.3.3 安装 WTP 模块 注:如果选择安装了 ElpeIEfrJv E Dvlpr 版本,忽略该步骤。 cis D o aa E eeoes WP 是 Wb Tos Pafr T e ol ltom的缩写,顾名思义是 Wb工具包,其官方网站是 e ht:/w.cis.r/etos,同样他跟 Elpe tp/wwelpeogwbol/ cis 一样是个 Fe 的软件。 re 先安装好 elpeIEfrjv, cis D o aa运行 Elpe然后菜单选择 hl-IsalNw cis, ep>ntl e Sfwr, Wr Wt 输入: otae在 ok ih ht:/onodelpeogwbol/pae/ tp/dwla.cis.r/etosudts 选中上述项目以后,点击 Nx。稍等片刻就会完成 WP et T 模块的安装。 8
  • 9. 浙江电信移动业务接入实践 1.3.4 安装 Tomcat 由于接口需要建立一个 Wb Srie进行发送结果的接受,需要开发相应的 Wb e evc e Srie evr evc Sre 程序,另外与 IM 的订购关系同步也需要开发相应的服务端软件,我们 SP 需要一个能够运行 WbSrie Wb e evc 的 e 服务器,Tma 是目前常用的 Jp oct s 服务器,当然 你可以其他的 JP S 引擎,比如 RsnWbpee ei,eShr 等,考虑到 Tma 是免费的, oct 容易获得, 所以我们下面的例子都会以 Tma 为例。 oct Tma 的官方网站是:ht:/octaah.r/ oct tp/tma.pceog,你可以到网站上下载 55 . 或者 60 . 版本。 如果你下载的是 Zp i 方式,安装与 Elpe cis 类似,解压缩到某个目录下即可, 当然你也可以选择 WnosSrieIsalr idw evc ntle 的文件包,下载后直接安装。 安装以后,在 tma 的安装目录有如下目录。 oct 其中: 目录 bn tma 的运行目录,运行该目录下的 satpbt即可启动 Tma i 是 oct tru.a oct 目录 wbps eap 是应用程序部署的目录,程序完成开发以后需要将文件部署到该目录 下。 其他目录的作用请参考相关资料,这里不再详述。 9
  • 10. 浙江电信移动业务接入实践 1.3.5 ISAG 接口相关通用参数及说明 在讲解具体的 ISAG 接口前,我们需要将 ISAG 的接口进行相关概要的说明。 在与 ISAG 进行交互的时候,Web Service 相关的程序都需要设置 SOAP HEADER,负责接口间鉴权 的实现。 SOAP HEADER 需要包含以下参数: 参数名 类型 描述 spid String SP 编号,这个编号是 8 位,比如浙江电信接入 的应该是 121XXXXXXX 这样的数字,其中 12 表示浙江,第三位的 1 表示 CDMA 的 SP spPassword String SP 密码(MD5 加密) MD5 加密算法如下: SP 密码=SPID+密钥+时间戳 密钥部分由 ISMP 分配,你在申请业务能力的 时候填写的密钥。 时间戳, SP 端生成, 由 格式:MMDDHHMMSS, 月日时分秒 timeStamp String 时间戳, SP 端生成, 由 格式:MMDDHHMMSS, 月日时分秒,要与上面加密用的密钥一致。 productId String 产品编号 SAN String 业务接入码,可选 transactionId String 业务流水号;可选 transEnd EndReason 交易技术标识,用户组和业务。可选 linkID String 事务关联 ID,用户点播业务 OA anyURI 业务订购地址。群发时不填 FA anyURI 付费地址。可选 Multi-cast Messaging Boolean True:群发 False:非群发 缺省为 false 10
  • 11. 浙江电信移动业务接入实践 程序中还会用到 anyURI 的类型,如果该类型标识用户号码的时候需要加上”tel:”,以说 明是电话号码,比如 18905718888 这个号码,anyURI 表示应该为 tel:+8618905718888。 另外用到的 MD5 加密,加密完成后需要转换成 16 进制表示的字串,我们需要增加一 个加密的类,代码如下: package cn.com.chinatelecom.util; import java.security.*; public class MD5 { private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; /** * 转换字节数组为16进制字串 * @param b 字节数组 * @return 16进制字串 */ public static String byteArrayToHexString(byte[] b) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) { resultSb.append(byteToHexString(b[i])); } return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n = 256 + n; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String compile(String origin) { String resultString = null; try { resultString=new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); 11
  • 12. 浙江电信移动业务接入实践 resultString=byteArrayToHexString(md.digest(resultString.getBytes())); } catch (Exception ex) { } return resultString; } } 这样的话我们就可以使用 MD5.compile(“SPID”+”密钥”+”时间戳”) 进行 spPassword 的数 据生成。 12
  • 13. 浙江电信移动业务接入实践 2. SMS 特别说明:目前短信业务接入有两种模式,一种是 IM+ SP短信网关,短信接入采用 SG MP 30 . 协议;一种是 IM+SG SPIA 方式接入,短信的接入采用 Wb evc。 e Srie 目前由于浙江 IA SG 的能力有限,所以浙江电信的短信业务是采用 IM+ SP短信网关方式,该方式不在这里讲述。 因为短信也是 IA SG的一个接入的一个基本功能,而且相对 WPPS A UH和彩信接口比 较简单,接口与彩信和 WPPS A UH相近,理解 IA SG短信接入的接口协议也有利于了解整 个 IA 的接口协议。所以这里还是就 IA 接入短信业务进行讲解。 SG SG 2.1 短信接口开发环境搭建 与 IA 相关的短信接口,需要实现 3 SG 个接口: 接口名称 接口方法 作用 谁是服务器端 SendSMS sendSms 发送短信 sendSmsLogo 发送图标 sendSmsRingtone 发送铃声 ISAG getSmsDeliverStatus 查询发送状态 SmsNotifactionService notifySmsReception 接受上行消息 SP 端程序 notifySmsDeliveryReception 接收状态报告 需要注意接口谁作为服务器端,谁作为客户端。这个开发的时候有很大的区别。 1)新建项目 如下图,新建一个项目,项目选择类型为:DnmcWbPoet 我们这里将这个项目 yai e rjc, 命名为 ss可以根据自己喜好确定) m( 。 13
  • 15. 浙江电信移动业务接入实践 我本机上安装的是 tma 55所以我在 Tre rnie oct ., agt utm 选择了它。 点击确认以后,我们会在 PoetEpoe 看到如下目录。 rjc xlrr 2)导入 WD SL 15
  • 16. 浙江电信移动业务接入实践 与短信接入相关的 wd 文件有如下: sl 与 IA 接口相关的 wd SG sl cc_m_ye__.s tcsstps21xd cc_m_edsrie21wd tcsssn_evc__.sl cc_m_editrae21wd tcsssn_nefc__.sl cc_m_eev_evc__.sl tcssrciesrie21wd cc_m_eev_nefc__.sl tcssrcieitrae21wd cc_m_oiiainsrie21wd tcssntfcto_evc__.sl cc_m_oiiainitrae21wd tcssntfcto_nefc__.sl cc_omntps21xd tccmo_ye__.s cc_omnfut__.sl tccmo_als20wd 与 IM 相关的 wd SP sl ImSEgn.sl sppniewd 为了区分其他程序的文件,我们为 wd sl新建一个目录,在 ss的项目按右键选择 m Nw>odr e-Fle,我们将这个目录起名为 wd。 sl 选中 wd 目录,按右键选择 Ipr。 sl mot 16
  • 17. 浙江电信移动业务接入实践 在 Import 的对话框选择 General->File System 找到你本机上 WSDL 的存放目录 17
  • 18. 浙江电信移动业务接入实践 选择我们需要的 WSDL 文件,然后点击 Finish,至此我们需要的 wsdl 文件就已经导入进 来。可能部分开发人员习惯新建一个 Web Service,然后指定相应的 wsdl 文件进行生成, 但由于 ISAG 的接口协议由多个描述文件构成,如果这样的方式很容易导致 Web Service 生成的时候提示语法不对,或者缺少相应描述文件。 18
  • 19. 浙江电信移动业务接入实践 2.2 SendSMS 短信发送接口开发 短信发送的接口过程中,SP 侧的软件是作为 Web Service Client,而 ISAG 作为 Server, 所以我们这里需要生成发送接口的客户端软件。 方法非常简单,选中 wsdl 目录下的 cc_m_edsrie21wd 文件,按右键 tcsssn_evc__.sl 选择 WbSrie-Gnrt Cin。 e evcs>eeae let 完成以后我们会看到 Java Resources:src 目录下有如下文件: 其中 SendSmsServiceLocator 就是我们需要发送短信的客户端软件。 19
  • 20. 浙江电信移动业务接入实践 我们再写个软件来测试下,新建一个 SendSmsTest 的类 代码如下: import java.math.BigDecimal; import java.net.MalformedURLException; import java.rmi.RemoteException; import java.text.SimpleDateFormat; import java.util.Date; import javax.xml.rpc.ServiceException; import javax.xml.soap.SOAPException; import org.apache.axis.message.SOAPHeaderElement; import org.apache.axis.types.URI.MalformedURIException; import cn.com.chinatelecom.util.MD5; import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation; import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException; import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference; import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsBindingStub; import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsServiceLocator; import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms; public class SendSmsTest { public static void main(String[] args) { String webserviceUrl = "isag接口地址,非wsdl地址"; String SPID = "SPID"; // SPID String Token = "密钥"; // 密钥 String DestNum = "tel:+86153XXXXXXXX"; // 发送号码 String ProductID = "21位的产品编号,1开头"; // 产品编号 String ServiceID = "21位的业务编号,2开头"; // 业务编号 String TimeStamp = dateString(); // 当前时间 String senderName = "10620000"; // 短信主叫号码,在浙江ISAG实际无效,ISAG会读 取业务部署时候的接入号 String message = "测试短信"; // 短信内容 20
  • 21. 浙江电信移动业务接入实践 SOAPHeaderElement SoapHeader = new SOAPHeaderElement( "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", "RequestSOAPHeader"); try { /* 初始化Web Service Client */ SendSmsServiceLocator ssl = new SendSmsServiceLocator(); SendSms sendSms = ssl.getSendSms(new java.net.URL(webserviceUrl)); /* 设置SOAP Header */ SoapHeader.addChildElement("spId").addTextNode(SPID); // SpID SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp); SoapHeader.addChildElement("spPassword").addTextNode( MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5加 密 SoapHeader.addChildElement("productId").addTextNode(ProductID); SoapHeader.addChildElement("OA").addTextNode(DestNum); SoapHeader.addChildElement("FA").addTextNode(DestNum); SoapHeader.addChildElement("multicastMessaging").addTextNode( "false"); // 是否群发 ((SendSmsBindingStub) sendSms).setHeader(SoapHeader); // 添加SOAP头 /* 设置被叫号码 */ org.apache.axis.types.URI[] addresses = new org.apache.axis.types.URI[1]; addresses[0] = new org.apache.axis.types.URI(DestNum); /* 设置ChargingInformation */ ChargingInformation charging = new ChargingInformation(); charging.setDescription("gm");// 描述 charging.setAmount(new BigDecimal(1));// 扣费数目 charging.setCode(ServiceID);// 业务代码 charging.setCurrency("0"); /* 设置SimpleReference */ SimpleReference receiptRequest = new SimpleReference(); receiptRequest.setCorrelator("1001559"); // 序号自己随机增加 receiptRequest.setInterfaceName("SmsNotificationService"); receiptRequest.setEndpoint(new org.apache.axis.types.URI( "http://开头的接收短信状态报告的webserivce地址,后续章节会讲")); /* 发送短信 */ String result = sendSms.sendSms(addresses, senderName, charging, 21
  • 22. 浙江电信移动业务接入实践 message, receiptRequest); System.out.println("result:" + result); }catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) { //鉴权失败 System.out.println("MessageId:" + e.getMessageId()); System.out.println("Text:" + e.getText()); String[] variables = e.getVariables(); for (int i = 0; i < variables.length; i++) { System.out.println("Variable:" + variables[i]); } } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException e) { System.out.println("MessageId:" + e.getMessageId()); System.out.println("Text:" + e.getText()); String[] variables = e.getVariables(); for (int i = 0; i < variables.length; i++) { System.out.println("Variable:" + variables[i]); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ServiceException e) { e.printStackTrace(); } catch (SOAPException e) { e.printStackTrace(); } catch (MalformedURIException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } private static String dateString() { SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss"); return sdf.format(new Date()); } } 22
  • 23. 浙江电信移动业务接入实践 注:红色部分请根据问题提示替换成你的实际数据。 我们来解释下这个程序,首先我们看下: 1)初始化 SendSmsServiceLocator a)类:SendSmsServiceLocator 说明: 他有如下方法: public SendSmsServiceLocator() 说明:构造函数 public SendSmsServiceLocator(org.apache.axis.EngineConfiguration config) 说 明 : 构 造 函 数 可 以 通 过 设 置 EngineConfiguration 的 方 式 , 构 造 一 个 SendSmsServiceLocator public SendSmsServiceLocator(java.lang.String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException 说明:构造函数,可以通过设置 wsdl 地址和 QName 来构造 Client public java.lang.String getSendSmsAddress() 说明:返回 SendSms 的接口地址 public java.lang.String getSendSmsWSDDServiceName() 说明:返回服务名称,这里固定返回 SendSms public void setSendSmsWSDDServiceName(java.lang.String name) 说明:设置服务名称 public cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms getSendSms() throws javax.xml.rpc.ServiceException 说明:返回发送短信接口方法。可以通过该方法得到一个实际可以发送短信的类 SendSms public cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms getSendSms(java.net.URL portAddress) throws javax.xml.rpc.ServiceException 说明:返回发送短信接口方法。可以通过该方法得到一个实际可以发送短信的类 SendSms public void setSendSmsEndpointAddress(java.lang.String address) 说明:设置服务器端 WebService 地址 23
  • 24. 浙江电信移动业务接入实践 public java.rmi.Remote getPort(Class serviceEndpointInterface) 说明:返回 Webservice 端口 public javax.xml.namespace.QName getServiceName() 说明:返回 QName 方式表示的服务名称 public java.util.Iterator getPorts() 说明:返回端口 public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException 说明:设置请求地址 public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) 说明:通过 QName 方式设置请求地址 b)类:SendSmsServiceLocator 使用 我们需要初始化一个SendSmsServiceLocator类,直接通过构造函数 public SendSmsServiceLocator() 构建,代码如下: SendSmsServiceLocator ssl = new SendSmsServiceLocator(); 由于提供给SP开发的WSDL文件里面,设定的WebService地址是: http://localhost:9080/SendSmsService/services/SendSms 所以需要根据实际请求地址设定WebService的调用地址,代码如下 : String webserviceUrl = "isag接口地址(非wsdl地址)"; SendSms sendSms = ssl.getSendSms(new java.net.URL(webserviceUrl)); 当然你可以直接修改SendSmsServiceLocator.java里面的代码: private java.lang.String SendSms_address = "http://localhost:9080/SendSmsService/services/SendSms"; 24
  • 25. 浙江电信移动业务接入实践 修改为 private java.lang.String SendSms_address = " isag接口地址(非 wsdl地址)"; 考虑到程序的通用性,建议在初始化服务的时候设置Web Service地址,而不是 直接修改SendSmsServiceLocator.java程序。 2)类 SendSMS 的使用 通过上述初始化,我们得到一个 SendSMS对象,他是我们发送短信实际需要的类,他 有如下方法: public java.lang.String sendSms( org.apache.axis.types.URI[] addresses, java.lang.String senderName, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging, java.lang.String message, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest ) throws java.rmi.RemoteException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException; 说明: org.apache.axis.types.URI[] addresses:接受方地址,由于这里是 URI 表示的,addresses 应 该为 new URI(“tel:+86 手机号码”) String senderName:String 类型,说明发送源地址号码 ChargingInformation charging:计费类型 String message:消息内容 SimpleReference receiptRequest:接口回调地址,也就是该短信的状态报告返回地址。 public java.lang.String sendSmsLogo( org.apache.axis.types.URI[] addresses, java.lang.String senderName, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging, byte[] image, cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest 25
  • 26. 浙江电信移动业务接入实践 ) throws java.rmi.RemoteException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException; 说明: org.apache.axis.types.URI[] addresses:接受方地址,由于这里是 URI 表示的,addresses 应 该为 new URI(“tel:+86 手机号码”) String senderName:String 类型,说明发送源地址号码 ChargingInformation charging:计费类型 String message:消息内容 byte[] image:图片数据 cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat:短信格式 SimpleReference receiptRequest:接口回调地址,也就是该短信的状态报告返回地址。 public java.lang.String sendSmsRingtone( org.apache.axis.types.URI[] addresses, java.lang.String senderName, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging, java.lang.String ringtone, cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest ) throws java.rmi.RemoteException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException; 说明: org.apache.axis.types.URI[] addresses:接受方地址,由于这里是 URI 表示的,addresses 应 该为 new URI(“tel:+86 手机号码”) String senderName:String 类型,说明发送源地址号码 ChargingInformation charging:计费类型 String message:消息内容 java.lang.String ringtone,:铃声数据 cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsFormat smsFormat:短信格式 26
  • 27. 浙江电信移动业务接入实践 SimpleReference receiptRequest:接口回调地址,也就是该短信的状态报告返回地址。 public cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.DeliveryInformation[] getSmsDeliveryStatus( java.lang.String requestIdentifier ) throws java.rmi.RemoteException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException; 说明:查询消息发送状态,requestIdentifier 为发送消息时候返回的字串。 我们这里需要调用的是 SendSms 方法 String DestNum = "tel:+86153XXXXXXXX"; // 发送号码 String ServiceID = "21位的业务编号,2开头"; // 业务编号 /* 设置被叫号码 */ org.apache.axis.types.URI[] addresses = new org.apache.axis.types.URI[1]; addresses[0] = new org.apache.axis.types.URI(DestNum); /* 设置ChargingInformation */ ChargingInformation charging = new ChargingInformation(); charging.setDescription("gm");// 描述 charging.setAmount(new BigDecimal(1));// 扣费数目 charging.setCode(ServiceID);// 业务代码 charging.setCurrency("0"); /* 设置SimpleReference */ SimpleReference receiptRequest = new SimpleReference(); receiptRequest.setCorrelator("1001559"); // 序号自己随机增加 receiptRequest.setInterfaceName("SmsNotificationService"); receiptRequest.setEndpoint(new org.apache.axis.types.URI( "http://开头的接收短信状态报告的webserivce地址,后续章节会讲")); /* 发送短信 */ String result = sendSms.sendSms(addresses, senderName, charging, message, receiptRequest); System.out.println("result:" + result); 27
  • 28. 浙江电信移动业务接入实践 调用 sendSms 的方法以后,系统会返回一个短信表示字串叫做 RequestIdentifier,这个 为长度为 32 位的数字,类似在短信网关里面 MessageID,用以识别短信,如果后续查询短 信状态报告的时候都需要通过此参数进行查询。比如 19120004a924d2c021b1,前面 191200 前面 6 为表示 isag 的设备号,后面一位 0 预留,4a924d2c021b1 由设备厂商内部编码。 3)设置 SOAP HEADER 正如 1.4.5 我们提到与 ISAG 交互的时候,需要传送 SOAPHeader 以作验证用。 SOAPHeader 在 AXIS 里面有一个对象:SOAPHeaderElement 对应: 相关文档可以查询: http://ws.apache.org/axis/java/apiDocs/org/apache/axis/message/SOAPHeaderElement.html 我们看下 SOAPHeaderElement 的定义: public class SOAPHeaderElement extends MessageElement implements SOAPHeaderElement A simple header element abstraction. Extends MessageElement with header-specific stuff like mustUnderstand, actor, and a 'processed' flag. 它是 MessageElement 的扩展类,用于定义 SOAP HEADER 其构造函数有如下方法: SOAPHeaderElement 构造函数 SOAPHeaderElement(Name nm) ae SOAPHeaderElement(QName qae nm) SOAPHeaderElement(QName qae jv.agOjc vle nm, aaln.bet au) SOAPHeaderElement(aaln.tig nmsae jv.agSrn aepc, jv.agSrn lclat aaln.tig oaPr) SOAPHeaderElement(aaln.tig nmsae jv.agSrn aepc, jv.agSrn lclat jv.agOjc vle aaln.tig oaPr, aaln.bet au) 28
  • 29. 浙江电信移动业务接入实践 SOAPHeaderElement(aaln.tig nmsae jv.agSrn aepc, jv.agSrn lclat aaln.tig oaPr, jv.agSrn pei, aaln.tig rfx ogxlsxAtiue atiue,DeserializationContext r.m.a.trbts trbts cnet otx) 参考文档《中国电信综合业务接入网关_ISAG_开放接口协议 01-总册 RC V1.0.0》7.2 SOAP Header 的定义,我们可以定义如下 soap header: SOAPHeaderElement SoapHeader = new SOAPHeaderElement( "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", "RequestSOAPHeader"); 如何在 SOAP Header 设置参数名和参数的值,我们看下 SOAPHeaderElement 的父类 MessageElement, 其增加参数的方法为:addChildElement 返回值 方法 SOAPElement addChildElement(Name childName) add the child element SOAPElement addChildElement(SOAPElement element) The added child must be an instance of MessageElement rather than an abitrary SOAPElement otherwise a (wrapped) ClassCastException will be thrown. SOAPElement addChildElement(java.lang.String localName) add a child element in the message element's own namespace SOAPElement addChildElement(java.lang.String localName, java.lang.String prefixName) add a child element SOAPElement java.lang.String childPrefix, java.lang.String uri) add a child element 通过 MessageElement 的 addChildElement 方法我们可以增加一个 SOAP Header 29
  • 30. 浙江电信移动业务接入实践 的 一 个 参 数 , 我 们 的 参 数 比 较 简 单 , 都 为 String 字 段 , 所 以 可 以 直 接 使 用 addChildElement(java.lang.String localName)方法进行参数的增加。 addChildElement 其返回值为 SOAPElement,所以我们可以直接通过 SOAPElement 设置相应的值,我们继续看下 SOAPElement ,他有 SOAPElement adetoejv.agSrn tx) dTxNd(aaln.tig et Creates a new Tx object initialized with the given Srn and adds it to et tig this SAEeet OPlmn object. 由于与 ISAG 涉及到的参数都是 String 类型,所以我们可以通过方法: //增加SPID SoapHeader.addChildElement("spId").addTextNode("12100000"); 可以通过上述这样的方法来设置 spId(注意字母的大小写),其他同理。 整个代码如下: /* 设置SOAP Header */ SoapHeader.addChildElement("spId").addTextNode(SPID); // SpID SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp); SoapHeader.addChildElement("spPassword").addTextNode( MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5 加密 SoapHeader.addChildElement("productId").addTextNode(ProductID); SoapHeader.addChildElement("OA").addTextNode(DestNum); SoapHeader.addChildElement("FA").addTextNode(DestNum); SoapHeader.addChildElement("multicastMessaging").addTextNode( "false"); // 是否群发 绑定 SOAP HEADER 我们构建好 SOAP Header 以后需要将 Soap header 与服务请求进行绑定,代码如 下: 30
  • 31. 浙江电信移动业务接入实践 ((SendSmsBindingStub) sendSms).setHeader(SoapHeader); 4)抛出异常处理 在 SendSms 类的使用介绍中,我们知道 SendSms 方法会抛出 3 个异常: java.rmi.RemoteException cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException java.rmi.RemoteException 是 Java 远程调用产生的异常,产生这个异常的原因很多这里不再详述。 PolicyException,ServiceException 这两个异常是 ISAG 服务端程序抛出的,具体异常查看规范《中 国电信综合业务网关_ISAG_开发接口协议 01-总册》查询。这两个异常都会返回 Messsage Id,以说明 错误的类别;会返回 Text 是错误的描述;还会返回 Variables 数组说明错误的具体错误原因。 因为这个两个错误很容易发生,比如用户订购关系不存在会抛出 ServiceException;比如你没有接 口权限会抛出 PolicyException。为了程序能够正常处理,我们需要对这两个异常做特殊处理。代码如 下: catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) { //鉴权失败 System.out.println("MessageId:" + e.getMessageId()); System.out.println("Text:" + e.getText()); String[] variables = e.getVariables(); for (int i = 0; i < variables.length; i++) { System.out.println("Variable:" + variables[i]); } } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException e) { System.out.println("MessageId:" + e.getMessageId()); System.out.println("Text:" + e.getText()); String[] variables = e.getVariables(); for (int i = 0; i < variables.length; i++) { System.out.println("Variable:" + variables[i]); } } 31
  • 32. 浙江电信移动业务接入实践 5)查询短信状态 查询短信状态有多种方式,这个章节只讨论如何通过SendSms接口的getSmsDeliverStatus方式来实现, 在开始的例子中的main方法的结束前增加如下几行。 代码如下: //等待10秒以后再查询 try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } DeliveryInformation[] delvierinfo = sendSms .getSmsDeliveryStatus(result); for (int i = 0; i < delvierinfo.length; i++) { System.out.println("发送号码:" + delvierinfo[i].getAddress()); System.out .println("发送状态:" + delvierinfo[i].getDeliveryStatus()); } 6)封装短信发送 SendSmsTest.java演示了如何发送短信,但是如果每个程序都这样调用的过于繁琐。我们需要把短信方 法封装成一个方便使用的类。 类:cn.com.chinatelecom.sms.SMS package cn.com.chinatelecom.sms; import java.math.BigDecimal; import java.net.MalformedURLException; import java.text.SimpleDateFormat; import java.util.Date; import javax.xml.rpc.ServiceException; import org.apache.axis.message.SOAPHeaderElement; import cn.com.chinatelecom.sms.bean.Result; 32
  • 33. 浙江电信移动业务接入实践 import cn.com.chinatelecom.util.MD5; import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation; import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference; import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1._interface.SendSms; import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsBindingStub; import cn.com.chinatelecom.www.wsdl.ctcc.sms.send.v2_1.service.SendSmsServiceLocator; public class SMS { private java.lang.String SendSms_address = "http://localhost:9080/SendSmsService/services/SendSms"; private String SPID = ""; private String Token = ""; private SendSmsServiceLocator ssl; private SendSms sendSms; private String receiptRequestUrl = ""; private String receiptRequestInterfaceName = "notifySmsDeliveryReception"; private ChargingInformation chargingInformation = new ChargingInformation(); public SMS(String spid, String token, String ws_address, String receiptrequestUrl) throws MalformedURLException, ServiceException { this.SendSms_address = ws_address; this.ssl = new SendSmsServiceLocator(); this.receiptRequestUrl = receiptrequestUrl; this.sendSms = ssl.getSendSms(new java.net.URL(this.SendSms_address)); this.SPID = spid; this.Token = token; this.chargingInformation.setDescription("Free"); this.chargingInformation.setAmount(new BigDecimal(1));// 扣费数目 this.chargingInformation.setCurrency("0"); } public void SetChargingInformation(ChargingInformation charginginformation){ //设置计费规则 this.chargingInformation=charginginformation; } public Result SendSms(String sendnum, String destnum, String message, String productid, String serviceid) { String[] destnumarray = new String[1]; destnumarray[0] = destnum; return SendSms(sendnum, destnumarray, message, productid, serviceid); 33
  • 34. 浙江电信移动业务接入实践 } public Result SendSms(String sendnum, String[] destnum, String message, String productid, String serviceid) { try { // 设置SoapHeader SOAPHeaderElement SoapHeader = new SOAPHeaderElement( "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", "RequestSOAPHeader"); String TimeStamp = dateString(); SoapHeader.addChildElement("spId").addTextNode(this.SPID); // SpID SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp); SoapHeader.addChildElement("spPassword").addTextNode( MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5加 密 SoapHeader.addChildElement("productId").addTextNode(productid); if (destnum.length == 1) { SoapHeader.addChildElement("OA").addTextNode( FormatMsisdn(destnum[0])); SoapHeader.addChildElement("FA").addTextNode( FormatMsisdn(destnum[0])); SoapHeader.addChildElement("multicastMessaging").addTextNode( "false"); // 是否群发 } else { SoapHeader.addChildElement("multicastMessaging").addTextNode( "true"); // 是否群发 } ((SendSmsBindingStub) this.sendSms).setHeader(SoapHeader); // 添加 SOAP头 /* 设置被叫号码 */ org.apache.axis.types.URI[] addresses = new org.apache.axis.types.URI[destnum.length]; for (int i = 0; i < destnum.length; i++) { destnum[i] = FormatMsisdn(destnum[i]); addresses[i] = new org.apache.axis.types.URI(destnum[i]); } /* 设置ChargingInformation */ 34
  • 35. 浙江电信移动业务接入实践 this.chargingInformation.setCode(serviceid);// 业务代码 /* 设置SimpleReference */ SimpleReference receiptRequest = new SimpleReference(); String Correlator = getCorrelator(); receiptRequest.setCorrelator(Correlator); // 序号自己随机增加 receiptRequest.setInterfaceName(this.receiptRequestInterfaceName); receiptRequest.setEndpoint(new org.apache.axis.types.URI( this.receiptRequestUrl)); Result result = new Result(); result.RequestIdentifier = this.sendSms.sendSms(addresses, sendnum, this.chargingInformation, message, receiptRequest); result.Correlator=Correlator; return result; } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) { // 鉴权失败 Result result = new Result(); result.MessageId = e.getMessageId(); result.Text = e.getText(); result.Variables = e.getVariables(); return result; } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException e) { // 规则健权失败 Result result = new Result(); result.MessageId = e.getMessageId(); result.Text = e.getText(); result.Variables = e.getVariables(); return result; } catch (Exception e) { // 其他错误 e.printStackTrace(); Result result = new Result(); result.MessageId = "-1"; result.Text = "Unkonw error"; result.Variables = new String[1]; result.Variables[0] = "Unkonw error"; return result; } 35
  • 36. 浙江电信移动业务接入实践 } private static String FormatMsisdn(String msisdn) { msisdn = msisdn.toLowerCase(); if ((msisdn.indexOf("+86") < 0) && (msisdn.indexOf("tel:") != 0) && (msisdn.length() == 11)) { // 不带+86,不带tel:的手机号码 return "tel:+86" + msisdn; } if ((msisdn.indexOf("86") == 0) && (msisdn.indexOf("tel:") != 0) && (msisdn.length() == 13)) { // 带86,不带+号,不带tel:的手机号码 return "tel:+" + msisdn; } return msisdn; } private static String getCorrelator() { SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss"); return sdf.format(new Date()); } private static String dateString() { SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss"); return sdf.format(new Date()); } } 为了方便返回数据,还需要构建一个类cn.com.chinatelecom.sms.bean.Result: package cn.com.chinatelecom.sms.bean; public class Result { public String RequestIdentifier=null; public String Correlator=""; public String MessageId=""; public String Text=""; public String[] Variables; } 36
  • 37. 浙江电信移动业务接入实践 另外加密用的的cn.com.chinatelecom.util.MD5 package cn.com.chinatelecom.util; import java.security.*; public class MD5 { private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; /** * 转换字节数组为16进制字串 * @param b 字节数组 * @return 16进制字串 */ public static String byteArrayToHexString(byte[] b) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) { resultSb.append(byteToHexString(b[i])); } return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n = 256 + n; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String compile(String origin) { String resultString = null; try { resultString=new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); resultString=byteArrayToHexString(md.digest(resultString.getBytes())); } catch (Exception ex) { } 37
  • 38. 浙江电信移动业务接入实践 return resultString; } } 生成这3个类以后,我们可以非常方便的使用这个接口: cn.com.chinatelecom.sms.SMS 方法 说明 public SMS(String spid, String token, String SMS构造函数,参数分别为:SPID,密钥,发 ws_address, String receiptrequestUrl) throws 送短信服务器端地址,发送短信回执地址 MalformedURLException, public void 设置计费规则,可选 SetChargingInformation(ChargingInformation charginginformation) public Result SendSms(String sendnum, String 发送单条短信。参数为:发送号码,目的号 destnum, String message, 码,消息内容,产品编号,服务编号 String productid, String 返回值为:Result。 serviceid) 其中Result.RequestIdentifier不为null值,表 示短信已经提交给网关,如果为null,表示 提交失败 public Result SendSms(String sendnum, 群发短信。参数为:发送号码,目的号码数 String[] destnum, String message, 组,消息内容,产品编号,服务编号。返回 String productid, String 值为:Result。 serviceid) 其中Result.RequestIdentifier不为null值,表 示短信已经提交给网关,如果为null,表示 提交失败 我们可以测试下上述这个类,代码如下: SMS sms=new SMS("spid","linlu","ISAG接口地址","短信回执接口地址"); Result result = sms.SendSms("主叫号码", "用户号码", "短信内容", "产品编号", " 38
  • 39. 浙江电信移动业务接入实践 服务编号"); if (result.RequestIdentifier!=null){ System.out.println("短信发送成功!"); System.out.println("RequestIdentifier:"+result.RequestIdentifier); System.out.println("Correlator:"+result.Correlator); }else { System.out.println("短信发送失败!"); System.out.println("MessageId:"+result.MessageId); System.out.println("Text:"+result.Text); } 注:红色部分替换成实际数据 2.3 SendSMS 短信上行,回执接口开发 短信上行的接口需要SP端作为服务器端,并实现SmsNotification接口,其中方法 notifySmsReception方法实现短信上行接受,notifySmsDeliveryReception实现短信回执接 收。 方法同样,找到我们先前导入的wsdl文件:ctcc_sms_notification_service_2_1.wsdl 按右键,选择Web Services->Generate Java bean skeleton 在出现的界面里面,选择Finish按钮即可: 39
  • 41. 浙江电信移动业务接入实践 获取SoapHeader: 由于在点播业务中,我们还需要换取LinkID,在下发的时候需要带上LinkID,由于 LinkID存在于服务器的请求的SoapHeader中,我们还需要获取SoapHeader相应的数值。 代码如下: NotifySOAPHeader.java package cn.com.chinatelecom.ws; import java.util.Iterator; import javax.xml.soap.SOAPElement; import org.apache.axis.AxisFault; import org.apache.axis.message.SOAPEnvelope; import org.apache.axis.message.SOAPHeaderElement; public class NotifySOAPHeader { private String spRevId = ""; private String spRevpassword = ""; private String spId = ""; private String SAN = ""; private String linkId = ""; public String getSpRevId() { return spRevId; } public NotifySOAPHeader(SOAPEnvelope envelope) { try { SOAPHeaderElement soapHeaderElement = envelope.getHeaderByName( "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", "NotifySOAPHeader"); Iterator iterator = soapHeaderElement.getChildElements(); while (iterator.hasNext()) { SOAPElement element = (SOAPElement) iterator.next(); String elementName = element.getElementName().getLocalName(); if (elementName.equals("spRevId")) { this.spRevId = element.getValue(); } else if (elementName.equals("spRevpassword")) { this.spRevpassword = element.getValue(); 41
  • 42. 浙江电信移动业务接入实践 } else if (elementName.equals("spId")) { this.spId = element.getValue(); } else if (elementName.equals("SAN")) { this.SAN = element.getValue(); } else if (elementName.equals("linkId")) { this.linkId = element.getValue(); } } } catch (AxisFault e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void setSpRevId(String spRevId) { this.spRevId = spRevId; } public String getSpRevpassword() { return spRevpassword; } public void setSpRevpassword(String spRevpassword) { this.spRevpassword = spRevpassword; } public String getSpId() { return spId; } public void setSpId(String spId) { this.spId = spId; } public String getSAN() { return SAN; } public void setSAN(String sAN) { SAN = sAN; } public String getLinkId() { 42
  • 43. 浙江电信移动业务接入实践 return linkId; } public void setLinkId(String linkId) { this.linkId = linkId; } } 说明:public NotifySOAPHeader(SOAPEnvelope envelope)是该类的构造函数,通过传入 SOAPEnvelope,程序从SOAPEnvelope分析出需要用到的SoapHeader里面的具体数值。 其中 SOAPEnvelope可以在WebService的具体实现代码里面:XXXXXXImpl.java里面通过以下代码获取: // 获取soapheader NotifySOAPHeader notifySOAPHeader = new NotifySOAPHeader( MessageContext.getCurrentContext().getRequestMessage() .getSOAPEnvelope()); System.out.println("LinkId:"+notifySOAPHeader.getLinkId()); System.out.println("SAN:"+notifySOAPHeader.getSAN()); System.out.println("SpId:"+notifySOAPHeader.getSpId()); System.out.println("RevId:"+notifySOAPHeader.getSpRevId()); System.out.println("SpRevpassword:"+notifySOAPHeader.getSpRevpassword()); 其中SmsNotificationBindingImpl.java是我们需要继续增加处理逻辑的文件。 package cn.com.chinatelecom.www.wsdl.ctcc.sms.notification.v2_1.service; import java.io.FileWriter; import java.io.IOException; import cn.com.chinatelecom.ws.NotifySOAPHeader; public class SmsNotificationBindingImpl implements cn.com.chinatelecom.www.wsdl.ctcc.sms.notification.v2_1._interface.SmsNotification{ public void notifySmsReception(java.lang.String registrationIdentifier, cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.SmsMessage message) throws java.rmi.RemoteException { // 获取soapheader NotifySOAPHeader notifySOAPHeader = new NotifySOAPHeader( MessageContext.getCurrentContext().getRequestMessage() .getSOAPEnvelope()); 43
  • 44. 浙江电信移动业务接入实践 System.out.println("LinkId:"+notifySOAPHeader.getLinkId()); System.out.println("SAN:"+notifySOAPHeader.getSAN()); System.out.println("SpId:"+notifySOAPHeader.getSpId()); System.out.println("RevId:"+notifySOAPHeader.getSpRevId()); System.out.println("SpRevpassword:"+notifySOAPHeader.getSpRevpassword()); try { FileWriter fw=new FileWriter("c:sms.log",true); fw.write("registrationIdentifier:"+registrationIdentifier + "rn"); fw.write("Sender:"+message.getSenderAddress()+ "rn"); fw.write("Message:"+message.getMessage()+ "rn"); fw.write("LinkId:"+notifySOAPHeader.getLinkId()+ "rn"); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void notifySmsDeliveryReceipt(java.lang.String correlator, cn.com.chinatelecom.www.schema.ctcc.sms.v2_1.DeliveryInformation deliveryStatus) throws java.rmi.RemoteException { try { FileWriter fw = new FileWriter("c:deliver.log",true); fw.write("correlator:"+correlator + "rn"); fw.write("Address:"+deliveryStatus.getAddress()+ "rn"); fw.write("DeliveryStatus:"+deliveryStatus.getDeliveryStatus()+ "rn"); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 绿底部分会在自动生成代码基础上增加的代码,作用是将短信上行写到文件 44
  • 45. 浙江电信移动业务接入实践 c:sms.log,状态报告写在:c: deliver.log。当然实际的程序远比这个复杂,或者入库或者 触发相应的程序。 代码完成后,由于接收上行消息和接收状态报告是Web Service服务端程序,需要部署 到Web服务器上;因此需要生成war文件,方法如下,选中sms项目,按右键选择 Export->WAR file,生成的文件拷贝到Tomcat安装目录的webapps目录下,tomcat会自动部 署该文件。 45
  • 46. 浙江电信移动业务接入实践 3. WAP PUSH 3.1 WAP PUSH 简介 WP A 业务发展初期基本上采用的是 PL 的方式, UL 也就是说你需要访问某个 WP A 网站, 那么需要打开 WP浏览器,并且输入网址比如:ht:/a.ntmb,访问中国电信 A tp/wpve.oi 的 WP A 门户网站。由于手机输入网址不方便,而且用户并非无时无刻连接在 WP A 网站上, 所以鉴于这样的原因,OA M 提出了 WPPS 的概念。其主要思想是通过某种特殊短信, A UH 来触发用户使用某种 WP A 业务。 A PS 目前主要分成两种,一种 Service Indication 方式(简称 SI) 通过短 WP UH , 信方式 PS 相关 WP UH A 网址以及简要的说明,至于用户是否访问这个网址,需要用户点击 确认。当然手机厂家对于 SI方式的 WPPS A UH展示方式不一样,显示的界面有很大的区 别,所以那个按钮可能叫确认也有可能叫转向。这个也就是窄义上的 WPPS,也是本 A UH 章节讲解的 WPPS。 A UH 另外一种 WP UH A PS 类型叫 Service Loading(简称 SL),通过短信 Ps 一个网 uh 址,手机主动联网并且下载该文件并且保存,最终以某种形式展示给用户。SL的种类非 常多,最典型的就是彩信,当用户手机收到 S 消息以后, L 自动到彩信中心下载彩信内容, 中间不需要用户干预;当然还有一些 OA T 下载,某些 Ps Mi 也采用类似 S 的方式, uh al L 这里不再详述。 3.2 WAP PUSH 网络结构和业务实现 我们看下目前 WPPS 网络的结构: A UH 46
  • 47. 浙江电信移动业务接入实践 在电信网内一个正常的 WbPs(I下发如上图蓝绿色箭头表示。整个 PS 的实 e uhS) UH 现从 SP发起,并经过 IA,uh代理网关(PG SGPs P)以及短信中心,最后以一种特殊短信 的方式下发给用户。其具体流程和接口协议如下: 1 S 使用 IA 的 WbSrie . P SG e evc 接口提交 S。 I 2 IA 将 S Wb evc 提交的数据,分装成 XL . SG P e Srie M 文件,并通过 PP A 协议(Ps uh Acs Pooo)协议,将 S 消息提交给 Ps 代理网关(PG。 ces rtcl I uh P) 3 PG收到 S . P I消息以后,将 SI消息按照 Ps-S uhWP协议,把 XL文件压缩成 M WXLWPBnr XL一种 S 的压缩方式) BM(A iay M, I 变成一条或者多条短信,提交给短 信中心。 4 短信中心下发这条或者这组特殊短信到用户的手机。 . 当然如果不通过 IA 接入,理论上可以直接通过 PP协议接入 PG代理网关,但 SG A P 协议相对于 WbSrie e evc 协议要复杂一些。 在 GM S 的网络中,当然还存在一种特殊的方式,S 侧直接将 S 根据 WXL P I BM 的方式 进行压缩成一条或者多条短信,直接通过短信网关,由短信网关提交给短信中心,从而 实现 WPPS 的下发,如上图棕色部分箭头。需要说明的是 CM 网络里面的 WPPS A UH DA A UH 封装与 GM S 存在相当大的差异,如果你通过 GM S 方式封装的 WP UH用户实际收到的短 A PS, 信很有可能是一段乱码。虽然我查询了 TAEA67A以及 OA I-I-3-, M 相关的 WP A 的协议,具 体地址:ht:/w.pnoielineogTcnclwpne.sx tp/wwoemblalac.r/ehia/aidxap,并未找到直 47
  • 48. 浙江电信移动业务接入实践 接通过短信网关下发实际有效的 WPPS。比较靠谱的消息是:CM A UH DA网络里面是通过 Tlsried eeevcI 来区分普通的短信还是 WPPS 亦或彩信,而 WPPS 和彩信都需要设 A UH A UH 置 Tlsried 602 eeevcI 为 50,可惜的是 Tlsried eeevcI 并不是 SP 协议能够传输的,需 MP 要短信中心对于不同的短信实体进行强制设置,也意味着你无法通过 SG 协议发送 WP MP A PS。当然如果您研究出来在 CM 的网络里面如何通过短信网关发送 WPPS, UH DA A UH欢迎您 发邮件到我的邮箱:dwlh@mi.o。 oelzgalcm 3.3 WAP PUSH 是什么?WAP PUSH 不是什么? 在您开发 WpPs 应用的时候,我觉得有必要跟你说明白“WPPS 是什么?WP a uh A UH A PS 不是什么?” 这个问题。 UH 首先 WpPs 并不是所有的手机都支持,虽然它本身属于 OA a uh M 标准协议的一部分, 我手头上的 CoPdD8 ola 1 就不支持,当有个 Ps 送达手机的时候,屏幕会一亮,然后就 uh 无下文了。 其次 Wp uh a Ps 在终端上显示有很大的差别,WnosMbl 的系统显示相对比较正 idw oie 常,而 CoPdN0 ola 90一条 Ps uh跟一条文字后面跟着网站地址的普通短信显示上没本质 的区别。 再次 Wp uh a Ps 无法显示主叫号码,在多普达 S0C 90 显示的主叫号码为:未验证用户, 而三星的 i2 显示为系统管理员。这估计也是为什么一度 GM 39 S 网络的手机收到大量的垃 圾 WpPs 短信的一个原因,因为用户都不知道谁发的。 a uh 还有需要说明的是,在某些情况下,一条 WPPS 和一条文字加网站链接构成的普 A UH 通的短信在用户的体验上没特别的差别,因为部分手机会自动识别普通短信中带了 ht:/ tp/开头的地址,用户点击这个地址也会自动关联相应的浏览器,唯一的区别 WP A Ps 用户点击的时候肯定会通过 CWP uh TA 方式连接,而普通短信里面的地址有可能用户连 接的 CWP TA,也有可能连接的是 CNT TE。 当然 WPPS 跟普通短信还有一个很大的区别是,用户至少直接拿终端(不通过直 A UH 接控制通讯模块)是无法发送 WPPS 的,也意味着无法转发 WPPS, A UH A UH这对于某些安 全级别要求较高的业务由于不能转发而不容易泄密,比如可以 ps 你一个通过加密生成 uh 的 Ul Ul r 串, r 串里面含有免登录数据,由于无法转发,用户泄漏数据的可能性大大降低。 48
  • 49. 浙江电信移动业务接入实践 3.4 WAP Push 接口开发环境搭建 为了完成 WPPs 开发,我们需要实现以下接口: A uh 接口名称 接口方法 作用 谁是服务器端 SendMessage SendMessage 发送 Wap Push getMessageDeliverStatus 查询发送状态 ISAG MessageNotification notifyMessageDeliveryReception 接收状态报告 SP 你会发现 WpPs a uh远比短信接口要少,很大的原因是在用户不通过某种特殊途径是 无法直接在终端上发送 WpPs 上行的,所以他的 Msaeoiiain a uh esgNtfcto 里面就没有接 受上行的接口。 1) 新建项目 因为接受状态报告需要 S 端作为服务器端,所以我们同样需要新建一个 Dnmc e P yai Wb Poet rjc。 选择 Fl-Nw>yai WbPoet ie>e-Dnmc e rjc 在弹出的确认窗口我这里起名叫 Wpuh你也可以起其他的项目名称 aPs, 49
  • 50. 浙江电信移动业务接入实践 点击 Fns, iih一个项目就新建成功。 2) 导入 WD 文件 SL 开发 WPPs 需要用到的 WD 文件如下: A uh SL 与 IA 接口相关的 wd SG sl cc_a_uhntfcto_nefc__.sl tcwpps_oiiainitrae10wd cc_a_uhntfcto_evc__.sl tcwpps_oiiainsrie10wd cc_a_uhsn_nefc__.sl tcwpps_editrae10wd cc_a_uhsn_evc__.sl tcwpps_edsrie10wd cc_a_uhtps10xd tcwpps_ye__.s cc_omntps21xd tccmo_ye__.s cc_omnfut__.sl tccmo_als20wd 与 IM 相关的 wd SP sl ImSEgn.sl( sppniewd 该接口实现不在这个章节讨论) 50
  • 51. 浙江电信移动业务接入实践 a同样我们为了不与其他程序混在一块,为 WD ) SL文件新建一个目录 wd, sl用户导入 wd 文件。 sl b选择建立的 wd 目录,按右键选择 Ipr ) sl mot c选择 Fl Sse ) ie ytm 51
  • 53. 浙江电信移动业务接入实践 导入完成后我们应该看到 PoetEpoe 有如下文件 rjc xlrr 3.5 WAP Push 发送接口开发 Wap Push 发送的接口过程中,SP 侧的软件是作为 Web Service Client,而 ISAG 作为 Server,所以我们这里需要生成发送接口的客户端软件。 方法非常简单,选中 wsdl 目录下的 cc_a_uhsn_evc__.sl tcwpps_edsrie10wd 文件, 按右键选择 WbSrie-Gnrt Cin。 e evcs>eeae let 53
  • 54. 浙江电信移动业务接入实践 生成以后,系统会多了如下代码: 其中:SendMessageServiceLocator.java 就是我们需要的客户端程序。 我们编写个测试代码: import java.math.BigDecimal; import java.net.MalformedURLException; import java.rmi.RemoteException; import java.text.SimpleDateFormat; import java.util.Date; import javax.xml.rpc.ServiceException; import javax.xml.soap.SOAPException; import org.apache.axis.message.SOAPHeaderElement; import org.apache.axis.types.URI.MalformedURIException; import cn.com.chinatelecom.util.MD5; 54
  • 55. 浙江电信移动业务接入实践 import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation; import cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference; import cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.MessagePriority; import cn.com.chinatelecom.www.wsdl.ctcc.wap_push.send.v1_0._interface.SendMessage; import cn.com.chinatelecom.www.wsdl.ctcc.wap_push.send.v1_0.service.SendMessageBindingStub; import cn.com.chinatelecom.www.wsdl.ctcc.wap_push.send.v1_0.service.SendMessageServiceLocator; public class SendWapPush { public static void main(String[] args) { String webserviceUrl = "ISAG WAP Push地址(非WSDL地址)"; String SPID = "SPID"; // SPID String Token = "密码"; // 密钥 String DestNum = "tel:+8615305711873"; // 发送号码 String ProductID = "112000000000000004112"; // 产品编号 String ServiceID = "212000000000000002488"; // 业务编号 String TimeStamp = dateString(); // 当前时间 String senderName = "10620068"; // WAP Push主叫号码,在浙江ISAG实际无效,ISAG会读取业 务部署时候的接入号 String targetURL="http://wap.189.cn"; String subject ="189邮箱"; SOAPHeaderElement SoapHeader = new SOAPHeaderElement( "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1", "RequestSOAPHeader"); try { /* 初始化WebService Client */ SendMessageServiceLocator ssl = new SendMessageServiceLocator(); SendMessage sendMessage = ssl.getSendMessage(new java.net.URL(webserviceUrl)); /* 设置SOAP Header */ SoapHeader.addChildElement("spId").addTextNode(SPID); // SpID SoapHeader.addChildElement("timeStamp").addTextNode(TimeStamp); SoapHeader.addChildElement("spPassword").addTextNode( MD5.compile(SPID + Token + TimeStamp).toUpperCase());// MD5加密 SoapHeader.addChildElement("productId").addTextNode(ProductID); SoapHeader.addChildElement("OA").addTextNode(DestNum); 55
  • 56. 浙江电信移动业务接入实践 SoapHeader.addChildElement("FA").addTextNode(DestNum); SoapHeader.addChildElement("multicastMessaging").addTextNode( "false"); // 是否群发 ((SendMessageBindingStub) sendMessage).setHeader(SoapHeader); // 添加SOAP头 /* 设置被叫号码 */ org.apache.axis.types.URI[] addresses = new org.apache.axis.types.URI[1]; addresses[0] = new org.apache.axis.types.URI(DestNum); /* 设置ChargingInformation */ ChargingInformation charging = new ChargingInformation(); charging.setDescription("gm");// 描述 charging.setAmount(new BigDecimal(1));// 扣费数目 charging.setCode(ServiceID);// 业务代码 charging.setCurrency("0"); /* 设置SimpleReference */ SimpleReference receiptRequest = new SimpleReference(); receiptRequest.setCorrelator("1001559"); // 序号自己随机增加 receiptRequest.setInterfaceName("notifyMessageDeliveryReception"); receiptRequest.setEndpoint(new org.apache.axis.types.URI( "http://202.101.166.196:8080/WebPush/services/notifyMessageDeliveryReception")); /* 发送WAP PUSH */ String result = sendMessage.sendMessage(addresses, new org.apache.axis.types.URI(targetURL), senderName, subject, MessagePriority.Normal, charging, receiptRequest); System.out.println("result:" + result); } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException e) { // 鉴权失败 System.out.println("MessageId:" + e.getMessageId()); System.out.println("Text:" + e.getText()); String[] variables = e.getVariables(); for (int i = 0; i < variables.length; i++) { System.out.println("Variable:" + variables[i]); } } catch (cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException e) { 56
  • 57. 浙江电信移动业务接入实践 System.out.println("MessageId:" + e.getMessageId()); System.out.println("Text:" + e.getText()); String[] variables = e.getVariables(); for (int i = 0; i < variables.length; i++) { System.out.println("Variable:" + variables[i]); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ServiceException e) { e.printStackTrace(); } catch (SOAPException e) { e.printStackTrace(); } catch (MalformedURIException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } private static String dateString() { SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss"); return sdf.format(new Date()); } } 注:红色部分替换成自己相应的数据。 关于 SOAP Header 的设置请查看短信章节里面的说明,设置完全一样。 类似短信方式我们需要初始化一个 SendMessage 的 Client,获得一个 SendMessage 的对象 /* 初始化WebService Client */ SendMessageServiceLocator ssl = new SendMessageServiceLocator(); SendMessage sendMessage = ssl.getSendMessage(new java.net.URL(webserviceUrl)); 其中 SendMessage 有如下方法: public java.lang.String sendMessage( org.apache.axis.types.URI[] addresses, //用户号码 org.apache.axis.types.URI targetURL, //WAP PUSH地址 java.lang.String senderAddress, //发送方地址 57
  • 58. 浙江电信移动业务接入实践 java.lang.String subject, //WAP PUSH标题 cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.MessagePriority priority, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ChargingInformation charging, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.SimpleReference receiptRequest ) throws java.rmi.RemoteException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException; 说明:这是实际发送 WAP Push 的方法,多数参数与发送短信类似。 其中 targetURL 表示推送给用户的 Web 地址 subject 表示 wap push 的标题,也就是 wap push 的正文 同样该函数还会返回一个 String 字段表示的 requestIdentifier 用以说明这条 Wap Push 的标识 public cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.DeliveryInformation[] getMessageDeliveryStatus(java.lang.String requestIdentifier) throws java.rmi.RemoteException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.PolicyException, cn.com.chinatelecom.www.schema.ctcc.common.v2_1.ServiceException; 说明:发送结果查询 3.6 WAP Push 状态报告接口开发 Wap Push 状态报告接收接口 ,SP 侧的软件是作为 Web Service Server,而 ISAG 作为 Client,所以我们这里需要生成发送接口的服务器端软件。 方法非常简单,选中 wsdl 目录下的 cc_a_uhntfcto_evc__.sl tcwpps_oiiainsrie10wd 文件,按右键选择 WbSrie-Gnrt Jv ba seeo。 e evcs>eeae aa en kltn 生成以后,在 Poet xlr 项目的 Jv Rsucssc rjc Epoe aa eore:r 分项里面会看到如下文件: 58
  • 59. 浙江电信移动业务接入实践 MessageNotificationBindingImpl.java 是我们需要完成的代码。代码如下: package cn.com.chinatelecom.www.wsdl.ctcc.wap_push.notification.v1_0.service; import java.io.FileWriter; import java.io.IOException; public class MessageNotificationBindingImpl implements cn.com.chinatelecom.www.wsdl.ctcc.wap_push.notification.v1_0._interface.MessageNotification { public void notifyMessageDeliveryReceipt( java.lang.String correlator, cn.com.chinatelecom.www.schema.ctcc.wap_push.v1_0.DeliveryInformation deliveryStatus) throws java.rmi.RemoteException { try { FileWriter fw = new FileWriter("c:wappushdeliver.log"); fw.write("correlator:" + correlator); fw.write("Address:" + deliveryStatus.getAddress()); fw.write("DeliveryStatus:" + deliveryStatus.getStatus()); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 绿底部分会在自动生成代码基础上增加的代码,作用是将短信上行写到文件 c:sms.log,状态报告写在:c: wappushdeliver.log。当然实际的程序远比这个复杂,或者 入库或者触发相应的程序。 代码完成后,由于接收上行消息和接收状态报告是Web Service服务端程序,需要部署 到Web服务器上;因此需要生成war文件,方法如下,选中wappush项目,按右键选择 59