移动MAS发送短信,接受状态和接受回复【HTTP】

移动MAS短信平台就是一个发送短信的平台,可以发送普通短信模板短信一对一,一对多等短信

下面主要是基于Java(HTTP方式)实现短信的下行(发送)上行(接受)和接受短信状态

接口全是根据HTTP接口文档写的,有需要的可以关注下面的公众号回复:移动MAS接口文档
在这里插入图片描述


一、创建账号

1-1、登录后的界面如下图所示(http://mas.10086.cn)

在这里插入图片描述

1-2、配置接口

从上图左边的管理菜单进入
在这里插入图片描述

1-3、获取签名

在这里插入图片描述
在这里插入图片描述


二、代码

根据接口文档我写了下面的工具类,其实就是把接口文档翻译一下。因为我们是http请求,json数据格式。所以使用到了一个jsonUtils和一个httpUtils

2-1、HttpUtils

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;public class HttpUtils {private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);public static String sendPost(String url, String param, String orderType) throws Exception {PrintWriter out = null;String result = "";DataInputStream dis=null;
//		logger.debug("url=" + url + ";orderType=" + orderType + ";param=" + param);try {URL realUrl = new URL(url);// 打开和URL之间的连接URLConnection conn = realUrl.openConnection();conn.addRequestProperty("orderType", orderType);// 设置通用的请求属性conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");conn.setRequestProperty("Content-Type", "application/Json; charset=UTF-8");conn.setConnectTimeout(5000);conn.setReadTimeout(5000);//conn.setRequestProperty("contentType", "UTF-8");// 发送POST请求必须设置如下两行conn.setDoOutput(true);conn.setDoInput(true);// 获取URLConnection对象对应的输出流
//			out = new PrintWriter(conn.getOutputStream());
//			// 发送请求参数
//			out.print(param);
//			// flush输出流的缓冲
//			out.flush();OutputStream os =  conn.getOutputStream();os.write(param.getBytes("UTF-8"));os.flush();// 定义BufferedReader输入流来读取URL的响应byte[] bs = new byte[0];byte[] btemp = new byte[1024];int count =0;dis = new DataInputStream(conn.getInputStream());while((count = dis.read(btemp))>-1) {byte[] temp = bs;bs=new byte[temp.length+count];System.arraycopy(temp, 0, bs, 0, temp.length);System.arraycopy(btemp, 0, bs, temp.length, count);}result = new String(bs, "UTF-8");}// 使用finally块来关闭输出流、输入流finally {try {if (out != null) {out.close();}if (dis != null) {dis.close();}} catch (IOException ex) {ex.printStackTrace();}}return result;}public static String sendGet(String url, Map<String, Object> param) throws Exception {// 创建Httpclient对象CloseableHttpClient httpclient = HttpClients.createDefault();String resultString = "";CloseableHttpResponse response = null;try {// 创建uriURIBuilder builder = new URIBuilder(url);if (param != null) {for (String key : param.keySet()) {builder.addParameter(key, param.get(key).toString());}}URI uri = builder.build();// 创建http GET请求HttpGet httpGet = new HttpGet(uri);// 执行请求response = httpclient.execute(httpGet);// 判断返回状态是否为200if (response.getStatusLine().getStatusCode() == 200) {resultString = EntityUtils.toString(response.getEntity(), "utf-8");}} catch (Exception e) {e.printStackTrace();throw e;} finally {try {if (response != null) {response.close();}httpclient.close();} catch (IOException e) {e.printStackTrace();throw e;}}return resultString;}public static String sendGet(String url) throws Exception {return sendGet(url, null);}public static String getEncoding(String str) {String encode = "GB2312";try {if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是GB2312String s = encode;return s; //是的话,返回“GB2312“,以下代码同理}} catch (Exception exception) {}encode = "ISO-8859-1";try {if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是ISO-8859-1String s1 = encode;return s1;}} catch (Exception exception1) {}encode = "UTF-8";try {if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是UTF-8String s2 = encode;return s2;}} catch (Exception exception2) {}encode = "GBK";try {if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是GBKString s3 = encode;return s3;}} catch (Exception exception3) {}return "";}
}

2-2、JsonUtils

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;import java.io.IOException;
import java.util.List;
import java.util.Map;/*** json 相关格式化*/
public class JsonUtils {// 定义jackson对象private static ObjectMapper MAPPER = new ObjectMapper();{MAPPER.setSerializationInclusion(Include.ALWAYS);}/*** 将对象转换成json字符串。* <p>Title: pojoToJson</p>* <p>Description: </p>* @param data* @return*/public static String objectToJson(Object data) {try {String string = MAPPER.writeValueAsString(data);return string;} catch (JsonProcessingException e) {e.printStackTrace();}return null;}public static JsonNode stringToJsonNode(String data) {try {JsonNode jsonNode = MAPPER.readTree(data);return jsonNode;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}/*** 将json结果集转化为对象** @param jsonData json数据* @param clazz 对象中的object类型* @return* @throws Exception*/public static <T> T objectToPojo(Object jsonData, Class<T> beanType) throws Exception {T t = MAPPER.readValue(MAPPER.writeValueAsString(jsonData), beanType);return t;}/*** 将json结果集转化为对象** @param jsonData json数据* @param clazz 对象中的object类型* @return* @throws Exception*/public static <T> T jsonToPojo(String jsonData, Class<T> beanType) throws Exception {T t = MAPPER.readValue(jsonData, beanType);return t;}/*** 将json数据转换成pojo对象list* <p>Title: jsonToList</p>* <p>Description: </p>* @param jsonData* @param beanType* @return*/public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);try {List<T> list = MAPPER.readValue(jsonData, javaType);return list;} catch (Exception e) {e.printStackTrace();}return null;}/*** 将object数据转换成pojo对象list* <p>Title: jsonToList</p>* <p>Description: </p>* @param jsonData* @param beanType* @return*/public static <T>List<T> objectToList(Object jsonData, Class<T> beanType) {JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);try {List<T> list = MAPPER.readValue(MAPPER.writeValueAsString(jsonData), javaType);return list;} catch (Exception e) {e.printStackTrace();}return null;}/*** 将JSON数据转换成Map* @param jsonData* @return*/public static Map<String,Object> jsonToMap(String jsonData) {try {Map map = MAPPER.readValue(jsonData, Map.class);return map;} catch (Exception e) {e.printStackTrace();}return null;}}

2-3、封装的方法

你只需要去完善下面的beasParams方法的参数就好,参数在上面的截图里面都说了

import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.util.DigestUtils;import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 基于移动云MAS平台发送短信** @author 小道仙* @date 2020/10/11*/
public class SmsServiceMas {/*** 一对一发送消息** @param mobiles    手机号* @param content   内容* @return  {"msgGroup":"0927152506001000833076","rspcod":"success","success":true}* 如果发送失败,msgGroup为空*/public static JsonNode singleShot(String mobiles, String content){Map<String, String> map = beasParams(mobiles, content, "",1);Base64.Encoder encoder = Base64.getEncoder();JsonNode jsonNode = null;System.out.println(JsonUtils.objectToJson(map));try {String params = encoder.encodeToString(JsonUtils.objectToJson(map).getBytes("UTF-8"));System.out.println(params);String json = HttpUtils.sendPost("http://112.35.1.155:1992/sms/norsubmit", params, "");jsonNode = JsonUtils.stringToJsonNode(json);}catch (Exception e){throw new RuntimeException("MAS消息发送失败");}return jsonNode;}/*** 一对多发送消息** @param mobiles    手机号* @param content   内容*/public static JsonNode multiple(List<String> mobiles, String content){if (mobiles == null || mobiles.isEmpty() || mobiles.size() > 5000){throw new RuntimeException("电话号码异常");}String tmp = "";for (String item : mobiles){tmp += ","+item;}tmp = tmp.substring(1);return singleShot(tmp, content);}/*** 发送模板消息** @param mobiles 手机号* @param templateId 模板Id* @param params 模板参数,格式["123","456"]*/public static JsonNode templateMsg(String mobiles, String templateId, String[] params){JsonNode jsonNode = null;Map<String, String> map = beasParams(mobiles, JsonUtils.objectToJson(params), templateId,2);map.put("templateId",templateId);Base64.Encoder encoder = Base64.getEncoder();try {System.out.println(JsonUtils.objectToJson(map));String tmpParams = encoder.encodeToString(JsonUtils.objectToJson(map).getBytes("UTF-8"));System.out.println(tmpParams);String json = HttpUtils.sendPost("http://112.35.1.155:1992/sms/tmpsubmit", tmpParams, "");jsonNode = JsonUtils.stringToJsonNode(json);}catch (Exception e){e.printStackTrace();throw new RuntimeException("MAS模板消息发送失败");}return jsonNode;}/*** 基本参数封装** type == 1,  传递的是短信消息* type == 2,  传递的模板参数*/private static Map<String,String> beasParams(String mobiles,String tmp,String templateId,int type){// TODO 参数补全String secretKey = "创建的账号";String apId = "账号密码";String sign = "签名编码";String ecName = "公司名称";// TODO 可以直接是空字符串String addSerial = "";String mac = "";Map<String,String> map = new HashMap();map.put("ecName",ecName);map.put("apId",apId);map.put("sign",sign);map.put("mobiles",mobiles);if (type == 1){mac = ecName+apId+secretKey+mobiles+tmp+sign+addSerial;map.put("content",tmp);}else{mac = ecName+apId+secretKey+templateId+mobiles+tmp+sign+addSerial;map.put("params",tmp);}mac = DigestUtils.md5DigestAsHex(mac.getBytes()).toLowerCase();map.put("addSerial",addSerial);map.put("mac",mac);return map;}
}

2-4、MasStatusBean (短信状态接受bean)

/*** MAS消息状态接受bean** @author 小道仙* @date 2020/10/11*/
public class MasStatusBean {/*** 发送成功状态码:DELIVRD*/private String reportStatus;/*** 回执手机号,每批次返回一个号码*/private String mobile;/*** 提交时间,格式:yyyyMMddHHmmss*/private String submitDate;/*** 接收时间 格式:yyyyMMddHHmmss*/private String receiveDate;/*** 发送失败的状态码,如DB:0140*/private String errorCode;/*** 消息批次号,唯一编码,与发送响应中的msgGroup对应*/private String msgGroup;public String getReportStatus() {return reportStatus;}public void setReportStatus(String reportStatus) {this.reportStatus = reportStatus;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}public String getSubmitDate() {return submitDate;}public void setSubmitDate(String submitDate) {this.submitDate = submitDate;}public String getReceiveDate() {return receiveDate;}public void setReceiveDate(String receiveDate) {this.receiveDate = receiveDate;}public String getErrorCode() {return errorCode;}public void setErrorCode(String errorCode) {this.errorCode = errorCode;}public String getMsgGroup() {return msgGroup;}public void setMsgGroup(String msgGroup) {this.msgGroup = msgGroup;}@Overridepublic String toString() {return "MasStatusBean{" +"reportStatus='" + reportStatus + '\'' +", mobile='" + mobile + '\'' +", submitDate='" + submitDate + '\'' +", receiveDate='" + receiveDate + '\'' +", errorCode='" + errorCode + '\'' +", msgGroup='" + msgGroup + '\'' +'}';}
}

2-5、短信回调bean

就是用户回复之后的回调函数

/*** 短信回调Bean** @author 陶梓洋* @date 2020/9/11*/
public class MsgCallbackBean {/*** 手机号码*/private String mobile;/*** 短信内容*/private String smsContent;/*** 短信发送时间,格式:yyyy-MM-dd HH:mm:ss*/private String sendTime;/*** 上行服务代码*/private String addSerial;public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}public String getSmsContent() {return smsContent;}public void setSmsContent(String smsContent) {this.smsContent = smsContent;}public String getSendTime() {return sendTime;}public void setSendTime(String sendTime) {this.sendTime = sendTime;}public String getAddSerial() {return addSerial;}public void setAddSerial(String addSerial) {this.addSerial = addSerial;}@Overridepublic String toString() {return "MsgCallbackBean{" +"mobile='" + mobile + '\'' +", smsContent='" + smsContent + '\'' +", sendTime='" + sendTime + '\'' +", addSerial='" + addSerial + '\'' +'}';}
}

三、测试

因为状态回调和上行短信回调都是移动要访问我们的服务器的,但是我开发又是本地,所以需要借助一个工具让我们本地地址给映射出去。
ngrok下载、安装、使用

我本地的项目端口是8123,所以我的映射代码是 ngrok http 8123


3-1、测试代码

import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 测试发送短信*/
@RestController
public class TestServlet {@GetMapping("/testMas")public Object fun(){String[] params = new String[1];params[0] = "3123da";JsonNode jsonNode = SmsServiceMas.templateMsg("188276739493", "472fee4d8c4858bb3bacc067bc5e6a",params);System.out.println(jsonNode);return jsonNode;}/*** 状态报告*/@RequestMapping("/mas/status")public void statusReport(@RequestBody MasStatusBean masStatusBean){System.out.println("接收到短信报告");System.out.println(masStatusBean.toString());}/*** 上行短信*/@RequestMapping("/visitCallback")public void visitCallback(@RequestBody MsgCallbackBean msgCallbackBean){System.out.println("接收到上行短信");System.out.println(msgCallbackBean.toString());}
}

3-2、配置回调地址

从上面的代码可以知道,我的回调地址是http://127.0.0.1:8123/mas/statushttp://127.0.0.1:8123/visitCallback


3-3、配置短信模板

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

新建完成后提交审核


四、其它

4-1、查看短信发送状态

1、我们可以在短信状态回调函数里面查看
2、我们可以去移动MAS平台查看
在这里插入图片描述
在这里插入图片描述
错误CM:4004除了格式错误之外还可能是因为你本来是模板短信但是你调用了普通短信接口
错误IB:0011直接联系移动人员
addSerial参数不为空可能会出现有些手机号无法接收短信的问题
发布到Linux下的时候要注意生成的MAC可能不同,主要是字符集的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/42352.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

杂学第一篇:applescript检测手机号码是否注册imessage,imessages数据检测,imessages过蓝检测

一、检测数据的两种方式: 1.人工筛选&#xff0c;将要验证的号码输出到文件中&#xff0c;以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏&#xff0c;iMessage客户端会自动逐个检验该号码是否为iMessage账号&#xff0c;检验速度视网速而定。红色表示不是iMessage…

验证码、通知短信API常见使用问题

如今短信应用于我们生活工作的方方面面&#xff0c;注册或者登录一个应用可以用短信验证码快速登录&#xff0c;支付可以使用短信验证码&#xff1b;商家搞促销活动可以发送通知短信给客户&#xff0c;会员到期了商家可以发送告警短信给会员用户…可见验证码短信API和通知短信A…

程序人生 | 与足球共舞的火柴人(致敬格拉利什,赋予足球更深的意义)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…

内测邀请:ChatGPT - PAM™ 工业界造车解决方案

作为 AI 界的「顶流」&#xff0c;生成式 AI 似乎正在变成无所不能的「创意机器」。它可以根据输入的信息&#xff0c;自动创造各种「新东西」&#xff0c;帮助人们在各个领域快速实现创作和开发。不仅仅是文字&#xff0c;设计、游戏、艺术作品…… 各种五花八门的需求&#x…

描述对未来计算机的畅想用英语作文,畅想未来人工智能的发展状况英语作文 关于畅想未来人工智能的发展状况的英语作文...

题目要求】H42答案圈 计算机科学的未来趋势是人工智能的一种&#xff0c;它是人类思维的研究和仿真&#xff0c;最终能够使人喜欢思考&#xff0c;为人类服务&#xff0c;帮助人们解决问题。随着科技越来越与人类生活相结合&#xff0c;随处可见的人工智能&#xff0c;让生活越…

小a的旅行计划

来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld文章目录 题目描述题解&#xff1a;代码&#xff1a; 题目描述 小a终于放假了&#xff0c;它想在假期中去一些地…

旅游计划

旅游n个城市&#xff0c;但并不是每一条路线花费都是一样的。想把所有的城市都旅游一遍&#xff0c;但是花费最小。 输入格式 第一行输入一个整数n,表示有n个城市 接下来有一个n*n的矩形&#xff0c;表示每两个城市之间的火车花费&#xff0c;每两个城市之间的花费不会超过100…

CHAP7:使用 R 编程进行数据分析

1.了解 R 的基础知识 R 是一种编程语言&#xff0c;可用于在数据分析过程的每个阶段执行任务。在这部分课程中&#xff0c;您将了解 R 和 RStudio&#xff0c;这是 R 的集成开发人员环境 (IDE)。您将探索使用 RStudio 与 R 一起工作的好处。RStudio 使您能够轻松利用 R 的特性…

记录常用的R语言的一些零碎知识(包括ggplot2作图)

平常使用R的时候&#xff0c;会遇到一些小问题&#xff0c;这时就会去上网查&#xff0c;但查到结果&#xff0c;如果不记录起来&#xff0c;常常会遇到相同的问题时再次查询&#xff0c;费时费力&#xff0c;因此决定记录下这些零碎的R语言知识&#xff08;不定时更新&#xf…

R语言入门-数据分析实操(tyidyverse工作流+代码)

1. 数据分析的开端&#xff0c;Tidyverse&#xff1f; tidyverse 是一个清晰的 R 包集合&#xff0c;在数据操作、探索和可视化领域提供统一的数据科学解决方案&#xff0c;这些解决方案具有共同的设计理念。它是由 RStudio 背后的首席科学家 Hadley Wickham 创建的。 tidyver…

从零开发基于chatGPT的社区交友系统 (前后端分离)丨主页框架 03

03 主页框架 前言开工引用iconfont字体图标template代码style代码页面展示 路由局部跳转script代码 总结 前言 上一章我们实现了基础的主题切换功能&#xff0c;这一章我们开始搭建主页主要框架&#xff0c;并测试一下我们的切换主题功能。 开工 引用iconfont字体图标 这里…

制造焦虑的一边去! AI 不会让我们失业,还会带来大量新机遇!

点击上方“编程技术进阶”&#xff0c;加"星标" 重磅干货&#xff0c;第一时间送达 大家好&#xff0c;我是编哥。先送上涛哥用 AI 画的美女&#xff0c;目测这个是涛哥最近的梦中情人 声明&#xff1a;本文引用图片来自涛哥&#xff08;公众号&#xff1a;涛哥聊Pyt…

AI崛起,我们应该保持自我意识!

目录 前言西部世界剧情&#xff1f;辅助还是威胁&#xff1f;如何自我保护?总结 前言 人工智能技术发展迅速&#xff0c;为我们的生活带来了很多便利。但就个人来说这些技术都是可控的&#xff0c;我并不怎么担心。直到ChatGPT的到来&#xff0c;把我惊呆了。一边感叹AI技术的…

GPT帮你写简历:求职日企篇

正文共 927 字&#xff0c;阅读大约需要 3 分钟 求职者必备技巧&#xff0c;您将在3分钟后获得以下超能力&#xff1a; 快速生成日文简历 Beezy评级 &#xff1a;B级 *经过简单的寻找&#xff0c; 大部分人能立刻掌握。主要节省时间。 推荐人 | nanako 编辑者 | Linda 在应聘…

chatgpt赋能Python-python如何构造矩阵

Intro Python是一门强大的编程语言&#xff0c;拥有广泛的应用领域&#xff0c;其中矩阵运算是其中一个重要的方向。在本文中&#xff0c;我们将介绍如何使用Python构造矩阵&#xff0c;并介绍常见的矩阵运算。 什么是矩阵&#xff1f; 矩阵是由一组有序数排列成的矩形阵列&…

chatgpt赋能python:Python怎么手动输入矩阵

Python怎么手动输入矩阵 若想在使用Python进行科学计算或机器学习时&#xff0c;我们经常会使用矩阵。要能够利用Python处理这些矩阵&#xff0c;我们需要了解如何输入一个矩阵。本文将介绍如何通过代码手动输入矩阵。 什么是矩阵 矩阵是一个二维数组&#xff0c;它包含了行…

新知实验室 TRTC在线上教育场景中的一种应用实践

一、参赛说明 很荣幸参与此次征文活动&#xff0c;我是从2年多以前&#xff0c;接触腾讯云TRTC相关产品&#xff0c;正逢疫情肆虐&#xff0c;很多业务迫切需要从线下转移到线上。 经过2年的实践&#xff0c;TRTC本身也经历了多次的迭代&#xff0c;功能更强大&#xff0c;也…

Auto_GPT:如何使用Auto-GPT、安装、开发

文章目录 前言一、使用前提二、如何在您的 PC 上安装 Auto-GPT第 1 步&#xff1a;安装 Python第 2 步&#xff1a;获取 Auto-GPT 源代码和 OpenAI API 密钥第 3 步&#xff1a;在 Windows、MacOS和 Linux上安装 Auto-GPT 三、如何在你的 PC 上运行Auto-GPT总结 前言 Auto-GPT…