说明:

1. 利用华为提供的jar包(smproxy.jar)进行开发。

2. 根据华为提供的“短消息代理(CMPP20 SMProxy)使用说明书.doc”文档说明。

3. 短信的开发:上行,下行,下行短信回执。

一、首先必须继承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;}@Overridepublic CMPPMessage onDeliver(CMPPDeliverMessage msg) {log.debug("启动接收短信");gatewaySmsService.processRecvDeliverMsg(msg);return super.onDeliver(msg);}@Overridepublic 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";@Overridepublic 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);}}//发送短信@Overridepublic 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消息总条数,短短信这里是1i + 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,铃声图片设11,//@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连接状态 正常等于nullString stateDesc = smProxy.getConnState();log.debug("网关TCP状态:" + stateDesc);if (stateDesc != null) {log.debug("网关重新连接");smProxy.close();init();}return OHResult.Fail("发送失败");}}//接收短信@Overridepublic 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();}}}@Overridepublic 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);elses = 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

基于华为SMProxy开发cmpp2.0(跳坑版)相关推荐

  1. Java企业微信会话存档开发(从跳坑到爬坑)

    Java企业微信会话存档开发(从跳坑到爬坑) 本文仅作为方便首次开发企业微信使用 文章目录 Java企业微信会话存档开发(从跳坑到爬坑) 前言 一.开发准备 1.企业微信后台配置 2.sdk下载 3. ...

  2. 半桶水开发 CMPP2.0 with Spring + JPA 2

    [list] [*][url=http://rikugun.iteye.com/blog/296384]半桶水开发 CMPP2.0 with Spring + JPA 1[/url] [*][url= ...

  3. 华为手机刷linux系统,华为Harmony OS 2.0手机Beta版刷机包流出:电脑助手一键刷入/手动...

    原标题:华为 Harmony OS 2.0 手机 Beta 版刷机包流出,Mate 30 Pro 可用(附下载地址) 月24日消息 IT360 论坛今日放出了三款 Mate 30 Pro 机型的华为鸿 ...

  4. 微信小程序原生开发技巧及跳坑心得

    常用功能 1.事件带参 在微信小程序中,给事件的回调函数内部传递参数不是通过函数调用传递实参的方式传递的,而是通过在view上绑定属性,然后在回调函数的事件对象的currentTarget属性中的da ...

  5. vue项目的停止_基于Vue项目开发中遇到的坑及终结

    之前一直在公司忙项目,忙项目的,好歹是发布了1.0版本.终于是有时间写一个总结了. 话说我就一个实习生一进来就要做项目核心,真的有点受宠若惊,还好项目是1.0版本,先实现部分功能,访问量也不大,加上一 ...

  6. HarmonyOS刷机包,华为Harmony OS 2.0手机Beta版刷机包流出 采用组件化设计方案

    IT360 论坛今日放出了三款 Mate 30 Pro 机型的华为鸿蒙 Harmony OS 2.0 手机系统 Beta 版固件全量包,仅包括华为 Mate 30 Pro 5G 的三个版本. 下载链接 ...

  7. 华为鸿蒙内测报名要报吗,华为鸿蒙HarmonyOS 2.0公测版/内测版申请和招募指南,快来报名尝鲜吧!...

    6月2日晚华为正式发布了大家期待已久的鸿蒙HarmonyOS2.0操作系统,发布会上展示了HarmonyOS2全新的系统架构.革命性的分布式技术.全新的原子化服务.全新的卡片设计.极致的系统性能.发布 ...

  8. 怎么给Mongodb设置账号密码(跳坑版)

    1.admin表创建一个admin user并设置密码并给userAdminAnyDatabase的权限; //可以在mongodb刚装好后,用官网自带的客户端MongoDB Compass一键con ...

  9. 两百条微信小程序开发跳坑指南(不定时更新)

    2019独角兽企业重金招聘Python工程师标准>>> 微信小程序联盟出品 跳坑textarea<二百二十三>不显示文本及textarea相关问题集合 跳坑<二百一 ...

  10. 华为软件开发云测评报告三:测试管理

    往期文章: 华为软件开发云测评报告一:项目管理 华为软件开发云测评报告二:代码检查 体验环境 体验方式:PC端 系统:Windows 64位 浏览器类型:Chrome浏览器 浏览器版本:58.0.30 ...

最新文章

  1. js中的失误导致的奇怪事
  2. 交通运输部:春节期间小客车免收高速通行费
  3. C++简易测试代码框架
  4. Java程序员需要掌握哪些技能才能通过大公司的面试
  5. IOS ActivityIndicator 活动指示器使用
  6. vs2013 编译libevent32和64bit
  7. 使用J-LINK烧写MICRO2440的NOR
  8. android记账本流程图,记账的基本流程
  9. 四针角oled屏连接arduino_Arduino提高篇03—OLED屏图片显示
  10. 手机如何登录企业邮箱,公司电子邮箱登录页面
  11. java 中counter什么意思_方便适用的计数器Counter
  12. 计算机国家级论文,计算机类期刊汇总(核心期刊,国家级期刊)
  13. 数据分析 - pandas(7)
  14. PHP 获取格式化的日期和时间
  15. 菜菜的刷题日记 | 66.加一 Plus One
  16. 李沐d2l《动手学深度学习》第二版——风格迁移源码详解
  17. CSS 列表样式 (ul)
  18. 微信小程序 03 数据劫持代理和事件绑定
  19. 循环结构中“当型”与“直到型”判断的理解
  20. 通过QQ号查询对方QQ绑定手机号

热门文章

  1. select2参数介绍
  2. Percona XtraBackup User Manual
  3. LPC4370 USERMANUAL
  4. 计算机作文600字关于科学事业,关于科学的作文600字(精选11篇)
  5. 联想消费生态秋季新品发布:拯救者手机、VR及小新平板等齐亮相
  6. 导出PDF /home/education/font/simsun.ttc not found as file or resource.
  7. GitHub 上受欢迎的 Android UI Library 整理一
  8. android集成第三方---集成wps实现文档阅读功能
  9. SQL注入双引号报错注入
  10. 抓包获取百度音乐API