packagecn.richinfo.cmail.vasp.common.util;importie.omk.smpp.Address;importie.omk.smpp.Connection;importie.omk.smpp.message.BindResp;importie.omk.smpp.message.EnquireLink;importie.omk.smpp.message.EnquireLinkResp;importie.omk.smpp.message.SMPPPacket;importie.omk.smpp.message.SMPPResponse;importie.omk.smpp.message.SubmitSM;importie.omk.smpp.message.SubmitSMResp;importie.omk.smpp.util.EncodingFactory;importorg.apache.commons.lang.StringUtils;importorg.apache.log4j.Logger;importcn.richinfo.cmail.common.config.PropertiesUtil;/*** @todo 长连接发短信
* @date 2017年8月15日
*@authorlinying*/
public classSMPPUtil {private Logger logger = Logger.getLogger(SMPPUtil.class);private boolean connected = false; //是否已连接
private boolean received = false; //是否接收心跳包
private Connection conn = null;//ESME到SMSC的连接
privateSMPPUtil() {
}public static finalSMPPUtil getInstance() {returnSMPPUtilHolder.SMPP_UTIL;
}/*** @todo 打开链接
*@throwsException*/
private void openLink() throwsException {
logger.info("open smsc service...");
String host= PropertiesUtil.getProperty("zte.notice.smsc.host");int port = PropertiesUtil.getPropertyInt("zte.notice.smsc.port", 0);
String systemId= PropertiesUtil.getProperty("zte.notice.smsc.systemId");
String password= PropertiesUtil.getProperty("zte.notice.smsc.password");
String systemType= PropertiesUtil.getProperty("zte.notice.smsc.systemType");
logger.info(String.format("openLink parameter | host=%s | port=%s | systemId=%s | password=%s | systemType=%s", host, port, systemId, password, systemType));if (StringUtils.isEmpty(host) || StringUtils.isEmpty(systemId) || StringUtils.isEmpty(password) || StringUtils.isEmpty(systemType) || port == 0) {
logger.error("parameter is empty");return;
}
conn= newConnection(host, port);
conn.autoAckLink(true);
conn.autoAckMessages(true);
BindResp resp=conn.bind(Connection.TRANSMITTER, systemId, password, systemType);if (null != resp && resp.getCommandStatus() == 0) {
connected= true;//new Thread(new KeepHeartbeat()).start();//发送心跳
new Thread(new ReceivePackets()).start(); //接收心跳
}
}/***
* @todo 发送心跳
* @date 2017年8月15日
*@authorlinying*/
class KeepHeartbeat implementsRunnable {private long delay = PropertiesUtil.getPropertyLong("zte.notice.smsc.keep.delay");public voidrun() {while(connected) {try{
Thread.sleep(delay);//心跳延时
EnquireLinkResp resp =conn.enquireLink();if (null != resp && resp.getCommandStatus() == 0) {
logger.info("[system request packet ok]");
}else{
logger.info("[system request packet err]");
}
}catch(Exception e) {
logger.error(e);
closeLink();
}
}
}
}/***
* @todo 接收心跳
* @date 2017年8月15日
*@authorlinying*/
class ReceivePackets implementsRunnable {public voidrun() {while(connected) {try{if(received) {
SMPPPacket packet=conn.readNextPacket();if (null != packet && packet.getCommandStatus() == 0) {
logger.info("[smsc request packet ok]");
EnquireLink link= newEnquireLink();
link.setSequenceNum(packet.getSequenceNum());
conn.ackEnquireLink(link);
}else{
logger.info("[smsc request packet err]");
}
}
logger.info("[smsc request packet stop]");
Thread.sleep(10000);
}catch(Exception e) {
logger.error(e);
closeLink();
}
}
}
}/*** @todo 关闭链接
*@returnvoid*/
private voidcloseLink() {
logger.info("close smsc service...");
connected= false;
received= false;try{if (conn != null &&conn.isBound()) {
conn.unbind();
}
conn= null;
}catch(Exception e) {
logger.error(e);
}
}/*** @todo 发送短信
*@paramaddress
*@paramtext
*@returnString
*@throwsException*/
public String sendSms(String address, String text) throwsException {int ton = PropertiesUtil.getPropertyInt("zte.notice.sms.ton", 0);int npi = PropertiesUtil.getPropertyInt("zte.notice.sms.npi", 0);
String source= PropertiesUtil.getProperty("zte.notice.sms.sourceAddress");int encode = PropertiesUtil.getPropertyInt("zte.notice.sms.encoding", 8);int count = 1;returnsendSms(ton, npi, source, address, text, encode, count);
}private String sendSms(int ton, int npi, String source, String address, String text, int encode, int count) throwsException {//发送短信中,停止接收心跳
received = false;//没有绑定
if (!connected) {
openLink();
}
logger.info("connected is true");
SubmitSM sm=(SubmitSM) conn.newInstance(SMPPPacket.SUBMIT_SM);if(StringUtils.isNotEmpty(source)) {
sm.setSource(newAddress(ton, npi, source));
}
sm.setDestination(new Address(0, 0, address));
sm.setMessageText(text);
sm.setMessageEncoding(EncodingFactory.getInstance().getEncoding(encode));
SMPPResponse response=(SubmitSMResp) conn.sendRequest(sm);
received= true;//发送失败,递归重试3次
if (response == null || response.getCommandStatus() != 0) {
Thread.sleep(300);
logger.error("send failed is retrying " +count);
count++;if (count > 3) {return "send failed";
}
sendSms(ton, npi, source, address, text, encode, count);
}
logger.info("send success");return "send success";
}/*** @todo SMPPUtil单例
* @date 2017年8月15日
*@authorlinying*/
private static classSMPPUtilHolder {private static final SMPPUtil SMPP_UTIL = newSMPPUtil();
}
}