package com.cku.oa.sys.service;

import static com.cku.oa.dog.service.DogBirthCertificateService.DOG_ACTIVATION_MILLIS;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
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.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cku.core.PageResultDto;
import com.cku.core.ZAErrorCode;
import com.cku.core.ZAException;
import com.cku.oa.dog.dao.DogAppraisalDao;
import com.cku.oa.dog.dao.DogBirthCertificateDao;
import com.cku.oa.dog.dao.DogChipDao;
import com.cku.oa.dog.dao.DogPedigreeCertifiedChangeDao;
import com.cku.oa.dog.dao.DogStickerApplyDao;
import com.cku.oa.dog.entity.DogAppraisal;
import com.cku.oa.dog.entity.DogBirthCertificate;
import com.cku.oa.dog.entity.DogChip;
import com.cku.oa.dog.entity.DogPedigreeCertifiedChange;
import com.cku.oa.dog.entity.DogStickerApply;
import com.cku.oa.dog.service.DogActivationService;
import com.cku.oa.finance.service.PaymentOrderRefundService;
import com.cku.oa.finance.service.SaPaymentDetailTotalService;
import com.cku.oa.sampling.entity.Sampling;
import com.cku.oa.sampling.enums.SamplingDistributionChannelEnum;
import com.cku.oa.sampling.service.SamplingService;
import com.cku.oa.sfexpress.dao.SfExpressStateDao;
import com.cku.oa.sfexpress.entity.ExpressBody;
import com.cku.oa.sfexpress.entity.ExpressOrder;
import com.cku.oa.sfexpress.entity.ExpressOrderRequest;
import com.cku.oa.sfexpress.entity.ExpressOrderResponse;
import com.cku.oa.sfexpress.entity.Route;
import com.cku.oa.sfexpress.entity.RouteBody;
import com.cku.oa.sfexpress.entity.RouteBodyResponse;
import com.cku.oa.sfexpress.entity.RouteRequest;
import com.cku.oa.sfexpress.entity.RouteResponse;
import com.cku.oa.sfexpress.entity.Routes;
import com.cku.oa.sfexpress.entity.RoutesResponse;
import com.cku.oa.sfexpress.entity.SFContactInfoRequest;
import com.cku.oa.sfexpress.entity.SFCreateOrderRequest;
import com.cku.oa.sfexpress.entity.SfCargoDetailRequst;
import com.cku.oa.sfexpress.entity.SfExpressState;
import com.cku.oa.sfexpress.utils.XMLUtils;
import com.cku.oa.sys.dao.ExpressSendDao;
import com.cku.oa.sys.entity.ExpressQueue;
import com.cku.oa.sys.entity.ExpressSend;
import com.cku.oa.sys.entity.user.Member;
import com.cku.oa.sys.util.HttpUtils;
import com.cku.oa.sys.util.JpushUtil;
import com.cku.oa.sys.util.VerifyCodeUtil;
import com.cku.oa.sys.web.ExpressSendController;
import com.cku.restful.v1.express.vo.RestExpressRespVo;
import com.cku.restful.v1.express.vo.RestExpressRouteVo;
import com.cku.restful.v1.express.vo.RestRoutesVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.sf.csim.express.service.CallExpressServiceTools;
import com.sf.csim.express.service.HttpClientUtil;
import com.sf.csim.express.service.IServiceCodeStandard;
import com.sf.csim.express.service.code.ExpressServiceCodeEnum;
import com.sf.dto.CargoInfoDto;
import com.sf.dto.RlsInfoDto;
import com.sf.dto.WaybillDto;
import com.sf.util.MyJsonUtil;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.Collections3;
import com.thinkgem.jeesite.common.utils.DateUtils;
import com.thinkgem.jeesite.modules.sys.entity.Dict;
import com.thinkgem.jeesite.modules.sys.service.DictService;
import com.thinkgem.jeesite.modules.sys.utils.DictUtils;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;

import edu.emory.mathcs.backport.java.util.Arrays;
import edu.emory.mathcs.backport.java.util.Collections;

/**
 * 邮寄发件Service
 * 
 * @author fanhuibin
 * @version 2016-09-01
 */
@Service
@Transactional(readOnly = true)
public class ExpressSendService extends CrudService<ExpressSendDao, ExpressSend> {
	@Autowired
	private ExpressQueueService expressQueueService;
	@Autowired
	private DogBirthCertificateDao dogBirthCertificateDao;
	@Autowired
	private DogPedigreeCertifiedChangeDao dogPedigreeCertifiedChangeDao;
	@Autowired
	private DogAppraisalDao dogAppraisalDao;
	@Autowired
	private DogChipDao dogChipDao;
	@Autowired
	private RemindService remindService;
	@Autowired
	private PaymentOrderRefundService paymentOrderRefundService;
	@Autowired
	private SfExpressStateDao sfExpressStateDao;
	@Autowired
	private DogStickerApplyDao dogStickerApplyDao;
	@Autowired
	private SamplingService samplingService;
	
	private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private Logger logger = LoggerFactory.getLogger(ExpressSendService.class);

	@Value("${sf.serviceUrl}")
	private String sfServiceUrl;

	@Value("${sf.clientcode}")
	private String clientcode;

	@Value("${sf.checkword}")
	private String checkword;

	@Value("${sf.printUrl}")
	private String printUrl;

	@Autowired
	private DictService dictService;

	@Autowired
	private SaPaymentDetailTotalService saPaymentDetailTotalService;
	
	@Autowired
	private ExpressQueueCommonService expressQueueCommonService;
	
	public ExpressSend get(String id) {
		return super.get(id);
	}

	public List<ExpressSend> findList(ExpressSend expressSend) {
		return super.findList(expressSend);
	}

	public Page<ExpressSend> findPage(Page<ExpressSend> page, ExpressSend expressSend) {
		return super.findPage(page, expressSend);
	}

	@Transactional(readOnly = false)
	public void save(ExpressSend expressSend) {

		if (expressSend.getIsNewRecord()) {
			expressSend.preInsert();
			expressSend.setRemarks("[创建：" + UserUtils.getUser().getName() + "(" + expressSend.getMemberCode() + ")|"
					+ format.format(expressSend.getCreateDate()) + "]");
			dao.insert(expressSend);
		} else {
			expressSend.preUpdate();
			expressSend.setRemarks(expressSend.getRemarks() + "[修改：" + UserUtils.getUser().getName() + "("
					+ expressSend.getMemberCode() + ")|" + format.format(expressSend.getCreateDate()) + "]");
			dao.update(expressSend);
		}
	}

	@Transactional(readOnly = false)
	public void delete(ExpressSend expressSend) {
		// 删除记录，需要更新所有的物品邮寄状态
		this.cancelSelect(expressSend);
		// 解绑当前邮寄记录绑定的采样包
		if (StringUtils.isNotBlank(expressSend.getContentValue())) {
			List<Sampling> samplingList = samplingService
					.findListBySamplingCodeList(Arrays.asList(expressSend.getContentValue().split(",")));
			if (samplingList.stream().anyMatch(s -> Objects.nonNull(s.getBindType()) && s.getBindType() == 1)) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "邮寄物品存在已绑定的采样包，无法删除");
			}
			samplingService.batchUnbindMemberInfo(samplingList);
		}
		super.delete(expressSend);
		// 顺丰邮寄取消订单
		if (StringUtils.isNotEmpty(expressSend.getOtherExpressNo())
				&& expressSend.getOtherExpressNo().startsWith("SF")) {
			try {
				// 新版版
				IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER; // 取消订单
				Map<String, String> params = new HashMap<String, String>();
				String timeStamp = String.valueOf(System.currentTimeMillis());
				params.put("partnerID", clientcode); // 顾客编码 ，对应丰桥上获取的clientCode
				params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
				params.put("serviceCode", standardService.getCode());// 接口服务码

				JSONObject obj = new JSONObject();
				obj.put("orderId", expressSend.getExpressNo());
				obj.put("dealType", "2");

				String msgData = obj.toJSONString();
				params.put("timestamp", timeStamp);
				params.put("msgData", msgData);
				params.put("msgDigest", CallExpressServiceTools.getMsgDigest(msgData, timeStamp, checkword));
				logger.info(" ===== 顺丰取消订单接口请求 =====:{}", params);
				String result = HttpClientUtil.post(sfServiceUrl, params);
				logger.info(" ===== 顺丰取消订单接口返回 =====:{}", result);

				// 老版本
//				OrderConfirmRequest request = new OrderConfirmRequest();
//				request.setHead("SLKJ2019");
//				request.setService("OrderConfirmService");
//				request.setLang("cn_ZH");
//				OrderConfirmBody body = new OrderConfirmBody();
//				OrderConfirm orderConfirm = new OrderConfirm();
//				orderConfirm.setDealtype(2);
//				orderConfirm.setOrderid(expressSend.getExpressNo());
//				body.setOrderConfirm(orderConfirm);
//				request.setBody(body);
//				String reqXml = XMLUtils.beanConvertXml(request, OrderConfirmRequest.class);
//
//				CallExpressServiceTools client = CallExpressServiceTools.getInstance();
//				String myReqXML = reqXml.replace("SLKJ2019", clientcode);
//				logger.info("===== 取消订单请求报文：{}", myReqXML);
//				@SuppressWarnings("static-access")
//				String respXml = client.callSfExpressServiceByCSIM(sfServiceUrl, myReqXML, clientcode, checkword);
//				logger.info("===== 取消订单返回报文：{}", respXml);

			} catch (Exception e) {
				e.printStackTrace();
			}

		}

	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = false)
	public boolean saveExpress(ExpressSend expressSend, HttpServletRequest request) throws Exception {
		//  待邮寄物品业务验证
		String[] ids = request.getParameterValues("ids");// 待发货物品的id
		if(!Objects.isNull(ids)) {
			expressQueueCommonService.cherkBusinessByIds(Arrays.asList(ids));
		}
		
		//  如果是修改记录，需要更新物品是否被邮寄的状态
		// （A物品本来被添加了，修改之后没有添加，那么A就可以继续邮寄）
		List<String> newSamplingCodeList = new ArrayList<>();
		if (StringUtils.isNotBlank(expressSend.getContentValue())) {
			newSamplingCodeList.addAll(Arrays.asList(expressSend.getContentValue().split(",")));
		}
		if (!expressSend.getIsNewRecord()) {
			this.cancelSelect(expressSend);
			ExpressSend dbExpressSend = this.get(expressSend.getId());
			if (StringUtils.isNotBlank(dbExpressSend.getContentValue())) {
				List<Sampling> dbSamplingList = samplingService
						.findListBySamplingCodeList(Arrays.asList(dbExpressSend.getContentValue().split(",")));
				// 查询原库中已经绑定的采样包记录
				List<String> bindSamplingCodeList = dbSamplingList.stream()
						.filter(s -> Objects.nonNull(s.getBindType()) && s.getBindType() == 1)
						.map(Sampling::getSamplingCode).collect(Collectors.toList());
				// 如原库中存在已绑定的采样包，但本次修改不存在已绑定的采样包记录，则不允许本次操作
				if (CollectionUtils.isNotEmpty(bindSamplingCodeList)
						&& (StringUtils.isEmpty(expressSend.getContentValue())
								|| !newSamplingCodeList.containsAll(bindSamplingCodeList))) {
					throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "邮寄物品存在已绑定的采样包，无法修改");
				}
				// 此操作为邮寄时绑定会员采样包准备，将会员已经绑定犬只的采样包记录移除
				newSamplingCodeList.removeAll(bindSamplingCodeList);
				// 如以上操作均校验通过，则先解绑未绑定的采样包记录
				List<Sampling> unbindSamplingList = dbSamplingList.stream()
						.filter(s -> !bindSamplingCodeList.contains(s.getSamplingCode())).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(unbindSamplingList)) {
					samplingService.batchUnbindMemberInfo(unbindSamplingList);
				}
			}

		}

		List<ExpressQueue> queues = new ArrayList<ExpressQueue>();
		String content = "";
		if (ids != null && ids.length > 0) {// 删除选中的待邮寄物品
			for (int j = 0; j < ids.length; j++) {
				ExpressQueue expressQueue = expressQueueService.get(ids[j]);
				content += expressQueue.getItemName();
				if (j != ids.length - 1) {
					content += ",";
				}
				queues.add(expressQueue);
				if (ExpressSendController.SAMPLING_CHARGING_ITEM_IDS.contains(expressQueue.getChargeItemId())
						&& paymentOrderRefundService.validOrderIsRefundingOrRefunded(expressQueue.getRunningNumber())) {
					throw new ZAException(ZAErrorCode.ZA_ERROR, "包含已申请退款的采样包不能邮寄");
				}
			}
		}
		expressSend.setContent(content);

		// 获取发件人信息
		Dict sender = new Dict();
		sender.setType("express_sender");
		List<Dict> expressSender = dictService.findList(sender);

		Dict sendAddress = new Dict();
		sendAddress.setType("express_send_address");
		List<Dict> expressSendAddress = dictService.findList(sendAddress);
		expressSend.setSendPhone("400-6607000");
		if ("1".equals(expressSend.getSender())) {
			expressSend.setSenderDetail(expressSender.get(0).getValue());
			expressSend.setSendAddress(expressSendAddress.get(0).getValue());
		} else {
			expressSend.setSenderDetail(expressSender.get(1).getValue());
			expressSend.setSendAddress(expressSendAddress.get(1).getValue());
		}

		this.save(expressSend);
		if (CollectionUtils.isNotEmpty(newSamplingCodeList)) {
			this.samplingService.batchExpress(newSamplingCodeList, expressSend.getMemberCode(),
					SamplingDistributionChannelEnum.MEMBER);
		}
		// 所有已经发送的物品标记邮寄记录表id
		for (ExpressQueue q : queues) {
			q.setExpressSendId(expressSend.getId());
			updateSendDate(q, expressSend.getPostDate());
			expressQueueService.save(q);
		}
		if (!Collections3.isEmpty(queues)) {
			// String businessTable = queues.get(0).getBusinessTable();
			// String businessId = queues.get(0).getBusinessId();
			// if (StringUtils.isNotBlank(businessTable) &&
			// StringUtils.isNotBlank(businessId)) {
			// if ("dog_birth_certificate".equals(businessTable)) {
			// sendMsg(queues, expressSend.getPostDate());
			// }
			// }
			List<String> temp = new ArrayList<>();
			for (ExpressQueue q : queues) {
				temp.add(q.getBusinessTable());
			}
			if (temp.contains("dog_birth_certificate")) {
				sendMsg(queues, expressSend.getPostDate());
			}

		}

		// 新增逻辑（顺丰下单）
		// TODO zhaoxy
		if ("顺丰到付快递".equals(expressSend.getExpressType()) && StringUtils.isEmpty(expressSend.getOtherExpressNo())) {
			// 调用顺丰下单接口
			if (!sfCreateOrder(expressSend)) {
				throw new Exception("顺丰下单失败");
			}
		}
		// 协会自取（确认财务收入）
		if ("协会自取".equals(expressSend.getExpressType())) {
			for (ExpressQueue queue : queues) {
				if (StringUtils.isNotEmpty(queue.getBusinessTable()) && StringUtils.isNotEmpty(queue.getBusinessId())) {
					// TODO 财务收入确认时点
					saPaymentDetailTotalService.financeConfirmTime(queue.getBusinessId(), queue.getBusinessTable());
				} else {
					// 犬只鉴定证书对应五个收费项且没存businessId和businessTable
					saPaymentDetailTotalService.financeConfirmTime(queue.getRunningNumber());
				}
			}
			expressSend.setReceiveDate(new Date());
			expressSend.setIsNewRecord(false);
			this.save(expressSend);
		}
		return true;
	}

	private boolean sfCreateOrder(ExpressSend expressSend) throws Exception {
		IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER; // 下订单
		Map<String, String> params = new HashMap<String, String>();
		String timeStamp = String.valueOf(System.currentTimeMillis());
		params.put("partnerID", clientcode); // 顾客编码 ，对应丰桥上获取的clientCode
		params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
		params.put("serviceCode", standardService.getCode());// 接口服务码

		String msgData = getCreateOrderMsgData(expressSend);
		params.put("timestamp", timeStamp);
		params.put("msgData", msgData);
		params.put("msgDigest", CallExpressServiceTools.getMsgDigest(msgData, timeStamp, checkword));
		logger.info(" ===== 顺丰下单接口 =====:{}", sfServiceUrl);
		logger.info(" ===== 顺丰下单接口请求 =====:{}", JSONObject.toJSONString(params));
		String result = HttpClientUtil.post(sfServiceUrl, params);
		logger.info(" ===== 顺丰下单返回结果 =====:{}", result);

		JSONObject obj = JSONObject.parseObject(result);
		JSONObject apiResultData = JSONObject.parseObject(obj.getString("apiResultData"));

		if (apiResultData.getBoolean("success")) {
			JSONObject resultMsgData = JSONObject.parseObject(apiResultData.getString("msgData"));
			// 修改send表第三方运单号
			SfExpressState sfExpressState = new SfExpressState();
			sfExpressState.setOrderNo(resultMsgData.getString("orderId"));
			sfExpressState.setOrigincode(resultMsgData.getString("originCode"));// 原寄地区域代码,可用于
			sfExpressState.setDestcode(resultMsgData.getString("destCode")); // 目的地区域代码,可用于

			JSONArray routeList = JSONObject.parseArray(resultMsgData.getString("routeLabelInfo"));
			if (!CollectionUtils.isEmpty(routeList)) { // 面单信息
				JSONObject routeObj = JSONObject.parseObject(routeList.get(0).toString());
				JSONObject routeLabel = JSONObject.parseObject(routeObj.getString("routeLabelData"));
				sfExpressState.setTwoDimensionCode(routeLabel.getString("twoDimensionCode")); // 中转二维码
				sfExpressState.setProCode(routeLabel.getString("proCode"));
				sfExpressState.setPrintIcon(routeLabel.getString("printIcon"));
				sfExpressState.setDestRouteLabel(routeLabel.getString("destRouteLabel"));
				sfExpressState.setCodingMapping(routeLabel.getString("codingMapping"));
				sfExpressState.setDestTeamCode(routeLabel.getString("destTeamCode"));
			}

			JSONArray waybillNoInfoList = JSONObject.parseArray(resultMsgData.getString("waybillNoInfoList"));
			System.out.println("");
			if (!CollectionUtils.isEmpty(waybillNoInfoList)) {
				for (Object array : waybillNoInfoList) {
					JSONObject waybillNoInfo = JSONObject.parseObject(array.toString());
					if ("1".equals(waybillNoInfo.getString("waybillType"))) {
						sfExpressState.setWaybillNo(waybillNoInfo.getString("waybillNo"));
					}
				}
			}

			ExpressSend expressSend2 = dao.selectByOrderNo(sfExpressState.getOrderNo());
			sfExpressStateDao.updateWaybill(sfExpressState, expressSend2.getId());
			return true;
		} else {
			return false;
		}
	}

	private String getCreateOrderMsgData(ExpressSend expressSend) {

		boolean sender = "1".equals(expressSend.getSender()); // 寄送方 1:平阳中爱 2:宠爱王国
		// 寄送方
		SFContactInfoRequest j_contactinfo = SFContactInfoRequest.builder().contactType("1")
				.company(expressSend.getSenderDetail()).contact(expressSend.getSenderDetail())
				.tel(sender ? "13396953132" : expressSend.getSendPhone()).province(sender ? "浙江省" : "北京市")
				.city(sender ? "温州市" : "朝阳区").county(sender ? "平阳县水头镇宠物小镇客厅" : "道家园")
				.address(expressSend.getSendAddress()).build();
		// 收件方
		SFContactInfoRequest d_contactinfo = SFContactInfoRequest.builder().contactType("2")
				.province(getProvince(expressSend.getProvince())).city(expressSend.getCity())
				.county(expressSend.getArea())
				.contact(expressSend.getReceiver()).tel(expressSend.getPhone()).address(expressSend.getAddress())
				.build();

		List<SFContactInfoRequest> contactInfos = new ArrayList<>();
		contactInfos.add(j_contactinfo);
		contactInfos.add(d_contactinfo);
		// 托寄物信息
		SfCargoDetailRequst cargoDetail = SfCargoDetailRequst.builder().name(expressSend.getSendRemarks()).build();
		List<SfCargoDetailRequst> cargoDetails = new ArrayList<>();
		cargoDetails.add(cargoDetail);
		SFCreateOrderRequest createOrderrequest = SFCreateOrderRequest.builder().language("zh-CN")
				.orderId(expressSend.getExpressNo()).payMethod("2").isReturnRoutelabel("1").cargoDetails(cargoDetails)
				.contactInfoList(contactInfos).remark(expressSend.getMemberCode()).build();
		return JSONObject.toJSONString(createOrderrequest);
	}

	@Deprecated
	private boolean sfOrder(ExpressSend expressSend) throws JAXBException {
		// 拼装下单请求报文
		ExpressOrderRequest expressOrderRequest = new ExpressOrderRequest();
		expressOrderRequest.setHead("SLKJ2019");
		expressOrderRequest.setService("OrderService");
		expressOrderRequest.setLang("cn_ZH");
		ExpressBody expressBody = new ExpressBody();
		ExpressOrder expressOrder = new ExpressOrder();
		expressOrder.setOrderid(expressSend.getExpressNo());

		expressOrder.setJ_province("北京市");
		expressOrder.setJ_city("朝阳区");
		expressOrder.setJ_company(expressSend.getSenderDetail());
		expressOrder.setJ_contact(expressSend.getSenderDetail());
		expressOrder.setJ_tel(expressSend.getSendPhone());
		expressOrder.setJ_address(expressSend.getSendAddress());
		if ("1".equals(expressSend.getSender())) { // 寄送方 1:平阳中爱 2:宠爱王国
			expressOrder.setJ_province("浙江省");
			expressOrder.setJ_city("温州市");
			expressOrder.setJ_county("平阳县水头镇宠物小镇客厅");
			expressOrder.setJ_company(expressSend.getSenderDetail());
			expressOrder.setJ_contact(expressSend.getSenderDetail());
			expressOrder.setJ_tel("13396953132");
			expressOrder.setJ_address(expressSend.getSendAddress());
		}

		expressOrder.setD_province(getProvince(expressSend.getProvince()));
		expressOrder.setD_city(expressSend.getCity());
		expressOrder.setD_contact(expressSend.getReceiver());
		expressOrder.setD_address(expressSend.getAddress());
		expressOrder.setD_tel(expressSend.getPhone());
		expressOrder.setPay_method("2");
		expressBody.setExpressOrder(expressOrder);
		expressOrderRequest.setExpressBody(expressBody);

		String reqXml = XMLUtils.beanConvertXml(expressOrderRequest, ExpressOrderRequest.class);

		CallExpressServiceTools client = CallExpressServiceTools.getInstance();
		String myReqXML = reqXml.replace("SLKJ2019", clientcode);
		logger.info("请求报文：{}", myReqXML);

//		@SuppressWarnings("static-access")
//		String respXml = client.callSfExpressServiceByCSIM(sfServiceUrl, myReqXML, clientcode, checkword);
		// 拷贝顺丰sdk代码 修改超时时间 10S
		String verifyCode = VerifyCodeUtil.md5EncryptAndBase64(String.valueOf(myReqXML) + checkword);
		String respXml = querySFAPIservice(sfServiceUrl, myReqXML, verifyCode);

		if (respXml != null) {
			logger.info("--------------------------------------");
			logger.info("返回报文: {}", respXml);
			logger.info("--------------------------------------");
			if (respXml.contains("ERR")) {
				return false;
			}
			ExpressOrderResponse expressOrderResponse = (ExpressOrderResponse) XMLUtils
					.xmlConvertBean(ExpressOrderResponse.class, respXml);

			// 修改send表第三方运单号
			SfExpressState sfExpressState = new SfExpressState();
			sfExpressState.setOrderNo(expressOrderResponse.getBody().getOrderResponse().getOrderid());
			sfExpressState.setWaybillNo(expressOrderResponse.getBody().getOrderResponse().getMailno());
			sfExpressState.setOrigincode(expressOrderResponse.getBody().getOrderResponse().getOrigincode());// 原寄地区域代码,可用于

			sfExpressState.setDestcode(expressOrderResponse.getBody().getOrderResponse().getDestcode() == null ? ""
					: expressOrderResponse.getBody().getOrderResponse().getDestcode()); // 目的地区域代码,可用于
			sfExpressState.setTwoDimensionCode(expressOrderResponse.getBody().getOrderResponse().getRlsInfo()
					.getRlsDetail().getTwoDimensionCode() == null ? ""
							: expressOrderResponse.getBody().getOrderResponse().getRlsInfo().getRlsDetail()
									.getTwoDimensionCode());

			if (expressOrderResponse.getBody().getOrderResponse().getRlsInfo() != null) {
				sfExpressState.setProCode(
						expressOrderResponse.getBody().getOrderResponse().getRlsInfo().getRlsDetail().getProCode());
				sfExpressState.setPrintIcon(
						expressOrderResponse.getBody().getOrderResponse().getRlsInfo().getRlsDetail().getPrintIcon());
				sfExpressState.setDestRouteLabel(expressOrderResponse.getBody().getOrderResponse().getRlsInfo()
						.getRlsDetail().getDestRouteLabel());
				sfExpressState.setCodingMapping(expressOrderResponse.getBody().getOrderResponse().getRlsInfo()
						.getRlsDetail().getCodingMapping());
				sfExpressState.setDestTeamCode(expressOrderResponse.getBody().getOrderResponse().getRlsInfo()
						.getRlsDetail().getDestTeamCode());
			}
			ExpressSend expressSend2 = dao.selectByOrderNo(sfExpressState.getOrderNo());
			sfExpressStateDao.updateWaybill(sfExpressState, expressSend2.getId());
		}
		return true;
	}

	// 顺丰地址适配
	private String getProvince(String pro) {
		String province = pro;
		if (pro.equals("新疆维吾尔族自治区")) {
			province = "新疆维吾尔自治区";
		}
		return province;
	}

	public String querySFAPIservice(String url, String xml, String verifyCode) {
		HttpClientUtil httpclient = new HttpClientUtil();
		if (url == null) {
			url = "http://bsp-oisp.sf-express.com/bsp-oisp/sfexpressService";
		}
		String result = null;
		try {
			result = httpclient.postSFAPI(url, xml, verifyCode);
			return result;
		} catch (Exception e) {
			logger.warn(" " + e);
			return null;
		}
	}

	/**
	 * 发送登记卡邮寄信息、提醒激活
	 * 
	 * @param queues
	 * @param date
	 */
	public void sendMsg(List<ExpressQueue> queues, Date date) {
		String birthCode = "";
		for (ExpressQueue q : queues) {
			String code = q.getItemName().substring(q.getItemName().indexOf("(") + 1, q.getItemName().indexOf(")"));
			DogBirthCertificate dogBirthCertificate = dogBirthCertificateDao.getByBirthCerRegCode(code);
			if (dogBirthCertificate != null) {
				if (dogBirthCertificate.getCreateDate().getTime() >= DOG_ACTIVATION_MILLIS
						&& !"1".equals(dogBirthCertificate.getActivitionState())) {
					birthCode += dogBirthCertificate.getBirthCerRegCode() + " 、";
				}
			}
		}
		if (birthCode.length() > 1) {
			String code = queues.get(0).getItemName().substring(queues.get(0).getItemName().indexOf("(") + 1,
					queues.get(0).getItemName().indexOf(")"));
			DogBirthCertificate birth = dogBirthCertificateDao.getByBirthCerRegCode(code);
			if (birth != null) {
				if (date == null) {
					date = new Date();
				}
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(date);
				calendar.add(Calendar.DATE, DogActivationService.EXPIRE_DAY);
				String content = "您申请的身份登记卡" + birthCode.substring(0, birthCode.length() - 1) + "已于"
						+ DateUtils.formatDate(date, "yyyy-MM-dd") + "寄出，" + "为保证身份登记卡的有效性，请于"
						+ DateUtils.formatDate(new Date(calendar.getTimeInMillis()), "yyyy-MM-dd") + "之前完成激活操作。";
				Map<String, String> extraMap = ImmutableMap.of("type", "BIRTHCERTIFICATE_GETLIST1");
				JpushUtil.pushByMemberCode(birth.getMemberCode(), content, extraMap);
				// 给会员中心推送激活消息站内信
				remindService.addMemberRemind(content, birth.getMemberCode());
			}
		}
		// 给APP推送激活通知消息
	}

	/**
	 * 取消发件记录与待邮寄物品的关联 及待邮寄物品业务表的邮寄时间更新为null
	 * 
	 * @param expressSend
	 */
	public void cancelSelect(ExpressSend expressSend) {
		String id = expressSend.getId();
		ExpressQueue q = new ExpressQueue();
		q.setExpressSendId(id);
		List<ExpressQueue> queues = expressQueueService.findList(q);
		for (ExpressQueue queue : queues) {
			queue.setExpressSendId(null);
			updateSendDate(queue, null);
			expressQueueService.save(queue);
		}
	}

	/**
	 * 更新邮寄时间
	 * 
	 * @param queue
	 */
	public void updateSendDate(ExpressQueue queue, Date d) {
		String businessTable = queue.getBusinessTable();
		String businessId = queue.getBusinessId();
		if (StringUtils.isNotBlank(businessTable) && StringUtils.isNotBlank(businessId)) {
			if ("dog_birth_certificate".equals(businessTable)) {
				// 根据code查询
				String code = queue.getItemName().substring(queue.getItemName().indexOf("(") + 1,
						queue.getItemName().indexOf(")"));
				DogBirthCertificate dogBirthCertificate = dogBirthCertificateDao.getByBirthCerRegCode(code);
				// DogBirthCertificate dogBirthCertificate =
				// dogBirthCertificateDao.findByFmdogBreedCertifiedCodeNoDate(businessId);
				if (dogBirthCertificate != null) {
					dogBirthCertificate.setSendDate(d);
					dogBirthCertificate.setUpdateDate(new Date());
					dogBirthCertificateDao.update(dogBirthCertificate);
				}
			} else if ("dog_pedigree_certified_change".equals(businessTable)) {
				DogPedigreeCertifiedChange dogPedigreeCertifiedChange = dogPedigreeCertifiedChangeDao.get(businessId);
				dogPedigreeCertifiedChange.setSendDate(d);
				dogPedigreeCertifiedChangeDao.update(dogPedigreeCertifiedChange);
			} else if ("dog_appraisal".equals(businessTable)) {
				DogAppraisal dogAppraisal = dogAppraisalDao.get(businessId);
				dogAppraisal.setSendDate(d);
				dogAppraisalDao.update(dogAppraisal);
			} else if ("dog_chip".equals(businessTable)) {
				DogChip dogChip = dogChipDao.get(businessId);
				dogChip.setSendDate(d);
				dogChipDao.update(dogChip);
			} else if ("dog_sticker_apply".equals(businessTable)) {
				DogStickerApply dogStickerApply = dogStickerApplyDao.get(businessId);
				dogStickerApply.setSendDate(d);
				dogStickerApplyDao.update(dogStickerApply);
			}
		}
	}

	/**
	 * 重置打印
	 * 
	 * @Author chaixueteng
	 * @2016年9月28日下午4:10:33
	 */
	@Transactional(readOnly = false)
	public void restPrint(String id) {
		dao.updatePrint(id, "0");
	}

	@Transactional(readOnly = false)
	public void print(ExpressSend expressSend) {
		/*
		 * String id = expressSend.getId(); ExpressQueue q = new ExpressQueue();
		 * q.setExpressSendId(id); List<ExpressQueue> queues =
		 * expressQueueService.findList(q); for(ExpressQueue queue:queues){
		 * updateSendDate(queue,new Date()); }
		 */
		dao.updatePrint(expressSend.getId(), "1");
	}

	/**
	 * 打印顺丰面单
	 * 
	 * @param expressSend
	 * @throws MalformedURLException
	 * @throws ProtocolException
	 */
	public String printWaybills(ExpressSend expressSend, HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		ExpressSend send = dao.get(expressSend.getId());

		// /********* 2联150 丰密面单 **************/
		// /** 调用打印机 不弹出窗口 适用于批量打印【二联单】 **/
		// String url7 = printUrl +
		// "/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=noAlertPrint";
		// /** 调用打印机 弹出窗口 可选择份数 适用于单张打印【二联单】 **/
		// String url8 = printUrl +
		// "/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=print";
		// /** 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【二联单】 **/
		String url9 = printUrl + "/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=image";
		// /********* 3联210 丰密面单 **************/
		// /** 调用打印机 不弹出窗口 适用于批量打印【三联单】 **/
		// String url10 = printUrl +
		// "/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=noAlertPrint";
		// /** 调用打印机 弹出窗口 可选择份数 适用于单张打印【三联单】 **/
		// String url11 = printUrl +
		// "/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=print";
		// /** 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【三联单】 **/
		// String url12 = printUrl
		// +"/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=image";
		// 根据业务需求确定请求地址
		String reqURL = url9;
		// 是否需要logo
		boolean topLogo = true;// true 需要logo false 不需要logo
		if (reqURL.contains("V2.0") && topLogo) {
			reqURL = reqURL.replace("V2.0", "V2.1");
		}
		if (reqURL.contains("V3.0") && topLogo) {
			reqURL = reqURL.replace("V3.0", "V3.1");
		}
		logger.info("请求路径: " + reqURL);
		/** 注意 需要使用对应业务场景的url **/
		URL myURL = new URL(reqURL);
		// 其中127.0.0.1:4040为打印服务部署的地址（端口如未指定，默认为4040），
		// type为模板类型（支持两联、三联，尺寸为100mm*150mm和100mm*210mm，type为poster_100mm150mm和poster_100mm210mm）
		// A5 poster_100mm150mm A5 poster_100mm210mm
		// output为输出类型,值为print或image，如不传，
		// 默认为print（print 表示直接打印，image表示获取图片的BASE64编码字符串）
		// V2.0/V3.0模板顶部是带logo的 V2.1/V3.1顶部不带logo
		HttpURLConnection httpConn = (HttpURLConnection) myURL.openConnection();
		httpConn.setDoOutput(true);
		httpConn.setDoInput(true);
		httpConn.setUseCaches(false);
		httpConn.setRequestMethod("POST");
		// httpConn.setRequestProperty("Content-Type",
		// "application/json;charset=utf-8");
		httpConn.setRequestProperty("Content-Type", "text/plain;charset=utf-8");
		httpConn.setConnectTimeout(5000);
		httpConn.setReadTimeout(3 * 5000);
		List<WaybillDto> waybillDtoList = new ArrayList<WaybillDto>();
		WaybillDto dto = new WaybillDto();
		// 必填
		dto.setAppId(clientcode);// 对应clientCode
		dto.setAppKey(checkword);// 对应checkWord

		dto.setMailNo(send.getOtherExpressNo());
		// Member member = memberService.getByMemberCode(send.getMemberCode());
		// 收件人信息
		dto.setConsignerProvince(send.getProvince());
		dto.setConsignerCity(send.getCity());
		dto.setConsignerCounty(send.getArea());
		dto.setConsignerAddress(send.getAddress());
		dto.setConsignerMobile(send.getPhone().replaceAll("(\\d{3})\\d{5}(\\d{3})", "$1*****$2"));
		dto.setConsignerName(StringUtils.isEmpty(send.getReceiver()) ? send.getMemberName() : send.getReceiver());

		String sender = send.getSender();
		String dProvince = "北京市";
		String dCity = "朝阳区";
		dto.setDeliverMobile(send.getSendPhone());
		if ("1".equals(sender)) {
			dProvince = "浙江省";
			dCity = "温州市";
			dto.setDeliverMobile("13396953132");
		}
		dto.setDeliverProvince(dProvince);
		dto.setDeliverCity(dCity);
		dto.setDeliverAddress(send.getSendAddress());
		dto.setDeliverName(send.getSenderDetail());

		dto.setDestCode(send.getDestcode());// 目的地代码 参考顺丰地区编号
		dto.setZipCode(send.getOrigincode());// 原寄地代码 参考顺丰地区编号
		dto.setExpressType(1);
		dto.setPayMethod(2);
		/** 丰密面单相关 **/
		List<RlsInfoDto> rlsInfoDtoList = new ArrayList<RlsInfoDto>();
		RlsInfoDto rlsMain = new RlsInfoDto();
		// 主面单号
		rlsMain.setWaybillNo(dto.getMailNo());
		rlsMain.setQRCode(send.getTwoDimensionCode());
		rlsMain.setProCode(send.getProCode());
		rlsMain.setPrintIcon(send.getPrintIcon());
		rlsMain.setDestRouteLabel(send.getDestRouteLabel());
		rlsMain.setDestTeamCode(send.getDestTeamCode());
		rlsMain.setCodingMapping(send.getCodingMapping());

		rlsMain.setAbFlag("");
		rlsMain.setCodingMappingOut("");
		rlsInfoDtoList.add(rlsMain);
		// 设置丰密面单必要参数
		dto.setRlsInfoDtoList(rlsInfoDtoList);

		// 加密项
		dto.setEncryptCustName(false);// 加密寄件人及收件人名称
		dto.setEncryptMobile(false);// 加密寄件人及收件人联系手机

		// 这是主面单的备注
		dto.setMainRemark(expressSend.getMemberCode());
		// dto.setInsureValue("1000");// 声明价值(元)
		// dto.setInsureFee("2.0");// 保价费用(元)
		// 邮寄物品
		CargoInfoDto cargo1 = new CargoInfoDto();
		cargo1.setCargo(expressSend.getSendRemarks());
		List<CargoInfoDto> cargoInfoList = new ArrayList<CargoInfoDto>();
		cargoInfoList.add(cargo1);
		dto.setCargoInfoDtoList(cargoInfoList);

		waybillDtoList.add(dto);
		logger.info("请求参数： {}", MyJsonUtil.object2json(waybillDtoList));
		ObjectMapper objectMapper = new ObjectMapper();
		StringWriter stringWriter = new StringWriter();
		objectMapper.writeValue(stringWriter, waybillDtoList);
		httpConn.getOutputStream().write(stringWriter.toString().getBytes());
		httpConn.getOutputStream().flush();
		httpConn.getOutputStream().close();
		InputStream in = httpConn.getInputStream();

		BufferedReader in2 = new BufferedReader(new InputStreamReader(in));
		String y = "";
		String strImg = "";
		while ((y = in2.readLine()) != null) {
			strImg = y.substring(y.indexOf("[") + 1, y.length() - "]".length() - 1);
			if (strImg.startsWith("\"")) {
				strImg = strImg.substring(1, strImg.length());
			}
			if (strImg.endsWith("\"")) {
				strImg = strImg.substring(0, strImg.length() - 1);
			}
		}
		System.out.println("img = " + strImg.replace("\\n", ""));
		// 将换行全部替换成空
		return strImg.replace("\\n", "");
		// System.out.println(strImg);
		// SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-HHmmss");
		// String dateStr = format.format(new Date());
		// List<String> files = new ArrayList<String>();
		// if(strImg.contains("\",\"")){
		// //如子母单及签回单需要打印两份或者以上
		// String[] arr = strImg.split("\",\"");
		// /**输出图片到本地 支持.jpg、.png格式**/
		// for(int i = 0; i < arr.length; i++) {
		// String fileName = "D:\\qiaoWay"+dateStr+"-"+i+".jpg";
		// Base64ImageTools.generateImage(arr[i].toString(), fileName);
		// files.add(fileName);
		// }
		// }else{
		// String fileName = "D:\\qiaoWaybill"+dateStr+".jpg";
		// Base64ImageTools.generateImage(strImg, fileName);
		// files.add(fileName);
		// }

	}

	public String printWaybillsNew(ExpressSend expressSend, HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		// 打印面单
		IServiceCodeStandard printWaybillsService = ExpressServiceCodeEnum.COM_RECE_CLOUD_PRINT_WAYBILLS;
		Map<String, String> params = new HashMap<String, String>();
		// 公共请求参数
		params.put("partnerID", clientcode); // 顾客编码 ，对应丰桥上获取的clientCode
		params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
		params.put("serviceCode", printWaybillsService.getCode());// 接口服务码
		String timeStamp = String.valueOf(System.currentTimeMillis());
		params.put("timestamp", timeStamp);
		// 业务参数
		JSONObject obj = new JSONObject();
		// 关联云打印接口后，点击查看，可在接口详情页获取模板编码，类似：fm_76130_standard_{partnerId}
		obj.put("templateCode", "fm_76130_standard_CAWGB8hcBXvY");
		// 版本号，传固定值:2.0
		obj.put("version", "2.0");
		// pdf格式
		obj.put("fileType", "pdf");
		// 是否同步
		obj.put("sync", true);
		// 运单号
		JSONArray documents = new JSONArray();
		JSONObject document = new JSONObject();
		document.put("masterWaybillNo", expressSend.getOtherExpressNo());
		documents.add(document);
		obj.put("documents", documents);
		String msgData = obj.toJSONString();
		params.put("msgData", msgData);
		// 签名
		params.put("msgDigest", CallExpressServiceTools.getMsgDigest(msgData, timeStamp, checkword));
		logger.info(" ===== 顺丰接口 =====:{}", sfServiceUrl);
		logger.info(" ===== 顺丰打印面单接口请求 =====:{}", JSONObject.toJSONString(params));
		String resultStr = HttpClientUtil.post(sfServiceUrl, params);
		logger.info(" ===== 顺丰打印面单接口返回 =====:{}", resultStr);
		JSONObject result = (JSONObject) JSONObject.parse(resultStr);
		if ("A1000".equals(result.getString("apiResultCode"))
				&& StringUtils.isNotBlank(result.getString("apiResultData"))) {// 请求成功
			JSONObject apiResultData = JSONObject.parseObject(result.getString("apiResultData"));
			if (apiResultData.getBoolean("success") && apiResultData.getJSONObject("obj") != null
					&& apiResultData.getJSONObject("obj").getJSONArray("files") != null) {// 请求成功
				JSONArray files = apiResultData.getJSONObject("obj").getJSONArray("files");
				String url = (String) ((JSONObject) files.get(0)).get("url");
				String token = (String) ((JSONObject) files.get(0)).get("token");
				return getWaybillImg(url, token);
			}
		}
		return null;
	}

	public static String getWaybillImg(String urlStr, String token) throws Exception {
		// 请求接口
		Map<String, String> headers = new HashMap<>();
		headers.put("X-Auth-token", token);
		HttpResponse response = HttpUtils.doGet(urlStr, null, null, headers, null);
		InputStream is = response.getEntity().getContent();

		// base64字符串
		return getImageBase64(is);
	}

	private static String getImageBase64(InputStream is) throws Exception {
		// pdf转图片
		PDDocument document = PDDocument.load(is);
		PDFRenderer renderer = new PDFRenderer(document);
		BufferedImage bufferedImage = null;
		for (int i = 0; i < document.getNumberOfPages(); i++) {
			bufferedImage = renderer.renderImageWithDPI(i, 300, ImageType.RGB);
		}
		document.close();

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			ImageIO.write(bufferedImage, "png", baos);
		} catch (IOException e) {
			e.printStackTrace();
		}
		byte[] bytes = baos.toByteArray();// 转换成字节
		String png_base64 = Base64.encodeBase64String(bytes);
		return png_base64.replaceAll("\n", "").replaceAll("\r", "");// 删除 \r\n;
	}

	public PageResultDto<RestExpressRespVo> restList(HttpServletRequest request, HttpServletResponse response) {
		String pageNo = request.getParameter("pageNo");
		String pageSize = request.getParameter("pageSize");
		int pageNoInt = 1;
		int pageSizeInt = 10;
		try {
			if (StringUtils.isNotBlank(pageNo)) {
				pageNoInt = Integer.parseInt(pageNo);
			}
			if (StringUtils.isNotBlank(pageSize)) {
				pageSizeInt = Integer.parseInt(pageSize);
			}
		} catch (Exception e) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "pageNo和pageSize必须都为数字");
		}
		ExpressSend expressSend = new ExpressSend();

		Member member = UserUtils.getLoginMember();
		expressSend.setMemberCode(member.getMemberCode());
		Page<ExpressSend> page = new Page<ExpressSend>();
		page.setPageNo(pageNoInt);
		page.setPageSize(pageSizeInt);
		expressSend.setPage(page);
		Page<ExpressSend> result = this.findPage(page, expressSend);
		List<ExpressSend> sendList = result.getList();
		List<RestExpressRespVo> resultVo = new ArrayList<>();
		// convert resp
		for (ExpressSend send : sendList) {
			RestExpressRespVo vo = new RestExpressRespVo();
			vo.setContent(
					send.getContent().endsWith(",") ? send.getContent().substring(0, send.getContent().length() - 1)
							: send.getContent());
			vo.setExpressNo(
					StringUtils.isEmpty(send.getOtherExpressNo()) ? send.getExpressNo() : send.getOtherExpressNo());
			vo.setExpressSfNo(StringUtils.isEmpty(send.getOtherExpressNo()) ? "" : send.getExpressNo());
			vo.setExpressType(send.getExpressType());
			vo.setSendTime(DateUtils.formatDateTime(send.getPostDate()));
			vo.setExpressTypeDesc(DictUtils.getDictLabel(send.getExpressType(), "delivery_certified", ""));
			vo.setRouteFlag(StringUtils.isNotEmpty(send.getOtherExpressNo()));
			resultVo.add(vo);
		}
		return PageResultDto.success(resultVo, result.getCount());
	}

	public RestExpressRouteVo restRoute(String orderId) throws Exception {
		RouteResponse route = searchSFRouteNew(orderId);
		RestExpressRouteVo resp = new RestExpressRouteVo();
		resp.setMailno(route.getBody().getRoutesResponse().getMailno());
		resp.setOrderiId(route.getBody().getRoutesResponse().getOrderid());
		List<Routes> routes = route.getBody().getRoutesResponse().getRoutes();
		List<RestRoutesVo> routeVo = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(routes)) {
			for (Routes r : routes) {
				RestRoutesVo vo = new RestRoutesVo();
				vo.setAccept_address(r.getAccept_address());
				vo.setAccept_time(DateUtils.formatDateTime(r.getAccept_time()));
				vo.setOrderByTime(r.getAccept_time());
				vo.setOpcode(r.getOpcode());
				vo.setRemark(r.getRemark());
				routeVo.add(vo);
			}
			Collections.sort(routeVo, new Comparator<RestRoutesVo>() {
				public int compare(RestRoutesVo vo1, RestRoutesVo vo2) {
					return vo2.getOrderByTime().compareTo(vo1.getOrderByTime());
				}
			});
		}

		resp.setRoutes(routeVo);
		return resp;
	}

	public RouteResponse searchSFRouteNew(String orderId) throws Exception {
		ExpressSend expressSend = dao.selectByOrderNo(orderId);
		String phone = "";
		if (expressSend != null && !StringUtils.isEmpty(expressSend.getPhone())) {
			phone = expressSend.getPhone().substring(expressSend.getPhone().length() - 4,
					expressSend.getPhone().length());
		}
		IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_SEARCH_ROUTES;
		Map<String, String> params = new HashMap<String, String>();
		String timeStamp = String.valueOf(System.currentTimeMillis());
		params.put("partnerID", clientcode); // 顾客编码 ，对应丰桥上获取的clientCode
		params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
		params.put("serviceCode", standardService.getCode());// 接口服务码

		List<String> trackingNumberList = new ArrayList<String>();
		trackingNumberList.add(expressSend.getOtherExpressNo());
		JSONObject obj = new JSONObject();
		obj.put("language", "0");
		obj.put("trackingType", "1");
		obj.put("trackingNumber", trackingNumberList);
		obj.put("checkPhoneNo", phone);

		String msgData = obj.toJSONString();
		params.put("timestamp", timeStamp);
		params.put("msgData", msgData);
		params.put("msgDigest", CallExpressServiceTools.getMsgDigest(msgData, timeStamp, checkword));
		logger.info(" ===== 查询路由接口请求 =====:{}", params);
		String result = HttpClientUtil.post(sfServiceUrl, params);
		logger.info(" ===== 查询路由接口返回 =====:{}", result);

		JSONObject apiResultData = JSONObject.parseObject(JSONObject.parseObject(result).getString("apiResultData"));

		RouteResponse routeResponse = new RouteResponse();
		routeResponse.setService(standardService.getCode());
		if (apiResultData.getBoolean("success")) {
			RoutesResponse routesResponse = new RoutesResponse();
			String routeResps = JSONObject.parseObject(apiResultData.getString("msgData")).getString("routeResps");
			JSONArray routeRespsInfo = JSONObject.parseArray(routeResps);
			if (!CollectionUtils.isEmpty(routeRespsInfo)) {
				JSONObject info = JSONObject.parseObject(routeRespsInfo.get(0).toString());
				ExpressSend send = dao.selectByOrderNo(orderId);
				routesResponse.setMailno(send.getOtherExpressNo());
				// routesResponse.setOrderid("true");
				JSONArray routes = JSONObject.parseArray(info.getString("routes"));
				List<Routes> routesList = new ArrayList<>();
				for (Object route : routes) {
					JSONObject routeJson = JSONObject.parseObject(route.toString());
					Routes r = new Routes();
					r.setAccept_address(routeJson.getString("acceptAddress"));
					r.setAccept_time(DateUtils.parseDate(routeJson.getString("acceptTime")));
					r.setOpcode(routeJson.getString("opcode"));
					r.setRemark(routeJson.getString("remark"));
					routesList.add(r);
				}
				routesResponse.setRoutes(routesList);
			}
			RouteBodyResponse body = new RouteBodyResponse();
			body.setRoutesResponse(routesResponse);
			routeResponse.setBody(body);
		} else {
			RouteBodyResponse body = new RouteBodyResponse();
			RoutesResponse routesResponse = new RoutesResponse();
			routesResponse.setMailno("");
			List<Routes> routes = new ArrayList<>();
			routesResponse.setRoutes(routes);

			body.setRoutesResponse(routesResponse);
			routeResponse.setBody(body);
			return routeResponse;
		}
		return routeResponse;
	}

	@Deprecated
	public RouteResponse searchSFRoute(String orderId) throws JAXBException {
		RouteRequest routeRequest = new RouteRequest();
		routeRequest.setHead("SLKJ2019");
		routeRequest.setService("RouteService");
		routeRequest.setLang("zh-CN");
		RouteBody routeBody = new RouteBody();
		Route route = new Route();
		route.setTracking_type("2");
		route.setTracking_number(orderId);
		routeBody.setRoute(route);
		routeRequest.setBody(routeBody);
		String reqXml = XMLUtils.beanConvertXml(routeRequest, RouteRequest.class);
		String myReqXML = reqXml.replace("SLKJ2019", clientcode);
		System.out.println("============================");
		System.out.println("请求报文:" + reqXml);
		System.out.println("============================");
		String respXml = CallExpressServiceTools.callSfExpressServiceByCSIM(sfServiceUrl, myReqXML, clientcode,
				checkword);
		RouteResponse routeResponse = (RouteResponse) XMLUtils.xmlConvertBean(RouteResponse.class, respXml);
		if (respXml != null) {
			System.out.println("============================");
			System.out.println("返回报文:" + JSON.toJSONString(routeResponse));
			System.out.println("============================");
		}
		return routeResponse;
	}

	@Transactional
	public void updateDownUlr(String otherExpressNo, String url) {
		int row = dao.getOtherExpressNo(otherExpressNo);
		if (row > 0) {
			dao.updateDownUlr(otherExpressNo, url);
		}
	}
	

}
