一.登录官网,下载http接入文档
官网地址为:云mas业务平台
二.创建http短信接口
登录中国移动云mas平台,新建短信接口:
新建短信接口(简称SMS接口),是为集团客户创建可以使用接口发送短信的用户。该用户只能通过指定协议(CMPP2.0、CMPP2.0s、CMPP3.0、SDK、HTTP)连接网关,连接网关成功后,该用户可以通过接口进行发送短信。
业务流程:
用户名:若指定为协议,则用户名不可重名,必须唯一;若指定为sdk,则用户名可重名。限制6位字符
用户密码:6-20位字符组成。
IP地址:是接入用户的IP地址,用来鉴权用户的,这个IP地址暂时没有使用
所属分组:所属分组记录当前用户所在组织架构。
生效|失效日期:非必填字段,不填为永久有效
协议:五种选择方式,CMPP2.0、CMPP2.0s、CMPP3.0、SDK、HTTP。选择SDK、HTTP时,不需要对用户名重名做全局校验;选择CMPP2.0、CMPP2.0s、CMPP3.0协议时,需要对用户名是否重名做校验。
回执状态: SMS接口用户是否接收回执,若选择开通则在发送成功时,会发送回执状态报告
SDK状态:只对当前SDK用户可用。开启代表当前SDK用户可用,关闭代表SDK用户不可用。
安全认证:IP白名单认证,暂未生效。
三.java开发工具类
1.根据文档编写对应实体类
SendReq.java:
/**集团客户名称*/
private String ecName;
/**用户名*/
private String apId;
/**密码*/
private String secretKey;
/**手机号码逗号分隔。(如“1813728****,1813728****,1813728****”)*/
private String mobiles;
/**发送短信内容*/
private String content;
/**网关签名编码,必填,签名编码在中国移动集团开通帐号后分配,可以在云MAS网页端管理子系统-SMS接口管理功能中下载。*/
private String sign;
/**扩展码,根据向移动公司申请的通道填写,如果申请的精确匹配通道,则填写空字符串(""),否则添加移动公司允许的扩展码。*/
private String addSerial;
/**按文档要求加密后的mac*/
private String mac;
// 省略get set方法
SendRes.java:
/**响应状态码*/
private String rspcod;
/**消息批次号,由云MAS平台生成,用于验证短信提交报告和状态报告的一致性(取值msgGroup)注:如果数据验证不通过msgGroup为空*/
private String msgGroup;
/**数据校验结果*/
private boolean success;
// 省略get set方法
2.短信发送工具类
package demo.krt;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.apache.commons.codec.binary.Base64;
import com.alibaba.fastjson.JSON;
/**
* @version 1.0
* @Author: lyp
* @Date: 2021/2/27 15:09
*/
public class SMSUtils {
/**账号*/
private static String apId = "";
/**密码*/
private static String secretKey = "";
/**集团名称*/
private static String ecName = "";
/**网关签名编码*/
private static String sign = "";
/**拓展码(可以为空)*/
private static String addSerial = "";
/**url*/
private static String url = "http://112.35.1.155:1992/sms/norsubmit";
/**
* 多用户发送短信信息
*
* @param mobiles 手机号码逗号分隔
* @param content 短信内容
* @return 返回1表示成功,0表示失败
* @throws IOException
*/
public static boolean sendMsg(String mobiles, String content) throws IOException {
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);
// BASE64编码
String encode = Base64.encodeBase64String(reqText.getBytes("UTF-8"));
System.out.println(encode);
String resStr = sendPost(url, encode);
System.out.println("发送短信结果:" + resStr);
SendRes sendRes = JSON.parseObject(resStr, SendRes.class);
if (sendRes.isSuccess() && !"".equals(sendRes.getMsgGroup()) && "success".equals(sendRes.getRspcod())) {
return true;
} else {
return false;
}
}
/**
* main方法测试发送短信,返回1表示成功,0表示失败
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String msg = "这是发送短信的内容!";
sendMsg("186****7603", msg);
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数
* @return 所代表远程资源的响应结果
*/
private static 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;
}
}
3.md5加密工具类(32位)
package demo.krt;
import java.security.MessageDigest;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* @version 1.0
* @Author: lyp
* @Date: 2021/2/27 15:11
*/
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());
}
}
四.注意(有坑)
apId和secretKey一般不会搞错,
但是集团名称ecName一定要写对,否则就会提示{“msgGroup”:”“,”rspcod”:”InvalidUsrOrPwd”,”success”:false},无效的用户名和密码,
还有一个就是mac字段sendReq.setMac(Md5Util.MD5(stringBuffer.toString()).toLowerCase());
MD5加密过后一定要把它变成小写.toLowerCase(),否则也会出错。
MD5加密过程中一定要注意字符编码,不同的字符编码加密后结果可能不一,例:
Smsa.1867603测试短信发送UsL
760f8998451f7f94d4ac1344094*****
Smsa.1867603测试短信发送UsL
41b48561faf3411b407110f9445*****
看起来完全一样,加密后结果却不一样,导致mac校验失败
加密前指定字符编码:
byte[] strTemp = plainText.getBytes(“UTF-8”);