JAVA调用梦网云通讯平台API实现短信发送
调用通讯平台API发送短信示意图
调用通讯平台API发送短信的示意图如下(根据我的理解简单画的,如果有不对的地方,欢迎留言指出)。
开发者首先设定必需的参数,包括 请求的url,请求方式,post数据 等等,发送出一个http请求;通讯平台接收到http请求后,解析请求体中的各项参数,并校验各项参数是否合法,如果参数合法,则将短信转发给收信人,最后将发送状态信息返回给接口调用方。
注册通讯平台账号
要调用通讯平台的API,首先需要在相应的通讯平台注册一个账号。本文以梦网云通讯平台为例。账号注册完成后,平台会赠送10元话费,如果仅仅做测试的话,这个钱足够了。
这个账号和密码仅仅是用于登录梦网云平台的账号和密码,或者说,是用于充值的账号和密码,与后面提到的用于发送短信的账号密码无关。
账号注册完成后,点击 业务中心 查看平台分配的用于短信发送的 发送账号 与 密码和APIKey ,当然还有 RestUrl ,其中,密码和APIKey是在点击获取后通过短信的方式发送到手机上的。
这个时候还不能发送短信,为什么呢?因为任何通讯平台都不允许随意发送短信,发送内容要符合要求才行。点击 信安中心 ,这里有很多短信预设模板,基本上会满足大多数的短信发送需求,如果没有满足需求的模板,可以进行模板定制,不过模板定制化需要上传证件进行认证。这里我们选择一个工资入账的模板开心开心。
模拟发送短信的http请求
一切准备就绪,现在可以发送短信了吗?做个测试先~
现在需要一个可以模拟发送http请求的工具,这样的工具有很多,如fiddler,postman,本文以 bejson 为例。
填好必要的参数后,发送请求数据,如果返回的请求结果中 result等于0,则代表短信发送成功。

其中post数据中,各项参数说明见下表:
参数 | 类型 | 是否必须 | 描述 | 示例 |
---|---|---|---|---|
userid | string | 是 | 用户账号,长度最大6个字符,统一大写 。 | 示例: J10003 |
pwd | string | 是 | 用户密码,定长小写32位字符 。 | 示例: 密码明文模式: 密码: 111111 密码加密模式: 账号: J10003 密码: 111111 固定字符串: 00000000 时间戳: 0803192020 MD5加密之前的对应字符串: J10003000000001111110803192020 MD5加密之后的密码字符串: 26dad7f364507df18f3841cc9c4ff94d |
mobile | string | 是 | 短信接收的手机号, 多个手机号请用英文逗号分隔,最大1000个号码 。 | 示例: 138xxxxxxxx,130xxxxxxxx |
content | string | 是 | 短信内容:最大支持1000个字(含签名),发送时请预留至少10个字符的签名长度,一个字母或一个汉字都视为一个字符。 | 示例: 短信内容:“验证码:6666,打死都不要告诉别人哦!” 短信内容进行urlencode编码后: %d1%e9%d6%a4%c2%eb%a3%ba6666%a3%ac%b4%f2%cb%c0%b6%bc%b2%bb%d2%aa%b8%e6%cb%df%b1%f0%c8%cb%c5%b6%a3%a1 |
timestamp | string | 否 | 时间戳,24小时制格式:MMDDHHMMSS, 即月日时分秒 ,定长10位,月、日、时、分、秒每段不足2位时左补0,密码选择MD5加密方式时必填该参数,密码选择明文方式时则不用填写 | 示例:0803192020 |
编码实现
经过之前的准备工作,现在可以编码实现了。而这个实现过程,其实就是将上一步中 模拟发送短信的http请求
由模拟器实现改为编码实现。
与模拟器所填写参数对应的JAVA编码实现如下:
public class CHttpPost {
// http请求失败
private static int ERROR_310099 = -310099;
// 连接超时时间(毫秒) 10秒
private static int HTTP_CONNECT_TIMEOUT = 10 * 1000;
// 从连接池获取connection的超时时间 1秒
private static int HTTP_CONNECTION_REQUEST_TIMEOUT = 1 * 1000;
// 响应超时时间(毫秒) 10秒
private static int HTTP_SOCKET_TIMEOUT = 10 * 1000;
// 请求路径
public static String REQUEST_PATH = "/sms/v2/std/";
public String singleSend(Message message, String ipAddress, String ipProxy, String portProxy) {
String result = String.valueOf(ERROR_310099);
try {
String urlSingleSend = "http://" + ipAddress + REQUEST_PATH + "single_send";
result = send(message, urlSingleSend, ipProxy, portProxy);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public String batchSend(Message message, String ipAddress, String ipProxy, String portProxy) {
String result = String.valueOf(ERROR_310099);
try {
String urlBatchSend = "http://" + ipAddress + REQUEST_PATH + "batch_send";
result = send(message, urlBatchSend, ipProxy, portProxy);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private String send(Message message, String httpUrl, String ipProxy, String portProxy) {
String result = String.valueOf(ERROR_310099);
try {
// 对密码进行加密
String encryptPwd = encryptPwd(message.getUserid(), message.getPwd(), message.getTimestamp());
// 设置加密后的密码
message.setPwd(encryptPwd);
Field[] fields = message.getClass().getDeclaredFields();
JSONObject requestBody = new JSONObject();
// 循环拼接请求参数
for (int i = 0; i < fields.length; i++) {
String fieldName = fields[i].getName();
String fieldNameUpper = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
Method getMethod = message.getClass().getMethod("get" + fieldNameUpper);
Object value = getMethod.invoke(message);
if (value != null) {
//拼接请求参数
requestBody.put(fieldName, value);
}
}
// 设定编码方式
StringEntity stringEntity = new StringEntity(requestBody.toString(), StandardCharsets.UTF_8);
// 定义请求头
HttpPost httpPost = new HttpPost(httpUrl);
httpPost.setHeader("Content-Type", "application/json");
// 定义请求体
httpPost.setEntity(stringEntity);
// 创建连接
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpHost proxy = null;
if (ipProxy != null && portProxy != null) {
// 设置代理
proxy = new HttpHost(ipProxy, Integer.parseInt(portProxy), "http");
}
// 设置请求超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setProxy(proxy)
.setConnectTimeout(HTTP_CONNECT_TIMEOUT)
.setConnectionRequestTimeout(HTTP_CONNECTION_REQUEST_TIMEOUT)
.setSocketTimeout(HTTP_SOCKET_TIMEOUT)
.build();
httpPost.setConfig(requestConfig);
HttpEntity entity = null;
HttpResponse httpResponse = null;
try {
// 向网关请求
httpResponse = httpClient.execute(httpPost);
// 若状态码为200,则代表请求成功
if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) {
//获取响应的实体
entity = httpResponse.getEntity();
result = EntityUtils.toString(entity);
} else {
// 设置错误码
result = String.valueOf(ERROR_310099);
System.out.println("请求失败:" + httpResponse.getStatusLine().toString());
}
} catch (Exception e) {
result = String.valueOf(ERROR_310099);
e.printStackTrace();
}
} catch (Exception e) {
result = String.valueOf(ERROR_310099);
e.printStackTrace();
}
return result;
}
public String encryptPwd(String userid, String pwd, String timestamp) {
// 加密后的字符串
String encryptPwd = null;
try {
String passwordStr = userid.toUpperCase() + "00000000" + pwd + timestamp;
// 对密码进行加密
encryptPwd = getMD5Str(passwordStr);
} catch (Exception e) {
e.printStackTrace();
}
return encryptPwd;
}
private static String getMD5Str(String str) {
MessageDigest messageDigest = null;
// 加密前的准备
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(str.getBytes("UTF-8"));
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
//初始化加密类失败,返回null。
return null;
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
//初始化加密类失败,返回null。
return null;
}
byte[] byteArray = messageDigest.digest();
// 加密后的字符串
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1){
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
} else {
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
}
return md5StrBuff.toString();
}
}
最后附上完整的Demo链接https://download.youkuaiyun.com/download/lanshanzhuyao/11094599