package com.chinacreator.video.restful.service;


import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chinacreator.video.bean.ChannelBean;
import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.exception.BussinessException;
import com.chinacreator.video.mapper.ChannelDao;
import com.chinacreator.video.mapper.CommConfDao;
import com.chinacreator.video.mapper.DictionaryDao;
import com.chinacreator.video.restful.bean.RechargeOrder;
import com.chinacreator.video.restful.dao.CallSendDao;
import com.chinacreator.video.restful.dao.HuaweiWalletDao;
import com.chinacreator.video.service.CommonService;
import com.chinacreator.video.service.HandleService;
import com.chinacreator.video.service.UniMobileService;
import com.chinacreator.video.util.IpAddrUtil;
import com.chinacreator.video.util.RedisService;
import com.chinacreator.video.util.RsaUtil;
import com.chinacreator.video.util.URLUtil;
import com.chinacreator.video.validate.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class HuaweiWalletService {

    @Autowired
    private ChannelDao channelDao;

    @Autowired
    private RedisService redisService;

    @Autowired
    private DictionaryDao dictionaryDao;

    @Autowired
    private CallSendDao callSendDao;

    @Autowired
    private CommConfDao commConfDao;

    @Autowired
    private CommonService commonService;

    @Autowired
    private HuaweiWalletDao huaweiWalletDao;

    @Autowired
    private UniMobileService uniMobileService;

    //我方提供的私钥用于解密，会提供配套的公钥给对方加密
    @Value("${univideo.privateKey}")
    String privateKey;
//    private String privateKey = "MIIEoQIBAAKCAQBTKK9bNrwIsY5ApEkYH3+3x0yoqHWoImtZl9ZULn6V9LlFfLL2" +
//            "EWVYi93K4g0nm6nT1BAdq5wTTmdGUJQH32bTwMo07QXWqTg5bm4p2ZNeprAehKa2" +
//            "Uh6Ey1nAqlGPV8w32PmekiHKApslqiJ0Q0FQbWdvhcPuZUhRqsYx+S55d3kO4Hae" +
//            "z4hDoYloVEypkfU4kPe2DwkpB7hT199lAewdNrRS9oQo0V/+SG6blzplyLnIaXAU" +
//            "lKzngP11bZGz6xAKZqauMjCxUX1UPLmhJ/nNk+CW5D0SY/0MuZv6UY9rBwQN/IQS" +
//            "cGcbUTrCYpIbPJuR2/NiU24EWQ/qxcKELCFhAgMBAAECggEAJPQocK0zA937K+iV" +
//            "fr3IoJ9VBoHNvwiEkcyydrgukm6swh8227hBRAbraZPoaph28GYFP1oaQk4OAKYg" +
//            "EhuJc0Hx2XEWrhyGmqbjF3/TSDVkgDtMZiq52yMOYFqPYdaPLqYhzwB7OWzNCwC+" +
//            "zNFyPc5QL7POrKqfZ4MvDdgAegNGNYFqz4ZF/kme6eDfRWBUVDcLC6xbpc41hcsA" +
//            "eb8fLzfSoyRZDcbV0t/XGYnEOG7AZbdgg0SwNAELMjeSsW2hhjvpBxOWd9CALqNA" +
//            "T6avg4aG7N5DisIKAKoLVgzBkyklHrq8PlUR4ZySm+Ch6a6NfZgu8jTsAsWWBqFS" +
//            "B07nDQKBgQCf4FnEF5FCR6/JFORhKE8ciYTiuTii4ddPhdrXrKuLDoj0c88JwB5T" +
//            "scTz038SPf8Zer5FrUDll1/R4FN0qbxJNVWrwnI3HE1G61qt0IlHpXLknqOcHoVK" +
//            "8rc6Puo1Xajn0h4CPpUKk5aKyyowSOR1ozj0ysYTb2zAFQPV5ST11wKBgQCFKDxP" +
//            "oQ0ESg7xLZRIu5IaNfCeaLDjc1gTv+kXZThIIANcCmBSxbyoy5JToFQFXJUYybgn" +
//            "24iGaHn+l2O3Jr+Ua8xy2xz9N74potwqd7J9gEBTlodsFmki5ICXyqUx4Zpox+rk" +
//            "lgXsFmISBIARoj1c04n/uPcbqda5gpbj1YvLhwKBgFNTTdXK5rVhwXePAPy2Uo0w" +
//            "C2dTW/ZguKREwmt4Hiwqliy6EyUk0WmTlG/0Qh1S3Jr+Ax8zjkhbHeC4Bycds/l/" +
//            "57fOb1LT2F7nGWrP7ky+KWSIXgNnUNdgKykbU1wfBYJVW7iVv340r9iEzOc/hnrd" +
//            "aDkFWjkU8Nwn18jqVdofAoGAEPrJfgn2Y/ahoyWBxCiO/+Ki9UA6VjauI46URZR1" +
//            "sdTLOOBl2gg2/3s+BIXsUOa2aHvIjOSUqzcFX26km4VIZr+8SWUhdDS4fgyzcILk" +
//            "8tX43e/TAvh0natvrmt71zmCfBwKGu36gVl1VgDW5+i9VGnxLffDIvbsV6mMXi8r" +
//            "7V8CgYBkAWkbE0FAn6vG5ku9kROO3Nq8FDN2R2zGyiX8jSC/IBu1q3FqPA4LzO6q" +
//            "z70f/+EteWYZGx9eaV4u9uDelNS7L3ME2PHOuF6WeKklnMG3RcFe7wgRnrIkMyvl" +
//            "NtdWSabvr8mxBjqM892rKfsWLp+LCcyzy1J2J6z61HL9IzuNpg==";

    //测试环境   华为方提供的公钥，用于给返回数据加密与验证签名
//    private String publicKey = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAmhTTZWk46S6dWMfLKWFZ8YkEibH1HFxNVnrnN7ZRHBV0bjG06U2SdhkKpOwG7qC+kHnsvDncD7pphez+aOzxKDR1A8/RFIo9p/Y7ODxJerfWUGHR0K8OWNyfIyk4EpZWudo7/s+mx0W7JSHTrq5sL9cLGfyK1KBkDNGGt5/FW0lnTdXD/46VuZ8H0jVfxs6jLatLpxr/u/6ScKve3UX672xu0qF+Lw+bI5zBkiVN5c7ZOl81pYgVtb4pqszPpOPnH6P3KOk6OBV9V42yrOz0f89LwWAkQuP1yPmOfnzw56nPCyEKRD2JUj4ZBiTdXWhAW8ht5XUGcqShqneHW07l/0S67TIWsE9QW2X+600S4u7+9eUUr3wC9PJdXcjM5WJiZxxUPLV9cJENgP4//CPVHX5lCLeewy5f/RU6hgMhTI5UeR/wiByIw+91lpZX3KFlLJqX8XMMYLfcLYL59twwcG2ZoWECJQgfZIpe6Mj6lrNjRM6pzzhybN3+sNFNdiKzAgMBAAE=";

    //测试环境我方公钥 提供给华为钱包 可用于我方测试
    @Value("${univideo.publicKey}")
    String publicKey;
//    String publicKey = "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBTKK9bNrwIsY5ApEkYH3+3" +
//            "x0yoqHWoImtZl9ZULn6V9LlFfLL2EWVYi93K4g0nm6nT1BAdq5wTTmdGUJQH32bT" +
//            "wMo07QXWqTg5bm4p2ZNeprAehKa2Uh6Ey1nAqlGPV8w32PmekiHKApslqiJ0Q0FQ" +
//            "bWdvhcPuZUhRqsYx+S55d3kO4Haez4hDoYloVEypkfU4kPe2DwkpB7hT199lAewd" +
//            "NrRS9oQo0V/+SG6blzplyLnIaXAUlKzngP11bZGz6xAKZqauMjCxUX1UPLmhJ/nN" +
//            "k+CW5D0SY/0MuZv6UY9rBwQN/IQScGcbUTrCYpIbPJuR2/NiU24EWQ/qxcKELCFh" +
//            "AgMBAAE=";

    private Logger logger = LoggerFactory.getLogger("huaweiwallet");


    public void  check(OrderInfo orderInfo,String params,String sign) throws Exception {
        if ("huaweiqueryrecharge".equals(orderInfo.getInvokeface())){
            //参数验证
            if (StringUtils.isEmpty(orderInfo.getUserid()) || StringUtils.isEmpty(orderInfo.getOrderid())){
                throw new BussinessException("1", "缺少参数或者业务参数非法");
            }
            //手机号码验证
            mobValidate(orderInfo);
            //timetamp验证
            validate(orderInfo.getTimestamp());
            //渠道验证
            valiCHannel(orderInfo.getChannel());
            orderInfo.setCpid("huaweiqueryrecharge");
            orderInfo.setSpid("huaweiqueryrecharge");
            //ip验证
            volidate(orderInfo,"1");
            //签名验证
            signValidate(orderInfo,params,sign);
        }else if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface())){
//            //参数验证
//            paramValidate(orderInfo);
            //手机号验证，包括联通号码认证
            mobValidate(orderInfo);
            //timetamp验证
            validate(orderInfo.getTimestamp());
            //渠道验证
            valiCHannel(orderInfo.getChannel());
            //ip验证
            volidate(orderInfo,"0");
            //签名验证
            signValidate(orderInfo,params,sign);
            //访问限制，一分钟只允许办理一次
            vistVali(orderInfo);
            //验证订购凭证
            valitoken(orderInfo);
        }else {
//            //参数验证
//            paramValidate(orderInfo);
            //手机号验证，包括联通号码认证
            mobValidate(orderInfo);
            //timetamp验证
            validate(orderInfo.getTimestamp());
            //渠道验证
            valiCHannel(orderInfo.getChannel());
            //ip验证
            volidate(orderInfo,"0");
            //签名验证
            signValidate(orderInfo,params,sign);
            //是否已经订购
            checkdupOrder(orderInfo);
            //访问限制，一分钟只允许办理一次
            vistVali(orderInfo);
            //验证渠道的省份是否有订购限制
//        valiProvLimit(orderInfo);
            //验证订购凭证
            valitoken(orderInfo);
        }
    }

    /**
     * 手机号验证，包括联通号码认证
     * @param orderInfo
     * @throws Exception
     */
    private void mobValidate(OrderInfo orderInfo) throws Exception {
        String userid = orderInfo.getUserid();
        if(isValid(userid) && userid.length() == 11){
        }else{
            throw new BussinessException("6001", "手机号错误");
        }

        Map<String,String> map = uniMobileService.getMobileInfo(userid);
        String resultInfo=map.get("resultInfo");
        if (resultInfo != null && !resultInfo.equals("")) {
            if (!resultInfo.equals("联通")) {
                throw new BussinessException("6001", "非联通号码");
            }
        }else {
            throw new BussinessException("6001", "没有查询到手机号运营商相关信息");
        }
    }

    private boolean isValid(String usermob){
        if (usermob == null) {
            return false;
        }
        usermob = usermob.replaceAll("[\\s-]", "");

        return usermob.matches(".*(1\\d{10}).*");
    }

    /**
     * 短信下发与短信认证签名认证
     * 按照参数KEY值ASCII码升序排列后签名，取值为空的参数不参与签名
     * @param orderInfo
     * @param params
     * @param sign
     * @throws BussinessException
     */
    private void signValidate(OrderInfo orderInfo,String params,String sign) throws BussinessException {
        String str = "";
        JSONObject object = JSON.parseObject(params);
        String caller = object.getString("caller");
        String spid = object.getString("spid");
        String phoneNumber = orderInfo.getUserid();
        String productCode = object.getString("productCode");
        String timestamp = object.getString("timestamp");
        String orderNo = object.getString("orderNo");
        String productType = object.getString("productType");
        String faceValue = object.getString("faceValue");
        String smsCode = object.getString("smsCode");
        String notifyUrl = object.getString("notifyUrl");
        String channelPrice = object.getString("channelPrice");
        String paymentType =object.getString("paymentType");
//        if (!StringUtils.isEmpty(caller)){
//            str += "caller="+caller;
//        }
//        if (!StringUtils.isEmpty(channelPrice)){
//            str += "&channelPrice="+channelPrice;
//        }
//        if (!StringUtils.isEmpty(faceValue)){
//            str += "&faceValue="+faceValue;
//        }
//        if (!StringUtils.isEmpty(notifyUrl)){
//            str += "&notifyUrl="+notifyUrl;
//        }
//        if (!StringUtils.isEmpty(orderNo)){
//            str += "&orderNo="+orderNo;
//        }
//        if (!StringUtils.isEmpty(paymentType)){
//            str += "&paymentType="+ paymentType;
//        }
//        if (!StringUtils.isEmpty(phoneNumber)){
//            str += "&phoneNumber="+ phoneNumber;
//        }
//        if (!StringUtils.isEmpty(productCode)){
//            str += "&productCode="+ productCode;
//        }
//        if (!StringUtils.isEmpty(productType)){
//            str += "&productType="+ productType;
//        }
//        if (!StringUtils.isEmpty(smsCode)){
//            str += "&smsCode="+ smsCode;
//        }
//        if (!StringUtils.isEmpty(spid)){
//            str += "&spid="+ spid;
//        }
//        if (!StringUtils.isEmpty(timestamp)){
//            str += "&timestamp="+ timestamp;
//        }
        if (caller!=null){
            str += "caller="+caller;
        }
        if (channelPrice!=null){
            str += "&channelPrice="+channelPrice;
        }
        if (faceValue!=null){
            str += "&faceValue="+faceValue;
        }
        if (notifyUrl!=null){
            str += "&notifyUrl="+notifyUrl;
        }
        if (orderNo!=null){
            str += "&orderNo="+orderNo;
        }
        if (paymentType!=null){
            str += "&paymentType="+ paymentType;
        }
        if (phoneNumber!=null){
            str += "&phoneNumber="+ phoneNumber;
        }
        if (productCode!=null){
            str += "&productCode="+ productCode;
        }
        if (productType!=null){
            str += "&productType="+ productType;
        }
        if (smsCode!=null){
            str += "&smsCode="+ smsCode;
        }
        if (spid!=null){
            str += "&spid="+ spid;
        }
        if (timestamp!=null){
            str += "&timestamp="+ timestamp;
        }
        boolean flag = false;
        logger.info("str: "+ str+",sign: "+ sign);
        try {
            flag = RsaUtil.verifyRSASign(str, publicKey, sign);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BussinessException("2", "鉴权失败");
        }
        if (!flag){
            throw new BussinessException("2", "鉴权失败");
        }
    }

    /**
     * 参数验证
     * @param orderInfo
     * @throws Exception
     */
    public void paramValidate(OrderInfo orderInfo,JSONObject object) throws Exception {
        if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface())){
            if (StringUtils.isEmpty(orderInfo.getSpid())){
                throw new BussinessException("1", "缺少参数productCode");
            }
        }else if ("huaweiCheckCapSmsCode".equals(orderInfo.getInvokeface())){
            if (!"BILLPAY".equals(object.getString("paymentType"))|| !"3".equals(object.getString("productType")) ||StringUtils.isEmpty(orderInfo.getSpid())){
                throw new BussinessException("1", "缺少参数或者业务参数非法");
            }
        }
    }
    /**
     * token验证
     * @param orderInfo
     * @return 当调校验接口时返回临时凭证
     * @throws Exception
     */
    public void valitoken(OrderInfo orderInfo) throws Exception{
        String key = "univideo_smscaporder_"+orderInfo.getChannel()+orderInfo.getUserid()+orderInfo.getCpid()+orderInfo.getSpid();
        //发送验证码
        if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface()) ){

            //校验验证码及订购
        }else if("huaweiCheckCapSmsCode".equals(orderInfo.getInvokeface())){
            /**
             * 验证token，以确保调此接口之前在sendcode接口已获取到验证码
             * 根据手机号码CPID，SPID获取redis的值，如果为空，可能未调sendcode接口，或者前者调用超时，redis的值已失效
             */
            //REDIS存放的接口调用凭证模拟token
            String token = (String)redisService.get(key);
            //token为空，或者已失效
            if(StringUtils.isEmpty(token)){
                throw new BussinessException("2012","验证码失效！");
            }

            orderInfo.setInvokeToken(token);
        }
    }

    /**
     * 设置token，获取验证码时设置临时凭证，校验验证码时移除临时凭证并设置真正token到redis
     * @param orderInfo
     * @return 当调下发接口时返回临时凭证
     */
    public void setToken(OrderInfo orderInfo){
        String key = "univideo_smscaporder_"+orderInfo.getChannel()+orderInfo.getUserid()+orderInfo.getCpid()+orderInfo.getSpid();
        //发送验证码
        if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface())){
            /**
             * 发送短信验证码成功后在redis预设token，用于调接口凭证，在valicode接口要取出来验证
             */
            String token = UUID.randomUUID().toString().replace("-", "");
            orderInfo.setToken(token);
            long expireTime = 6 * 60; //短信验证码的有效时间为5分钟，此处设置为6分钟
            //把模拟TOKEN设置到redis，90秒的有效期
            redisService.set(key, token, expireTime);
            //校验验证码及订购
        }else if("huaweiCheckCapSmsCode".equals(orderInfo.getInvokeface())){
            //过期时间
            long expireTime = 5 * 60;
            //调置token到redis，用于videoif订购接口验证
            redisService.incr(orderInfo.getToken(), 1, expireTime);

            //删除调用凭证
            //redisService.remove(key);
        }
    }

    /**
     * 订购成功后移除redis接口调用凭证
     * @param orderInfo
     */
    private void removeRedisCert(OrderInfo orderInfo){
        String key = "univideo_smscaporder_"+orderInfo.getChannel()+orderInfo.getUserid()+orderInfo.getCpid()+orderInfo.getSpid();
        //删除调用凭证
        redisService.remove(key);
    }

    /**
     * 业务处理
     * @param orderInfo
     * @throws Exception
     */
    public void process(OrderInfo orderInfo) throws Exception {
        //日志表数据
        Map<String, String> logMap = new HashMap<String, String>();
        String resultcode = "-1";
        String errorinfo = "处理中";
        String result = "";
        String invokeUrl = "";
        String invokeToken = ""; //调接口发送短信验证码凭证
        try {
            logMap.put("USERID", orderInfo.getUserid());
            logMap.put("CPID", orderInfo.getCpid());
            logMap.put("SPID", orderInfo.getSpid());
            logMap.put("CHANNEL", orderInfo.getChannel());
//            logMap.put("TYPE", orderInfo.getType());
            logMap.put("INVOKEFACE", orderInfo.getInvokeface());

            //发送验证码
            if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface())){
                //设置调用接口临时凭证
                setToken(orderInfo);
                invokeUrl = dictionaryDao.getValue("callSendcoUrl");
                invokeUrl = invokeUrl + "?usermob=" + orderInfo.getUserid() + "&cpid=" + orderInfo.getCpid() + "&spid=" + orderInfo.getSpid();
                result = URLUtil.get(invokeUrl, 30000);

                JSONObject resObj = new JSONObject().parseObject(result);
                resultcode = resObj.getString("resultcode");
                errorinfo =  resObj.getString("errorinfo");

                //失败
                if(!"0".equals(resultcode)){
                    throw new BussinessException(resultcode, errorinfo);
                }
                //校验验证码及订购
            }else if("huaweiCheckCapSmsCode".equals(orderInfo.getInvokeface()) ){
                invokeToken = orderInfo.getInvokeToken();
                invokeUrl = dictionaryDao.getValue("callCheckactUrl");
                invokeUrl = invokeUrl + "?usermob=" + orderInfo.getUserid() + "&cpid=" + orderInfo.getCpid() + "&spid=" + orderInfo.getSpid() + "&vcode=" + orderInfo.getVcode();
                result = URLUtil.get(invokeUrl,30000);

                JSONObject resObj = new JSONObject().parseObject(result);
                resultcode = resObj.getString("resultcode");
                errorinfo = resObj.getString("errorinfo");
                String token = resObj.getString("token");

                //cap返回token为空
                if (StringUtils.isEmpty(token)) {
                    throw new BussinessException(resultcode, "短信校验出现问题{token}为空->" + errorinfo);
                }else{
                    //判断token是否使用过
                    long num = redisService.incr("token" + token, 1, 300);
                    if (num == 1){//只使用过一次
                        orderInfo.setToken(token);
                        orderInfo.setAccess("1");
                        orderInfo.setSubtype("1"); //1为CAP短信接口，2为自有短信接口
                        //设置videoif/order.do的token并移除调用接口凭证
                        setToken(orderInfo);
//                        //调办理接口
//                        handleService.handle(orderInfo);
                        if (huaweiWalletDao.isBlackUser(orderInfo.getUserid(), orderInfo.getCpid())>0) {
                            throw new BussinessException("4", "用户为黑名单用户");
                        }
                        commonService.valiChannelSpidLimit(orderInfo);
                        resultcode = "0";
                        errorinfo = "ok";
                        //办理成功后移除接口调用凭证
                        removeRedisCert(orderInfo);
                    }else{
                        throw new BussinessException("2007", "CAP重复TOKEN");
                    }
                }
            }else{
                throw new BussinessException("2007", "无业务办理配置");
            }
        } catch (Exception e) {
            if (e instanceof BussinessException) {
                resultcode = ((BussinessException) e).getCode();
                errorinfo = e.getMessage();
            } else {
                e.printStackTrace();
                resultcode = "2007";
                errorinfo = "办理业务出现异常，"+e.getMessage();
                logger.info("办理业务出现异常，"+e.getMessage(),e);
            }
            throw e;
        } finally {
            logMap.put("TOKEN", orderInfo.getToken());
            logMap.put("INVOKEURL", invokeUrl);
            logMap.put("RESULT", result);
            logMap.put("RESULTCODE", resultcode);
            logMap.put("ERRORINFO", errorinfo);

            try{
                if(errorinfo != null && errorinfo.length()>500){
                    errorinfo = errorinfo.substring(0,500);
                    logMap.put("ERRORINFO", errorinfo);
                }
                //发送验证码
                if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface())){
                    logMap.put("TOKEN", orderInfo.getToken()); //调发送短信验证码接口的凭证
                    //写日志
                    callSendDao.addSmsorderLog(logMap);
                    //校验验证码及订购
                }else if("huaweiCheckCapSmsCode".equals(orderInfo.getInvokeface())){
                    logMap.put("TOKEN", invokeToken); //调发送短信验证码接口的凭证
                    logMap.put("SMSTOKEN", orderInfo.getToken());//调videoif的token
                    callSendDao.updSmsorderLog(logMap);
                }
                logMap.put("入库日志", "成功");
            }catch(Exception e2){
                e2.printStackTrace();
                logger.error("记录日志出现异常，"+e2.getMessage(),e2);
                logMap.put("入库日志", "失败，"+e2.getMessage());
            }

            logger.info(JSON.toJSONString(logMap));
        }

        if("-1".equals(resultcode)){
            throw new BussinessException("2007", "业务处理出现错误");
        }
    }

    /**
     * 验证是否有订购关系
     * @param orderInfo
     * @throws Exception
     */
    public void checkdupOrder(OrderInfo orderInfo) throws Exception{
        String userid = orderInfo.getUserid();
        String spid = orderInfo.getSpid();
        List<HashMap> orderList = commConfDao.findOrderRelaAll(userid);
        if (orderList != null && orderList.size() > 0) {
            for (HashMap hm : orderList) {
                if (spid.equals(hm.get("SPID")) && "0".equals(hm.get("STATUS"))) {//已订购
                    throw new BussinessException("2008", "重复订购");
                }
            }
        }
    }

    /**
     * 验证访问限制，1分钟内同一业务只能办理一次
     * @param orderInfo
     * @throws Exception
     */
    private void vistVali(OrderInfo orderInfo) throws Exception {
        if("huaweiSendCapSmsCode".equals(orderInfo.getInvokeface())){
            String [] params = new String [2];
            params[0] = orderInfo.getUserid();
            params[1] = orderInfo.getSpid();
            if(commonService.vistVali2(params, orderInfo.getInvokeface())){
                throw new BussinessException("6002", "获取验证码过于频繁，请稍后重试");
            }
        }
    }

    /**
     * 验证timestamp
     * @param timetamp
     * @throws Exception
     */
    public void validate(String timetamp) throws Exception {
        if(org.apache.commons.lang.StringUtils.isEmpty(timetamp)) {
            throw new BussinessException("1", "timestamp不能为空");
        }
        long localTimestamp = (System.currentTimeMillis())/1000;
        try {
            if((localTimestamp - dateToStamp(timetamp)/1000) >300 || (localTimestamp - dateToStamp(timetamp)/1000) <-300) {
                throw new BussinessException("1", "timestamp已失效");
            }
        } catch (Exception e) {
            if(e instanceof BussinessException) {
                throw e;
            }else {
                throw new BussinessException("1", "timestamp已失效");
            }
        }
    }

    public  long dateToStamp(String s) throws ParseException {
        //设置时间模版
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        return ts;
    }

    /**
     * 查询订单状态
     * @param orderInfo
     * @return
     */
    public Map<String, Object> query(OrderInfo orderInfo) {
        List<Map<String, Object>> list = huaweiWalletDao.queryrecharge(orderInfo);
        if (list!=null && list.size()>0){
            return  list.get(0);
        }else {
            return null;
        }
    }


    /**
     * 组建查询接口返回签名
     * 按照参数KEY值ASCII码升序排列后签名，取值为空的参数不参与签名
     * 签名的请求/响应结构体中，存在数组结构的，例如充值产品列表，按照指定标识在列表内升序排列，列表内记录按照统一原则升序排序
     * @param respMap
     * @param rechargeOrder
     * @return
     */
    public String signByRSA(Map<String, Object> respMap, RechargeOrder rechargeOrder) {
        String str = "";
        String returnCode = respMap.get("returnCode").toString();
        String returnDesc = respMap.get("returnDesc").toString();
        String orderCount = respMap.get("orderCount").toString();

        String spOrderNo = rechargeOrder.getSpOrderNo();
        String orderNo = rechargeOrder.getOrderNo();
        String spid =rechargeOrder.getSpid();
        String orderTime = rechargeOrder.getOrderTime();
        String rechargeTime =rechargeOrder.getRechargeTime();
        String status = rechargeOrder.getStatus();
        String phoneNumber = rechargeOrder.getPhoneNumber();
        String productCode = rechargeOrder.getProductCode();
        String productType = rechargeOrder.getProductType();
        String faceValue = rechargeOrder.getFaceValue();
        String callbackParam1 =rechargeOrder.getCallbackParam1();
        String callbackParam2 =rechargeOrder.getCallbackParam2();
        String callbackParam3 =rechargeOrder.getCallbackParam3();
        String subType = rechargeOrder.getSubType();

        boolean flag = false;

        str += "orderCount="+orderCount+"&orderList=";
//        if (!StringUtils.isEmpty(callbackParam1)){
//            str += "callbackParam1="+callbackParam1;
//            flag =true;
//        }
//        if (!StringUtils.isEmpty(callbackParam2)){
//            if (flag){
//                str += "&callbackParam2="+callbackParam2;
//            }else {
//                str += "callbackParam2="+callbackParam2;
//            }
//            flag =true;
//        }
//        if (!StringUtils.isEmpty(callbackParam3)){
//            if (flag){
//                str += "&callbackParam3="+callbackParam3;
//            }else {
//                str += "callbackParam3="+callbackParam3;
//            }
//            flag = true;
//        }
//        if (!StringUtils.isEmpty(faceValue)){
//            if (flag){
//                str += "&faceValue="+faceValue;
//            }else {
//                str += "faceValue="+faceValue;
//            }
//        }
//        if (!StringUtils.isEmpty(orderNo)){
//            str += "&orderNo="+orderNo;
//        }
//        if (!StringUtils.isEmpty(orderTime)){
//            str += "&orderTime="+orderTime;
//        }
//        if (!StringUtils.isEmpty(phoneNumber)){
//            str += "&phoneNumber="+phoneNumber;
//        }
//        if (!StringUtils.isEmpty(productCode)){
//            str += "&productCode="+productCode;
//        }
//        if (!StringUtils.isEmpty(productType)){
//            str += "&productType="+productType;
//        }
//        if (!StringUtils.isEmpty(rechargeTime)){
//            str += "&rechargeTime="+rechargeTime;
//        }
//        if (!StringUtils.isEmpty(spOrderNo)){
//            str += "&spOrderNo="+spOrderNo;
//        }
//        if (!StringUtils.isEmpty(spid)){
//            str += "&spid="+spid;
//        }
//        if (!StringUtils.isEmpty(status)){
//            str += "&status="+status;
//        }
//        if (!StringUtils.isEmpty(subType)){
//            str += "&subType="+subType;
//        }
        if (callbackParam1!=null){
            str += "callbackParam1="+callbackParam1;
            flag =true;
        }
        if (callbackParam2!=null){
            if (flag){
                str += "&callbackParam2="+callbackParam2;
            }else {
                str += "callbackParam2="+callbackParam2;
            }
            flag =true;
        }
        if (callbackParam3!=null){
            if (flag){
                str += "&callbackParam3="+callbackParam3;
            }else {
                str += "callbackParam3="+callbackParam3;
            }
            flag = true;
        }
        if (faceValue!=null){
            if (flag){
                str += "&faceValue="+faceValue;
            }else {
                str += "faceValue="+faceValue;
            }
        }
        if (orderNo!=null){
            str += "&orderNo="+orderNo;
        }
        if (orderTime!=null){
            str += "&orderTime="+orderTime;
        }
        if (phoneNumber!=null){
            str += "&phoneNumber="+phoneNumber;
        }
        if (productCode!=null){
            str += "&productCode="+productCode;
        }
        if (productType!=null){
            str += "&productType="+productType;
        }
        if (rechargeTime!=null){
            str += "&rechargeTime="+rechargeTime;
        }
        if (spOrderNo!=null){
            str += "&spOrderNo="+spOrderNo;
        }
        if (spid!=null){
            str += "&spid="+spid;
        }
        if (status!=null){
            str += "&status="+status;
        }
        if (subType!=null){
            str += "&subType="+subType;
        }
        str += "&returnCode=" + returnCode + "&returnDesc=" + returnDesc;

        return str;
    }

    /**
     * 入库华为钱包订单表，用于订购定时任务与回调定时任务
     * @param orderInfo
     * @param object
     */
    public void addHuaweiOrderRec(OrderInfo orderInfo, JSONObject object) {
        HashMap<String,String> map = new HashMap<>();
        map.put("userid",orderInfo.getUserid());
        map.put("spid",orderInfo.getSpid());
        map.put("cpid",orderInfo.getCpid());
        map.put("channel",orderInfo.getChannel());
        map.put("vcode",orderInfo.getVcode());
        map.put("token",orderInfo.getToken());
        map.put("orderno",object.getString("orderNo"));
        map.put("hwspid",object.getString("spid"));
        map.put("productType",object.getString("productType"));
        map.put("faceValue",object.getString("faceValue"));
        map.put("notifyParam1",object.getString("notifyParam1"));
        map.put("notifyParam2",object.getString("notifyParam2"));
        map.put("notifyParam3",object.getString("notifyParam3"));
        map.put("timestamp",orderInfo.getTimestamp());
        map.put("signType",object.getString("signType"));
        map.put("notifyUrl",object.getString("notifyUrl"));
        huaweiWalletDao.addHuaweiOrderRec(map);
    }


    /**
     * IP限制验证
     * @param orderInfo
     * @param busitype 业务类型，1查询，0办理
     * @return
     */
    public void volidate(OrderInfo orderInfo, String busitype) throws BussinessException{
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //String ip = IpAddrUtil.getIpAddr2(request, orderInfo);
        //取remoteaddr的IP的渠道配置，如果有配置，就只有配置的渠道才取
        String remoteAddrChannel = dictionaryDao.getValue("RemoteAddrChannel");
        //取所有IP地址
        List<String> ipList = IpAddrUtil.getIpAddrs(request, orderInfo, remoteAddrChannel);
        try {
            //busitype 业务类型，1查询，0办理
            List<Map> list = null;
            //invokeface不为空
            if(org.apache.commons.lang.StringUtils.isNotEmpty(orderInfo.getInvokeface()) && !"null".equals(orderInfo.getInvokeface())) {
                list = commConfDao.getIpLimitConfByInvokeface(busitype,orderInfo.getChannel(), orderInfo.getInvokeface());
            }else{
                list = commConfDao.getIpLimitConf(busitype,orderInfo.getChannel());
            }

            if(list == null || list.size() == 0){
                throw new BussinessException("4", "IP限制无业务配置信息");
            }else{
                boolean result = false;
                boolean hasExists = false;
                boolean hasinvokeface = true; //是否有允许调指定接口
                //[{CHANNEL=TX20_wtqd, SPID=1167, IP=172.16.33.16, CPID=youtu}]
                for(Map map : list){
                    //CPID级别验证
                    if("*".equals(map.get("CPID"))){ //不限CPID
                        hasExists = true;
                    }else if(orderInfo.getCpid() != null && orderInfo.getCpid().equals(map.get("CPID"))
                            && (orderInfo.getSpid() != null && orderInfo.getSpid().equals(map.get("SPID")) || "*".equals(map.get("SPID")))){
                        hasExists = true;
                    }

                    if(hasExists){
                        if("*".equals(map.get("IP"))){
                            result = true;
                        }else if(map.get("IP") != null && !"".equals(map.get("IP"))){
                            String [] ips = map.get("IP").toString().split("\\|");
                            for(String str : ips){
                                //if(str != null && ip != null && str.contains(ip)){
                                //获得的IP里包含了白名单ip
                                if(str != null && ipList != null && ipList.contains(str)){
                                    result = true;
                                }
                                //如果IP地址配置有*号，访问的IP包含*号前面的部分
                                //if(!result && str.indexOf("*") != -1 && ip.startsWith(str.split("[*]")[0])){
                                if(!result && str.indexOf("*") != -1 && hasStartsWith(ipList, str)){
                                    result = true;
                                }
                            }
                        }

                        //有接口调用限制
                        if(result && map.get("INVOKEFACE") != null && !"".equals(map.get("INVOKEFACE"))
                                && !map.get("INVOKEFACE").equals(orderInfo.getInvokeface())){
                            hasinvokeface = false;
                        }

                        break;
                    }
                }
                if(!hasExists){ //无业务配置
                    throw new BussinessException("4", "IP限制无业务配置信息");
                }
                if(!result){
                    throw new BussinessException("4", "IP验证失败:"+ipList);
                }
                if(!hasinvokeface){
                    throw new BussinessException("4", "渠道【"+orderInfo.getChannel()+"】无【"+orderInfo.getInvokeface()+"】接口调用权限");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            if(e instanceof BussinessException) {
                //记录IP限制日志
                logger.info("IP被限制: ip=>"+ipList+"，channel=>"+orderInfo.getChannel()+"，调用接口=>"+(request.getHeader("x-forwarded-path"))+"，限制原因=>"+((BussinessException)e).getCode()+"，"+((BussinessException)e).getMessage());
                throw e;
            }else {
                if(e.getMessage() != null && e.getMessage().indexOf("SQLException") != 0){
                    throw new BussinessException("4", "IP限制验证出现SQLException异常。");
                }else{
                    throw new BussinessException("4", "IP限制验证出现异常，"+e.getMessage());
                }
            }
        }
    }

    /**
     * 判断是否模糊匹配
     * @param ipList
     * @param confip
     * @return
     */
    private boolean hasStartsWith(List<String> ipList, String confip){
        boolean res = false;
        for(String ip : ipList){
            if(ip.startsWith(confip.split("[*]")[0])){
                res = true;
                break;
            }
        }
        return res;
    }

    public void valiCHannel(String channel) throws BussinessException {
        try {
            if(org.apache.commons.lang.StringUtils.isEmpty(channel)) {
                throw new BussinessException("1", "渠道参数不能为空");
            }
            ChannelBean channelBean = channelDao.queryChannel(channel);
            if(channelBean == null) {
                throw new BussinessException("1", "渠道参数错误");
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw e;
        }
    }
}
