package cn.jeesoft.mvc.outapi; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import cn.jeesoft.core.util.MD5; import cn.jeesoft.core.utils.DateUtils; import cn.jeesoft.core.utils.JsonUtils; import cn.jeesoft.core.utils.StringUtils; import cn.jeesoft.mvc.Config; import com.alibaba.fastjson.JSONObject; /** * 短信验证码 * @author king */ public class SmsHelper { private static HashMap<String, Long> mSms = new HashMap<String, Long>(); /** * 验证码过期时长:秒 */ private static final int ValidityDuration = 3 * 60; /** * 重复发送时间间隔:秒 */ private static final int RepeatDuration = 30; /** * 验证码状态 * @author king */ public static enum CodeStatus { YES, // 有效 NO, // 无效 EXPIRE, // 过期 ; } /** * 发送验证码 * @param phone * @return 1:成功,0:失败,-1:余额不足 */ public static synchronized int sendMessage(String phone) { String code = getCode(); mSms.put(code, System.currentTimeMillis()); return sendCode("淘金站", code, ValidityDuration, phone); } /** * 验证是否正确 * @param code * @return */ public static synchronized CodeStatus verify(String code) { if (StringUtils.isEmpty(code) || !mSms.containsKey(code)) { // 无效 return CodeStatus.NO; } Long time = mSms.get(code); if (System.currentTimeMillis() - time > ValidityDuration * 1000) { // 过期 return CodeStatus.EXPIRE; } // 有效 return CodeStatus.YES; } /** * 删除验证码 * @param code */ public static synchronized void remove(String code) { mSms.remove(code); } /** * 获取随机不重复的验证码 * @return */ private static synchronized String getCode() { clearCode(); int num = 1000; String code = StringUtils.getRandomNum(6); while (mSms.containsKey(code)) { if (num-- < 0) { break; } code = StringUtils.getRandomNum(6); } if (StringUtils.isEmpty(code)) { num = 1000; while (mSms.containsKey(code)) { if (num-- < 0) { break; } code = StringUtils.getRandomStr(6); } } return code; } private static synchronized void clearCode() { try { Iterator<Entry<String, Long>> iterator = mSms.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, Long> entry = iterator.next(); Long time = entry.getValue(); if (System.currentTimeMillis() - time > ValidityDuration * 1000) { iterator.remove(); } } } catch (Exception e) { } } /** * 发送短信验证码 * @param appName 应用名称 * @param code 验证码 * @param second 有效时长[秒] * @param phone 目标手机,用于接收验证码 * @return 1:成功,0:失败,-1:余额不足 */ private static int sendCode(String appName, String code, int second, String phone) { try { String message = doSendCode(appName, code, second, phone); if (!StringUtils.isEmpty(message)) { JSONObject json = (JSONObject) JsonUtils.fromJson(message); if (json != null) { JSONObject resp = json.getJSONObject("resp"); String respCode = resp.getString("respCode"); if (!StringUtils.isEmpty(respCode) && "000000".equals(respCode)) { return 1; } else if (!StringUtils.isEmpty(respCode) && "100001".equals(respCode)) { return -1; } } } } catch (Throwable e) { } return 0; } private static String doSendCode(String appName, String code, int second, String phone) throws Throwable { Date time = new Date(); String timestamp = DateUtils.format(time, "yyyyMMddHHmmssSSS"); final String param = appName+","+code+","+(second/60); String url = Config.UCPAAS_HOST; url += "?sid=" + Config.UCPAAS_ACCOUNTSID; url += "&appId=" + Config.UCPAAS_APPID; url += "&time=" + timestamp; url += "&sign=" + getSignature(Config.UCPAAS_ACCOUNTSID, Config.UCPAAS_AUTHTOKEN, timestamp); url += "&to=" + phone; url += "&templateId=" + Config.UCPAAS_TEMPLATEID; url += "¶m=" + param; HttpClient httpclient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); HttpResponse response = httpclient.execute(httpGet); HttpEntity resEntity = response.getEntity(); InputStream inStream = resEntity.getContent(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] data = new byte[1024]; int len = -1; while ((len = inStream.read(data)) != -1) { baos.write(data, 0, len); } byte[] result = baos.toByteArray(); return new String(result, "UTF-8"); } /** * 生成sig * @param accountSid 账户SID * @param authToken 账户TOKEN * @param timestamp 时间戳 * @return */ private static String getSignature(String accountSid, String authToken, String timestamp) { String sig = accountSid + timestamp + authToken; return MD5.md5(sig); } }