一、首先必须继承SMProxy的抽象类,代码如下:
import com.huawei.insa2.comm.cmpp.message.CMPPDeliverMessage;
import com.huawei.insa2.comm.cmpp.message.CMPPMessage;
import com.huawei.insa2.util.Args;
import com.huawei.smproxy.SMProxy;
import lombok.extern.slf4j.Slf4j;
/**
* 重写华为方法
*/
@Slf4j
public class SmsSendProxy extends SMProxy {
private GatewaySmsServiceImpl gatewaySmsService;
public SmsSendProxy(Args args, GatewaySmsServiceImpl gatewaySmsService) {
super(args);
this.gatewaySmsService = gatewaySmsService;
}
@Override
public CMPPMessage onDeliver(CMPPDeliverMessage msg) {
log.debug("启动接收短信");
gatewaySmsService.processRecvDeliverMsg(msg);
return super.onDeliver(msg);
}
@Override
public void onTerminate() {
gatewaySmsService.onTerminate();
}
}
二、基于该类,进行短信的接收和发送的编写
import com.huawei.insa2.comm.cmpp.message.CMPPDeliverMessage;
import com.huawei.insa2.comm.cmpp.message.CMPPSubmitMessage;
import com.huawei.insa2.comm.cmpp.message.CMPPSubmitRepMessage;
import com.huawei.insa2.util.Args;
import com.huawei.insa2.util.Cfg;
import com.huawei.insa2.util.TypeConvert;
import com.demo.common.model.OHResult;
import com.demo.order.service.GatewaySmsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.*;
/**
* 网关短信
*/
@Slf4j
@Service
public class GatewaySmsServiceImpl implements GatewaySmsService {
SmsSendProxy smProxy;
private static String RETURN_UNICODE_SC = "UnicodeBigUnmarked";
private static String RETURN_UNICODE_TEST = "GB2312";
@Override
public void init() {
try {
File file = new File("/home/weihu/cmpp.xml");
if (!file.exists()) {
return;
}
Args args = new Cfg("/home/weihu/cmpp.xml").getArgs("ismg");
smProxy = new SmsSendProxy(args, this);
} catch (Exception e) {
log.error("建立网关连接失败", e);
}
}
//发送短信
@Override
public OHResult sendMessage(String[] phones, String message) {
int rstNum = -1;
long msgId = -1;
List<byte[]> list = this.getLongByte(message);
if (CollectionUtils.isEmpty(list)) {
return OHResult.Fail("发送失败");
}
try {
for (String phone : phones) {
log.debug("发送号码:{}", phone);
for (int i = 0; i < list.size(); i++) {
CMPPSubmitMessage cmppSubmitMessage = new CMPPSubmitMessage(
list.size(),//@pk_Total 相同msg_Id消息总条数,短短信这里是1
i + 1,//@pk_Number 相同msg_Id的消息序号
1,//@registered_Delivery 是否要求返回状态报告
1,//@msg_Level 信息级别
"",// @service_Id 业务类型 用户自定义 用来分类查询
2,//@fee_UserType 0对目的终端计费;1对源终端计费;2对SP计费;
"",//@fee_Terminal_Id 被计费用户的号码
0,//@tp_Pid GSM协议类型 一般文本的时候设0,铃声图片设1
1,//@tp_Udhi GSM协议类型 0不包含头部信息 1包含头部信息
8,//@msg_Fmt 消息格式
"123456",//@msg_Src 消息内容来源 6位的企业代码,这里需修改
"02",// @fee_Type 资费类别 一般为02:按条计信息费
"0",//@fee_Code 资费代码(以分为单位)
null,//@valid_Time 存活有效期
null,//@at_Time 定时发送时间
"10085",//@src_Terminal_Id 移动所提供的服务代码 此处需修改
phones,//@dest_Terminal_Id 接收业务的MSISDN号码,就是接收短信的手机号,String数组
list.get(i),//@msg_Content 消息内容 byte[],发送的消息内容,需要转化为byte[]
"" //预留
);
CMPPSubmitRepMessage sub = (CMPPSubmitRepMessage) smProxy.send(cmppSubmitMessage);
//发送结果
rstNum = sub.getResult();
//网关生成的唯一标识
msgId = TypeConvert.byte2long(sub.getMsgId());
log.debug("发送号码:{} result:{} msgId:{}", phone, rstNum, msgId);
}
if (rstNum == 0) {
log.debug("{} 发送成功", phone);
return OHResult.Success("发送成功", String.valueOf(msgId));
} else {
log.debug("{} 发送失败", phone);
return OHResult.Fail("1", "发送失败", String.valueOf(msgId));
}
}
} catch (Exception e) {
log.error("发送异常:", e);
//查询 SMGPSMProxy 与网关的 TCP连接状态 正常等于null
String stateDesc = smProxy.getConnState();
log.debug("网关TCP状态:" + stateDesc);
if (stateDesc != null) {
log.debug("网关重新连接");
smProxy.close();
init();
}
return OHResult.Fail("发送失败");
}
}
//接收短信
@Override
public void processRecvDeliverMsg(CMPPDeliverMessage deliverMsg) {
if (deliverMsg.getRegisteredDeliver() == 0) {
//上行短信
try {
//字节
int msgFmt = deliverMsg.getMsgFmt();
//上行号码
String srcTerminalId = esc0(deliverMsg.getSrcterminalId());
//上行短信内容
String msgContent;
if (deliverMsg.getMsgFmt() == 8) {
msgContent = esc0(new String(deliverMsg.getMsgContent(), RETURN_UNICODE_SC));
} else {
msgContent = esc0(new String(deliverMsg.getMsgContent(), RETURN_UNICODE_TEST));
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
//发送短信后的回执状态
try {
//发送号码
String srcTerminalId = esc0(deliverMsg.getSrcterminalId());
//回执状态
String stat = esc0(deliverMsg.getStat());
//statusMsgId 和 sendMessage类回调的msgId 一致
long statusMsgId = TypeConvert.byte2long(deliverMsg.getStatusMsgId());
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onTerminate() {
log.debug("网关重新连接");
smProxy.close();
init();
}
public List<byte[]> getLongByte(String message) {
List<byte[]> list = new ArrayList<byte[]>();
try {
//转换为byte[]
byte[] messageUCS2 = message.getBytes("UnicodeBigUnmarked");
// 长短信长度
int messageUCS2Len = messageUCS2.length;
int maxMessageLen = 140;
// 长短信发送
if (messageUCS2Len > maxMessageLen) {
//int tpUdhi = 1;
//长消息是1.短消息是0
//int msgFmt = 0x08;//长消息不能用GBK // 长短信分为多少条发送
int messageUCS2Count = messageUCS2Len / (maxMessageLen - 6) + 1;
byte[] tp_udhiHead = new byte[6];
Random random = new Random();
//随机填充tp_udhiHead[3] 标识这批短信
random.nextBytes(tp_udhiHead);
tp_udhiHead[0] = 0x05;
tp_udhiHead[1] = 0x00;
tp_udhiHead[2] = 0x03;
// tp_udhiHead[3] = 0x0A;
tp_udhiHead[4] = (byte) messageUCS2Count;
// 默认为第一条
tp_udhiHead[5] = 0x01;
for (int i = 0; i < messageUCS2Count; i++) {
tp_udhiHead[5] = (byte) (i + 1);
byte[] msgContent;
// 不为最后一条
if (i != messageUCS2Count - 1) {
msgContent = byteAdd(tp_udhiHead, messageUCS2, i * (maxMessageLen - 6), (i + 1) * (maxMessageLen - 6));
list.add(msgContent);
} else {
msgContent = byteAdd(tp_udhiHead, messageUCS2, i * (maxMessageLen - 6), messageUCS2Len);
list.add(msgContent);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
public byte[] byteAdd(byte[] tpUdhiHead, byte[] messageUCS2, int i, int j) {
byte[] msgb = new byte[j - i + 6];
System.arraycopy(tpUdhiHead, 0, msgb, 0, 6);
System.arraycopy(messageUCS2, i, msgb, 6, j - i);
return msgb;
}
public String esc0(String s) {
if (s == null || s.length() == 0) {
s = "";
return s;
} else {
int i = s.indexOf('\0');
if (i > 0)
s = s.substring(0, i);
else
s = s.replaceAll("\0", "");
}
return s;
}
}
三、cmpp.xml网关配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<!--与InfoX建立连接所需参数-->
<ismg>
<!-- InfoX主机地址,与移动签合同时移动所提供的地址 需修改-->
<host>127.0.0.1</host>
<!-- InfoX主机端口号 cmpp2.0默认为7890,cmpp3.0为7891-->
<port>7890</port>
<!--(登录帐号SP…ID)与移动签合同时所提供的企业代码 6位 需修改-->
<source-addr>123456</source-addr>
<!--登录密码 默认为空 如有需修改-->
<shared-secret>654321</shared-secret>
<!-- 心跳信息发送间隔时间(单位:秒) -->
<heartbeat-interval>10</heartbeat-interval>
<!-- 连接中断时重连间隔时间(单位:秒)-->
<reconnect-interval>10</reconnect-interval>
<!-- 需要重连时,连续发出心跳而没有接收到响应的个数(单位:个)-->
<heartbeat-noresponseout>5</heartbeat-noresponseout>
<!-- 操作超时时间(单位:秒) -->
<transaction-timeout>10</transaction-timeout>
<!--双方协商的版本号(大于0,小于256)-->
<version>1</version>
<!--是否属于调试状态,true表示属于调试状态,所有的消息被打印输出到屏幕,false表示不属于调试状态,所有的消息不被输出-->
<debug>true</debug>
</ismg>
</config>
PS:
1、接收短信中的号码会有86,+86开头出现,需要人工处理。
2、接收短信中的号码和内容会有特殊字符,此处代码已经进行了处理。
3、发送短信后回调的msgId和接收短信中statusMsgId是一致,从而确定是哪条短信发送的回执。
4、SMProxy说明书:http://www.docin.com/p-43812154.html