java实现移动云mas短信发送

开发框架: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。

错误原因:变量参数和模版中的变量规则不符。

发送短信的参数,必需与申请模板中的格式完全匹配,否则就会导致失败。

相关推荐
PH = 72 小时前
Spring AI整合聊天模型DeepSeek
java·spring boot·后端
珹洺2 小时前
Java-Spring入门指南(十三)SpringMVC基本概念与核心流程详解
java·开发语言·spring
ccccczy_2 小时前
SpringCloudGateway:像城市交通指挥系统一样的微服务网关
java·springcloud·微服务网关·api网关·springcloudgateway
hello 早上好3 小时前
深入理解 SPI:从定义到 Spring Boot 实践
java·spring boot·python
【上下求索】3 小时前
学习笔记092——Windows如何将 jar 包启动设置成系统服务
java·windows·笔记·学习·jar
vistaup3 小时前
android studio 无法运行java main()
android·java·android studio
liuyao_xianhui4 小时前
四数之和_优选算法(C++)双指针法总结
java·开发语言·c++·算法·leetcode·职场和发展
珹洺4 小时前
Java-Spring入门指南(十二)SpringAop的三种实现方式
java·开发语言·spring
nbsaas-boot4 小时前
使用 DuckDB 构建高性能 OLAP 分析平台
java·服务器·数据库