123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- package com.iamberry.app.service;
- import static com.iamberry.app.config.ImberryConfig.INTER_SMS_KEY;
- import static com.iamberry.app.config.ImberryConfig.INTER_SMS_TEXT;
- import static com.iamberry.app.config.ImberryConfig.INTER_SMS_URL;
- import static com.iamberry.app.config.ImberryConfig.SMS_PASSWORD;
- import static com.iamberry.app.config.ImberryConfig.SMS_TEXT;
- import static com.iamberry.app.config.ImberryConfig.SMS_URL;
- import static com.iamberry.app.config.ImberryConfig.SMS_USERNAME;
- import java.text.MessageFormat;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import net.sf.json.JSONObject;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.http.HttpEntity;
- import org.apache.http.NameValuePair;
- import org.apache.http.client.entity.UrlEncodedFormEntity;
- import org.apache.http.client.methods.CloseableHttpResponse;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.impl.client.CloseableHttpClient;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.util.EntityUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import com.iamberry.app.config.Response;
- import com.iamberry.app.config.ResponseHeader;
- import com.iamberry.app.core.entity.CodeValid;
- import com.iamberry.app.face.CodeService;
- import com.iamberry.app.mapper.CodeMapper;
- import com.iamberry.app.tool.util.Result;
- import com.iamberry.app.ulitity.Utility;
- import com.iamberry.wechat.tools.ResponseJson;
- import com.thoughtworks.xstream.XStream;
- import com.thoughtworks.xstream.io.xml.StaxDriver;
- /**
- * @company 深圳爱贝源科技有限公司
- * @website www.iamberry.com
- * @author 献
- * @tel 18271840547
- * @date 2016年11月1日
- * @explain 验证码业务实现类
- */
- @Service
- public class CodeServiceImpl implements CodeService {
- @Autowired
- private CodeMapper codeMapper;
- private static String ENCODING = "UTF-8";
- @Override
- public ResponseJson sendCode(String phone, int codeScenario) {
- // TODO Auto-generated method stub
- // 第一步,判断使用通道,如果是+86开头,优先使用国内通道,否则默认使用国外通道
- ResponseJson json = new ResponseJson();
- if (StringUtils.isEmpty(phone)) {
- json.setReturnCode(404);
- json.addResponseKeyValue("Phone Empty!");
- return json;
- }
-
- // 第二步,如果是国内,判断是否存在
- CodeValid codeValid = codeMapper.getLast(phone);
- Date now = new Date();
-
- // 通道是否是中国的
- boolean IS_CHANNEL_ZH = false;
- if (StringUtils.indexOf(phone, "+") != -1) {
- if (StringUtils.startsWith(phone, "+86")) {
- IS_CHANNEL_ZH = true;
- }
- } else {
- IS_CHANNEL_ZH = true;
- }
- // 判断通道
- if (IS_CHANNEL_ZH && codeValid != null) {
- // ** 切换通道需求:每次请求验证码,如果上一次验证码在一分钟以后,三分钟以内没有使用,那么切换通道 **//
- if (now.getTime() <= (codeValid.getCodeValidDate().getTime()) &&
- (now.getTime() - 60000) >= codeValid.getCodeSendDate().getTime() && codeValid.getCodeUse() == 2 && codeValid.getCodeScenario() == codeScenario) {
- // 如果等待三分钟后,那么切换通道,暂时不切换
- // IS_CHANNEL_ZH = false;
- }
- }
- // 获取验证码
- String code = Utility.getRandomCode(4);
- json = sendCMS(phone, code, IS_CHANNEL_ZH ? 1 : 2);
- if (json.getReturnCode() != 200) {
- json = sendCMS(phone, code, IS_CHANNEL_ZH ? 1 : 2);
- }
- // 保存发送记录
- codeValid = new CodeValid();
- codeValid.setCodeChannel(IS_CHANNEL_ZH ? 1 : 2);
- codeValid.setCodeMsg(json.getReturnMsg().get("returnMsg").toString());
- codeValid.setCodePhone(phone);
- codeValid.setCodeScenario(codeScenario);
- codeValid.setCodeSendDate(now);
- codeValid.setCodeValidDate(new Date(now.getTime() + 180000));
- codeValid.setCodeStatus(json.getReturnCode() == 200 ? 3 : 4);
- codeValid.setCodeUse(2);
- codeValid.setCodeValue(Integer.parseInt(code));
- codeMapper.save(codeValid);
- return json;
- }
-
- /**
- * @param phone 手机号码
- * @param code 短信验证码
- * @param channel 通道 1:主通道;2:备用通道(国外的电话通通使用此)
- * @return
- */
- private ResponseJson sendCMS(String phone, String code, int channel) {
-
- // 国内号码
- ResponseJson json = new ResponseJson();
- json.setReturnCode(500);
- String result = null;
- try {
- if (channel == 1) {
- // 使用主通道
- // result = sendZHCMS(phone, code);
- result = sendOtherCMS(phone, code);
- } else {
- // 使用备用通道
- result = sendOtherCMS(phone, code);
- }
- } catch (Exception e) {
- result = e.getMessage();
- }
- if (StringUtils.equals(result, "SUCCESS")) {
- json.setReturnCode(200);
- }
- json.addResponseKeyValue(result);
- return json;
- }
-
- private String sendOtherCMS(String phone, String code) {
- String text = MessageFormat.format(INTER_SMS_TEXT, code);
- String results = sendSms(text, phone);
- JSONObject json = JSONObject.fromObject(results);
- String resultcod = json.get("code").toString();
- if(resultcod.equals("0")){
- System.out.println("使用备用通道,发送验证码成功!" + code);
- return "SUCCESS";
- }else{
- System.out.println("使用备用通道,发送失败...!" + code);
- return results;
- }
-
- }
- public static String sendSms(String text, String mobile) {
- Map<String, String> params = new HashMap<String, String>();
- params.put("apikey", INTER_SMS_KEY);
- params.put("text", text);
- params.put("mobile", mobile);
- return post(INTER_SMS_URL, params);
- }
- /** 基于HttpClient 4.3的通用POST方法
- * @param url 提交的URL
- * @param paramsMap 提交<参数,值>Map
- * @return 提交响应
- */
- public static String post(String url, Map<String, String> paramsMap) {
-
- CloseableHttpClient client = HttpClients.createDefault();
- String responseText = "";
- CloseableHttpResponse response = null;
- try {
- HttpPost method = new HttpPost(url);
- if (paramsMap != null) {
- List<NameValuePair> paramList = new ArrayList<NameValuePair>();
- for (Map.Entry<String, String> param : paramsMap.entrySet()) {
- NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
- paramList.add(pair);
- }
- method.setEntity(new UrlEncodedFormEntity(paramList, ENCODING));
- }
- response = client.execute(method);
- HttpEntity entity = response.getEntity();
- if (entity != null) {
- responseText = EntityUtils.toString(entity);
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- response.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return responseText;
- }
- private String sendZHCMS(String phone, String code) throws Exception {
- CloseableHttpClient client = HttpClients.createDefault();
- Map<String, String> params = new HashMap<String, String>();
- CloseableHttpResponse response = null;
- params.put("username", SMS_USERNAME);
- params.put("password", SMS_PASSWORD);
- params.put("mobile", phone);
- params.put("content", MessageFormat.format(SMS_TEXT, code));
- HttpPost method = new HttpPost(SMS_URL);
- if (params != null) {
- List<NameValuePair> paramList = new ArrayList<NameValuePair>();
- for (Map.Entry<String, String> param : params.entrySet()) {
- NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
- paramList.add(pair);
- }
- method.setEntity(new UrlEncodedFormEntity(paramList, "UTF-8"));
- }
- response = client.execute(method);
- HttpEntity entity = response.getEntity();
- if (entity != null) {
- String result = EntityUtils.toString(entity);
- XStream xs = new XStream(new StaxDriver());
- xs.alias("result", Result.class);
- Result object = (Result)xs.fromXML(result);
- response.close();
- if (0 == object.getResultcode()) {
- return "SUCCESS";
- } else {
- return object.getResultcode() + ":" + object.getErrordescription();
- }
- }
- return null;
- }
- @Override
- public ResponseJson validCode(String phone, String code, int codeScenario) {
- ResponseJson json = new ResponseJson();
- // 校验
- CodeValid codeValid = codeMapper.getLast(phone);
- if (codeValid == null) {
- // 操作有误
- json.setReturnCode(404);
- json.addResponseKeyValue("Wrong operation, No send record");
- return json;
- }
- Date now = new Date();
- if (now.getTime() >= codeValid.getCodeValidDate().getTime()) {
- // 验证码无效
- json.setReturnCode(403);
- json.addResponseKeyValue("Verification code is invalid");
- return json;
- }
- // 验证码是否使用 1:已经使用;2:未使用
- if (codeValid.getCodeUse().intValue() == 1) {
- // 验证码无效
- json.setReturnCode(402);
- json.addResponseKeyValue("Verification code has been used");
- return json;
- }
- // 必须 验证码正确,并且场景正确
- if (!(codeValid.getCodeValue() == (Integer.parseInt(code))
- && codeScenario == codeValid.getCodeScenario())) {
- // 验证码错误
- json.setReturnCode(405);
- json.addResponseKeyValue("Verification code error");
- return json;
- }
- // 只要校验成功,表示本次验证码已使用
- codeMapper.update(codeValid.getCodeId());
- json.setReturnCode(200);
- json.addResponseKeyValue("SUCCESS");
- return json;
- }
-
- /**
- * 放轰炸原则:
- * 1、每个手机号码,每60秒只能发送1次!
- * 2、每个手机号码,每小时只能发送三次!
- * 3、每个手机号码,每天只能发送10次!
- * @param phone
- * @return
- * @author 献
- * @Time 2016年12月5日
- */
- public Response interval(String phone) {
- CodeValid codeValid = codeMapper.getLast(phone);
- Date now = new Date();
-
- // 每个手机号,限制每60秒,只能发送一次
- if (codeValid != null && (60000 > (now.getTime() - codeValid.getCodeSendDate().getTime()))) {
- return new Response(new ResponseHeader(404, "每个手机号码,每60秒只能发送1次!", 0));
- }
-
- // 生成时间规则
- Date startDate = new Date();
- startDate.setMinutes(0);
- startDate.setSeconds(0);
- Date endDate = new Date();
- endDate.setMinutes(59);
- endDate.setSeconds(60);
-
- // 每个手机号码,每个小时最多3条
- if (codeMapper.getInterval(startDate, endDate, phone) >= 3) {
- return new Response(new ResponseHeader(404, "每个手机号码,每小时只能发送3次!", 0));
- }
-
- // 每个手机号码,每天最多10条
- endDate.setHours(23);
- startDate.setHours(0);
- if (codeMapper.getInterval(startDate, endDate, phone) >= 10) {
- return new Response(new ResponseHeader(404, "每个手机号码,每天只能发送10次!", 0));
- }
-
- return new Response(new ResponseHeader(200, "SUCCESS", 0));
- }
-
- }
|