package com.ruoyi.common.utils;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.ruoyi.common.utils.http.HttpUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import java.io.BufferedReader;
|
import java.io.IOException;
|
import java.io.InputStreamReader;
|
import java.io.OutputStream;
|
import java.net.HttpURLConnection;
|
import java.net.URL;
|
import java.nio.charset.StandardCharsets;
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 短信发送工具类
|
* 参考PHP版本的SmsUtils实现
|
*
|
* @author ruoyi
|
* @date 2025-12-07
|
*/
|
public class SmsUtils {
|
|
private static final Logger log = LoggerFactory.getLogger(SmsUtils.class);
|
|
|
/**
|
* 发送 POST 请求
|
*
|
* @param url 服务器地址
|
* @param data 请求参数
|
* @return 响应内容
|
* @throws IOException
|
*/
|
public static String post(String url, String data) throws IOException {
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
connection.setRequestMethod("POST");
|
connection.setRequestProperty("Content-Type", "application/json");
|
connection.setDoOutput(true);
|
try (OutputStream os = connection.getOutputStream()) {
|
os.write(data.getBytes(StandardCharsets.UTF_8));
|
os.flush();
|
}
|
StringBuilder response = new StringBuilder();
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
String line;
|
while ((line = br.readLine()) != null) {
|
response.append(line);
|
}
|
}
|
return response.toString();
|
}
|
|
/**
|
* 计算 MD5 值
|
*
|
* @param str 字符串
|
* @return MD5 值
|
* @throws NoSuchAlgorithmException
|
*/
|
public static String md5(String str) throws NoSuchAlgorithmException {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
byte[] array = md.digest(str.getBytes(StandardCharsets.UTF_8));
|
StringBuilder sb = new StringBuilder();
|
for (byte item : array) {
|
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
|
}
|
return sb.toString();
|
}
|
|
/**
|
* 获取当前时间戳(毫秒)
|
*
|
* @return 时间戳字符串
|
*/
|
public static Long getTimestamp() {
|
return System.currentTimeMillis();
|
}
|
|
/**
|
* 生成签名
|
* 签名算法:MD5(userName + password + timestamp)
|
*
|
* @param userName 用户名
|
* @param password 密码
|
* @param timestamp 时间戳
|
* @return 签名字符串
|
*/
|
public static String generateSign(String userName, String password, Long timestamp) throws NoSuchAlgorithmException {
|
// 时间戳
|
|
|
// 计算 sign 参数
|
String sign = md5(userName + timestamp + md5(password));
|
return sign;
|
}
|
|
/**
|
* 发送HTTP POST请求
|
*
|
* @param url 请求地址
|
* @param data 请求数据
|
* @return 响应结果
|
*/
|
public static JSONObject sendPost(String url, Map<String, Object> data) {
|
try {
|
String jsonData = JSON.toJSONString(data);
|
log.debug("短信API请求,URL:{},数据:{}", url, jsonData);
|
|
String response = post(url,jsonData);;//HttpUtils.sendPost(url, jsonData, "application/json");
|
log.debug("短信API响应:{}", response);
|
|
if (StringUtils.isNotEmpty(response)) {
|
return JSON.parseObject(response);
|
}
|
} catch (Exception e) {
|
log.error("短信API请求失败,URL:{}", url, e);
|
}
|
return null;
|
}
|
|
/**
|
* 群发短信
|
*
|
* @param address 短信服务地址
|
* @param userName 账号
|
* @param password 密码
|
* @param phoneList 手机号列表,多个用逗号分隔
|
* @param content 短信内容
|
* @return 发送结果
|
*/
|
public static JSONObject sendSmsMass(String address, String userName, String password,
|
String phoneList, String content) throws NoSuchAlgorithmException{
|
Long timestamp = getTimestamp();
|
String sign = generateSign(userName, password, timestamp);
|
String url = "http://" + address + "/sms/api/sendMessageMass";
|
|
Map<String, Object> data = new HashMap<>();
|
data.put("userName", userName);
|
data.put("content", content);
|
data.put("phoneList", phoneList);
|
data.put("timestamp", timestamp);
|
data.put("sign", sign);
|
data.put("sendTime", "");
|
data.put("extCode", "");
|
data.put("callData", "");
|
|
return sendPost(url, data);
|
}
|
|
/**
|
* 单条/点对点短信发送
|
*
|
* @param address 短信服务地址
|
* @param userName 账号
|
* @param password 密码
|
* @param messageList 消息列表 [{phone: "手机号", content: "内容"}, ...]
|
* @return 发送结果
|
*/
|
public static JSONObject sendSmsOne(String address, String userName, String password,
|
List<Map<String, String>> messageList) throws NoSuchAlgorithmException {
|
Long timestamp = getTimestamp();
|
String sign = generateSign(userName, password, timestamp);
|
String url = "http://" + address + "/sms/api/sendMessageOne";
|
|
Map<String, Object> data = new HashMap<>();
|
data.put("userName", userName);
|
data.put("timestamp", timestamp);
|
data.put("sign", sign);
|
data.put("messageList", messageList);
|
|
return sendPost(url, data);
|
}
|
|
/**
|
* 发送单条短信(简化方法)
|
*
|
* @param address 短信服务地址
|
* @param userName 账号
|
* @param password 密码
|
* @param phone 手机号
|
* @param content 短信内容
|
* @return 发送结果
|
*/
|
public static JSONObject sendSms(String address, String userName, String password,
|
String phone, String content) throws NoSuchAlgorithmException{
|
List<Map<String, String>> messageList = new ArrayList<>();
|
messageList.add(new HashMap<String, String>() {{
|
put("phone", phone);
|
put("content", content);
|
}});
|
return sendSmsOne(address, userName, password, messageList);
|
}
|
|
/**
|
* 查询账户余额
|
*
|
* @param address 短信服务地址
|
* @param userName 账号
|
* @param password 密码
|
* @return 余额信息
|
*/
|
public static JSONObject getBalance(String address, String userName, String password) throws NoSuchAlgorithmException {
|
Long timestamp = getTimestamp();
|
String sign = generateSign(userName, password, timestamp);
|
String url = "http://" + address + "/sms/api/getBalance";
|
|
Map<String, Object> data = new HashMap<>();
|
data.put("userName", userName);
|
data.put("timestamp", timestamp);
|
data.put("sign", sign);
|
|
return sendPost(url, data);
|
}
|
|
/**
|
* 获取发送报告
|
*
|
* @param address 短信服务地址
|
* @param userName 账号
|
* @param password 密码
|
* @return 发送报告
|
*/
|
public static JSONObject getReport(String address, String userName, String password) throws NoSuchAlgorithmException {
|
Long timestamp = getTimestamp();
|
String sign = generateSign(userName, password, timestamp);
|
String url = "http://" + address + "/sms/api/getReport";
|
|
Map<String, Object> data = new HashMap<>();
|
data.put("userName", userName);
|
data.put("timestamp", timestamp);
|
data.put("sign", sign);
|
|
return sendPost(url, data);
|
}
|
}
|