package com.smp.sev.sms; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.smp.bean.MsgSubmit; import com.smp.sev.cache.OperatorInfo; import com.smp.sev.service.MsgService; import com.smp.util.MsgUtil; import com.smp.util.SmpProperty; import com.smp.util.Tools; /** * @author xml * */ @Service public class MsgSender { @Autowired private MsgService ms; @Autowired private OperatorInfo op; private static final Logger logger = Logger.getLogger(MsgSender.class); private Timer msgTimer = new Timer("msgTimer"); public MsgSender() { setSno(SmpProperty.getInstance().getStartSno(), SmpProperty.getInstance().getEndSno()); } /** * 短信服务器请求地址 */ private static int msgid = 0; /** * 当前的短号 */ private int curShortNo = 0; /** * 短号的开始号码--字符串形式,方便上行时匹配 */ private static String STARTSHORTNO_STR = "0"; /** * 短号的开始号码- */ private int STARTSHORTNO = 0; /** * 短号的结束号码 */ private int ENDSHORTNO = 0; private synchronized int getShortNo() { if(curShortNo==0) { curShortNo = ms.getMaxShortNo(); } if(curShortNo<STARTSHORTNO||curShortNo>=ENDSHORTNO)curShortNo=STARTSHORTNO+10; curShortNo++; return curShortNo; } public synchronized int getMsgid() { if(msgid==0) { msgid = ms.getMaxMsgid(); if(msgid==-1)msgid = 0; } msgid++; return msgid; } public void setSno(int startSno, int endSno) { STARTSHORTNO = startSno; STARTSHORTNO_STR = String.valueOf(startSno); ENDSHORTNO = endSno; } public static String getStartSno() { return STARTSHORTNO_STR; } public MsgSubmit setIdAndShortNo(MsgSubmit ms) { ms.setMsId(getMsgid()); if("选项调查".equals(ms.getMsType())){ ms.setMsShortno(String.valueOf(getShortNo())); }else ms.setMsShortno(STARTSHORTNO_STR); return ms; } private void send(final MsgSubmit msg, final List<String[]> users, String phones, final boolean isSaveLog,final boolean issavemsg){ if(msg==null||users==null||(users!=null&&users.size()==0)) { return; } //判断手机号是那个运营商,分别调用不同的网关 Map<String, String> operator=op.getHeNanYiDong(); final StringBuffer yidong=new StringBuffer(); final StringBuffer other=new StringBuffer(); for(String[] u:users){ String phone=u[1]; if(phone!=null&&phone.length()>6){ if(operator.containsKey(phone.substring(0, 7))){ yidong.append(phone+","); }else{ other.append(phone+","); } } } if(yidong.length()>0){ yidong.deleteCharAt(yidong.length()-1); } if(other.length()>0){ other.deleteCharAt(other.length()-1); } System.out.println(yidong.length()+":"+other.length()); new Thread(new Runnable(){ public void run() { long spendtime = 0; if (logger.isDebugEnabled()) { spendtime = System.currentTimeMillis(); logger.debug("$MsgSenderRunnable.run() - start"); } DefaultHttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(SmpProperty.getInstance().getSendMessageUrl()); List <NameValuePair> nvps = new ArrayList <NameValuePair>(); if("立即发送".equals(msg.getMsTimer())) { msg.setMsSendtime(new Timestamp(System.currentTimeMillis())); } String state = "发送成功"; try { if(other.length()>0){ //其它网关发送 //添加签名【掌上校园】 String sMsg = msg.getMsContent()+MsgUtil.QM_YYS; httpclient = new DefaultHttpClient(); nvps.add(new BasicNameValuePair("id",SmpProperty.getInstance().getSendMessageId())); nvps.add(new BasicNameValuePair("MD5_td_code",SmpProperty.getInstance().getSendMessageMD5_td_code())); nvps.add(new BasicNameValuePair("mesg_id",String.valueOf(msg.getMsId()))); nvps.add(new BasicNameValuePair("mobile",other.toString())); nvps.add(new BasicNameValuePair("msg_content", sMsg)); if(Tools.isNotEmpty(msg.getMsShortno())) nvps.add(new BasicNameValuePair("extend", msg.getMsShortno())); httppost = new HttpPost(SmpProperty.getInstance().getSendMessageUrl()); httppost.setEntity(new UrlEncodedFormEntity(nvps, "GBK")); HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); String entitys = EntityUtils.toString(entity, "GBK"); // String entitys = "ok:3"; if (logger.isDebugEnabled()) { logger.debug("entitys:"+entitys); } entitys = entitys.toLowerCase(); int okIndex = entitys.indexOf("ok:"); if(okIndex==-1){ if(logger.isInfoEnabled()) logger.info("其它:发送失败,状态码"+entitys+"用户数"+other.toString().split(",").length+":"+sMsg); state = "发送失败"; } if(logger.isInfoEnabled()) { if(okIndex!=-1) { logger.info("其它:发送消息成功,用户数:"+other.toString().split(",").length+":"+sMsg); state="发送成功"; } } }else if(yidong.length()>0){ } } catch (UnsupportedEncodingException e) { logger.error("UnsupportedEncodingException", e); state = "发送失败"; } catch (ClientProtocolException e) { logger.error("ClientProtocolException", e); state = "发送失败"; } catch (IOException e) { logger.error("IOException", e); state = "发送失败"; } if(yidong.length()>0){ try { //移动 网关发送 nvps = new ArrayList <NameValuePair>(); nvps.add(new BasicNameValuePair("msgid",String.valueOf(msg.getMsId()))); nvps.add(new BasicNameValuePair("phone",yidong.toString())); nvps.add(new BasicNameValuePair("msg", msg.getMsContent())); if("长短信".equals(msg.getMsLongmsg())) { nvps.add(new BasicNameValuePair("longmsg","1")); }else { nvps.add(new BasicNameValuePair("longmsg","0")); } if(Tools.isNotEmpty(msg.getMsShortno())) nvps.add(new BasicNameValuePair("sno", msg.getMsShortno())); httppost = new HttpPost(SmpProperty.getInstance().getYidong()); httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); String entitys = EntityUtils.toString(entity, "UTF-8"); // String entitys = "0"; if("0".equals(entitys)){ logger.info("移动:发送消息成功,用户数:"+yidong.toString().split(",").length+":"+msg.getMsContent()); state="发送成功"; //标记发送状态 if("回执确认".equals(msg.getMsType())) state = "接收回执"; }else if("-1".equals(entitys)){ logger.info("移动:发送消息失败,用户数"+yidong.toString().split(",").length+":"+msg.getMsContent()); state = "发送失败"; }else { logger.info("移动:短信服务器返回未知状态:<"+entitys+"> 用户数:"+yidong.toString().split(",").length+":"+msg.getMsContent()); state = "未知状态"; } }catch (UnsupportedEncodingException e) { logger.error("UnsupportedEncodingException", e); state = "发送失败"; } catch (ClientProtocolException e) { logger.error("ClientProtocolException", e); state = "发送失败"; } catch (IOException e) { logger.error("IOException", e); state = "发送失败"; } } msg.setMsState(state); if("定时发送".equals(msg.getMsTimer())) { ms.updateSubmitState(msgid, state,true,true,true); //更新信息发送状态,包括信息详细 每条状态 } if(isSaveLog)ms.addSubmit(msg, users,issavemsg); if (logger.isDebugEnabled()) { spendtime = System.currentTimeMillis()-spendtime; logger.debug("$MsgSenderRunnable.run() - end spendtime:"+spendtime); } } }).start(); } /**发送短信通知,短信内容不能超过500字 * @param users 用户手机号和uid的集合,不能为空 * @param msgSubmit 发送的短信内容,不能为空。如果为普通短信msSendtime和msSendtime不用填写 */ public void sendMsg(MsgSubmit msg, List<String[]> users,String sendtype) { List<String[]> vUser = new ArrayList<String[]>(); StringBuffer phones = new StringBuffer(); for(String[] user: users) { if(user.length!=2) { String[] eru = {user[0],"","手机号为空"}; vUser.add(eru); }else { String pho = user[1]; if(Tools.isEmpty(pho)||pho.length()!=11) { String[] eru = {user[0],user[1],"手机号格式错误"}; vUser.add(eru); }else { //检查运营商 //加入发送号码 phones.append(",").append(user[1]); vUser.add(user); } } } //去除第一个手机号前的逗号 if(phones.length()>0)phones.deleteCharAt(0); if(phones.length()==0) { msg.setMsState("发送失败"); ms.addSubmit(msg, vUser,true); }else { //超时后修改发送状态为 "调查结束" if(msg.getMsOvertime()!=null) { final OverMsgTask overTask = new OverMsgTask(msg, ms); msgTimer.schedule(overTask, msg.getMsOvertime()); } if("定时发送".equals(msg.getMsTimer())) { msg.setMsState("未发送"); String ct = msg.getMsContent(); ms.addSubmit(msg, vUser,true); msg.setMsContent(ct); final SendMsgTask msgTask = new SendMsgTask(msg, vUser, phones.toString(), this); msgTimer.schedule(msgTask , msg.getMsSendtime()); }else { if("resend".equals(sendtype)){ //如果是重新发送,则不进行记录 sendLongMsg(msg, vUser, phones.toString(), false); }else{ sendLongMsg(msg, vUser, phones.toString(), true); } } } } public void sendMsgFromServer(MsgSubmit msg, List<String[]> users,String sendtype) { List<String[]> vUser = new ArrayList<String[]>(); StringBuffer phones = new StringBuffer(); for(String[] user: users) { if(user.length!=2) { String[] eru = {user[0],"","手机号为空"}; vUser.add(eru); }else { String pho = user[1]; if(Tools.isEmpty(pho)||pho.length()!=11) { String[] eru = {user[0],user[1],"手机号格式错误"}; vUser.add(eru); }else { //检查运营商 //加入发送号码 phones.append(",").append(user[1]); vUser.add(user); } } } //去除第一个手机号前的逗号 if(phones.length()>0)phones.deleteCharAt(0); if(phones.length()==0) { msg.setMsState("发送失败"); ms.addSubmit(msg, vUser,true); }else { if("定时发送".equals(msg.getMsTimer())) { final SendMsgTask msgTask = new SendMsgTask(msg, vUser, phones.toString(), this); msgTimer.schedule(msgTask , msg.getMsSendtime()); }else { if("resend".equals(sendtype)){ //如果是重新发送,则不进行记录 sendLongMsg(msg, vUser, phones.toString(), false); }else{ sendLongMsg(msg, vUser, phones.toString(), true); } } } } class SendMsgTask extends TimerTask { private MsgSubmit msg; private List<String[]> users; String phones; private MsgSender sender; SendMsgTask(MsgSubmit msg, final List<String[]> users, String phones, MsgSender sender) { this.msg = msg; this.users = users; this.sender = sender; this.phones = phones; } @Override public void run() { this.sender.sendLongMsg(msg, users, phones, false); } } class OverMsgTask extends TimerTask { private MsgSubmit msg; private MsgService ms; OverMsgTask(MsgSubmit msg, MsgService ms) { this.msg = msg; this.ms = ms; } @Override public void run() { //修改MsgSubmit的state为调查结束 ms.updateSubmitState(msg.getMsId(), "调查结束"); } } private void sendLongMsg(MsgSubmit msg, List<String[]> users, String phones, boolean isSaveLog) { //首先保存msg信息 然后发送信息,如果超过100条,则进行分隔100发送, if("立即发送".equals(msg.getMsTimer())) { msg.setMsSendtime(new Timestamp(System.currentTimeMillis())); } // if("定时发送".equals(msg.getMsTimer())) { // ms.updateSubmitState(msgid, "发送成功"); // } if(isSaveLog){ msg.setMsState("发送成功"); String ct = msg.getMsContent(); ms.addSub(msg); msg.setMsContent(ct); } //百悟网关自动判断是否使用长短信发送, 字数不能超过500字 //判断人数是否超过100,如果超过100条则,分次数发完。 int count=users.size(); int maxsize=90; if (count <= maxsize) { logger.debug("第" + 1 + "次/共 1 次发送..."); System.out.println("第" + 1 + "次/共 1 次发送..."); send(msg, users, phones, isSaveLog,false); } else { for (int i = 0; i < count / maxsize; i++) { logger.debug("第" + (i + 1) + "次发送..."); System.out.println("第" + (i + 1) + "次发送..."); List myusers=users.subList(i * maxsize, (i + 1) * maxsize); logger.debug("用户数:"+myusers.size()); send(msg, myusers, phones, isSaveLog,false); try { Thread.sleep (500); //发送程序暂停1秒 } catch (InterruptedException e) { e.printStackTrace(); } } if (count % maxsize != 0) { logger.debug("第" + (count / maxsize + 1) + "次发送..."); System.out.println("第" + (count / maxsize + 1) + "次发送..."); List myusers=users.subList((count - count % maxsize), users.size()); logger.debug("用户数:"+myusers.size()); send(msg, myusers, phones, isSaveLog,false); } } /*if(msg.getMsContent().length()<192) { send(msg, users, isSaveLog); }else { //TODO 此处设计有问题,当字数多时,只要全部发送成功才算成功。 while(true) { String message = msg.getMsContent(); if(message.length()>192) { String str = message.substring(0, 192); msg.setMsContent(str); send(msg, users, isSaveLog); message = message.substring(192); }else { send(msg, users, isSaveLog); break; } } }*/ } }