package com.ruoyi.message.sms.provider.nhfy; import com.alibaba.fastjson2.JSON; import com.ruoyi.message.config.MessageProperties; import com.ruoyi.message.config.MtSmsConfig; import com.ruoyi.message.config.RootMessageProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * MT消息发送工具类(SP 向行业汇聚平台提交 MT 消息)。 *

* 接口地址:{@code http://ip:port/submitsm};编码:UTF-8;鉴权算法:MD5。 *

* 迁移说明:原类为 {@code com.smartor.common.MtSubmitSmUtil}({@code @Component} + {@code @Value} 注入), * 迁移后配置改为从 {@link MessageProperties} 读取(底层仍是同一批 configuration key),行为不变。 */ @Slf4j @Component public class MtSubmitSmUtil { private static final RestTemplate REST_TEMPLATE = new RestTemplate(); private final MessageProperties properties; public MtSubmitSmUtil(MessageProperties properties) { this.properties = properties; } /** * 发送 MT 消息 * * @param destAddr 目标号码 * @param content 短信内容 * @return 响应结果 */ public Map submitSm(String destAddr, String content) { MtSmsConfig mt = properties.getSms().getMt(); try { log.info("南华附一发送短信,destAddr:{},content:{}", destAddr, content); String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); String hashHex = buildHashHex(mt.getAccountName(), mt.getPassword(), date); Map authMap = new HashMap<>(); authMap.put("Algorithm", "MD5"); authMap.put("Date", date); authMap.put("HASHHEX", hashHex); Map reqMap = new HashMap<>(); reqMap.put("accountName", mt.getAccountName()); reqMap.put("Authorization", authMap); reqMap.put("DestAddr", destAddr); reqMap.put("SourceAddr", mt.getSourceAddr()); reqMap.put("Content", mt.getFlag() + content); reqMap.put("ServiceCode", mt.getServiceCode()); HttpHeaders headers = new HttpHeaders(); headers.setContentType(new MediaType("application", "json", StandardCharsets.UTF_8)); headers.set("Accept-Language", "UTF-8"); //TODO 待确认:原实现把 app-key 写死为 ak-BFq4NN0TMf92J7KAioNYGz74, // 而 yml 里同时存在 sms_appkey 配置项却未被使用。这里为保持线上行为仍用原硬编码值, // 建议改为读取 mt.getAppkey()(已支持)并确认哪个才是正确的 app-key。 headers.set("app-key", "ak-BFq4NN0TMf92J7KAioNYGz74"); HttpEntity entity = new HttpEntity<>(JSON.toJSONString(reqMap), headers); log.info("MtSubmitSm 请求地址:{},请求参数:{}", mt.getUrl() + "/submitsm", JSON.toJSONString(reqMap)); ResponseEntity response = REST_TEMPLATE.postForEntity(mt.getUrl(), entity, String.class); log.info("MtSubmitSm 响应结果:{}", response.getBody()); return JSON.parseObject(response.getBody(), Map.class); } catch (Exception e) { log.error("MtSubmitSm 发送失败,url:{},destAddr:{},error:{}", mt.getUrl(), destAddr, e.getMessage(), e); Map resp = new HashMap<>(); resp.put("code", -1); resp.put("message", "发送异常:" + e.getMessage()); return resp; } } /** * 计算 HASHHEX:MD5(Algorithm:帐号名:密码:Date) *

* 例:{@code MD5:95555:12345:2016-10-09 16:19:43} */ private static String buildHashHex(String accountName, String password, String date) throws Exception { String plain = "MD5:" + accountName + ":" + password + ":" + date; MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(plain.getBytes(StandardCharsets.UTF_8)); StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } /** * 判断 MT 响应是否成功({@code result == "0"}) */ public static boolean isSuccess(Map resp) { if (resp == null) { return false; } Object result = resp.get("result"); return result != null && "0".equals(result.toString()); } /** * 判断响应的 result 字段是否为空 */ public static boolean hasResult(Map resp) { return resp != null && StringUtils.isNotEmpty(String.valueOf(resp.get("result"))); } }