SMPP SMS发送长短信

时间:2018-11-18 19:44:00

标签: smpp jsmpp

我有一个Java代码可以向SMPP提交长SMS,但是在执行过程中,我收到“ 长度必须小于或等于254。实际长度为270 ”的错误。使用长字符串或任何阿拉伯字符时。

任何人都可以帮助我确定原因并建议我如何解决问题。

下面是我正在尝试的代码。

import java.io.IOException;
import java.util.Date;
import java.util.Random;

import org.jsmpp.InvalidResponseException;
import org.jsmpp.PDUException;
import org.jsmpp.bean.Alphabet;
import org.jsmpp.bean.BindType;
import org.jsmpp.bean.ESMClass;
import org.jsmpp.bean.GeneralDataCoding;
import org.jsmpp.bean.MessageClass;
import org.jsmpp.bean.NumberingPlanIndicator;
import org.jsmpp.bean.OptionalParameter;
import org.jsmpp.bean.OptionalParameters;
import org.jsmpp.bean.RegisteredDelivery;
import org.jsmpp.bean.SMSCDeliveryReceipt;
import org.jsmpp.bean.TypeOfNumber;
import org.jsmpp.extra.NegativeResponseException;
import org.jsmpp.extra.ResponseTimeoutException;
import org.jsmpp.session.BindParameter;
import org.jsmpp.session.SMPPSession;
import org.jsmpp.util.AbsoluteTimeFormatter;
import org.jsmpp.util.TimeFormatter;

public class SendLongSMSMessage
{
        private static TimeFormatter    timeFormatter   = new AbsoluteTimeFormatter();

    public String[] submitLongSMS(String MSISDN, String senderAddr, String message) throws Exception
    {
            SMPPSession session = getSession();

            String[] msgId = null;
            int splitSize = 135;
            int totalSize = 140;
            int totalSegments = 0;

            RegisteredDelivery registeredDelivery = new RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT);

            GeneralDataCoding dataCoding = new GeneralDataCoding(false, false, MessageClass.CLASS1,
            Alphabet.ALPHA_8_BIT);
            ESMClass esmClass = new ESMClass();

            if (message != null && message.length() > totalSize)
            {
                    totalSegments = getTotalSegmentsForTextMessage(message);
            }

            Random random = new Random();
            OptionalParameter sarMsgRefNum = OptionalParameters.newSarMsgRefNum((short) random.nextInt());
            OptionalParameter sarTotalSegments = OptionalParameters.newSarTotalSegments(totalSegments);

            String[] segmentData = splitIntoStringArray(message, splitSize, totalSegments);

            msgId = new String[totalSegments];
            for (int i = 0, seqNum = 0; i < totalSegments; i++)
            {
                    seqNum = i + 1;
                    OptionalParameter sarSegmentSeqnum = OptionalParameters.newSarSegmentSeqnum(seqNum);
                    try
                    {       byte[] byteText = segmentData[i].getBytes("UTF-16BE");
                            msgId[i] = session.submitShortMessage("", TypeOfNumber.NATIONAL,
                            NumberingPlanIndicator.ISDN, "9999999999", TypeOfNumber.NATIONAL,
                            NumberingPlanIndicator.ISDN, MSISDN, esmClass, (byte) 0, (byte) 0, timeFormatter
                            .format(new Date()), null, registeredDelivery, (byte) 0, dataCoding, (byte) 0, byteText, sarMsgRefNum, sarSegmentSeqnum, sarTotalSegments);

                            System.out.println("Message id  for segment " + seqNum + " out of totalsegment "
                            + totalSegments + "is" + msgId[i]);

                    }
                    catch (PDUException e)
                    {
                            System.out.println("PDUException has occured" + e.getMessage());
                    }
                    catch (ResponseTimeoutException e)
                    {
                            System.out.println("ResponseTimeoutException has occured" + e.getMessage());
                    }
                    catch (InvalidResponseException e)
                    {
                            System.out.println("InvalidResponseException has occured" + e.getMessage());
                    }
                    catch (NegativeResponseException e)
                    {
                            System.out.println("NegativeResponseException has occured" + e.getMessage());
                    }
                    catch (IOException e)
                    {
                            System.out.println("IOException has occured" + e.getMessage());
                    }
            }
             session.unbindAndClose();
            return msgId;
    }

    private SMPPSession getSession() throws Exception
    {
            return newSession();
    }

    private SMPPSession newSession() throws Exception
    {
            BindParameter bindParam = new BindParameter(BindType.BIND_TX, "<user_name>", "<pass_word>", "tdd",
            TypeOfNumber.UNKNOWN, NumberingPlanIndicator.UNKNOWN, null);

            return new SMPPSession("17.1.1.1", 6666, bindParam);
    }

    public int getTotalSegmentsForTextMessage(String message)
    {
            int splitPos = 135;
            int totalsegments = 1;
            if (message.length() > splitPos)
            {
                    totalsegments = (message.length() / splitPos) + ((message.length() % splitPos > 0) ? 1 : 0);
            }
            return totalsegments;
    }

    public String[] splitIntoStringArray(String msg, int pos, int totalSegments)
    {
            String[] segmentData = new String[totalSegments];
            if (totalSegments > 1)
            {
                    int splitPos = pos;

                    int startIndex = 0;

                    segmentData[startIndex] = new String();
                    segmentData[startIndex] = msg.substring(startIndex, splitPos);

                    for (int i = 1; i < totalSegments; i++)
                    {
                            segmentData[i] = new String();
                            startIndex = splitPos;
                            if (msg.length() - startIndex <= pos)
                            {
                                    segmentData[i] = msg.substring(startIndex, msg.length());
                            }
                            else
                            {
                                    splitPos = startIndex + pos;
                                    segmentData[i] = msg.substring(startIndex, splitPos);
                            }
                    }
            }
            return segmentData;
    }

    public static void main(String[] args) throws Exception
    {
            SendLongSMSMessage slSMS = new SendLongSMSMessage();

            String message = "Tech Dive heralds the arrival of a community of Developers "
            + "who share, collaborate and exchange ideas, concepts, technical know-how. "
            + "This forum lets you take a deep dive in technical topics that are hot and happening as well as on legacy systems."
            + "The idea of the forum is to ensure collaboration amongst developers through exchange of ideas/concepts "
            + "so their technical skills are enhanced."
            + "We plan to bring in experienced professionals on board so content/blog written is authentic and precise."
            + "Come, join us and be a part of new way of collaboration!";

            String MSISDN = "9500000000";

            String senderAddr = "8500000000";

            slSMS.submitLongSMS(MSISDN, senderAddr, message);
    }
}

1 个答案:

答案 0 :(得分:0)

解决此类问题的最佳方法是使用SMPP官方文档: https://smpp.org/SMPP_v3_4_Issue1_2.pdf

要发送带有长消息的SubmitSm,您需要使用名为message_payload的optional_parameter而不是通用的short_message参数。

您也可以在文档中阅读此信息:

可以在sm_length字段中指定的最大消息长度 是254个八位位组。如果ESME希望提交更长的信息 如果长度超过254个八位字节,则必须将sm_length字段设置为NULL,并且 message_payload可选参数必须填充消息 长度值和用户数据。

要解决您的问题,您需要在每次发送消息时检查一次,其中有多少字节,如果大于254,则将message_payload添加为您的optional_parameter而不是short_message。

使用cloudhopper库,您可以这样做:

    if (length > 254) {
        submitSm.setOptionalParameter(new Tlv(
                SmppConstants.TAG_MESSAGE_PAYLOAD,
                CharsetUtil.encode(messageBody, CharsetUtil.CHARSET_UCS_2),
                "message_payload"));
    } else {
        submitSm.setShortMessage(CharsetUtil.encode(messageBody, CharsetUtil.CHARSET_UCS_2));
    }