开发框架:spring boot
对接移动的短信发送平台,具体实现逻辑如下:
yaml配置项
sa:
# 手机短信发送配置
phonemassage:
#普通短信接口地址
url: "https://112.22.33.44:55555/sms/submit"
#模板短信接口地址
urltemplate: "https://112.22.33.44:55555/sms/tmpsubmit"
ecname: "上海测试有限公司"
apid: "AAAA"
secretkey: "123456"
sign: "abcdef"
addserial: ""
templateid: "123321"
普通短信发送请求实体类 SendReq.java
java
import lombok.Data;
//普通短信发送请求类
@Data
public class SendReq {
private String ecName; // 企业名称
private String apId; // 接口账号用户名
private String secretKey; // 密钥
private String mobiles; // 收信手机号码,英文逗号分隔,每批次限5000个号码
/**
* 在云MAS平台『管理』→『接口管理』→『短信接入用户管理』获取。
*/
private String sign; // 签名编码
/**
* 在云MAS平台创建模板,路径:『短信』→『模板短信』→『模板管理』,创建后提交审核,审核通过将获得模板ID。
*/
private String templateId; // 模板ID
/**
* 依据申请开户的服务代码匹配类型而定,
* 如为精确匹配,此项填写空字符串("");
* 如为模糊匹配,此项可填写空字符串或自定义的扩展码,注:服务代码加扩展码总长度不能超过20位。
*/
private String addSerial; // 扩展码
/**
* 将ecName、apId、secretKey、templateId、mobiles、params、sign、addSerial按序拼接(无间隔符),通过MD5(32位小写)计算出的值
*/
private String mac; // 参数校验序列
private String content; // 参数校验序列
}
模板短信发送请求实体类 SendTemplateReq.java
java
import lombok.Data;
//模板短信发送请求类
@Data
public class SendTemplateReq {
/**
* 接口账号用户名。
*/
private String apId;
/**
* 签名编码。在云MAS平台『管理』→『接口管理』→『短信接入用户管理』获取。
*/
private String sign;
/**
* 模板ID。在云MAS平台创建模板,路径:『短信』→『模板短信』→『模板管理』,创建后提交审核,审核通过将获得模板ID。
*/
private String templateId;
/**
* 模板变量。格式:["param1","param2"],无变量模板填[""]。
*/
private String params;
/**
* 扩展码。依据开户时申请的服务代码匹配类型而定,如为精确匹配,此项填写空字符串("");如为模糊匹配,此项可填写空字符串或自定义的扩展码,注:服务代码加扩展码总长度不能超过20位。
*/
private String addSerial;
/**
* 参数校验序列,生成方法:将ecName、apId、secretKey、templateId、mobiles、params、sign、addSerial按序拼接(无间隔符),通过MD5(32位小写)计算出的值。
*/
private String mac;
/**
* 收信手机号码。英文逗号分隔,每批次限5000个号码,例:"13800138000,13800138001,13800138002"。
*/
private String mobiles;
/**
* 企业名称。
*/
private String ecName;
/**
* 密钥
*/
private String secretKey;
}
发送短信接口响应类 SendRes.java
java
import lombok.Data;
//发送短信接口响应类
@Data
public class SendRes {
/**
* 响应状态
* IllegalMac mac校验不通过。
* IllegalSignId 无效的签名编码。
* InvalidMessage 非法消息,请求数据解析失败。
* InvalidUsrOrPwd 非法用户名/密码。
* NoSignId 未匹配到对应的签名信息。
* success 数据验证通过。
* TooManyMobiles 手机号数量超限(>5000),应≤5000。
*/
private String rspcod;
/**
* 消息批次号,由云MAS平台生成,用于关联短信发送请求与状态报告,注:若数据验证不通过,该参数值为空
*/
private String msgGroup;
/**
* 数据校验结果。
*/
private boolean success;
}
短信发送实现类 MobileCloudSmsUtil.java
java
package net.lab1024.sa.base.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.lab1024.sa.base.common.domain.massage.SendReq;
import net.lab1024.sa.base.common.domain.massage.SendRes;
import net.lab1024.sa.base.common.domain.massage.SendTemplateReq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.List;
/**
* @author 梁萌
* @ClassName:
* @Description: 移动云mas短信工具类
* @date 2025年9月25日 16:48:49
*/
@Component
public class MobileCloudSmsUtil {
@Value("${sa.phonemassage.url}")
private String url;
@Value("${sa.phonemassage.urltemplate}")
private String urlTemplate;
@Value("${sa.phonemassage.ecname}")
private String ecName;
@Value("${sa.phonemassage.apid}")
private String apId;
@Value("${sa.phonemassage.secretkey}")
private String secretKey;
@Value("${sa.phonemassage.sign}")
private String sign;
@Value("${sa.phonemassage.addserial}")
private String addSerial;
@Value("${sa.phonemassage.templateid}")
private String templateId;
@Autowired
private RestTemplate restTemplate;
/**
* 发送普通短信
*
* @param mobiles 多个手机号用逗号隔开
* @param content 短信内容
* @return
* @throws UnsupportedEncodingException
*/
public SendRes sendOrdinarySms(String mobiles, String content) throws UnsupportedEncodingException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
SendReq sendReq = new SendReq();
sendReq.setEcName(ecName);
sendReq.setApId(apId);
sendReq.setSecretKey(secretKey);
sendReq.setSign(sign);
sendReq.setAddSerial(addSerial);
sendReq.setMobiles(mobiles);
sendReq.setContent(content);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(sendReq.getEcName())
.append(sendReq.getApId())
.append(sendReq.getSecretKey())
.append(sendReq.getMobiles())
.append(sendReq.getContent())
.append(sendReq.getSign())
.append(sendReq.getAddSerial());
sendReq.setMac(DigestUtils.md5DigestAsHex(stringBuffer.toString().getBytes()).toLowerCase());
String jsonText = JSON.toJSONString(sendReq);
String body = Base64.getEncoder().encodeToString(jsonText.getBytes("UTF-8"));
HttpEntity<String> httpEntity = new HttpEntity<String>(body, httpHeaders);
JSONObject result = restTemplate.postForObject(url, httpEntity, JSONObject.class);
return result.toJavaObject(SendRes.class);
}
/**
* 发送模板短信
*
* @param mobiles 手机号
* @param params 参数列表
* @return
* @throws UnsupportedEncodingException
*/
public SendRes sendTemplateSms(String mobiles, List<String> params) throws UnsupportedEncodingException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
SendTemplateReq sendTemplateReq = new SendTemplateReq();
sendTemplateReq.setApId(apId);
sendTemplateReq.setEcName(ecName);
sendTemplateReq.setSign(sign);
sendTemplateReq.setTemplateId(templateId);
sendTemplateReq.setParams(JSON.toJSONString(params.toArray()));
sendTemplateReq.setAddSerial(addSerial);
sendTemplateReq.setMobiles(mobiles);
sendTemplateReq.setSecretKey(secretKey);
//设置mac
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(sendTemplateReq.getEcName())
.append(sendTemplateReq.getApId())
.append(sendTemplateReq.getSecretKey())
.append(sendTemplateReq.getTemplateId())
.append(sendTemplateReq.getMobiles())
.append(sendTemplateReq.getParams())
.append(sendTemplateReq.getSign())
.append(sendTemplateReq.getAddSerial());
sendTemplateReq.setMac(DigestUtils.md5DigestAsHex(stringBuffer.toString().getBytes()).toLowerCase());
String jsonText = JSON.toJSONString(sendTemplateReq);
String body = Base64.getEncoder().encodeToString(jsonText.getBytes("UTF-8"));
HttpEntity<String> httpEntity = new HttpEntity<String>(body, httpHeaders);
JSONObject result = restTemplate.postForObject(urlTemplate, httpEntity, JSONObject.class);
return result.toJavaObject(SendRes.class);
}
}
方法调用的控制器类 PhoneMessageController.java
java
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.system.message.domain.form.SendPhoneMessageForm;
import net.lab1024.sa.admin.module.system.message.domain.form.SendPhoneTemplateMessageForm;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.domain.massage.SendRes;
import net.lab1024.sa.base.common.util.MobileCloudSmsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
/**
* 手机短信
*
* @author: 梁萌
* @date: 2025年9月26日 10:17:26
*/
@Tag(name = AdminSwaggerTagConst.System.PHONE_MESSAGE)
@RestController
public class PhoneMessageController {
@Autowired
private MobileCloudSmsUtil mobileCloudSmsUtil;
@Operation(summary = "发送手机短信 @author 梁萌")
@PostMapping("/phone/sendPhoneMessages")
public ResponseDTO<SendRes> sendPhoneMessages(@RequestBody @Valid SendPhoneMessageForm reqForm) throws UnsupportedEncodingException {
//发送普通短信
SendRes sendRes = mobileCloudSmsUtil.sendOrdinarySms(reqForm.getPhoneNum(), reqForm.getContent());
return ResponseDTO.ok(sendRes);
}
@Operation(summary = "发送模板手机短信 @author 梁萌")
@PostMapping("/phone/sendTemplatePhoneMessages")
public ResponseDTO<SendRes> sendTemplatePhoneMessages(@RequestBody @Valid SendPhoneTemplateMessageForm reqForm) throws UnsupportedEncodingException {
//发送普通短信
SendRes sendRes = mobileCloudSmsUtil.sendTemplateSms(reqForm.getPhoneNum(), reqForm.getParams());
return ResponseDTO.ok(sendRes);
}
}
apifox调用结果:


模板短信发送后,接口返回成功,但实际没有收到短信,后台查询发送记录,错误代码CM2007。

错误原因:变量参数和模版中的变量规则不符。
发送短信的参数,必需与申请模板中的格式完全匹配,否则就会导致失败。