package com.yd.rmi.tencent.wechat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.yd.api.result.CommonResult;
import com.yd.rmi.cache.SystemConfigService;
import com.yd.dal.entity.tencent.TenInterfRecord;
import com.yd.dal.entity.transaction.TranLog;
import com.yd.dal.service.tencent.TenInterfRecordDALService;
import com.yd.dal.service.transaction.TranLogDALService;
import com.yd.rmi.tencent.wechat.service.WechatService;
import com.yd.rmi.tencent.wechat.vo.WeChatInfoByENV;
import com.yd.rmi.tencent.wechat.vo.WxNATIVEPayQueryReqVO;
import com.yd.rmi.tencent.wechat.vo.WxNATIVEPayQueryRespVO;
import com.yd.rmi.tencent.wechat.vo.WxUserInfo;
import com.yd.rmi.tencent.wechatinterf.pojo.accesstoken.AccessTokenRequest;
import com.yd.rmi.tencent.wechatinterf.pojo.accesstoken.AccessTokenResponse;
import com.yd.rmi.tencent.wechatinterf.pojo.ticket.TicketRequest;
import com.yd.rmi.tencent.wechatinterf.pojo.ticket.TicketResponse;
import com.yd.rmi.tencent.wechatinterf.pojo.token.TokenRequest;
import com.yd.rmi.tencent.wechatinterf.pojo.token.TokenResponse;
import com.yd.rmi.tencent.wechatinterf.pojo.unifiedorder.UnifiedorderRequest;
import com.yd.rmi.tencent.wechatinterf.pojo.unifiedorder.UnifiedorderResponse;
import com.yd.rmi.tencent.wechatinterf.service.WechatInterfService;
import com.yd.util.*;
import com.yd.util.config.ZHBErrorConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.Map.Entry;

@Service("wechatService")
public class WechatServiceImpl implements WechatService {
	@Autowired
	private TenInterfRecordDALService tenInterfRecordDALService;
	@Autowired
	private WechatInterfService wechatInterfService;
	@Autowired
	private SystemConfigService systemConfigService;
	@Autowired
	private TranLogDALService tranLogDALService;

	@Override
	public String obtainToken(TokenRequest tokenRequest) {
		String accessToken = null;
		
		String pGrantType = tokenRequest.getGrant_type() == null || "".equals(tokenRequest.getGrant_type()) ? systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TOKEN_GRANT_TYPE") : tokenRequest.getGrant_type();
		String pAppid = tokenRequest.getAppid() == null || "".equals(tokenRequest.getAppid()) ? systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APPID"):tokenRequest.getAppid();
		String pSecret = tokenRequest.getSecret() == null || "".equals(tokenRequest.getSecret()) ? systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APP_SECRET") : tokenRequest.getSecret();
		if(SpringContextUtil.isProd()){
			pAppid =systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_APPID");
			pSecret =systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_APP_SECRET");
		}
		TenInterfRecord tencentInterfRecord = new TenInterfRecord();
		tencentInterfRecord.setInterfType("TOKEN");
		tencentInterfRecord.setGrantType(pGrantType);
		tencentInterfRecord.setAppid(pAppid);
		tencentInterfRecord.setSecret(pSecret);
		String orderBy = "created_at desc";
		List<TenInterfRecord> tencentTnterfRecordList = tenInterfRecordDALService.findByTenInterfRecordOrderBy(tencentInterfRecord,orderBy);

		boolean needReload = false;
		if(tencentTnterfRecordList != null && tencentTnterfRecordList.size() >0){
			tencentInterfRecord = tencentTnterfRecordList.get(0);
			if(tencentInterfRecord.getExpiresIn() != null && !CommonUtil.isNullOrBlank(tencentInterfRecord.getAccessToken())){
				Date overdueDate = CommonUtil.dateOperation(tencentInterfRecord.getCreatedAt(), "ADD", "S", tencentInterfRecord.getExpiresIn().intValue());
				if(new Date().compareTo(overdueDate) > 0){
					needReload = true;
				}else{
					accessToken = tencentInterfRecord.getAccessToken();
				}
			}else{
				needReload = true;
			}
		}else{
			needReload = true;
		}
		if(needReload){
			String url = "https://api.weixin.qq.com/cgi-bin/token?"
					+"grant_type="+pGrantType
					+"&appid="+pAppid
					+"&secret="+pSecret;
			tranLogDALService.logDB("wechat", "accessToken", "in", tokenRequest.getAppid(), url, null, null);
			String responseStr = wechatInterfService.transaction(url,null,null);
			tranLogDALService.logDB("wechat", "accessToken", "out", tokenRequest.getAppid(), responseStr, null, null);
			TokenResponse tokenResponse = (TokenResponse)JsonUtil.jsonToObj(responseStr,TokenResponse.class);
			accessToken = tokenResponse.getAccess_token();
			
			Long expiresIn = null;
			if(tokenResponse.getExpires_in() != null && !"".equals(tokenResponse.getExpires_in())){
				expiresIn = Long.parseLong(tokenResponse.getExpires_in());
			}

			tencentInterfRecord = new TenInterfRecord();
			tencentInterfRecord.setInterfType("TOKEN");
			tencentInterfRecord.setGrantType(pGrantType);
			tencentInterfRecord.setAppid(pAppid);
			tencentInterfRecord.setSecret(pSecret);
			tencentInterfRecord.setAccessToken(tokenResponse.getAccess_token());
			tencentInterfRecord.setExpiresIn(expiresIn);
			tencentInterfRecord.setErrcode(tokenResponse.getErrcode());
			tencentInterfRecord.setErrmsg(tokenResponse.getErrmsg());
			tencentInterfRecord.setCreatedAt(new Date());
			tenInterfRecordDALService.saveTenInterfRecord(tencentInterfRecord);
		}
		return accessToken;
	}

	@Override
	public String obtainTicket(TicketRequest ticketRequest) {
		String ticket = null;
		String pType = ticketRequest.getType() == null || "".equals(ticketRequest.getType()) ? systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TICKET_TYPE") : ticketRequest.getType();
		TenInterfRecord tencentInterfRecord = new TenInterfRecord();
		tencentInterfRecord.setInterfType("TICKET");
		tencentInterfRecord.setAccessToken(ticketRequest.getAccessToken());
		tencentInterfRecord.setIType(pType);
		String orderBy = "created_at desc";
		List<TenInterfRecord> tencentTnterfRecordList = tenInterfRecordDALService.findByTenInterfRecordOrderBy(tencentInterfRecord,orderBy);

		boolean needReload = false;
		if(tencentTnterfRecordList != null && tencentTnterfRecordList.size() >0){
			tencentInterfRecord = tencentTnterfRecordList.get(0);
			if(tencentInterfRecord.getExpiresIn() != null && !CommonUtil.isNullOrBlank(tencentInterfRecord.getTicket())){
				Date overdueDate = CommonUtil.dateOperation(tencentInterfRecord.getCreatedAt(), "ADD", "S", tencentInterfRecord.getExpiresIn().intValue());
				if(new Date().compareTo(overdueDate) > 0){
					needReload = true;
				}else{
					ticket = tencentInterfRecord.getTicket();
				}
			}else{
				needReload = true;
			}
		}else{
			needReload = true;
		}
		if(needReload){
			TicketResponse ticketResponse = wechatInterfService.ticket(ticketRequest);
			ticket = ticketResponse.getTicket();
			
			Long expiresIn = null;
			if(ticketResponse.getExpires_in() != null && !"".equals(ticketResponse.getExpires_in())){
				expiresIn = Long.parseLong(ticketResponse.getExpires_in());
			}
			tencentInterfRecord = new TenInterfRecord();
			tencentInterfRecord.setInterfType("TICKET");
			tencentInterfRecord.setIType(pType);
			tencentInterfRecord.setAccessToken(ticketRequest.getAccessToken());
			tencentInterfRecord.setTicket(ticket);
			tencentInterfRecord.setExpiresIn(expiresIn);
			tencentInterfRecord.setErrcode(ticketResponse.getErrcode());
			tencentInterfRecord.setErrmsg(ticketResponse.getErrmsg());
			tencentInterfRecord.setCreatedAt(new Date());
			tenInterfRecordDALService.saveTenInterfRecord(tencentInterfRecord);
		}
		return ticket;
	}

	@Override
	public AccessTokenResponse getOpenID(String appid, String secret, String code) {
		AccessTokenResponse response = null;
		String zhbCode = "800000";
		String zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode);
		String responseJson = null;
		if(!CommonUtil.isNullOrBlank(appid) &&!CommonUtil.isNullOrBlank(appid) &&!CommonUtil.isNullOrBlank(appid)){
			String accessTokenUrl = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_ACCESS_TOKEN_URL");
			response = new AccessTokenResponse();
			String authorizeURL = accessTokenUrl+"?"+
                    "appid="+appid+
                    "&secret="+secret+
                    "&code="+code+
                    "&grant_type=authorization_code";
			tranLogDALService.logDB("wechat", "getOpenId", "URL", appid, authorizeURL, null, null);
			responseJson = transaction(authorizeURL,null);
			if(!CommonUtil.isNullOrBlank(responseJson)){
				response = (AccessTokenResponse) JsonUtil.jsonToObj(responseJson,AccessTokenResponse.class);
				zhbMessage = response.getErrmsg();
				zhbCode = response.getErrcode();
			}else {
				zhbCode = "900003";
				zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode);
			}
		}else {
			zhbCode = "610002";
			String[] params = {"appid、secret、code"};
			zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode, params);
		}
		tranLogDALService.logDB("wechat", "getOpenId", "response", appid, responseJson, zhbCode, zhbMessage);
		return response;
	}
	
	@Override
	public UnifiedorderResponse unifiedorder(String appId, String openId, String wCpayMethod, String timeExpire,String mchId,Double orderPrice,String planName,String orderNo,String notifyUrl) {
		UnifiedorderResponse response = new UnifiedorderResponse();
		String unifiedorderURL = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_UNIFIEDORDER_URL");
		String result = "SUCCESS";
		String zhbCode = "800000";
		String zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode);
		String signType = "MD5";
		String responseXml = null;
//		String notifyUrl = null;
		String key = null;
		if(CommonUtil.isNullOrBlank(appId) || CommonUtil.isNullOrBlank(wCpayMethod) ){
	    	result = "FAIL";
	    	zhbCode = "610002";
	    	String[] params = {"appId(微信公众账号ID)、orderId(订单ID)、wCpayMethod(微信支付方式)"};
			zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode, params);
	    }
	    String mchIdYD = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_MCH_ID");//银盾商户号id
		String mchIdYD2 = systemConfigService.getSingleConfigValue("YD2-TENCENT_WECHAT_MCH_ID");//银盾商户号id--福利产品
	    String mchIdAJB = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_MCH_ID");//安吉保商户号id
	    String simulateSwitch = systemConfigService.getSingleConfigValue("SimulateSwitch");
	    String spbillCreateIp = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_UNIFIEDORDER_SPBILL_CREATE_IP");
	
	    if(mchId.equals(mchIdYD)){//银盾
//	    	notifyUrl = systemConfigService.getSingleConfigValue("YD_TENCENT_WECHAT_UNIFIEDORDER_NOTIFY_URL");//微信支付结果通知地址
	    	key = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_API_KEY");//第三方用户唯一凭证密钥
	    }else if(mchId.equals(mchIdAJB)){//安吉保
//	    	notifyUrl = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_UNIFIEDORDER_NOTIFY_URL");//微信支付结果通知地址
	    	key = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_API_KEY");//第三方用户唯一凭证密钥
	    }else if(mchId.equals(mchIdYD2)){//银盾2--福利产品支付
//	    	notifyUrl = systemConfigService.getSingleConfigValue("YD2_TENCENT_WECHAT_UNIFIEDORDER_NOTIFY_URL");//微信支付结果通知地址
	    	key = systemConfigService.getSingleConfigValue("YD2-TENCENT_WECHAT_API_KEY");//第三方用户唯一凭证密钥
	    }else{
	    	result = "FAIL";
	    	zhbCode = "820001";
	    	String[] params = {"ag_md_code,mchId-key"};
	    	zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode, params);
	    }
	
	    if("SUCCESS".equals(result)){
	    	String nonceStr = CommonUtil.getRandomString(30);

	    	int	totalFee = (int)(orderPrice*100);
	    	if("1".equals(simulateSwitch)){
	    		totalFee = 1;
	    	}
	    	UnifiedorderRequest unifiedorderRequest = new UnifiedorderRequest();
	    	unifiedorderRequest.setSign_type(signType);
	        unifiedorderRequest.setAppid(appId);
	    	unifiedorderRequest.setMch_id(mchId);
	    	unifiedorderRequest.setNonce_str(nonceStr);
	    	unifiedorderRequest.setBody(planName);
	    	unifiedorderRequest.setOut_trade_no(orderNo);
	    	unifiedorderRequest.setTotal_fee(totalFee);
	    	unifiedorderRequest.setSpbill_create_ip(spbillCreateIp);
	    	unifiedorderRequest.setNotify_url(notifyUrl);
	    	unifiedorderRequest.setProduct_id(orderNo);
	    	unifiedorderRequest.setTrade_type(wCpayMethod);
	    	unifiedorderRequest.setOpenid(openId);
	    	unifiedorderRequest.setTime_expire(timeExpire);
	    	
	    	Map<String,String> paraMap = new HashMap<String,String>();
			paraMap.put("appid", appId);
			paraMap.put("mch_id", mchId);
			paraMap.put("nonce_str", nonceStr);
			paraMap.put("body", planName);
			paraMap.put("out_trade_no", orderNo);
			paraMap.put("total_fee", String.valueOf(totalFee));
			paraMap.put("spbill_create_ip", spbillCreateIp);
			paraMap.put("notify_url", notifyUrl);
			paraMap.put("trade_type", wCpayMethod);
			paraMap.put("product_id", orderNo);
			paraMap.put("openid", openId);
			paraMap.put("sign_type", signType);
			paraMap.put("time_expire", timeExpire);
			String signValue = getSignValue(paraMap,false,false,appId,key);
	
			paraMap.put("sign", signValue);
			unifiedorderRequest.setSign(signValue);
			
			XmlUtil xmlUtil = new XmlUtil(UnifiedorderRequest.class, XmlUtil.CollectionWrapper.class);
			String requestXml = xmlUtil.toXml(unifiedorderRequest, "UTF-8");
			tranLogDALService.logDB("YD-wechatpay", "unifiedorder", "in", orderNo, requestXml, null, null);
			
			responseXml = transaction(unifiedorderURL, requestXml);
			
			if(responseXml != null && !"".equals(responseXml)){
				xmlUtil = new XmlUtil(UnifiedorderResponse.class, XmlUtil.CollectionWrapper.class);
				response = xmlUtil.fromXml(responseXml);
			}else{
				zhbCode = "900003";
				zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode);
			}
	    }
	    tranLogDALService.logDB("YD-wechatpay", "unifiedorder", "out", orderNo, responseXml, zhbCode, zhbMessage);
		return response;
	}
	
	@Override
	public WxUserInfo getWxUserInfo(String openId, String accessToken) {
		WxUserInfo userInfo = null;
		String zhbCode = "800000";
		String zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode);
		String responseJson = null;
		if(!CommonUtil.isNullOrBlank(openId) &&!CommonUtil.isNullOrBlank(accessToken)){
			userInfo = new WxUserInfo();
			String url = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_AUTHORIZE_GETUSERINFO_URL")+"?access_token="+accessToken+"&openid="+openId;
			tranLogDALService.logDB("wechat", "getWxUserInfo", "URL", openId, url, null, null);
			responseJson = transaction(url,null);
			if(!CommonUtil.isNullOrBlank(responseJson)){
				userInfo = (WxUserInfo) JsonUtil.jsonToObj(responseJson, WxUserInfo.class);
				if(!CommonUtil.isNullOrBlank(userInfo.getErrcode())){
					zhbCode = userInfo.getErrcode();
					zhbMessage = userInfo.getErrmsg();
				}
			}else {
				zhbCode = "900003";
				zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode);
			}
		}else {
			zhbCode = "610002";
			String[] params = {"appid、accessToken"};
			zhbMessage = ZHBErrorConfig.getErrorInfo(zhbCode, params);
		}
		try {
			responseJson=URLEncoder.encode(responseJson ,"utf-8" );
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		tranLogDALService.logDB("wechat", "getWxUserInfo", "response", openId, responseJson, zhbCode, zhbMessage);
		return userInfo;
	}

	
	/**
	 * http连接
	 * @param httpURL 地址
	 * @param object XML内容
	 * @return
	 */
	public String transaction(String  httpURL,Object object){
		String responseXML = null;
		HttpsURLConnection connection = null;
		OutputStream output = null;
		InputStream input = null;

		try {
			URL url = new URL(httpURL);
			connection = (HttpsURLConnection) url.openConnection();
			connection.setReadTimeout(30000);
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setAllowUserInteraction(true);
//			conn.setRequestMethod("POST"); //默认的请求方式是GET 
//			conn.setRequestProperty("Content-type", "text/html");  
			connection.setRequestProperty("Accept-Charset", "utf-8");
			connection.setRequestProperty("contentType", "utf-8");
			connection.setHostnameVerifier(new HostnameVerifier() {
				@Override
				public boolean verify(String hostname, SSLSession session) {
					return true;
				}
			});
			connection.connect();
			if (object != null && !"".equals(object)) {
				output = connection.getOutputStream();
				output.write((object.toString()).getBytes("utf-8"));
			}
			input = connection.getInputStream();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				if (output != null) {
					output.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		StringBuffer stringBuffer = new StringBuffer();
		if (input != null) {
			try {
				BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
				String string = null;
				while ((string = reader.readLine()) != null) {
					stringBuffer.append(string);
				}
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		responseXML = stringBuffer.toString();
		return responseXML;
	}
	
	/**
     * 签名算法
     * 方法用途：对所有传入参数按照字段名的Unicode码从小到大排序（字典序），并生成url参数串
     * @param paraMap 需要排序的Map对象
     * @param urlEncode 是否需要RULENCODE
     * @param keyToLower 是否需要将Key转换为全小写 true：key转化成小写，false：不转化
     */
	@Override
	public String getSignValue(Map<String, String> paraMap,boolean urlEncode,boolean keyToLower,String appId,String key){
		
        String signValue = null;
        String tmpString = null;
        if (paraMap!=null) {
            try {
                Map<String , String> tmpMap = paraMap;
                //将map中的映射关系存入到一个list集合中，而这个关系的数据类型就是Map.Entry
                List<Entry<String, String>> infoIds = new ArrayList<Entry<String, String>>(tmpMap.entrySet());
                //对所有传入的参数按照字段名的ASCII码从小到到排序（字典序）
                Collections.sort(infoIds,new Comparator<Entry<String, String>>() {
                	@Override
                    public int compare(Entry<String, String> o1, Entry<String, String> o2) {
                        return (o1.getKey()).toString().compareTo(o2.getKey());
                    }
                });
                //构建URL键值对的格式
                StringBuilder buf = new StringBuilder();
                for (Entry<String, String> item : infoIds){
                    if(item.getKey()!=null){
                        String infokey = item.getKey();
                        String value = item.getValue();
                        if(value != null && !"".equals(value)){
                        	 if (urlEncode) {
                                 value= URLEncoder.encode(value,"UTF-8");
                             }
                             if (keyToLower) {
                                 buf.append(infokey.toLowerCase()+"="+value);
                             }else{
                                 buf.append(infokey+"="+value);
                             }
                             buf.append("&");
                        }
                    }
                }
                tmpString = buf.toString();
                if (!tmpString.isEmpty()) {
                    tmpString = tmpString.substring(0,tmpString.length()-1);
                }
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            
        }
        String stringSignTemp = tmpString+"&key="+key;
        signValue = EncryptUtil.encrypt(stringSignTemp,null).toUpperCase();
        return signValue;
    }

	@Override
	public WxNATIVEPayQueryRespVO nativePayQuery(WxNATIVEPayQueryReqVO wxNATIVEPayQueryReqVO) {
		WxNATIVEPayQueryRespVO response = new WxNATIVEPayQueryRespVO();
		boolean success = false;
		String message = null;
		TranLog tranLog = null;
    	String tranNo = wxNATIVEPayQueryReqVO.getOrderNo();
    	if (tranNo != null && !"".equals(tranNo)) {
    		TranLog obj = new TranLog();
        	obj.setTranNo(tranNo);
        	obj.setCategory("YD-wechatpay");
        	obj.setType("paynotice");
        	obj.setInOrOut("in");
        	String orderBy = " id desc";
        	List<TranLog> tranLogs = tranLogDALService.findByTranLogOrderBy(obj, orderBy);
        	if (tranLogs.size()>0) {
        		tranLog = tranLogs.get(0);
			}
		}else{
			success = false;
			String[] params = {"订单号-tranNo"};
			message = ZHBErrorConfig.getErrorInfo("610001", params);
			response.setCommonResult(new CommonResult(success, message));
			return response;
		}
    	String returnCode = null ;
    	String returnMessage = null;
    	String url = null;
    	if(tranLog != null){
    		success = true;
    		message = ZHBErrorConfig.getErrorInfo("800000");
    		returnCode = tranLog.getReturnCode();
    		returnMessage = tranLog.getReturnMessage();
    		
    		TranLog tranLogNew = new TranLog();
        	tranLogNew.setTranNo(tranNo);
        	tranLogNew.setCategory("YD-wechatpay");
        	tranLogNew.setType("NATIVE-URL");
        	tranLogNew.setInOrOut("request");
        	tranLogNew.setReturnCode("SUCCESS");
			String orderBy = " id desc";
        	List<TranLog> tranLogNews = tranLogDALService.findByTranLogOrderBy(tranLogNew,orderBy);
        	if(tranLogNews.size()>0){
        		tranLogNew = tranLogNews.get(0);
        		url = tranLogNew.getReturnMessage();
        	} 
    	}
    	
    	response.setResult(returnCode);
    	response.setResultMessage(returnMessage);
    	response.setUrl(url);
    	response.setCommonResult(new CommonResult(success,message));
		return response;
	}

	
	@Override
	public String weixinJSBridge(String appid, String timeStamp, String nonceStr, String prepayId, String notifyUrl,
			String key) {
		String indexUrl = systemConfigService.getSingleConfigValue("FilePathPrefix");
		indexUrl = indexUrl.substring(0,indexUrl.length()-1);;
		String signType = "MD5";
		String packageStr = "prepay_id="+prepayId;
	
		Map<String,String> paraMap = new HashMap<String,String>();
		paraMap.put("appId", appid);
		paraMap.put("nonceStr", nonceStr);
		paraMap.put("package", packageStr);
		paraMap.put("signType",signType);
		paraMap.put("timeStamp", timeStamp);
		String paySignValue = getSignValue(paraMap,false,false,appid,key);
		
		String result = ""
				+"<script>"
				+"\n	function onBridgeReady(){"
				+"\n		WeixinJSBridge.invoke("
				+"\n			'getBrandWCPayRequest', {"
				+"\n				\"appId\" : \""+appid+"\","
				+"\n				\"timeStamp\": \""+timeStamp+"\","
				+"\n				\"nonceStr\" : \""+nonceStr+"\","
				+"\n				\"package\" : \""+packageStr+"\","
				+"\n				\"signType\" : \""+signType+"\","
				+"\n				\"paySign\" : \""+paySignValue+"\""
				+"\n			},"
				+"\n			function(res){"
				+"\n				if(res.err_msg == \"get_brand_wcpay_request:ok\" ) {"
				+"\n					window.location.href=\""+notifyUrl+"\";"
				+"\n				}else if (res.err_msg == \"get_brand_wcpay_request:cancel\"){"
				+"\n					window.location.href=\""+indexUrl+"\";"
				+"\n				}else{"
				+"\n				   alert(JSON.stringify(res));"
				+"\n				   alert(res.err_msg);"
				+"\n				}"
				+"\n			}"
				+"\n		);"
				+"\n	}"
				+"\n    function callpay(){"
				+"\n        if (typeof WeixinJSBridge == \"undefined\"){"
				+"\n            if( document.addEventListener ){"
				+"\n                document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);"
				+"\n            }else if (document.attachEvent){"
				+"\n                document.attachEvent('WeixinJSBridgeReady', onBridgeReady);"
				+"\n                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);"
				+"\n            }"
				+"\n        }else{"
				+"\n            onBridgeReady();"
				+"\n        }"
				+"\n    }"
				+"\n	callpay();"
				+"\n</script>";
		return result;
	}

	@Override
	public WeChatInfoByENV getWeChatInfoByENV(String gzhName, boolean getAccessToken) {
		WeChatInfoByENV weChatInfoByENV = new WeChatInfoByENV();
		boolean isProd = SpringContextUtil.isProd();
		boolean isLocal = SpringContextUtil.isLocal();
		String appId,secret,accessToken;
		String grantType = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TOKEN_GRANT_TYPE");
		//根据不同环境和不同公众号获取公众号的appId和secret
		if("YDBJ".equals(gzhName)){
			appId = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_APPID");
			secret = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_APP_SECRET");
		}else{
			if(isProd){
				appId = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APPID");
				secret = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APP_SECRET");
			}else{
				appId = systemConfigService.getSingleConfigValue("AJB-TENCENT_WECHAT_APPID");
				secret = systemConfigService.getSingleConfigValue("AJB-TENCENT_WECHAT_APP_SECRET");
			}
		}

//		if(isProd){
//			if("YDBJ".equals(gzhName)){
//				appId = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_APPID");
//				secret = systemConfigService.getSingleConfigValue("YD-TENCENT_WECHAT_APP_SECRET");
//			}else{
//				appId = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APPID");
//				secret = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APP_SECRET");
//			}
//		}else{
//			appId = systemConfigService.getSingleConfigValue("AJB-TENCENT_WECHAT_APPID");
//			secret = systemConfigService.getSingleConfigValue("AJB-TENCENT_WECHAT_APP_SECRET");
//		}
		if(getAccessToken){
			AccessTokenRequest accessTokenRequest = new AccessTokenRequest();
			accessTokenRequest.setAppid(appId);
			accessTokenRequest.setSecret(secret);
			accessTokenRequest.setGrant_type(grantType);
			//本地环境需要通过dev环境去获取
			accessToken = isLocal ? getAccessTokenByDEV(accessTokenRequest) : getAccessToken(accessTokenRequest);
			weChatInfoByENV.setAccessToken(accessToken);
		}
		weChatInfoByENV.setAppId(appId);
		weChatInfoByENV.setSecret(secret);
		return weChatInfoByENV;
	}

	/**
	 * 在本地开发时，通过dev去获取access_token
	 * @param accessTokenRequest
	 * @return
	 */
	private String getAccessTokenByDEV(AccessTokenRequest accessTokenRequest) {
		String requestJson = JsonUtil.objToJson(accessTokenRequest);
		String responseJson = HttpUtil.postForJson("https://mdev.zuihuibi.cn/api/getAccessToken",requestJson);
		JSONObject result = JSON.parseObject(responseJson);
		return result.getString("data");
	}

	@Override
	public String getAccessToken(AccessTokenRequest accessTokenRequest) {
		refactorRequest(accessTokenRequest);
		String grantType = accessTokenRequest.getGrant_type();
		String appId = accessTokenRequest.getAppid();
		String secret = accessTokenRequest.getSecret();
		//1、查询数据库是否存在
		String accessToken = getAccessTokenOrTicketByDB(grantType,appId,secret,null,null,"TOKEN");
		//2、如果不存在则重新生成
		if(Strings.isNullOrEmpty(accessToken)){
			AccessTokenResponse accessTokenResponse = wechatInterfService.getAccessToken(accessTokenRequest);
			accessToken = accessTokenResponse.getAccess_token();
			//保存数据进数据库
			String expiresInStr = accessTokenResponse.getExpires_in();
			Long expiresIn = Strings.isNullOrEmpty(expiresInStr) ? null : Long.parseLong(expiresInStr);
			TenInterfRecord tenCentRecord = new TenInterfRecord();
			tenCentRecord.setInterfType("TOKEN");
			tenCentRecord.setGrantType(grantType);
			tenCentRecord.setAppid(appId);
			tenCentRecord.setSecret(secret);
			tenCentRecord.setAccessToken(accessToken);
			tenCentRecord.setExpiresIn(expiresIn);
			tenCentRecord.setErrcode(accessTokenResponse.getErrcode());
			tenCentRecord.setErrmsg(accessTokenResponse.getErrmsg());
			tenCentRecord.setCreatedAt(new Date());
			tenInterfRecordDALService.saveTenInterfRecord(tenCentRecord);
		}
		return accessToken;
	}

	private void refactorRequest(AccessTokenRequest accessTokenRequest) {
		String appId = accessTokenRequest.getAppid();
		String secret = accessTokenRequest.getSecret();
		if (Strings.isNullOrEmpty(appId) || Strings.isNullOrEmpty(secret)) {
			appId = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APPID");
			secret = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_APP_SECRET");
			String grantType = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TOKEN_GRANT_TYPE");
			accessTokenRequest.setAppid(appId);
			accessTokenRequest.setGrant_type(grantType);
			accessTokenRequest.setSecret(secret);
		}
	}
	/**
	 * 获取获取access_token或者ticket时 查询数据库是否存在相关记录
	 * @param grantType
	 * @param appId
	 * @param secret
	 * @param pType
	 * @param accessToken
	 * @param type "TOKEN":获取access_token  TICKET:获取ticket
	 * @return
	 */
	private String getAccessTokenOrTicketByDB(String grantType, String appId, String secret, String pType, String accessToken, String type) {
		String result = null;
		TenInterfRecord tenCentRecord = new TenInterfRecord();
		tenCentRecord.setInterfType(type);
		List<TenInterfRecord> tenCentInterfaceRecordList = null;
		/** 查询最近一天（24H）内 有效期（expires_in）不为空的数据（倒序） **/
		if("TOKEN".equals(type)){
			tenCentInterfaceRecordList = tenInterfRecordDALService.findByAppIdAndGrantType(appId,grantType);
		}else if("TICKET".equals(type)){
			tenCentInterfaceRecordList = tenInterfRecordDALService.findByAccessTokenAndIType(accessToken,pType);
		}
		if(tenCentInterfaceRecordList != null && tenCentInterfaceRecordList.size() >0){
			tenCentRecord = tenCentInterfaceRecordList.get(0);
			Long expiresIn = tenCentRecord.getExpiresIn();
			Date createAt = tenCentRecord.getCreatedAt();
			if(expiresIn != null){
				Date overdueDate = CommonUtil.dateOperation(createAt, "ADD", "S", expiresIn.intValue());
				if(new Date().compareTo(overdueDate) < 0){
					result = ("TOKEN".equals(type)) ? tenCentRecord.getAccessToken() : ("TICKET".equals(type)) ? tenCentRecord.getTicket() : null;
				}
			}
		}
		return  result;
	}

	@Override
	public Map<String, String> jsapiTicketSign(String jsapiTicket, String url) {
		Map<String, String> ret = new HashMap<String, String>();
        String nonceStr = createNonceStr();
        String timestamp = createTimestamp();
        String string1;
        String signature = "";
        //注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapiTicket +"&noncestr=" + nonceStr +"&timestamp=" + timestamp +"&url=" + url;
        System.out.println(string1);
        try{
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }catch(NoSuchAlgorithmException e){
            e.printStackTrace();
        }catch(UnsupportedEncodingException e){
            e.printStackTrace();
        }
        ret.put("url", url);
        ret.put("jsapi_ticket", jsapiTicket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        return ret;
	}	
	private static String byteToHex(final byte[] hash){
        Formatter formatter = new Formatter();
        for (byte b : hash){
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
    private static String createNonceStr(){
        return UUID.randomUUID().toString();
    }
    private static String createTimestamp(){
        return Long.toString(System.currentTimeMillis() / 1000);
    }






//	private String transaction(String httpURL,String requestXML,String requestMethod){
//		HttpsURLConnection conn = null; 
//		OutputStream out = null; 
//		InputStream in = null;
//		try {
//			URL url = new URL(httpURL);
//			conn = (HttpsURLConnection) url.openConnection();
//			conn.setReadTimeout(30000);
//			conn.setDoInput(true);
//			conn.setDoOutput(true);
//			conn.setAllowUserInteraction(true);
//			if (requestMethod != null) {
//				conn.setRequestMethod(requestMethod);  
//				conn.setRequestProperty("Content-type", "text/html");
//			} 
//			conn.setRequestProperty("Accept-Charset", "utf-8");  
//			conn.setRequestProperty("contentType", "utf-8");  
//			conn.setHostnameVerifier(new HostnameVerifier() {
//				@Override
//				public boolean verify(String arg0, SSLSession arg1) {
//					return true;
//				}
//			});
//			conn.connect();
//			if(requestXML != null && !"".equals(requestXML)){
//				requestXML = URLEncoder.encode(requestXML, "utf-8");
//				out = conn.getOutputStream();
//				out.write(requestXML.getBytes("utf-8"));
//			}
//			in  = conn.getInputStream();
//		} catch (Exception e) {
//			e.printStackTrace();
//		}finally{
//			try {
//				if(out != null){out.close();}
//			} catch (Exception e2) {
//				e2.printStackTrace();
//			}
//		}
//		StringBuffer sbf = new StringBuffer();
//		if(in != null){
//			try {
//				BufferedReader reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
//				String str = null ;
//				while((str = reader.readLine()) != null){
//					sbf.append(str);
//				}
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}
//		String responseXML = sbf.toString();
//		return responseXML;
//	}
}
