中国移动Mas(普通短信)_mas.10086.cn 查看短信发送记录-程序员宅基地

技术标签: java  云Mas  短信  

最近由于业务需求,需要将原先的阿里元短信功能修改成中国移动的Mas。经过几天的研究接口文档,最终实现了:将移动的Mas的普通短信功能打成一个 jar 包,运行在服务器上,实现在业务代码中调用接口中的接口,发送短信的功能。

0 前言

要使用中国移动的Mas短信功能,就要先了解接口文档(本案例使用HTTP的方式)。
浏览器打开:http://mas.10086.cn/login ,下载相关接口文档和案例。
0
1

这里我使用的是普通短信功能,由于账号未开通模板短信功能。暂不进行说明(与普通短信差不多)。

1 准备工作

1.1 引入移动Mas jar包

mvn install:install-file  -DgroupId=com.masmgc -DartifactId=masmgc-sdk -Dversion=0.0.1-SNAPSHOT -Dpackaging=jar -Dfile=C:\masmgc.sdk.sms-0.0.1-SNAPSHOT.jar

mvn install:install-file  -DgroupId=com.masmgc -DartifactId=mmasmgc-sdk-mms -Dversion=0.0.1-SNAPSHOT -Dpackaging=jar -Dfile=C:\masmgc.sdk.mms-0.0.1-SNAPSHOT.jar

1.2 引入依赖

使用SpringBoot初始化一个Maven项目,加入以下依赖:

<!--web模块-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--测试-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--移动短信-->
<dependency>
    <groupId>com.masmgc</groupId>
    <artifactId>masmgc-sdk</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.masmgc</groupId>
    <artifactId>masmgc-sdk-mms</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

2 完成短信发送功能

2.1 编写普通短信发送Service

  • 请求Entity

package com.ifknow.pojo;

import lombok.Data;

/**
 * @author: GongShiYong <br>
 * @date: 2020/10/9  15:05 <br>
 * @description: NO Description
 */
@Data
public class SendReq {
    
    /**
     * 集团客户名称
     */
    private String ecName;
    /**
     * 用户名
     */
    private String apId;
    /**
     * 密码
     */
    private String secretKey;
    /**
     * 手机号码逗号分隔。(如“18137282928,18137282922,18137282923”)
     */
    private String mobiles;
    /**
     * 发送短信内容
     */
    private String content;
    /**
     * 网关签名编码,必填,签名编码在中国移动集团开通帐号后分配,可以在云MAS网页端管理子系统-SMS接口管理功能中下载。
     */
    private String sign;
    /**
     * 扩展码,根据向移动公司申请的通道填写,如果申请的精确匹配通道,则填写空字符串(""),否则添加移动公司允许的扩展码。
     */
    private String addSerial;
    /**
     * API输入参数签名结果,签名算法:将ecName,apId,secretKey,mobiles,content ,sign,addSerial按照顺序拼接,然后通过md5(32位小写)计算后得出的值。
     */
    private String mac;
    /**
     * 参数
     */
    private String params;
    /**
     * 模板id
     */
    private String templateId;
}
  • 响应Entity

package com.ifknow.pojo;

import lombok.Data;

/**
 * @author: GongShiYong <br>
 * @date: 2020/10/9  15:11 <br>
 * @description: NO Description
 */
@Data
public class SendRes {
    
    /**
     * 响应状态码
     */
    private String rspcod;
    /**
     * 消息批次号,由云MAS平台生成,用于验证短信提交报告和状态报告的一致性(取值msgGroup)注:如果数据验证不通过msgGroup为空
     */
    private String msgGroup;
    /**
     * 数据校验结果
     */
    private boolean success;

}
  • Md5工具类

package com.ifknow.utils;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

/**
 * @author: GongShiYong <br>
 * @date: 2020/10/10  15:11 <br>
 * @description: Md5 加密工具类
 */
public class Md5Util {
    
    static final char hexDigits[] = {
    '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 生成MD5码
     *
     * @param plainText 要加密的字符串
     * @return md5值
     */
    public final static String MD5(String plainText) {
    
        try {
    
            byte[] strTemp = plainText.getBytes("UTF-8");
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(strTemp);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
    
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
    
            return null;
        }
    }

    /**
     * 生成MD5码
     *
     * @param plainText 要加密的字符串
     * @return md5值
     */
    public final static String MD5(byte[] plainText) {
    
        try {
    
            byte[] strTemp = plainText;
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(strTemp);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
    
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
    
            return null;
        }
    }

    /**
     * 先进行HmacSHA1转码再进行Base64编码
     *
     * @param data 要SHA1的串
     * @param key  秘钥
     * @return
     * @throws Exception
     */
    public static String HmacSHA1ToBase64(String data, String key) throws Exception {
    
        SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(data.getBytes());
        return Base64.encodeBase64String(rawHmac);
    }

    /**
     * 校验MD5码
     *
     * @param text 要校验的字符串
     * @param md5  md5值
     * @return 校验结果
     */
    public static boolean valid(String text, String md5) {
    
        return md5.equals(MD5(text)) || md5.equals(MD5(text).toUpperCase());
    }

    /**
     * @param params
     * @return
     */
    public static String MD5(String... params) {
    
        StringBuilder sb = new StringBuilder();
        for (String param : params) {
    
            sb.append(param);
        }
        return MD5(sb.toString());
    }
}
  • 短信发送Service

package com.ifknow.service;

import com.alibaba.fastjson.JSON;
import com.ifknow.pojo.SendReq;
import com.ifknow.pojo.SendRes;
import com.ifknow.utils.Md5Util;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;

/**
 * @author: GongShiYong <br>
 * @date: 2020/10/9  15:01 <br>
 * @description: 普通短信发送 一对一
 */
@Component
public class SMSService {
    
    /**
     * 登录名
     */
    private static String apId = "apId";
    /**
     * 登录密码
     */
    private static String secretKey = "secretKey";
    /**
     * 集团名称
     */
    private static String ecName = "ecName";
    /**
     * 网关签名编码
     */
    private static String sign = "sign";
    /**
     * 拓展码 填空
     */
    private static String addSerial = "";
    /**
     * 请求url 该接口为模板短信
     */
    private static String url = "http://112.35.1.155:1992/sms/norsubmit";

    private static Logger logger = LoggerFactory.getLogger(SMSService.class);

    /**
     * 多用户发送短信信息
     *
     * @param mobiles 手机号码逗号分隔
     * @param content 短信内容
     * @return 返回1表示成功,0表示失败
     * @throws IOException
     */
    public int sendMsg(String mobiles, String content) throws IOException {
    
        //Calendar calendar = Calendar.getInstance();
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //String nowDatestr = sdf.format(calendar.getTimeInMillis());
        //短信内容后跟个日期时间(可有可无),需求要求
        //content += nowDatestr;

        SendReq sendReq = new SendReq();
        sendReq.setApId(apId);
        sendReq.setEcName(ecName);
        sendReq.setSecretKey(secretKey);
        sendReq.setContent(content);
        sendReq.setMobiles(mobiles);
        sendReq.setAddSerial(addSerial);
        sendReq.setSign(sign);

        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(sendReq.getEcName());
        stringBuffer.append(sendReq.getApId());
        stringBuffer.append(sendReq.getSecretKey());
        stringBuffer.append(sendReq.getMobiles());
        stringBuffer.append(sendReq.getContent());
        stringBuffer.append(sendReq.getSign());
        stringBuffer.append(sendReq.getAddSerial());

        sendReq.setMac(Md5Util.MD5(stringBuffer.toString()).toLowerCase());

        String reqText = JSON.toJSONString(sendReq);

        String encode = Base64.encodeBase64String(reqText.getBytes("UTF-8"));

        String resStr = sendPost(url, encode);

        logger.info("发送短信结果:" + resStr);

        SendRes sendRes = JSON.parseObject(resStr, SendRes.class);

        if (sendRes.isSuccess() && !"".equals(sendRes.getMsgGroup()) && "success".equals(sendRes.getRspcod())) {
    
            return 1;
        } else {
    
            return 0;
        }
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数
     * @return 所代表远程资源的响应结果
     */
    public String sendPost(String url, String param) {
    
        OutputStreamWriter out = null;

        BufferedReader in = null;
        String result = "";
        try {
    
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setDoOutput(true);
            conn.setDoInput(true);

            out = new OutputStreamWriter(conn.getOutputStream());
            out.write(param);
            out.flush();

            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
    
                result += "\n" + line;
            }
        } catch (Exception e) {
    
            e.printStackTrace();
        } finally {
    
            try {
    
                if (out != null) {
    
                    out.close();
                }
                if (in != null) {
    
                    in.close();
                }
            } catch (IOException ex) {
    
                ex.printStackTrace();
            }
        }
        return result;
    }
}

注意:需要将代码中的 apId、secretKey等变量进行修改。

我们的需求是将该短信服务做成一个jar包,进行部署使用,这就要求暴露出一个向外的接口,仅仅传手机号和发送的短信内容即可。

  • 编写controller,暴露接口

package com.ifknow.controller;

import com.ifknow.service.SMSService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * @author: GongShiYong <br>
 * @date: 2020/10/10  10:20 <br>
 * @description: 移动 mas 发送 【普通短信】
 */
@RestController
public class HttpMasSendController {
    

    @Autowired
    private SMSService smsService;

    private Logger logger = LoggerFactory.getLogger(getClass());

    @PostMapping("/sendMas")
    public Integer sendMas(String mobile, String msg) {
    
        try {
    
            int result = smsService.sendMsg(mobile, msg);
            System.out.println("短信发送成功===" + result);
            return 1;
        } catch (IOException e) {
    
            logger.error("短信发送失败===" + mobile + msg);
        }
        return 0;
    }
}

经过本地接口测试 http://localhost:8088/sendMas?mobile=123&msg=123
使用PostMan或者其他接口测试工具,进行调试。

3 打包部署

打开控制台

// 清理
mvn clean
// 打包
mvn install / mvn package

将最终生成的 jar 包,传到服务器上,并放开服务器相关端口。

4 在项目中调用

  • 编写远程调用工具类
package com.ifknow.utils;

import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketTimeoutException;

/**
 * @author: GongShiYong <br>
 * @date: 2020/10/10  13:53 <br>
 * @description: 使用移动 Mas 发送普通短信的 工具类
 */
public class MasSendUtil {
    

    private static Logger logger = LoggerFactory.getLogger(MasSendUtil.class);

    public static int MasSend(String mobile, String msg) {
    

        String url = null;
        try {
    
            CloseableHttpClient httpClient = HttpClients.createDefault();
            RequestConfig requestConfig =
                    RequestConfig.custom().setSocketTimeout(300 * 1000).setConnectTimeout(300 * 1000).build();
            url = "http://192.168.1.104:8088/sendMas?mobile=" + mobile + "&msg=" + msg;
            HttpPost post = new HttpPost(url);
            post.setConfig(requestConfig);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            HttpResponse response = httpClient.execute(post);
            String content = EntityUtils.toString(response.getEntity());
            System.out.println(content);
            return 1;
        } catch (SocketTimeoutException e) {
    
            logger.error("调用sendMas接口超时,超时时间:" + 300 + "秒,url:" + url, e);
            return 0;
        } catch (Exception e) {
    
            logger.error("调用sendMas接口失败,url:" + url, e);
            return 0;
        }
    }
}

工具类的使用很简单,只需要传一个手机号和要发送的内容。

到这里,中国移动云Mas发送普通短信就完成了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41373681/article/details/109015682

智能推荐

29、华为 华三中小型企业网络架构搭建 【分支篇之虚拟专用网部署(包括对接、双链路冗余、优化与分析、策略路由与NAT的影响)】_华为生产专网及搭建-程序员宅基地

文章浏览阅读2.1k次,点赞2次,收藏16次。拓扑拓扑可以保存到本地,然后扩大查看,这样才能看的更清楚。(拖动到新窗口打开即可)路由器配置VPN,实现财务部门互访,并且AP能够正常关联到总部AC。3.1、创建环回口[GW]interface lo0[GW-LoopBack0]ip address 2.2.2.2 32说明:该地址是与总部建立Tunnel用的3.2 定义IKE peer[GW]ike peer to-center1[GW-ike-peer-to-center]pre-shared-key simple ._华为生产专网及搭建

【北邮果园大三】Software Engineering 软件工程 - Block 1 Day 1 - Introduction-程序员宅基地

文章浏览阅读934次,点赞17次,收藏25次。北邮国际学院大三软件工程第一周第一讲复习

不定积分与机器学习的关系-程序员宅基地

文章浏览阅读851次,点赞24次,收藏25次。1.背景介绍不定积分和机器学习之间的关系是一个有趣且复杂的话题。在这篇文章中,我们将探讨这两个领域之间的联系,并深入了解其核心概念、算法原理以及实际应用。不定积分是一种在数学中用于解决微分方程的工具,它可以用来计算函数的积分。机器学习则是一种通过计算机程序自动学习和预测的方法,它广泛应用于各个领域,如图像识别、自然语言处理、推荐系统等。尽管这两个领域似乎是相互独立的,但在近年来,越来越...

Kubernetes Pod 网络精髓:pause 容器详解_sandbox pause-程序员宅基地

文章浏览阅读2.6k次,点赞2次,收藏12次。本文经授权摘自杜军大佬的新书《Kubernetes 网络权威指南》,详情请看微信公众号。当检查你的 Kubernetes 集群的节点时,在节点上执行 docker ps 命令,你可能会注意到一些被称为“暂停”(pause)的容器,例如:???? → docker psCONTAINER ID IMAGE COMMAND ...3b45e983c859 gcr.io/google_con..._sandbox pause

mtk预装apk 方案公司内置预装apk-程序员宅基地

文章浏览阅读267次。mtk预装apk 方案公司内置预装apk韩梦飞沙 韩亚飞 [email protected] yue31313 han_meng_fei_sha==MTK 预知第三方的APK 流程_yuan关于MTK平台第三方APK的定制方法 - 推酷Android:源码环境下移植第三方的apk内置到ROM(System Image)中 - 混迹于移动互联网和手机行业 - ..._mtk内置apk的安装流程

从此告别PPT制作的烦恼:ChatGPT和MindShow帮你快速完成-程序员宅基地

文章浏览阅读8.5k次,点赞9次,收藏36次。随着科技的不断发展,人们对于AI技术的依赖和需求也在逐渐增加。然而,如何让这些高级技术更好地服务于我们的日常生活和工作仍然是一个亟待解决的问题。在这样的背景下,我们探索了一种全新的方式,结合了自然语言处理技术和深度学习算法,开发出了一个名为ChatGPT的AI语言模型。它不仅可以帮助我们更加高效地完成一些工作任务,还可以为我们带来全新的创意和思路。在本文中,我们将重点介绍ChatGPT和MindShow的完美结合。_mindshow

随便推点

重磅!100位校高校教师晒工资,详细晒,全国各地!要进高校的博士们参考-程序员宅基地

文章浏览阅读6.3k次。点击上方“码农突围”,马上关注这里是码农充电第一站,回复“666”,获取一份专属大礼包真爱,请设置“星标”或点个“在看”转载于:来源 | 小木虫论坛,察言观数公众号编辑|各省高校引才@everwanna211高校行政岗,中部省份,正式编制,工作两年,某权利部门科员。工资:每个月到手工资大约4000左右,年终绩效工资2.5万。房子:住房公积金每月500多。加班工资:..._高校教师工资

【C语言篇】贪吃蛇小游戏-程序员宅基地

文章浏览阅读57次。C语言基础知识

访问Github速度慢解决方法之一_mac访问github慢-程序员宅基地

文章浏览阅读2.2k次。被某墙屏蔽了,由于网络代理商的原因,所以访问下载和访问速度很慢。Ping github.com 时,速度只有 300 多 ms,有时候甚至还会访问超时。Windows 系统:C:\Windows\System32\drivers\etc\hosts。查询github.com,github.global.ssl.fastly.net 的地址。Github 访问速度很慢的原因是因为 Github 的。Mac(苹果电脑)系统:/etc/hosts。Linux 系统:/etc/hosts。_mac访问github慢

KEIL MDK的数据类型及两个重要关键词volatile & const_keil编程 volatile-程序员宅基地

文章浏览阅读1.7k次,点赞5次,收藏17次。STM32编程入门之编译器KEIL MDK的数据类型及两个重要关键词volatile& const本文适合刚刚入门的ST新手阅读,高手就不需要看了。哈哈首先说一下编程过程中几个步骤吧第一,选择一门语言,C语言或汇编语言,嵌入式编程一般目前流行还是C,这个需要基础与时间第二读懂了解 MCU的寄存器各寄存器的功能,尤其是一些IO口设置,各模块时钟设置比如定时器,I2C,同步异步串口,PWM等等,以前的话51的话没有这样设置。而现在MCU基本上各模块时钟都分开了。这个可以看官方数据说明书就_keil编程 volatile

浅析电力监控在新型数据中心的设计和应用-Susie 周_电力监控类 数据库设计-程序员宅基地

文章浏览阅读1.1k次。为了实现大型数据中心高低压配电设备的安全、可靠、自动化运行,提出了融入传统配电自动化技术的新型数据中心电力监控设计。新型监控系统是集计算机技术、数据传输、自动化控制技术、智能管理于一体的综合监控管理系统,不仅提高整个数据中心的可靠性、灵活性,而且对提升数据中心的运维管理水平有很大的帮助。_电力监控类 数据库设计

【云计算】云网络是未来的网络基础设施-程序员宅基地

文章浏览阅读1.2k次,点赞21次,收藏26次。到底什么是云网络?它和传统的网络有什么不同?当云计算把分散在各企业的算力与存储资源集中起来,并向企业、分支、IoT终端、家庭、个人移动端传输数据时,基于云连接构建的云网络就是一个面向企业租户和应用的虚拟网络。云网络基于数字经济的云平台,建立面向计算、存储、终端、应用的连接。