Authored by DengXinFei

更新短信运营商

@@ -101,7 +101,8 @@ public class SMSSendHelper { @@ -101,7 +101,8 @@ public class SMSSendHelper {
101 String beanName = SmsProviderCodeEnum.getBeanNameByValue(smsProviderCode); 101 String beanName = SmsProviderCodeEnum.getBeanNameByValue(smsProviderCode);
102 if (StringUtils.isEmpty(beanName)) { 102 if (StringUtils.isEmpty(beanName)) {
103 // 默认玄武 103 // 默认玄武
104 - beanName = "XWSendSMSServiceImpl"; 104 + //beanName = "XWSendSMSServiceImpl";
  105 + beanName = "YTSendSMSServiceImpl";
105 } 106 }
106 ISendSMSService sms = SpringContextUtil.getBean(beanName, ISendSMSService.class); 107 ISendSMSService sms = SpringContextUtil.getBean(beanName, ISendSMSService.class);
107 return sms.sendSMS(mobileList, content, params); 108 return sms.sendSMS(mobileList, content, params);
  1 +package com.yoho.yhmessage.sms.service.impl;
  2 +
  3 +import com.yoho.yhmessage.sms.service.ISendSMSService;
  4 +import com.yoho.yhmessage.sms.service.model.Response;
  5 +import com.yoho.yhmessage.sms.service.model.SendNoticeResultBean;
  6 +import com.yoho.yhmessage.sms.util.HttpUtils;
  7 +import com.yoho.yhmessage.sms.util.PhoneUtil;
  8 +import com.yoho.yhmessage.sms.util.StringUtil;
  9 +import org.apache.commons.codec.binary.Hex;
  10 +import org.apache.commons.lang3.tuple.Pair;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.springframework.stereotype.Service;
  14 +
  15 +import java.io.UnsupportedEncodingException;
  16 +import java.util.ArrayList;
  17 +import java.util.List;
  18 +import java.util.Map;
  19 +
  20 +/**
  21 + * 上海移通短信发送实现
  22 + * @remark 默认使用移通进行短信发送
  23 + *
  24 + *
  25 + * @ClassName YTSendSMSServiceImpl
  26 + * @Author xinfei
  27 + * @Date 2018/7/30 11:38
  28 + **/
  29 +@Service("YTSendSMSServiceImpl")
  30 +public class YTSendSMSServiceImpl implements ISendSMSService {
  31 +
  32 + static Logger logger = LoggerFactory.getLogger(YTSendSMSServiceImpl.class);
  33 +
  34 + private final static int pageSize = 100; //定义批量发送的条数
  35 +
  36 + /**
  37 + * 上海移通消息中心,通知类型的短信发送接口
  38 + *
  39 + * 使用限制:1. 批量发送短信,只能是相同内容。
  40 + * 2. 只支持发送国内短信,不支持发送国际短信。
  41 + *
  42 + * 备注:1. 当前接口发送失败为统一失败,不存在同一批次的短信,部分失败,部分成功。
  43 + * 2. 配置的参数暂时先写死在程序中,由于需要紧急切换(缺点:不安全,如果后面发生信息改变,不易切换)。
  44 + *
  45 + * @param mobileList 批量发送手机号码
  46 + * @param content 发送短信的内容
  47 + * @param params 短信内容里面可以替换的参数
  48 + * @return 发送成功的列表,发送失败返回空
  49 + *
  50 + * @throws Exception HTTP发送请求异常
  51 + *
  52 + * @add 2018-07-30 添加移通发送短信的功能 by 邓新飞
  53 + * @Modify
  54 + */
  55 + @Override
  56 + public Response<SendNoticeResultBean> sendSMS(List<String> mobileList, String content, Map<String, String> params) throws Exception {
  57 + logger.info("Begin send sms by YiTong. mobileList={}, content={}, params={}", mobileList, content, params);
  58 + //(1)定义返回的参数类型
  59 + SendNoticeResultBean bean = new SendNoticeResultBean();
  60 + List<String> successList = new ArrayList<String>();
  61 +
  62 + //(2)判断发送的手机号码,如果发送的手机号码为空,直接返回
  63 + if(null == mobileList || mobileList.size() == 0) {
  64 + bean.setSendNum(0);
  65 + bean.setSuccessNum(0);
  66 + bean.setSuccessList(successList);
  67 + return new Response<SendNoticeResultBean>(bean);
  68 + }
  69 +
  70 + //(3)分页处理短信发送情况
  71 + int size = mobileList.size();
  72 + if (size <= pageSize) {
  73 + successList.addAll(immediateSendSMS(mobileList, content, params));
  74 + } else {
  75 + int lastPageSize = size % pageSize;
  76 + int pageTotal = size / pageSize;
  77 + if (lastPageSize > 0) {
  78 + pageTotal += 1;
  79 + }
  80 + for (int i = 0; i < pageTotal; i++) {
  81 + int begin = i * pageSize;
  82 + int end = (i + 1) * pageSize < size ? (i + 1) * pageSize : size;
  83 + successList.addAll(immediateSendSMS(mobileList.subList(begin, end), content, params));
  84 + }
  85 + }
  86 + logger.info("sendSMS success with mobileList={}, content={}, params={}", mobileList.size(), content, params);
  87 +
  88 + //(4)组装返回结果
  89 + bean.setSendNum(successList.size());
  90 + bean.setSuccessNum(successList.size());
  91 + bean.setSuccessList(successList);
  92 + return new Response<SendNoticeResultBean>(bean);
  93 + }
  94 +
  95 +
  96 + /**
  97 + * 直接发送短信-使用上海移通进行短信发送
  98 + *
  99 + * @param mobileList
  100 + * @param content
  101 + * @param params
  102 + * @return
  103 + * @throws Exception
  104 + */
  105 + private List<String> immediateSendSMS(List<String> mobileList, String content, Map<String, String> params) throws Exception {
  106 + //(1)准备移通发送短信所需要的执行参数
  107 + String command = "MULTI_MT_REQUEST";// 操作命令、SP编号、SP密码,必填参数
  108 + String spid = "8020"; //参数spid为SP编号,必须填写
  109 + String sppassword = "yh8020@yoho"; //参数sppassword为SP帐号的密码,必须填写;
  110 + String spsc = "00"; // sp服务代码,可选参数,默认为 00
  111 + String url = "http://esms200.10690007.net/sms/mt"; //短信运营商发送请求的URL。
  112 + int dc = 15; // 下行内容以及编码格式,必填参数
  113 +
  114 + //(2) 对发送短信内容进行重新编码
  115 + String sm = new String(Hex.encodeHex(content.getBytes("GBK")));
  116 + logger.debug("End recode send content. content={}, sm={}", content, sm);
  117 +
  118 + //(4)整理发送短信的手机号码,按照移通支持的格式组装. 手机号码之间用,隔开
  119 + StringBuilder mobiles = new StringBuilder();
  120 + int size = mobileList.size();
  121 + for(int i = 0; i < size; i++){
  122 + if(mobileList.get(i).length() != 11 || !mobileList.get(i).startsWith("1") ){
  123 + logger.info("sms send mobile is invalid. mobile={}", mobileList.get(i));
  124 + continue;
  125 + }
  126 + if(i == (size - 1)){
  127 + mobiles.append("86" + mobileList.get(i));
  128 + continue;
  129 + }
  130 + mobiles.append("86" + mobileList.get(i) + ",");
  131 + }
  132 +
  133 + //(3)组装发送请求的URL
  134 + StringBuilder smsUrl = new StringBuilder();
  135 + smsUrl.append(url);
  136 + smsUrl.append("?command=" + command);
  137 + smsUrl.append("&spid=" + spid);
  138 + smsUrl.append("&sppassword=" + sppassword);
  139 + smsUrl.append("&spsc=" + spsc);
  140 + smsUrl.append("&das=" + mobiles.toString());
  141 + smsUrl.append("&sm=" + sm);
  142 + smsUrl.append("&dc=" + dc);
  143 +
  144 + //(3) 发送http请求,并接收http响应
  145 + Pair<Integer, String> result = HttpUtils.httpGet(smsUrl.toString(), null, "GBK", 1000);
  146 + if(result.getLeft() != 200){
  147 + return new ArrayList<String>();
  148 + }
  149 + return mobileList;
  150 + }
  151 +
  152 + public static void main(String[] args) throws Exception {
  153 + String content = "您在Yoho!buy有货的预售订单5555商品已经到货,请及时付款。";
  154 +// String message = "校验码{code},南京技术部测试";
  155 +// String[] params = {"222222"};//1-9176028238
  156 +// //香港-852-98050283
  157 +// //美国 1-2066058408
  158 +// //日本 81-8041882889
  159 +// String result = YTSendSMSServiceImpl.sendMessage(content, "8618001582955,8618994021292", params);
  160 +// System.out.println("==================" + result + "====================");
  161 + YTSendSMSServiceImpl service = new YTSendSMSServiceImpl();
  162 + List<String> mobiles = new ArrayList<String>(5);
  163 + mobiles.add("18001582955");
  164 + mobiles.add("18994021292");
  165 + Response<SendNoticeResultBean> response = service.sendSMS(mobiles, content, null);
  166 + System.out.println("==============发送成功===================");
  167 +
  168 +
  169 + }
  170 +
  171 +
  172 +
  173 +
  174 +
  175 +}
  1 +package com.yoho.yhmessage.sms.util;
  2 +
  3 +import java.util.regex.Matcher;
  4 +import java.util.regex.Pattern;
  5 +
  6 +public class PhoneUtil {
  7 +
  8 + //中国国家码
  9 + private final static String CHINA_AREA = "86";
  10 +
  11 +
  12 + /**
  13 + * 判断号码是否是国内号码
  14 + *
  15 + * @param mobile
  16 + * @return
  17 + */
  18 + public static boolean isDomestic(String mobile) {
  19 + if (null != mobile && !mobile.isEmpty()) {
  20 + mobile = ltrim(mobile, "0");
  21 + mobile = mobile.replaceAll("\\+", "");
  22 + String[] mobiles = mobile.split("-");
  23 + if (mobiles.length == 1) {
  24 + return true;
  25 + } else if (mobiles.length == 2
  26 + && ("86".equals(mobiles[0].trim())
  27 + || "086".equals(mobiles[0].trim()) || "0086"
  28 + .equals(mobiles[0].trim()))) {
  29 + return true;
  30 + }
  31 + }
  32 + return false;
  33 + }
  34 +
  35 + /**
  36 + * 根据国家码判断是否是国内号码
  37 + *
  38 + * @param area 国家码
  39 + * @return boolean
  40 + */
  41 + public static boolean isInternationalMobile(String area){
  42 + if(null == area || CHINA_AREA.equals(area)){
  43 + return true;
  44 + }
  45 + return false;
  46 + }
  47 +
  48 + public static void main(String[] args) {
  49 + System.out.print(isMobile("15951889346@163.com"));
  50 + }
  51 +
  52 + /**
  53 + * 手机号码加上国家码 : 如8612012221467
  54 + *
  55 + * @param mobile
  56 + * @return
  57 + */
  58 + public static String makeMobile(String mobile){
  59 + //判断是否是国内号码,如果是国内号码, 则在号码前加上86, 如8612012221467
  60 + boolean isDomestic = PhoneUtil.isDomestic(mobile);
  61 + if(!isDomestic){ //如果不是国内号码
  62 + String[] mobiles = mobile.split("-");
  63 + if(null != mobiles && 2 == mobiles.length){
  64 + mobile = mobiles[0] + mobiles[1];
  65 + return mobile;
  66 + }
  67 + return mobile;
  68 + }
  69 + //如果不是国际号码,返回号码+86
  70 + return "86" + mobile;
  71 + }
  72 +
  73 + public static boolean isMobile(String mobile){
  74 + if(null == mobile || "".equals(mobile)){
  75 + return false;
  76 + }
  77 +
  78 + int mobileLength = mobile.length();
  79 + if(mobileLength>20){
  80 + return false;
  81 + }
  82 + //如果有字母也不是手机
  83 + String regex=".*[a-zA-Z]+.*";
  84 + Matcher m=Pattern.compile(regex).matcher(mobile);
  85 + if(m.matches()){
  86 + return false;
  87 + }
  88 + return true;
  89 + }
  90 +
  91 +
  92 + public static String ltrim(String message, String regex) {
  93 + if (message == null || message.isEmpty() || regex == null
  94 + || regex.isEmpty()) {
  95 + return message;
  96 + }
  97 + while (message.indexOf(regex) == 0) {
  98 + message = message.substring(regex.length());
  99 + }
  100 + return message;
  101 + }
  102 +}
  1 +
  2 +package com.yoho.yhmessage.sms.util;
  3 +
  4 +public class StringUtil {
  5 +
  6 + /**
  7 + * 函数移除字符串左侧的预定义字符。
  8 + *
  9 + * @param message 字符串内容
  10 + * @param regex 需要替换为空的字符串
  11 + * @return String
  12 + */
  13 + public static String ltrim(String message, String regex) {
  14 + if (message == null || message.isEmpty() || regex == null
  15 + || regex.isEmpty()) {
  16 + return message;
  17 + }
  18 + while (message.indexOf(regex) == 0) {
  19 + message = message.substring(regex.length());
  20 + }
  21 + return message;
  22 + }
  23 +
  24 + /**
  25 + * 替換字符串{}中的內容
  26 + * @param message
  27 + * @param args
  28 + * @return
  29 + */
  30 + public static String strFormat(String message, Object[] args){
  31 + if(StringUtil.isEmpty(message)){
  32 + return message;
  33 + }
  34 + int i = 0;
  35 + while(message.indexOf("{") != -1 && message.indexOf("}") != -1){
  36 + int startIndex = message.indexOf("{");
  37 + int endIndex = message.indexOf("}");
  38 +
  39 + String startMsg = "";
  40 + String endMsg = "";
  41 + if(startIndex != 0){
  42 + startMsg = message;
  43 + startMsg = startMsg.substring(0, startIndex);
  44 + }
  45 + if(endIndex != message.length() - 1){
  46 + endMsg = message;
  47 + endMsg = endMsg.substring(endIndex + 1, message.length());
  48 + }
  49 + message = startMsg + args[i] + endMsg;
  50 + i++;
  51 + }
  52 + return message;
  53 + }
  54 +
  55 +
  56 +
  57 + public static void main(String[] args) {
  58 + String message = "{sss}while loading:{dd}";
  59 + String[] param = {"xinfei", "test"};
  60 + System.out.println(StringUtil.strFormat(message, param));
  61 + }
  62 +
  63 +
  64 + /**
  65 + * 判断字符串是否为空
  66 + *
  67 + * @param str
  68 + * @return
  69 + */
  70 + public static boolean isEmpty(String str) {
  71 + if (null == str || str.isEmpty()) {
  72 + return true;
  73 + }
  74 + return false;
  75 + }
  76 +
  77 +}