联通spApi.jar短信接口二次开发
提示:调试时一定要和联通工程师联调,让他们监控服务端,可能存在ip授权,手机号码白名单的问题。不要执着于代码和配置参数的检查。
1.新建web工程,导入联通spApi.jar包
2.创建一个配置类SmsRequest
package com;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class SmsRequest
{
public String cLocalIp;
public int iLocalPort;
public String cSmgIp;
public int cSmgPort;
public String cLoginName;
public String cPassword;
public int lSocketTimeOut;
public int lMTTimeOut;
public long iSrcNode;
public int lMTThread;
public int lMaxListNode;
public int lMTMaxRetryTime;
public int lMOThread;
public String corpId;
public String service_type;
public byte fee_type;
public String fee_value;
public String given_value;
public byte agent_flag;
public byte mo_flag;
public byte priority;
public String expire_time;
public byte report_flag;
public byte tp_pid;
public byte tp_udhi;
public byte message_coding;
public byte messagetype;
public String chargenumber;
public String ScheduleTime;
public String spnumber;
public String content;
public int message_length;
public long messageid;
public int startUpResult;
public int submitResult;
public int submitError;
public long sequencenumber1;
public long sequencenumber2;
public long sequencenumber3;
public int sysid;
public String sysloginname;
public String syspassword;
public String posturl;
public String mmsposturl;
public SmsRequest()
{
GetsmsRequest();
}
public void GetsmsRequest()
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
System.out.print(pce.toString());
}
Document doc = null;
String className = SmsRequest.class.getName();
String classNamePath = className.replace(".", "/") + ".class";
URL xmlpath = SmsRequest.class.getClassLoader().getResource(classNamePath);
System.out.println("xmlpath="+xmlpath.toString());
String xmlfile=xmlpath.toString();
xmlfile = xmlfile.substring(0,xmlfile.lastIndexOf("/"));
xmlfile = xmlfile.substring(0,xmlfile.lastIndexOf("/"));
xmlfile = xmlfile.substring(0,xmlfile.lastIndexOf("/"));
xmlfile = xmlfile.substring(0,xmlfile.lastIndexOf("/"));
xmlfile=xmlfile+ "/config.xml";
System.out.println("xmlfile="+xmlfile);
try
{
doc = db.parse(xmlfile);
}
catch (Exception e) {
System.out.print(e.toString());
}
Element root = doc.getDocumentElement();
NodeList startup = root.getElementsByTagName("startup");
Element start = (Element)startup.item(0);
this.cLocalIp = start.getElementsByTagName("cLocalIp").item(0).getFirstChild().getNodeValue();
this.iLocalPort = Integer.parseInt(start.getElementsByTagName("iLocalPort").item(0).getFirstChild().getNodeValue());
this.cSmgIp = start.getElementsByTagName("cSmgIp").item(0).getFirstChild().getNodeValue();
this.cSmgPort = Integer.parseInt(start.getElementsByTagName("cSmgPort").item(0).getFirstChild().getNodeValue());
this.cLoginName = start.getElementsByTagName("cLoginName").item(0).getFirstChild().getNodeValue();
this.cPassword = start.getElementsByTagName("cPassword").item(0).getFirstChild().getNodeValue();
this.lSocketTimeOut = Integer.parseInt(start.getElementsByTagName("lSocketTimeOut").item(0).getFirstChild().getNodeValue());
this.lMTTimeOut = Integer.parseInt(start.getElementsByTagName("lMTTimeOut").item(0).getFirstChild().getNodeValue());
this.iSrcNode = Long.parseLong(start.getElementsByTagName("iSrcNode").item(0).getFirstChild().getNodeValue());
this.lMTThread = Integer.parseInt(start.getElementsByTagName("lMTThread").item(0).getFirstChild().getNodeValue());
this.lMaxListNode = Integer.parseInt(start.getElementsByTagName("lMaxListNode").item(0).getFirstChild().getNodeValue());
this.lMTMaxRetryTime = Integer.parseInt(start.getElementsByTagName("lMTMaxRetryTime").item(0).getFirstChild().getNodeValue());
this.lMOThread = Integer.parseInt(start.getElementsByTagName("lMOThread").item(0).getFirstChild().getNodeValue());
NodeList submit = root.getElementsByTagName("submit");
Element sub = (Element)submit.item(0);
this.corpId = sub.getElementsByTagName("corpId").item(0).getFirstChild().getNodeValue();
this.service_type = sub.getElementsByTagName("service_type").item(0).getFirstChild().getNodeValue();
this.fee_type = Byte.parseByte(sub.getElementsByTagName("fee_type").item(0).getFirstChild().getNodeValue());
this.fee_value = sub.getElementsByTagName("fee_value").item(0).getFirstChild().getNodeValue();
this.given_value = "";
this.agent_flag = Byte.parseByte(sub.getElementsByTagName("agent_flag").item(0).getFirstChild().getNodeValue());
this.mo_flag = Byte.parseByte(sub.getElementsByTagName("mo_flag").item(0).getFirstChild().getNodeValue());
this.priority = Byte.parseByte(sub.getElementsByTagName("priority").item(0).getFirstChild().getNodeValue());
this.expire_time = "";
this.report_flag = Byte.parseByte(sub.getElementsByTagName("report_flag").item(0).getFirstChild().getNodeValue());
this.tp_pid = Byte.parseByte(sub.getElementsByTagName("tp_pid").item(0).getFirstChild().getNodeValue());
this.tp_udhi = Byte.parseByte(sub.getElementsByTagName("tp_udhi").item(0).getFirstChild().getNodeValue());
this.message_coding = Byte.parseByte(sub.getElementsByTagName("message_coding").item(0).getFirstChild().getNodeValue());
this.ScheduleTime = "";
this.spnumber = sub.getElementsByTagName("spnumber").item(0).getFirstChild().getNodeValue();
this.chargenumber = sub.getElementsByTagName("chargenumber").item(0).getFirstChild().getNodeValue();
this.messagetype = 0;
System.out.println("config.xml cLocalIp="+this.cLocalIp);
}
}
3.config.xml配置文件放在web-inf下
<?xml version="1.0" standalone="yes"?>
<config>
<startup>
<cLocalIp>你服务器ip这个是需要联通鉴权的</cLocalIp>
<iLocalPort>你服务器port</iLocalPort>
<cSmgIp>联通服务ip</cSmgIp>
<cSmgPort>联通服务port</cSmgPort>
<cLoginName>用户名联通分配</cLoginName>
<cPassword>密码联通分配</cPassword>
<lSocketTimeOut>5</lSocketTimeOut>
<lMTTimeOut>10</lMTTimeOut>
<iSrcNode>节点编码联通分配</iSrcNode>
<lMTThread>50</lMTThread>
<lMaxListNode>50</lMaxListNode>
<lMTMaxRetryTime>5</lMTMaxRetryTime>
<lMOThread>0</lMOThread>
</startup>
<submit>
<spnumber>spid联通分配</spnumber>
<chargenumber>000000000000000000000</chargenumber>
<corpId>联通分配</corpId>
<service_type>TEST</service_type>
<fee_type>1</fee_type>
<fee_value>0</fee_value>
<given_value />
<agent_flag>0</agent_flag>
<mo_flag>2</mo_flag>
<priority>0</priority>
<expire_time />
<report_flag>1</report_flag>
<tp_pid>0</tp_pid>
<tp_udhi>0</tp_udhi>
<message_coding>15</message_coding>
</submit>
</config>
4.创建发送短信测试类
package com;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import spApi.Bind;
import spApi.BindResp;
import spApi.Deliver;
import spApi.SGIP_Command;
import spApi.SGIP_Exception;
import spApi.Submit;
import spApi.SubmitResp;
import spApi.Unbind;
import spApi.UnbindResp;
public class Send {
public SmsRequest request;
public Send() {
request = new SmsRequest();
}
public void printError(int ret) {
String error = "";
switch (ret){
case 0:
error="无错误,命令正确接收";
break;
case 1:
error="非法登录,如登录名、口令出错、登录名与口令不符等。";
break;
case 2:
error="重复登录,如在同一TCP/IP连接中连续两次以上请求登录。";
break;
case 3:
error="连接过多,指单个节点要求同时建立的连接数过多。";
break;
case 4:
error="登录类型错,指bind命令中的logintype字段出错。";
break;
case 5:
error="参数格式错,指命令中参数值与参数类型不符或与协议规定的范围不符。";
break;
case 6:
error="非法手机号码,协议中所有手机号码字段出现非86130号码或手机号码前未加“86”时都应报错。";
break;
case 7:
error="消息ID错";
break;
case 8:
error="信息长度错";
break;
case 9:
error="非法序列号,包括序列号重复、序列号格式错误等";
break;
case 10:
error="非法操作GNS";
break;
case 11:
error="节点忙,指本节点存储队列满或其他原因,暂时不能提供服务的情况";
break;
case 12:
error="关机或停机";
break;
case 21:
error="目的地址不可达,指路由表存在路由且消息路由正确但被路由的节点暂时不能提供服务的情况";
break;
case 22:
error="路由错,指路由表存在路由但消息路由出错的情况,如转错SMG等";
break;
case 23:
error="路由不存在,指消息路由的节点在路由表中不存在";
break;
case 24:
error="计费号码无效,鉴权不成功时反馈的错误信息";
break;
case 25:
error="用户不能通信(如不在服务区、未开机等情况)";
break;
case 26:
error="手机内存不足";
break;
case 27:
error="手机不支持短消息";
break;
case 28:
error="手机接收短消息出现错误";
break;
case 29:
error="不知道的用户";
break;
case 30:
error="不提供此功能";
break;
case 31:
error="非法设备";
break;
case 32:
error="系统失败";
break;
case 33:
error="短信中心队列满";
break;
case 51:
error="屏蔽";
break;
case 72:
error="没有路由";
break;
default:
error="其它错误码(待定义)";
}
System.out.println("【错误信息】:" + error);
}
@SuppressWarnings("unused")
public void sendMsg() {
Socket so = null;
OutputStream out = null;
InputStream input = null;
Bind command = null;
Bind com = null;
SGIP_Command sgip = null;
SGIP_Command tmp = null;
int i = 0;
try {
//bind连接服务
sgip = new SGIP_Command();
command = new Bind(request.iSrcNode, 1, request.cLoginName,request.cPassword);
int err;
byte[] byte_content = new byte[140];
Deliver deliver = null;
Submit submit = null;
SubmitResp submitresp = null;
Bind active = null;
Unbind term = null;
BindResp resp = null;
UnbindResp Unresp = null;
so = new Socket(request.cSmgIp, request.cSmgPort);//建立连接套接字
out = new DataOutputStream(so.getOutputStream());
input = new DataInputStream(so.getInputStream());
//发送bind数据
err = command.write(out);
if (err != 0) {
System.out.println("err" + err);
}
//接收bind返回数据
tmp = sgip.read(input);//接收sgip消息
if (sgip.getCommandID() == SGIP_Command.ID_SGIP_BIND_RESP) {
resp = (BindResp) tmp;// 强制转换为bindresp
resp.readbody();// 对消息进行解包
System.out.println("tmp.getSeqno_1=" + tmp.getSeqno_1());
System.out.println("tmp.getSeqno_2=" + tmp.getSeqno_2());
System.out.println("tmp.getSeqno_3=" + tmp.getSeqno_3());
System.out.println("resp.GetResult=" + resp.GetResult());
if(resp.GetResult()!=0){
printError(resp.GetResult());//0成功 其他失败
}
}
for (i = 0; i < 140; i++) {
byte_content[i] = 51;
i++;
byte_content[i] = 51;
i++;
byte_content[i] = 52;
i++;
byte_content[i] = 53;
i++;
byte_content[i] = 54;
i++;
byte_content[i] = 55;
i++;
byte_content[i] = 56;
i++;
byte_content[i] = 57;
i++;
byte_content[i] = 58;
i++;
byte_content[i] = 59;
}
// 封装submit数据
String mobile="";
submit = new Submit(request.iSrcNode,
request.spnumber,
request.chargenumber,
1,
"86"+mobile,
request.corpId,
request.service_type,
request.fee_type,
request.fee_value,
request.given_value,
request.agent_flag,
request.mo_flag,
request.priority,
"",
"",
request.report_flag,
request.tp_pid,
request.tp_udhi,
request.message_coding,
request.messagetype,
4,
"短信测试");
submit.write(out);//发送submit
//读取submit返回结果
tmp = sgip.read(input);
if (tmp.getCommandID() == SGIP_Command.ID_SGIP_SUBMIT_RESP) {
submitresp = (SubmitResp) tmp;// 强制转换
submitresp.readbody();// 解包
System.out.println("tmp.getSeqno_1=" + tmp.getSeqno_1());
System.out.println("tmp.getSeqno_2=" + tmp.getSeqno_2());
System.out.println("tmp.getSeqno_3=" + tmp.getSeqno_3());
System.out.println("submitresp.getResult="+ submitresp.getResult());
if(submitresp.getResult()!=0){
printError(submitresp.getResult());
}
}
//发送unbind
term = new Unbind(request.iSrcNode);
term.write(out);
tmp = sgip.read(input);
if (sgip.getCommandID() == SGIP_Command.ID_SGIP_UNBIND_RESP) {
Unresp = (UnbindResp) tmp;
System.out.println("tmp.getSeqno_1=" + tmp.getSeqno_1());
System.out.println("tmp.getSeqno_2=" + tmp.getSeqno_2());
System.out.println("tmp.getSeqno_3=" + tmp.getSeqno_3());
}
//关闭流和套接字
out.close();
so.close();
} catch (SGIP_Exception e) {
System.out.println(e.toString());
} catch (Exception e) {
System.out.println(e.toString());
} finally {
try {
System.in.read();
} catch (Exception s) {
System.out.println(s.toString());
}
}
}
}
5.测试调用
Send send=new Send();
send.sendMsg();