因为工作的需求,需要对接短信网关,业务上就是一个注册用户时,需要发送手机验证码;可能别的公司都是使用第三方接口,但是大点的公司,为了安全,他们都有自己的短信消息中心(SMSC)

1.业务需求

- 1.对接短信网关,发送消息,下行发送(MT)   使用openSMPP开源的开发包

- 2.验证码使用redis存储(主要原因是,分布式存储,支持过期时间)

2. 下面是简单的代码实例(包括发送短信和redis存储验证码)

pom中添加依赖

   <dependency>
<groupId>org.opensmpp</groupId>
<artifactId>opensmpp-core</artifactId>
<version>3.0.2</version>
</dependency>
public class SmsController {    

   @Autowiredprivate RedisTemplate redisTemplate;

    public boolean sendVerifyCode() {
String destination = "8613594312686";
String host = "192.168.XX";
String port = "12345";
String userName = "test";
String password = "test";
//存储redis中的key
String key = getDestinationNumKey(destination);
//redis中已存在验证码,则使用redis中存储的验证码(在15分钟的过期时间内发送同一条验证码),否则生成6位数字验证码
Object valueByKey = getValueByKey(key);
String verificationCode = Objects.nonNull(valueByKey) ? valueByKey.toString() : String.valueOf((int) (Math.random() * 900000 + 100000));
//租户(不传,默认default)
boolean sendSuccess = sendMessage(host, port, userName, password, destination, verificationCode);
//发送成功后,验证码存入redis中,并设置过期时间(默认15分钟)
if (sendSuccess) {
putValueToRedisWithTimeout(key, verificationCode, 15, TimeUnit.MINUTES);
}
return sendSuccess;
} private String getDestinationNumKey(String destination) {
return String.format("%s:%s", "DESTINATION", destination);
} public boolean sendMessage(String host,
String port,
String userName,
String password,
String phonenumber,
String verifyCode) {
log.info("start to send sms notification, reciever,host {},port {}, userName {} password {} destinations is {} verifyCode {}", host, port, userName, password, phonenumber, verifyCode);
try {
TCPIPConnection connection = new TCPIPConnection(host, Integer.parseInt(port));
Session session = new Session(connection);
BindRequest request = new BindTransmitter();
request.setSystemId(userName);
request.setPassword(password);
//SMPP protocol version
request.setInterfaceVersion((byte) 0x34);
request.setSystemType("SMPP");
BindResponse bind = session.bind(request);
log.info("bind response debugString {},response command status {}", bind.debugString(), bind.getCommandStatus());
String content = "[Registration]" + verifyCode + " is your verification code. Valid in 15 minutes. Please do not share this code with anyone else.";
SubmitSM submitSM = constructRequest(phonenumber, content);
//bund faild 会导致TCPIPConnection关闭从而导致outputStream关闭从而导致no
SubmitSMResp response = session.submit(submitSM);
log.info("send message result {},command status is {}", response.debugString(), response.getCommandStatus());
} catch (Exception e) {
log.error("invoke sms session exception", e);
} } private SubmitSM constructRequest(String phoneNumber, String content) throws WrongLengthOfStringException, UnsupportedEncodingException {
String recipientPhoneNumber = phoneNumber; SubmitSM request = new SubmitSM();
request.setSourceAddr(createAddress("test")); request.setDestAddr(createAddress(recipientPhoneNumber));
request.setShortMessage(content, Data.ENC_UTF8);
request.setReplaceIfPresentFlag((byte) 0);
request.setEsmClass((byte) 0);
request.setProtocolId((byte) 0);
request.setPriorityFlag((byte) 0);
request.setRegisteredDelivery((byte) 1);// we want delivery reports
request.setDataCoding((byte) 0);
request.setSmDefaultMsgId((byte) 0);
return request;
} private Address createAddress(String address) throws WrongLengthOfStringException {
Address addressInst = new Address();
// national ton
addressInst.setTon((byte) 5);
// numeric plan indicator
addressInst.setNpi((byte) 0);
addressInst.setAddress(address, Data.SM_ADDR_LEN);
return addressInst;
} /**
* Redis中存储Value(value可为string,map,list,set等),并设置过期时间
*
* @param key
* @param value
* @param timeout
* @param unit
*/
public void putValueToRedisWithTimeout(Object key, Object value, final long timeout, final TimeUnit unit) {
try {
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set(key, value, timeout, unit);
} catch (Exception e) {
}
} /**
* 根据key获取Value值
*
* @param key
*/
public Object getValueByKey(Object key) {
Object value = null;
try {
ValueOperations valueOperations = redisTemplate.opsForValue();
value = valueOperations.get(key);
} catch (Exception e) {
}
return value;
} /**
* 根据key获取Value值
*
* @param key
*/
public Object deleteKey(Object key) {
Object value = null;
try {
if (redisTemplate.hasKey(key)) {
redisTemplate.delete(key);
}
} catch (Exception e) {
}
return value;
} }

3. 校验验证码

此处代码就不贴了,直接根据手机号去redis中查询,若有值进行比较是否对错,若无值,直接抛出验证码无效即可

4. 对接网关的api

请参考https://www.world-text.com/docs/interfaces/SMPP/ 和 https://www.smssolutions.net/tutorials/smpp/smpperrorcodes/

5.短信网关模拟器

对接在测试环境时怎么测试是个问题,从网上找到一个模拟SMPP的,感觉挺好用,此处分享地址:SMPP模拟器

其他的参考:

http://read.pudn.com/downloads97/sourcecode/java/400090/OpenSMPP/src/org/smpp/test/SMPPTest.java__.htm

https://support.nowsms.com/discus/messages/1/SMPP_v3_4_Issue1_2-24857.pdf

https://stackoverflow.com/questions/26729958/using-smpp-to-send-sms-texts-in-java?answertab=active#tab-top

https://www.activexperts.com/sms-component/smpp-specifications/smpp-pdu-definition/

https://www.openmarket.com/docs/Content/apis/v4smpp/bind.htm

https://zhuanlan.zhihu.com/p/58237629

sms短信网关对接的更多相关文章

  1. Nagios 安装及微信短信提醒

    引言 Nagios 作为业界非常强大的一款开源监视系统. 监控网络服务(SMTP.POP3.HTTP.NNTP.PING 等): 监控主机资源(处理器负荷.磁盘利用率等): 简单地插件设计使得用户可以 ...

  2. Zabbix 安装及微信短信提醒

    Zabbix简介 Zabbix 近几年得到了各大互联网公司的认可,当然第一点归功与它强大的监控功能,第二点免费开源也得到了广大用户的青睐.Zabbix 能将操作系统中的绝大部分指标进行监控,比如(CP ...

  3. 自学Zabbix3.7-事件Event

    配置item.trigger.都是为发送报警做准备的,什么是事件通知呢?简单的说故障发生了,zabbix会发邮件或者短信给你,告诉你服务器的一些状况. 1. 通知条件 发送通知,需要有如下步骤 定义一 ...

  4. (25)zabbix事件通知

    概述 我们前面花了大量时间去讲解item.trigger.event都是为发送报警做准备的,什么是事件通知呢?简单的说故障发生了,zabbix会发邮件或者短信给你,告诉你服务器的一些状况. 如果没有通 ...

  5. JavaWeb-SpringBoot(抖音)_一、抖音项目制作

    JavaWeb-SpringBoot(抖音)_一.抖音项目制作 传送门 JavaWeb-SpringBoot(抖音)_二.服务器间通讯 传送门 JavaWeb-SpringBoot(抖音)_三.抖音项 ...

  6. 【SMS】移动短信网关返回信息状态代码说明【China Mobile】

    1 由SMSC返回的一般结果状态报告 含义 说明 处理建议DELIVRD 消息发送成功 用户成功接收到短信 ??EXPIRED 因为用户长时间关机或者不在服务区等导致的短消息超时没有递交到用户手机上 ...

  7. 如何对接网建SMS短信通短信验证码接口

    1首先注册登录网建SMS网站  http://www.smschinese.cn/ 2.下载Java代码 3.JAVA调用 import java.io.UnsupportedEncodingExce ...

  8. Android系统应用Mms之Sms短信发送流程(Mms应用部分)二

    1. 新建一条短信, 在发送短信之前, 首先创建的是一个会话Conversation, 以后所有与该接收人(一个或多个接收人)的消息交互, 都在该会话Conversation中. ComposeMes ...

  9. Android 4.4 (KitKat) SMS Apis Change——Android 4.4的一个重大变化

    Android团队通过Android开发博客透漏今年会放出Android 4.4 (KitKat) ,同时更新了 SMS 的部分API.博客上讲只有default SMS app才能对短信数据库有写权 ...

随机推荐

  1. CapstoneCS5210|CS5210低BOM成本方案CS5210|HDMI转VGA芯片方案

    Capstone最新推出的一款HDMI转VGA音视频转接线或者转换器方案芯片CS5210. 其设计的优势在于内置晶振,外围电路器件较少设计简单,芯片封装集成度较高,方案BOM成本低,相比其他方案产品更 ...

  2. Android物联网应用程序开发(智慧园区)—— 登录界面开发

    效果: 布局代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:an ...

  3. 使用 JavaScript 中的变量、数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算符的不同位置得到不同的结果

    查看本章节 查看作业目录 需求说明: 使用 JavaScript 中的变量.数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算 ...

  4. 【】JSON语法RFC4627

    Network Working Group D. Crockford Request for Comments: 4627 JSON.org Category: Informational July ...

  5. Eclipse导入Elasticsearch源码

    Eclipse导入Elasticsearch源码的步骤, 基于Elasticsearch 6.2.2的源码版本. 1.安装JDK1.9 Elasticsearch 6.2.2需要JDK1.9编译,否则 ...

  6. html基础 字符实体 用于html中特殊符号的展示 比如:多个空格、代码展示

    结构:&+英文: 常见的字符实体  

  7. 双buffer实现无锁切换

    大家好,我是雨乐! 在我们的工作中,多线程编程是一件太稀松平常的事.在多线程环境下操作一个变量或者一块缓存,如果不对其操作加以限制,轻则变量值或者缓存内容不符合预期,重则会产生异常,导致进程崩溃.为了 ...

  8. 初识python: 装饰器

    定义: 本质是函数,功能是"装饰"其它函数,即为其他函数添加附加功能原则: 1.不能修改被装饰函数的源代码: 2.不能修改被装饰函数的调用方式实现装饰器知识储备: 1.函数即&qu ...

  9. 基于appnium+python+夜神模拟器的自动化

    首先搭好appnium环境!参考https://www.cnblogs.com/testlearn/p/11419797.html 1.安装夜神模拟器 下载安装夜神模拟器后,在cmd命令输入adb c ...

  10. vim安装使用pathogen

    pathogen是什么? pathogen一般作为vim新手的第一个插件,用来统一管理vim插件包, (官方解释)非常容易的管理你的 'runtimepath' ,在实际项目中,vim-pathoge ...