java长连接发短信-smppapi-0.3.9

package cn.richinfo.cmail.vasp.common.util;

import ie.omk.smpp.Address;
import ie.omk.smpp.Connection;
import ie.omk.smpp.message.BindResp;
import ie.omk.smpp.message.EnquireLink;
import ie.omk.smpp.message.EnquireLinkResp;
import ie.omk.smpp.message.SMPPPacket;
import ie.omk.smpp.message.SMPPResponse;
import ie.omk.smpp.message.SubmitSM;
import ie.omk.smpp.message.SubmitSMResp;
import ie.omk.smpp.util.EncodingFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import cn.richinfo.cmail.common.config.PropertiesUtil;

/**
 * @todo 长连接发短信
 * @date 2017年8月15日
 * @author linying
 */
public class SMPPUtil {

    private Logger logger = Logger.getLogger(SMPPUtil.class);
    private boolean connected = false; // 是否已连接
    private boolean received = false; // 是否接收心跳包
    private Connection conn = null;// ESME到SMSC的连接

    private SMPPUtil() {
    }

    public static final SMPPUtil getInstance() {
        return SMPPUtilHolder.SMPP_UTIL;
    }

    /**
     * @todo 打开链接
     * @throws Exception
     */
    private void openLink() throws Exception {
        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 = new Connection(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日
     * @author linying
     */
    class KeepHeartbeat implements Runnable {
        private long delay = PropertiesUtil.getPropertyLong("zte.notice.smsc.keep.delay");

        public void run() {
            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日
     * @author linying
     */
    class ReceivePackets implements Runnable {
        public void run() {
            while (connected) {
                try {
                    if (received) {
                        SMPPPacket packet = conn.readNextPacket();
                        if (null != packet && packet.getCommandStatus() == 0) {
                            logger.info("[smsc request packet ok]");
                            EnquireLink link = new EnquireLink();
                            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 关闭链接
     * @return void
     */
    private void closeLink() {
        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 发送短信
     * @param address
     * @param text
     * @return String
     * @throws Exception
     */
    public String sendSms(String address, String text) throws Exception {
        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;
        return sendSms(ton, npi, source, address, text, encode, count);
    }

    private String sendSms(int ton, int npi, String source, String address, String text, int encode, int count) throws Exception {
        // 发送短信中,停止接收心跳
        received = false;
        // 没有绑定
        if (!connected) {
            openLink();
        }
        logger.info("connected is true");
        SubmitSM sm = (SubmitSM) conn.newInstance(SMPPPacket.SUBMIT_SM);
        if (StringUtils.isNotEmpty(source)) {
            sm.setSource(new Address(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日
     * @author linying
     */
    private static class SMPPUtilHolder {
        private static final SMPPUtil SMPP_UTIL = new SMPPUtil();
    }

}

 

#heart beat delay(milliseconds)
zte.notice.smsc.keep.delay=20000

#heart beat message
zte.notice.smsc.keep.message=message[send heart beat data package]

#stop the number of heart beats
zte.notice.smsc.keep.count=5

#the request conten to send to the SMSC
zte.notice.msg=【%s】你有1封新邮件,来自%s,主题是%s

#the hostname of the SMSC.
zte.notice.smsc.host=127.0.0.1

#the port to connect to. If 0, use the default SMPP port * number.
zte.notice.smsc.port=80

#the system ID to identify as to the SMSC.
zte.notice.smsc.systemId=0

#password to use to authenticate to the SMSC.
zte.notice.smsc.password=0

#the system type to bind as.
zte.notice.smsc.systemType=0

#SMS coding(1.US-ASCII, 3.ISO-8859-1, 8.ISO-10646-UCS-2)
zte.notice.sms.encoding=8

#the type of number
zte.notice.sms.ton=0

#the numbering plan indicator
zte.notice.sms.npi=0

#source address
zte.notice.sms.sourceAddress=88888888

#new mail notification URL
zte.notice.url=http://127.0.0.1/vaservices/TestURL?act=1&msisdn=%s

 

posted @ 2017-08-08 17:19  呱哇  阅读(973)  评论(0编辑  收藏  举报