因为工作的需求,需要对接短信网关,业务上就是一个注册用户时,需要发送手机验证码;可能别的公司都是使用第三方接口,但是大点的公司,为了安全,他们都有自己的短信消息中心(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. Java面向对象笔记 • 【第6章 Java常用类】

    全部章节   >>>> 本章目录 6.1 Object类 6.1.1 Object类概述 6.1.2 Object的常用方法 6.1.3 实践练习 6.2 String类和St ...

  2. Java基础(八)——IO流3_对象流

    一.对象流 1.序列化与反序列化 序列化:将内存中的Java对象保存到磁盘中或通过网络传输出去. 反序列化:将磁盘文件中的对象还原为内存中的一个Java对象. 用途: (1)将对象保存到物理硬盘:比如 ...

  3. Python项目生成requirements.txt文件及pip升级问题解决及流程

    缘由:新项目使用Python, PC上的python包不全,需要通过requirements.txt文件指定安装所需包 pip安装遇到一些坑 一.直接使用pip包管理工具生成requirements. ...

  4. Python_paramiko-与linux交互

    一.基础功能介绍 # coding=utf-8 import paramiko from time import sleep # 建立通信 transport = paramiko.Transport ...

  5. [ flask-migrate ] 记自己犯的一次低级错误

    问题描述 从github上pull了别人的项目学习,项目用flask-migrate来迁移数据库.查看了一下,作者把数据库文件 app.db 删除了,不过migrations文件夹留着的,因此我只需要 ...

  6. MATLAB绘图入门

    %%%1.运算符:(1).% mean() -->平均值 1.对于一个数组,mean(数组名)则返回均值2.对于一个矩阵,mean(数组名,1或2) 1代表返回矩阵每列的平均值 2代表返回矩阵每 ...

  7. Docker 安装与常用命令

    目录 Docker 安装 1)安装 2)启动 3)镜像加速器 Docker 常用命令 1)Docker 进程相关命令 2)Docker 镜像相关命令 docker search:查找镜像仓库中的镜像 ...

  8. Hadoop 代码实现文件上传

    本项目主要实现Windows下利用代码实现Hadoop中文件上传至HDFS 实现上传文本文件中单词个数的计数 1.项目结构 2.相关代码 CopyFromLocalFile 1 package com ...

  9. 新手学习Java,如何快速从入门到精通!

    首先我要给你说的是,任何一个东西从零到精通,都是需要一个过程的,就相当于我们在小学的时候学乘法口诀表,背文言文一样,都是需要我们慢慢的去渡过这个阶段,我们才能慢慢的掌握,其次,毕竟这是一门编程语言,你 ...

  10. 【刷题-LeetCode】121 Best Time to Buy and Sell Stock

    Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of a gi ...