调用大汉三通短信接口,很详细

最近在做发送短信接口,公司选择了大汉三通短信平台,这里记录一下接口的调用步骤。

一、获取大汉三通的账号、密码请求参数

这个到大汉三通官网或者找公司相关人员要

二、查看大汉三通短信云通信接口手册

手册地址:

http://help.dahantc.com/docs/oss/1apkb302nt0tv.html

1、查询接口参数,这里以短信下发接口为例

在这里插入图片描述

2、申请短信模板

注意:

短信内容模板可以到大汉三通的后台申请,通过之后就可以使用了。

后台登录地址:

https://3tong.net/

在这里插入图片描述

这里的用户名和密码和调用接口的用户名和密码是同一个东西。

3、大汉三通jar包地址(非必要)

大汉三通是有自己jar包的,使用他们自己的jar包可以调用接口时密码不需要md5加密(目前就发现这个好处),但是大汉三通没有对应的maven依赖,需要把jar包变成本地依赖包再在maven工程中引入,这个过程比较繁琐,如果直接把jar包放到项目中引入,在项目打包后可能找不到jar包里面的工具类。
不使用大汉三通的jar包的情况下调用大汉三通的短信接口没有那么多弯,接口的必填参数拿到之后就可以调用接口了。使用了大汉三通的jar也不过调用接口时不要md5加密,这里就没有使用他们的jar包了。

jar包在这里
在这里插入图片描述
点击跳转到示例地址
在这里插入图片描述
在示例的lib目录下
在这里插入图片描述
之后将jar包导入到本地maven即可,导入步骤在这里

三、示例代码

import cn.hutool.core.util.RandomUtil;
import org.jeecg.modules.system.util.MD5Util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * 大汉三通短信工具类
 *
 * @author:user
 * @date: 2022-08-16 17:53
 */
public class DahanUtil {
    
    
    private static String account = "你的大汉三通用户名";		// 用户名(必填)
    private static String password = "你的大汉三通密码";		// 密码(必填)
    private static String phone = "19900000000"; 	// 手机号码(必填,多条以英文逗号隔开,国际短信要+国别号)
    private static String content = "";		// 短信内容(必填)
    public static String sign = "【大汉三通】"; 		// 短信签名(必填,格式如【大汉三通】)
    public static String subcode = ""; 		// 子号码(选填)
    public static String msgid = UUID.randomUUID().toString().replace("-", ""); 	// 短信id,(可选,不传我们生成一个返回)
    public static String sendtime = ""; 	// 定时发送时间(可选)

    public static void main(String[] args) throws Exception {
    
    
        long start = System.currentTimeMillis();
        String encryptPassword = MD5Util.encrypt(password);
        String _url = "http://www.dh3t.com/json/sms/Submit";

        String mesCode = RandomUtil.randomNumbers(4);

		//这是来自后台的短信模板,不能随便写,定义在模板中的验证码等变量类似${0,5}这种形式
        String info = "测试费用发放计划,金额0.01验证码为" + mesCode + "请在测试平台中输入验证码进行费用发放审核。"; // 短信内容

		//请求参数
        String requestParam = "{\"account\":\"" + account + "\",\"password\":\"" + encryptPassword + "\",\"msgid\":\"" + msgid + "\",\"phones\":\"" + phone + "\",\"content\":\"" + info + "\",\"sign\":\"" + sign + "\",\"subcode\":\"" + subcode + "\"}";

        URL url = new URL(_url);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestMethod("POST");
        urlConnection.setDoOutput(true);

        OutputStream outputStream = urlConnection.getOutputStream();
        outputStream.write(requestParam.getBytes("UTF-8"));

        outputStream.flush();
        outputStream.close();

		//响应结果
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
        StringBuffer stringBuffer = new StringBuffer();
        int ch;
        while ((ch = bufferedReader.read()) > -1) {
    
    
            stringBuffer.append((char) ch);
        }

		//返回结果,类似这种{"msgid":"","result":"0","desc":"请求成功","failPhones":""}
        System.out.println(stringBuffer); 
        
        bufferedReader.close();
        Long end = System.currentTimeMillis();

        System.out.println("发送短信耗时:" + (end - start));
    }
}

测试结果:

{“msgid”:“”,“result”:“0”,“desc”:“请求成功”,“failPhones”:“”}

因为我这里没有白名单所以会报“ip鉴权失败”,就没有截图,如果报这个错就表示其他都没有问题了,就差白名单了。如果返回请求成功的话,那对应的手机号码过一会就可以收到验证码了。

四、工具类

这是我在项目中使用的工具类。

1、请求参数dto

import lombok.Data;

/**
 * 大汉三通配置dto
 *
 * @author:user
 * @date: 2022-08-16 18:14
 */
@Data
public class DahanConfig {
    
    
    //设置默认值是为了让发送请求时为空的参数值不为“null”
    // 用户名(必填)
    private String account = "";

    // 密码(必填)
    private String password = "";

    // 手机号码(必填,多条以英文逗号隔开,国际短信要+国别号)
    private String phone = "";

    // 短信内容(必填)
    private String content = "";

    // 短信签名(必填,格式如【大汉三通】)
    private String sign = "";

    // 大汉三通请求地址
    private String url = "";

    // 子号码(选填)
    private String subcode = "";

    // 短信id,(可选,不传我们生成一个返回)
    private String msgid = "";

    // 定时发送时间(可选)
    private String sendtime = "";
}

2、替换短信内容的dto

import lombok.Data;

/**
 * 替换短信内容dto
 *
 * @author:user
 * @date: 2022-08-17 18:28
 */
@Data
public class ReplaceInfoDto {
    
    
    //索引,用来和传入参数对应
    private Integer index;

    //被替换字符在原始字符串中的开始索引
    private Integer start;

    //被替换字符在原始字符串中的结束索引
    private Integer end;

    //在原始字符串中被替换字符
    private String waitToReplaceStr;

    //将替换原始字符串中被替换字符的参数
    private Object replaceStr;
}

3、响应状态码枚举类

/**
 * 大汉三通响应状态码
 *
 * @author:user
 * @date: 2022-08-16 18:09
 */
public enum DahanSmsCodeEnum {
    
    

    SUBMITTED_SUCCESSFULLY("0", "提交成功"),
    INCORRECT_USERNAME_OR_PASSWORD("1", "账号或密码错误"),
    MSGID_TOO_LONG("3", "msgid 太长,不得超过 64 位"),
    WRONG_NUMBER("4", "错误号码 / 限制运营商号码"),
    PHONE_NUMBER_LIMIT("5", "手机号码个数超过最大限制"),
    SMS_CONTENT_LIMIT("6", "短信内容超过最大限制"),
    INVALID_EXTENSION_SUBNUMBER("7", "扩展子号码无效"),
    TIMING_TIME_FORMAT_ERROR("8", "定时时间格式错误"),
    PHONE_EMPTY("14", "手机号码为空"),
    USER_BANNED_OR_DISABLED("19", "用户被禁发或禁用"),
    IP_AUTHENTICATION_FAILED("20", "ip 鉴权失败"),
    SMS_CONTENT_EMPTY("21", "短信内容为空"),
    NO_NUMBER_AVAILABLE("24", "无可用号码"),
    BATCH_SMS_NUMBER_LIMIT("25", "批量提交短信数超过最大限制"),
    SYSTEM_BUSY("98", "系统正忙"),
    MALFORMED_MESSAGE("99", "消息格式错误");

    private String code;
    private String desc;
    DahanSmsCodeEnum(String code, String desc) {
    
    
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
    
    
        return code;
    }

    public String getDesc() {
    
    
        return desc;
    }
}

4、MD5的加密工具类

可以使用自己的MD5加密工具类,使用了大汉三通jar包不需要MD5加密。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密类(封装jdk自带的md5加密方法)
 * 32位小写
 */
public class MD5Util {
    
    

    public static String encrypt(String source) {
    
    
        return encodeMd5(source.getBytes());
    }

    private static String encodeMd5(byte[] source) {
    
    
        try {
    
    
            return encodeHex(MessageDigest.getInstance("MD5").digest(source));
        } catch (NoSuchAlgorithmException e) {
    
    
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private static String encodeHex(byte[] bytes) {
    
    
        StringBuffer buffer = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
    
    
            if (((int) bytes[i] & 0xff) < 0x10) {
    
    
                buffer.append("0");
            }
            buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
        }
        return buffer.toString();
    }

}

5、调用接口的工具类

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.VerifyUtil;
import org.jeecg.modules.dahan.dto.DahanConfig;
import org.jeecg.modules.dahan.dto.ReplaceInfoDto;
import org.jeecg.modules.dahan.enums.DahanSmsCodeEnum;
import org.jeecg.modules.system.util.MD5Util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 大汉三通短信工具类
 *
 * @author:user
 * @date: 2022-08-16 17:53
 */
@Slf4j
public class DahanUtil {
    
    

    private static String REGULAR = "\\$\\{\\d+\\,\\d+\\}"; //大汉三通模板中的匹配规则:\${\d+,\d+},匹配例如:${0,4}
    private static Pattern PATTERN = Pattern.compile(REGULAR);

    private static String account = "你的大汉三通账号";		// 用户名(必填)
    private static String password = "你的大汉三通密码";		// 密码(必填)
    private static String phone = "19000000000"; 	// 手机号码(必填,多条以英文逗号隔开,国际短信要+国别号)
    private static String content = "";		// 短信内容(必填)
    public static String sign = "【大汉三通】"; 		// 短信签名(必填,格式如【大汉三通】)
    public static String subcode = ""; 		// 子号码(选填)
    public static String msgid = UUID.randomUUID().toString().replace("-", ""); 	// 短信id,(可选,不传我们生成一个返回)
    public static String sendtime = ""; 	// 定时发送时间(可选)

    public static void main(String[] args) throws Exception {
    
    

        String originalInfo = "${4,20}费用发放计划,金额${3,20}验证码为${0,5}请在测试平台中输入验证码进行费用发放审核。";

        //使用参数替换短信中的字符(形如:${4,20}),按顺序替换
        String content = getTargetStr(originalInfo, "测试", "0.01", "1122");
        System.out.println(content);

        DahanConfig config = new DahanConfig();
        config.setAccount(account);
        config.setPassword(password);
        config.setPhone(phone);
        config.setContent(content);
        config.setSign(sign);
        config.setUrl("http://www.dh3t.com/json/sms/Submit");

        sendSms(config);
    }

    /**
     * 获取替换参数替换了待替换字符串的字符串值
     * @param source  原始字符串
     * @param targetValues  替换参数,要按照替换字符的顺序传入
     * @return
     */
    public static String getTargetStr(String source, Object ...targetValues) {
    
    
        List<ReplaceInfoDto> replaceInfoList = getReplaceInfoList(source, targetValues);

        StringBuilder sourceStrBuilder = new StringBuilder(source);

        int start;
        int end;
        int indexDifference = 0; //被替换的字符和将替换的字符的索引长度差,用来重新设置开始字符的索引
        String currentWaitToReplaceStr = null; //当前待替换字符
        String currentTargetStr = null;  //当前目标字符
        ReplaceInfoDto replaceInfo = null;

        for (int i = 0; i < replaceInfoList.size(); i++) {
    
    
            replaceInfo = replaceInfoList.get(i);
            start = replaceInfo.getStart();
            end = replaceInfo.getEnd();
            currentWaitToReplaceStr = replaceInfo.getWaitToReplaceStr();
            currentTargetStr = replaceInfo.getReplaceStr().toString();

            if (i != 0) {
    
     //第一个待替换的字符不需要加上索引差
                start += indexDifference;
                end += indexDifference;
            }

            indexDifference += currentTargetStr.length() - currentWaitToReplaceStr.length(); //后面开始索引有偏差的话,索引长度差需要累加

            sourceStrBuilder.replace(start, end, currentTargetStr); //从当前开始索引和结束索引,以目标参数替换待替换字符串
        }
        return sourceStrBuilder.toString();
    }

    /**
     * 取出字符串中的符合正则表达式的所有字符串map,value为这个字符串的开始索引
     * @param source 字符串
     * @return
     */
    public static Map<Integer, Integer> getTargetIndexMap(String source) {
    
    
        VerifyUtil.checkParam(source, "被替换字符串不能为空!"); //这是校验空字符串的方法,之前的博客中有,也可以用自己的方式校验

        Matcher matcher = PATTERN.matcher(source);

        Map<Integer, Integer> result = new HashMap<>();//value为目标字符串中的开始索引
        Integer index = 0; //map中的索引
        while (matcher.find()) {
    
     //匹配成功的结果是按字符串中从左至右的顺序,使用索引方便后面取出
            //当前目标字符串在原始字符串中的开始索引
            result.put(index, matcher.start());
            index++;
        }
        return result;
    }

    /**
     * 取出字符串中的符合正则表达式的所有字符串,将它们的开始索引,结束索引,字符串值以及对应替换值设置到替换内容dto中
     * @param source  原始字符串
     * @param targetValues  替换数组
     * @return
     */
    public static List<ReplaceInfoDto> getReplaceInfoList(String source, Object ...targetValues) {
    
    
        VerifyUtil.checkParam(source, "被替换字符串不能为空!");

        if (getTargetIndexMap(source).size() != targetValues.length)
            throw new RuntimeException("传入替换值数量与字符串中待替换字符数量不一致!");

        Matcher matcher = PATTERN.matcher(source);

        //因为每遍历一次,对象中的值都会被重新设置,所以只要new一个就可以了
        ReplaceInfoDto replaceInfoDto = null;

        //返回的替换内容集合
        List<ReplaceInfoDto> replaceInfoDtoList = new ArrayList<>();

        Integer index = 0; //索引,后面要从数组中取数据,索引从0开始
        while (matcher.find()) {
    
     //匹配成功的结果是按字符串中从左至右的顺序,使用索引方便后面取出
            replaceInfoDto = new ReplaceInfoDto();
            replaceInfoDto.setIndex(index);
            replaceInfoDto.setStart(matcher.start());
            replaceInfoDto.setEnd(matcher.end());
            replaceInfoDto.setWaitToReplaceStr(matcher.group());
            replaceInfoDto.setReplaceStr(targetValues[index]); //传入替换参数与字符串中待替换的参数一致则可以用索引对应上
            replaceInfoDtoList.add(replaceInfoDto);
            index++;
        }
        return replaceInfoDtoList;
    }

    /**
     * 发送大汉三通短信配置
     * @param config
     * @throws Exception
     */
    public static void sendSms(DahanConfig config) throws Exception {
    
    
        List<String> emptyFiledList = Arrays.asList("subcode", "msgid", "sendtime");//可以以自己的方式校验必填字段,这三个是可以为空的字段
        VerifyUtil.checkBean(config, emptyFiledList);

        long start = System.currentTimeMillis();

        //没有使用大汉三通的jar包,需要进行md5加密
        config.setPassword(MD5Util.encrypt(config.getPassword()));

        String requestParam = "{\"account\":\"" + config.getAccount() + "\",\"password\":\"" + config.getPassword() + "\",\"msgid\":\"" + config.getMsgid() + "\",\"phones\":\"" + config.getPhone() + "\",\"content\":\"" + config.getContent() + "\",\"sign\":\"" + config.getSign() + "\",\"subcode\":\"" + config.getSubcode() + "\"}";

        log.info("大汉三通请求参数:{}", requestParam);

		//我这里是想用HttpURLConnection发送请求,可以用自己的方式发送请求
        HttpURLConnection urlConnection = null;
        OutputStreamWriter outputStream = null;
        try {
    
    
            //创建连接
            URL url = new URL(config.getUrl());
            urlConnection = (HttpURLConnection) url.openConnection();

            //设置请求参数
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("Content-Type", "application/json");// 发送请求参数类型
            urlConnection.setDoInput(true); //是否输入参数
            urlConnection.setDoOutput(true); //是否输出参数

            //获取写数据流
            outputStream = new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8");
            outputStream.write(requestParam); //写数据,这里就是请求的返回结果

            log.info("发送大汉三通短信:{}", outputStream);
            outputStream.flush();
        } catch (IOException e) {
    
    
            e.printStackTrace();

            log.error("大汉三通请求参数信息错误:{}", e.getMessage());

            throw new RuntimeException(e.getMessage());
        } finally {
    
    
            if (null != outputStream) {
    
    
                outputStream.close();
            }
        }

        log.info("大汉三通请求响应状态码:{}", urlConnection.getResponseCode());

        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
    
    
            //获取响应参数
            inputStream = urlConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            bufferedReader = new BufferedReader(inputStreamReader);

            int ch;
            while ((ch = bufferedReader.read()) > -1) {
    
    
                stringBuilder.append((char) ch);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();

            log.error("获取响应体失败: {}", e.getMessage());

            throw new RuntimeException(e.getMessage());
        } finally {
    
    
            if (null != inputStream) {
    
    
                inputStream.close();
            }

            if (null != inputStreamReader) {
    
    
                inputStreamReader.close();
            }

            if (null != bufferedReader) {
    
    
                bufferedReader.close();
            }

            if (null != urlConnection) {
    
    
                urlConnection.disconnect();
            }
        }

        log.info("大汉三通响应信息:{}", stringBuilder);

        JSONObject responseJson = JSONObject.parseObject(stringBuilder.toString());

        //短信发送失败是返回错误信息
        if (!DahanSmsCodeEnum.SUBMITTED_SUCCESSFULLY.getCode().equals(responseJson.getString("result")))
            throw new RuntimeException(responseJson.getString("desc"));

        long end = System.currentTimeMillis();
        log.info("发送大汉三通短信耗时:{}", end - start);
    }
}

猜你喜欢

转载自blog.csdn.net/studio_1/article/details/126407621