From 1991863573a075364977d72976417c2024ca6629 Mon Sep 17 00:00:00 2001 From: chenbowen Date: Fri, 12 Dec 2025 10:13:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E7=A7=BB=E5=8A=A8=E4=BA=91?= =?UTF-8?q?=20mas=20=E7=9F=AD=E4=BF=A1=E7=9B=B8=E5=85=B3=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/client/impl/CmccMasSmsClient.java | 444 +++++++++--------- .../client/impl/SmsClientFactoryImpl.java | 2 +- 2 files changed, 223 insertions(+), 223 deletions(-) diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/CmccMasSmsClient.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/CmccMasSmsClient.java index 1821ca16..d6fea6e7 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/CmccMasSmsClient.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/CmccMasSmsClient.java @@ -1,222 +1,222 @@ -package com.zt.plat.module.system.framework.sms.core.client.impl; - -import cn.hutool.core.codec.Base64; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.digest.DigestUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import com.zt.plat.framework.common.core.KeyValue; -import com.zt.plat.framework.common.util.http.HttpUtils; -import com.zt.plat.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; -import com.zt.plat.module.system.framework.sms.core.client.dto.SmsSendRespDTO; -import com.zt.plat.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; -import com.zt.plat.module.system.framework.sms.core.property.SmsChannelProperties; -import lombok.extern.slf4j.Slf4j; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 中国移动云MAS短信客户端实现类 - * - * @author zt-team - * @since 2025-01-19 - */ -@Slf4j -public class CmccMasSmsClient extends AbstractSmsClient { - - private static final String URL = "https://112.35.10.201:28888/sms/submit"; - private static final String RESPONSE_SUCCESS = "success"; - - public CmccMasSmsClient(SmsChannelProperties properties) { - super(properties); - Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); - Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); - validateCmccMasConfig(properties); - } - - /** - * 参数校验中国移动云MAS的配置 - * - * 原因是:中国移动云MAS需要三个参数:ecName、apId、secretKey - * - * 解决方案:考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 ecName 和 apId 拼接到 apiKey 字段中,格式为 "ecName apId"。 - * secretKey 存储在 apiSecret 字段中。 - * - * @param properties 配置 - */ - private static void validateCmccMasConfig(SmsChannelProperties properties) { - String combineKey = properties.getApiKey(); - Assert.notEmpty(combineKey, "apiKey 不能为空"); - String[] keys = combineKey.trim().split(" "); - Assert.isTrue(keys.length == 2, "中国移动云MAS apiKey 配置格式错误,请配置为 [ecName apId]"); - } - - /** - * 获取 ecName(企业名称) - */ - private String getEcName() { - return StrUtil.subBefore(properties.getApiKey(), " ", true); - } - - /** - * 获取 apId(应用ID) - */ - private String getApId() { - return StrUtil.subAfter(properties.getApiKey(), " ", true); - } - - /** - * 获取 secretKey(密钥) - */ - private String getSecretKey() { - return properties.getApiSecret(); - } - - /** - * 发送短信 - * - * @param logId 日志ID - * @param mobile 手机号 - * @param apiTemplateId 模板ID(本平台不使用模板,传入内容) - * @param templateParams 模板参数 - * @return 发送结果 - */ - @Override - public SmsSendRespDTO sendSms(Long logId, String mobile, String apiTemplateId, - List> templateParams) throws Throwable { - - // 1. 构建短信内容 - String content = buildContent(apiTemplateId, templateParams); - - // 2. 计算MAC校验值 - String mac = calculateMac(mobile, content); - - // 3. 构建请求参数 - JSONObject requestBody = new JSONObject(); - requestBody.set("ecName", getEcName()); // 企业名称 - requestBody.set("apId", getApId()); // 应用ID - requestBody.set("secretKey", getSecretKey()); // 密钥 - requestBody.set("sign", properties.getSignature()); // 签名编码 - requestBody.set("mobiles", mobile); - requestBody.set("content", content); - requestBody.set("addSerial", ""); - requestBody.set("mac", mac); - - log.info("[sendSms][发送短信 {}]", JSONUtil.toJsonStr(requestBody)); - - // 4. Base64编码请求体 - String encodedBody = Base64.encode(requestBody.toString()); - log.info("[sendSms][Base64编码后: {}]", encodedBody); - - // 5. 构建请求头(需要JWT Token) - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + getJwtToken()); - headers.put("Content-Type", "text/plain"); - - // 6. 发起请求 - String responseBody = HttpUtils.post(URL, headers, encodedBody); - JSONObject response = JSONUtil.parseObj(responseBody); - - log.info("[sendSms][收到响应 - {}]", response); - - // 7. 解析响应 - return new SmsSendRespDTO() - .setSuccess(response.getBool("success", false)) - .setSerialNo(response.getStr("msgGroup")) - .setApiCode(response.getStr("rspcod")) - .setApiMsg(response.getStr("message", "未知错误")); - } - - /** - * 解析短信接收状态回调 - * - * @param text 回调文本 - * @return 接收状态列表 - */ - @Override - public List parseSmsReceiveStatus(String text) throws Throwable { - // TODO: 根据移动云MAS回调格式实现 - log.warn("[parseSmsReceiveStatus][暂未实现短信状态回调解析]"); - return Collections.emptyList(); - } - - /** - * 查询短信模板 - * - * @param apiTemplateId 模板ID - * @return 模板信息 - */ - @Override - public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { - // 移动云MAS不使用模板机制,直接发送内容 - log.debug("[getSmsTemplate][中国移动云MAS不支持模板查询]"); - return null; - } - - /** - * 计算MAC校验值 - * 算法:MD5(ecName + apId + secretKey + mobiles + content + sign + addSerial) - * - * @param mobile 手机号 - * @param content 短信内容 - * @return MAC校验值 - */ - private String calculateMac(String mobile, String content) { - String rawString = getEcName() // ecName - + getApId() // apId - + getSecretKey() // secretKey - + mobile // mobiles - + content // content - + properties.getSignature() // sign - + ""; // addSerial - - String mac = DigestUtil.md5Hex(rawString).toLowerCase(); - log.debug("[calculateMac][原始字符串长度: {}, MAC: {}]", rawString.length(), mac); - return mac; - } - - /** - * 构建短信内容 - * - * @param apiTemplateId 模板ID - * @param templateParams 模板参数 - * @return 短信内容 - */ - private String buildContent(String apiTemplateId, List> templateParams) { - // 简单实现:直接返回模板ID作为内容 - // 实际使用时需要根据业务需求构建短信内容 - if (templateParams == null || templateParams.isEmpty()) { - return apiTemplateId; - } - - // 替换模板参数,支持 {{key}} 格式 - String content = apiTemplateId; - for (KeyValue param : templateParams) { - String placeholder = "{{" + param.getKey() + "}}"; - String value = String.valueOf(param.getValue()); - content = content.replace(placeholder, value); - } - return content; - } - - /** - * 获取JWT Token - * TODO: 实现Token获取逻辑,可能需要: - * 1. 调用认证接口获取Token - * 2. 缓存Token并在过期前自动刷新 - * 3. 处理Token失效情况 - * - * @return JWT Token - */ - private String getJwtToken() { - // 临时实现:从配置中读取或调用认证接口获取 - // 实际生产环境需要实现完整的Token管理机制 - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example.token"; - log.warn("[getJwtToken][使用临时Token,生产环境需实现完整的Token获取机制]"); - return token; - } -} +//package com.zt.plat.module.system.framework.sms.core.client.impl; +// +//import cn.hutool.core.codec.Base64; +//import cn.hutool.core.lang.Assert; +//import cn.hutool.core.util.StrUtil; +//import cn.hutool.crypto.digest.DigestUtil; +//import cn.hutool.json.JSONObject; +//import cn.hutool.json.JSONUtil; +//import com.zt.plat.framework.common.core.KeyValue; +//import com.zt.plat.framework.common.util.http.HttpUtils; +//import com.zt.plat.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +//import com.zt.plat.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +//import com.zt.plat.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +//import com.zt.plat.module.system.framework.sms.core.property.SmsChannelProperties; +//import lombok.extern.slf4j.Slf4j; +// +//import java.util.Collections; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +// +///** +// * 中国移动云MAS短信客户端实现类 +// * +// * @author zt-team +// * @since 2025-01-19 +// */ +//@Slf4j +//public class CmccMasSmsClient extends AbstractSmsClient { +// +// private static final String URL = "https://112.35.10.201:28888/sms/submit"; +// private static final String RESPONSE_SUCCESS = "success"; +// +// public CmccMasSmsClient(SmsChannelProperties properties) { +// super(properties); +// Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); +// Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); +// validateCmccMasConfig(properties); +// } +// +// /** +// * 参数校验中国移动云MAS的配置 +// * +// * 原因是:中国移动云MAS需要三个参数:ecName、apId、secretKey +// * +// * 解决方案:考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 ecName 和 apId 拼接到 apiKey 字段中,格式为 "ecName apId"。 +// * secretKey 存储在 apiSecret 字段中。 +// * +// * @param properties 配置 +// */ +// private static void validateCmccMasConfig(SmsChannelProperties properties) { +// String combineKey = properties.getApiKey(); +// Assert.notEmpty(combineKey, "apiKey 不能为空"); +// String[] keys = combineKey.trim().split(" "); +// Assert.isTrue(keys.length == 2, "中国移动云MAS apiKey 配置格式错误,请配置为 [ecName apId]"); +// } +// +// /** +// * 获取 ecName(企业名称) +// */ +// private String getEcName() { +// return StrUtil.subBefore(properties.getApiKey(), " ", true); +// } +// +// /** +// * 获取 apId(应用ID) +// */ +// private String getApId() { +// return StrUtil.subAfter(properties.getApiKey(), " ", true); +// } +// +// /** +// * 获取 secretKey(密钥) +// */ +// private String getSecretKey() { +// return properties.getApiSecret(); +// } +// +// /** +// * 发送短信 +// * +// * @param logId 日志ID +// * @param mobile 手机号 +// * @param apiTemplateId 模板ID(本平台不使用模板,传入内容) +// * @param templateParams 模板参数 +// * @return 发送结果 +// */ +// @Override +// public SmsSendRespDTO sendSms(Long logId, String mobile, String apiTemplateId, +// List> templateParams) throws Throwable { +// +// // 1. 构建短信内容 +// String content = buildContent(apiTemplateId, templateParams); +// +// // 2. 计算MAC校验值 +// String mac = calculateMac(mobile, content); +// +// // 3. 构建请求参数 +// JSONObject requestBody = new JSONObject(); +// requestBody.set("ecName", getEcName()); // 企业名称 +// requestBody.set("apId", getApId()); // 应用ID +// requestBody.set("secretKey", getSecretKey()); // 密钥 +// requestBody.set("sign", properties.getSignature()); // 签名编码 +// requestBody.set("mobiles", mobile); +// requestBody.set("content", content); +// requestBody.set("addSerial", ""); +// requestBody.set("mac", mac); +// +// log.info("[sendSms][发送短信 {}]", JSONUtil.toJsonStr(requestBody)); +// +// // 4. Base64编码请求体 +// String encodedBody = Base64.encode(requestBody.toString()); +// log.info("[sendSms][Base64编码后: {}]", encodedBody); +// +// // 5. 构建请求头(需要JWT Token) +// Map headers = new HashMap<>(); +// headers.put("Authorization", "Bearer " + getJwtToken()); +// headers.put("Content-Type", "text/plain"); +// +// // 6. 发起请求 +// String responseBody = HttpUtils.post(URL, headers, encodedBody); +// JSONObject response = JSONUtil.parseObj(responseBody); +// +// log.info("[sendSms][收到响应 - {}]", response); +// +// // 7. 解析响应 +// return new SmsSendRespDTO() +// .setSuccess(response.getBool("success", false)) +// .setSerialNo(response.getStr("msgGroup")) +// .setApiCode(response.getStr("rspcod")) +// .setApiMsg(response.getStr("message", "未知错误")); +// } +// +// /** +// * 解析短信接收状态回调 +// * +// * @param text 回调文本 +// * @return 接收状态列表 +// */ +// @Override +// public List parseSmsReceiveStatus(String text) throws Throwable { +// // TODO: 根据移动云MAS回调格式实现 +// log.warn("[parseSmsReceiveStatus][暂未实现短信状态回调解析]"); +// return Collections.emptyList(); +// } +// +// /** +// * 查询短信模板 +// * +// * @param apiTemplateId 模板ID +// * @return 模板信息 +// */ +// @Override +// public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { +// // 移动云MAS不使用模板机制,直接发送内容 +// log.debug("[getSmsTemplate][中国移动云MAS不支持模板查询]"); +// return null; +// } +// +// /** +// * 计算MAC校验值 +// * 算法:MD5(ecName + apId + secretKey + mobiles + content + sign + addSerial) +// * +// * @param mobile 手机号 +// * @param content 短信内容 +// * @return MAC校验值 +// */ +// private String calculateMac(String mobile, String content) { +// String rawString = getEcName() // ecName +// + getApId() // apId +// + getSecretKey() // secretKey +// + mobile // mobiles +// + content // content +// + properties.getSignature() // sign +// + ""; // addSerial +// +// String mac = DigestUtil.md5Hex(rawString).toLowerCase(); +// log.debug("[calculateMac][原始字符串长度: {}, MAC: {}]", rawString.length(), mac); +// return mac; +// } +// +// /** +// * 构建短信内容 +// * +// * @param apiTemplateId 模板ID +// * @param templateParams 模板参数 +// * @return 短信内容 +// */ +// private String buildContent(String apiTemplateId, List> templateParams) { +// // 简单实现:直接返回模板ID作为内容 +// // 实际使用时需要根据业务需求构建短信内容 +// if (templateParams == null || templateParams.isEmpty()) { +// return apiTemplateId; +// } +// +// // 替换模板参数,支持 {{key}} 格式 +// String content = apiTemplateId; +// for (KeyValue param : templateParams) { +// String placeholder = "{{" + param.getKey() + "}}"; +// String value = String.valueOf(param.getValue()); +// content = content.replace(placeholder, value); +// } +// return content; +// } +// +// /** +// * 获取JWT Token +// * TODO: 实现Token获取逻辑,可能需要: +// * 1. 调用认证接口获取Token +// * 2. 缓存Token并在过期前自动刷新 +// * 3. 处理Token失效情况 +// * +// * @return JWT Token +// */ +// private String getJwtToken() { +// // 临时实现:从配置中读取或调用认证接口获取 +// // 实际生产环境需要实现完整的Token管理机制 +// String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example.token"; +// log.warn("[getJwtToken][使用临时Token,生产环境需实现完整的Token获取机制]"); +// return token; +// } +//} diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java index 4411b153..7b9f5d0b 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java @@ -81,7 +81,7 @@ public class SmsClientFactoryImpl implements SmsClientFactory { case TENCENT: return new TencentSmsClient(properties); case HUAWEI: return new HuaweiSmsClient(properties); case QINIU: return new QiniuSmsClient(properties); - case CMCC_MAS: return new CmccMasSmsClient(properties); +// case CMCC_MAS: return new CmccMasSmsClient(properties); case HL95: return new Hl95SmsClient(properties); } // 创建失败,错误日志 + 抛出异常