用spapi.jar开发包通过联通平台发长短信

阅读更多
      最近项目中遇到用java程序通过中国联通G网短信平台发送长短信的需求,所谓长短信就是将内容超过70个字符的短消息拆分成多条70字符以内的短信分别发送,而在用户的手机上将所有的内容在一条消息中显示出来。因为我之前一直是做j2ee开发的,对短信这一块并不熟悉,拿到需求之后请教了几位做SP的朋友。从他们哪里得知运营商处理短信发送有两种方式,移动采取CMPP协议、联通采用SGIP协议,由于这两个协议都是由所谓SMPP协议派生出来的,所以两者许多共同之处。虽然如此在项目实施过程中仍然遇到了一些问题,鉴于blogjava鼓励原创的风格,也尝试写一篇小文,记录解决这些问题的过程,希望对需要的朋友有帮助,也简单总结一下本人在调用他人jar包和处理java编码问题时积累的一点小经验,有不当之处请朋友们指正。
一、关于spapi.jar短信发送包br /> 要让用户的手机能够识别该短信是否是长短信,根据协议规定,应在内容字段中增加包头: 
包头一共6个字节,如下: 
1 、字节一:包头长度,固定填写0x05;
2 、字节二:包头类型标识,固定填写0x00,表示长短信;
3 、字节三:子包长度,固定填写0x03,表示后面三个字节的长度;
4 、字节四到字节六:包内容:
  
1 )字节四:长消息参考号,每个SP给每个用户发送的每条参考号都应该不同,可以从0开始,每次加1,最大255,便于同一个终端对同一个SP的消息的不同的长短信进行识别;
  
2 )字节五:本条长消息的的总消息数,从1到255,一般取值应该大于2;
  
3 )字节六:本条消息在长消息中的位置或序号,从1到255,第一条为1,第二条为2,最后一条等于第四字节的值。
包头和内容部分经过本人试验必须采用UCS2也就是Unicode编码方式发送给短信网关,发送过程采用spapi.jar包中的spApi.Submit类的对象绑定Socket流的方式。这里要特别指出,Submit类的默认初始化方法对编码方式和字符缓冲区进行了区分,造成UCS2编码发送短信时加上包头后手机显示乱码。所幸该类还提供了setContent()方法,只要通过该方法以指定的编码方式传入String型的短信内容,即可解决乱码问题。

Submit submit = null ;
   .......
//获得输入输出流,可参考spapi.jar示例程序


submit 
= new Submit(spConfig.getSmsNodeID(), // node id同上
    spConfig.getSmsSpNumber(), // cp_phone
    spConfig.getSmsCPNUMBER(), // 付费号码
    1// 接收短消息的手机数
    "86130xxxxxxx"// 手机号码前面加86
    spConfig.getSmsCPID(), // cp_id
    "",// 业务代码
    0,// 计费类型
    "500",// 短消息收费值
    "500",// 赠送话费
    1,// 代收标志
    1,// 引起MT的原因
    9,// 优先级
    "",// 短消息终止时间
    "",// 011125120000032+短消息定时发送时间
    1,// 状态报告标志
    1,// GSM协议类型
    1,// GSM协议类型
    8,// 短消息编码格式
    0,// 信息类型
    2,// 短消息长度,此处仅为了得到对象任意填入
   new byte[]{0x00,0x00});// 内容,任意填入
//该方法才真正写入内容。
submit.setContent(8, new String (byte_content);

submit.write(out);
// 发送submit
当然,最佳的方法是重写Submit类的初始化方法,希望该开发包在下一版本推出时候已经解决了此问题。
二、关于编码
    通过String.getByte(String charsetName)方法以指定编码格式产生字符串的byte数组,而String的构造方法String(byte[] bytes, String charsetName),可以将byte数组以指定的编码格式解析为字符串。在这里采用iso-10646-ucs-2编码方式:
String message = " xxxx " ; // 中英文混合字符串
byte [] messageUCS2  =  message.getBytes( " iso-10646-ucs-2 " );
byte [] tp_udhiHead  =   new   byte [ 6 ];
tp_udhiHead[
0 =   0x05 ;
tp_udhiHead[
1 =   0x00 ;
tp_udhiHead[
2 =   0x03 ;
tp_udhiHead[
3 =   0x0A ;
tp_udhiHead[
4 =   0x02 ; //  共两条短信
tp_udhiHead[ 5 =   0x01 ; //  默认为第一条
byte [] tp_udhiHead  =  byteAdd(tp_udhiHead,messageUCS2); // 将messageUCS2加入到tp_udhiHead后面
String strContent = new  String (tp_udhiHead, " ISO8859-1 " )
message和strContent(除去包头部分)的内部编码是一致的,这样保证了发送的短信在用户手机上不会因为内容部分增加了包头而显示乱码。
    小结如下:
1、在采用项目外部提供的公共类包时候,要有怀疑态度,不能想当然认为原程序作者已经实现了所有你要的功能,毕竟写程序的是人,他也可能犯错。
2、遇到乱码问题,最好能将程序化繁为简,并尽可能在测试平台上多做测试,光凭想象有时候并不能很快解决问题,反而容易浪费时间。
3、在遇到问题时要和有经验的人多讨论,这有助于你找到解决问题方法,但是记住最终解决问题的,只有你自己,不能完全寄希望于他人。

你可能感兴趣的:(中国移动,Socket)