Переглянути джерело

医生端登录和快递物流

LiTaohong 5 роки тому
батько
коміт
f373a77367

+ 25 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/dao/WlyyExpressagePriceDao.java

@ -0,0 +1,25 @@
package com.yihu.jw.hospital.prescription.dao;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.yihu.jw.entity.hospital.prescription.WlyyExpressagePriceDO;
/**
 * 
 *  数据库访问层
 * 
 * @version 
 * <pre>
 * Author	Version		Date		Changes
 * Administrator 	1.0  		2019年06月05日 	Created
 *
 * </pre>
 * @since 1.
 */
public interface WlyyExpressagePriceDao extends PagingAndSortingRepository<WlyyExpressagePriceDO, String>, JpaSpecificationExecutor<WlyyExpressagePriceDO>  {
    @Query("from WlyyExpressagePriceDO where code = ?1 and endAddressName LIKE ?2 ")
    WlyyExpressagePriceDO getExprePriceByIdAndEndAdressName(String code,String end_address_name);
}

+ 21 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/dao/WlyyOutpatientExpressageLogDao.java

@ -0,0 +1,21 @@
package com.yihu.jw.hospital.prescription.dao;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.yihu.jw.entity.hospital.prescription.WlyyOutpatientExpressageLogDO;
/**
 * 
 * 门诊物流日志表 数据库访问层
 * 
 * @version 
 * <pre>
 * Author	Version		Date		Changes
 * Administrator 	1.0  		2019年06月05日 	Created
 *
 * </pre>
 * @since 1.
 */
public interface WlyyOutpatientExpressageLogDao extends PagingAndSortingRepository<WlyyOutpatientExpressageLogDO, String>, JpaSpecificationExecutor<WlyyOutpatientExpressageLogDO>  {
}

+ 16 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/service/PrescriptionExpressageLogService.java

@ -0,0 +1,16 @@
package com.yihu.jw.hospital.prescription.service;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionExpressageLogDO;
import com.yihu.jw.hospital.prescription.dao.PrescriptionExpressageLogDao;
import com.yihu.mysql.query.BaseJpaService;
import org.springframework.stereotype.Service;
/**
 *  门诊物流日志服务
 * lith 2019.06.04
 */
@Service
public class PrescriptionExpressageLogService extends BaseJpaService<WlyyPrescriptionExpressageLogDO, PrescriptionExpressageLogDao> {
}

+ 638 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/service/PrescriptionExpressageService.java

@ -0,0 +1,638 @@
package com.yihu.jw.hospital.prescription.service;
import com.yihu.jw.entity.base.org.BaseOrgDO;
import com.yihu.jw.entity.hospital.prescription.*;
import com.yihu.jw.hospital.prescription.dao.*;
import com.yihu.jw.hospital.prescription.service.entrance.util.SFUtils;
import com.yihu.jw.org.dao.BaseOrgDao;
import com.yihu.jw.util.date.DateUtil;
import com.yihu.jw.util.http.HttpClientKit;
import com.yihu.mysql.query.BaseJpaService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
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.orm.jpa.JpaTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import java.util.*;
/**
 *  门诊物流服务
 * lith 2019.06.04
 */
@Service
public class PrescriptionExpressageService extends BaseJpaService<WlyyPrescriptionExpressageDO, PrescriptionExpressageDao> {
    private static Logger logger = LoggerFactory.getLogger(PrescriptionExpressageService.class);
    //顺丰快递接口请求地址
    @Value("${express.sf_url}")
    private String sf_url;
    //顺丰快递接口接入编码
    @Value("${express.sf_code}")
    private String sf_code;
    //顺丰快递接口checkword
    @Value("${express.sf_check_word}")
    private String sf_check_word;
    @Autowired
    private SFUtils SFUtils;
    @Autowired
    private JpaTransactionManager transactionManager;
    //处方日志
    @Autowired
    private WlyyOutpatientExpressageLogDao outpatientExpressageLogDao;
    @Autowired
    private PrescriptionDao prescriptionDao;
    @Autowired
    private WlyyExpressagePriceDao expressagePriceDao;
    @Autowired
    private PrescriptionExpressageLogDao prescriptionExpressageLogDao;
    @Autowired
    private PrescriptionExpressageDao prescriptionExpressageDao;
    @Autowired
    private BaseOrgDao baseOrgDao;
    /**
     * 组装请求参数,发送请求
     * @param xml
     * @return
     * @throws Exception
     */
    private String SFExpressPost(String xml)throws Exception{
        String verifyCode = SFUtils.verifyCodeSFXmlStr(xml,sf_check_word);
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("xml", xml));
        params.add(new BasicNameValuePair("verifyCode", verifyCode));
        String re = HttpClientKit.post(sf_url, params, "UTF-8");
        return re;
    }
    /**
     * 校验返回的xml报文
     * @param responseXml
     * @param title
     */
    private void verificationResponXml(String responseXml,String title) throws Exception {
        String error = "";
        if (StringUtils.isBlank(responseXml)) {
            // 如果返回的XML报文为空,请求也算失败
            //保存http日志
            error = title + ",返回的XML为空!";
            logger.info(error);
            throw new Exception(error);
        }else{
//          报错的报文示例<Response service="ScopeService"><Head>ERR</Head><ERROR code="8014">校验码错误 </ERROR></Response>
            Document doc = DocumentHelper.parseText(responseXml);
            String headvalue = doc.selectSingleNode("/Response/Head").getText();
            if(StringUtils.isNotBlank(headvalue) && "ERR".equals(headvalue)){
                //错误代码
                String errorCode = "";
                //错误代对应的文字
                String errorMessage = doc.selectSingleNode("/Response/ERROR").getText();
                Document error_doc = doc.selectSingleNode("/Response/ERROR").getDocument();
                Element root = error_doc.getRootElement();
                List<?> child = root.elements();
                for (Object o : child){
                    Element e = (Element) o;
                    errorCode = e.attributeValue("code");
                }
                error = title+","+errorCode+","+errorMessage;
                logger.info(error);
                throw new Exception(error);
            }
        }
    }
    /**
     * 查询派送地址是否属于顺丰的派送范围
     * @param d_address 派送地址
     * @return
     */
    public Boolean getSFOrderFilterService(String d_address) throws Exception {
        boolean result = false;
        String xml = SFUtils.getSFOrderFilterXml(d_address,sf_code,"","","","");
        String re = this.SFExpressPost(xml);
//        String re = "<Response service=\"OrderFilterService\"><Head>OK</Head><Body><OrderFilterResponse orderid=\"TE201407020016\" filter_result=\"2\" origincode=\"755\" remark=\"2\"/></Body></Response>";
        //xml验证
        verificationResponXml(re,"查询派送地址是否有效失败!");
        Document doc = DocumentHelper.parseText(re);
        String headvalue = doc.selectSingleNode("/Response/Head").getText();
        Element root = doc.getRootElement();
        if(StringUtils.isNotBlank(headvalue) && "OK".equals(headvalue)) {
            //是否能派送:1:人工确认;2:可收派;3:不可以收派
            String filter_result = "";
            Element firstWorldElement = root.element("Body");
            List<Element> elements = firstWorldElement.elements();
            for (Element o : elements){
                filter_result = o.attributeValue("filter_result");
            }
            if(StringUtils.isNotBlank(filter_result) && "2".equals(filter_result)){
                result = true;
            }
        }
        return result;
    }
    /**
     * 向顺丰快递下订单
     * @param sfexpress_obj
     * @return
     * @throws Exception
     */
    public WlyyPrescriptionExpressageDO postSFOrderService(WlyyPrescriptionExpressageDO sfexpress_obj) throws Exception {
        //获取医生所处的医院详细地址,作为寄件人地址
        WlyyPrescriptionDO prescription = prescriptionDao.findOne(sfexpress_obj.getOutpatientId());
        BaseOrgDO hospital = baseOrgDao.findByCode(prescription.getHospital());
        String xml = SFUtils.postSFOrderService(sfexpress_obj,hospital,sf_code);
        logger.info("顺丰快递下订单:xml"+xml);
        String re = this.SFExpressPost(xml);
//        String re = "<Response service=\"OrderService\"><Head>OK</Head><Body><OrderResponse filter_result=\"2\" destcode=\"592\" mailno=\"444844978335\" origincode=\"592\" orderid=\"6daa6baec5fd4b65a1b023a8b60e2e91\"/></Body></Response>";
        //xml验证
        logger.info("顺丰快递下订单:re"+re);
        verificationResponXml(re,"向顺丰快递下订单失败!");
        Document doc = DocumentHelper.parseText(re);
        String headvalue = doc.selectSingleNode("/Response/Head").getText();
        if(StringUtils.isNotBlank(headvalue) && "OK".equals(headvalue)) {
            Element root = doc.getRootElement();
            if (root.element("Body") != null)     //包含OrderResponse节点
            {
                root = root.element("Body");
            }
            //是否能派送:1:人工确认;2:可收派;3:不可以收派
            String filter_result = "";
            String orderid = "";//业务订单号
            String mailno = "";//顺丰运单号
            String destCode = "";//目的地区域代码
            List<?> child = root.elements();
            for (Object o : child) {
                Element e = (Element) o;
                filter_result = e.attributeValue("filter_result");
                orderid = e.attributeValue("orderid");
                mailno = e.attributeValue("mailno");
                destCode = e.attributeValue("destcode");
            }
            if(StringUtils.isNotBlank(filter_result) && "3".equals(filter_result)){
                logger.info("顺丰快递下订单失败:派送地址不可派送,门诊编号:"+sfexpress_obj.getOutpatientId());
                throw new Exception("顺丰快递下订单失败:派送地址不可派送");
            }
            if(StringUtils.isBlank(mailno)){
                logger.info("顺丰快递下订单失败:未获取到快递单号!门诊编号:"+sfexpress_obj.getOutpatientId());
                throw new Exception("顺丰快递下订单失败:未获取到快递单号!");
            }
            sfexpress_obj.setMailno(mailno);
            sfexpress_obj.setCityCode(destCode);
        }
        return sfexpress_obj;
    }
    /**
     * 调用顺丰接口获取物流路由日志,与本地匹配,进行增量修改,并返回完整日志列表
     * @param prescription
     * @param sfexpress_obj
     * @param sfexpresslogList
     * @return
     */
    public List<WlyyPrescriptionExpressageLogDO> getRoutInfos(WlyyPrescriptionDO prescription, WlyyPrescriptionExpressageDO sfexpress_obj, List<WlyyPrescriptionExpressageLogDO> sfexpresslogList) throws Exception {
        String xml = SFUtils.getRoutInfos(sfexpress_obj,sf_code);
        String re = this.SFExpressPost(xml);
        //xml验证
        verificationResponXml(re,"查询顺丰快递路由信息失败!");
        Document doc = DocumentHelper.parseText(re);
        String headvalue = doc.selectSingleNode("/Response/Head").getText();
        if(StringUtils.isNotBlank(headvalue) && "OK".equals(headvalue)) {
            Element root = doc.getRootElement();
            if (root.element("Body") != null)     //取报文根节点
            {
                root = root.element("Body");
            }
            List<?> child = root.elements();
            String mailno = "";
            Map<String,List<WlyyPrescriptionExpressageLogDO>> wayroutlsit = new HashMap<>();
            for (Object o : child) {
                Element e = (Element) o;
                mailno = e.attributeValue("mailno");
                //判断快递单号不为空,且和我们本地的一致
                if(StringUtils.isNotBlank(mailno) &&
                        sfexpress_obj.getMailno().equals(mailno)){
                    //解析报文,结合本地数据返回最终的日志结果
                    return this.xmltologlist(e,sfexpresslogList,sfexpress_obj);
                }else{
                    continue;
                }
            }
        }
        return null;
    }
    private List<WlyyPrescriptionExpressageLogDO> xmltologlist(Element e, List<WlyyPrescriptionExpressageLogDO> sfexpresslogList, WlyyPrescriptionExpressageDO sfexpress_obj)throws Exception{
        //获取本地所有路由信息的时间集
        Set<String> routAcceptTimeSet = new HashSet<>();
        for (WlyyPrescriptionExpressageLogDO log: sfexpresslogList) {
            routAcceptTimeSet.add(DateUtil.dateToStrLong(log.getAcceptTime()));
        }
        List<?> child = e.elements();
        List<WlyyPrescriptionExpressageLogDO> newroutinfolist = new ArrayList<>();
        //用于判断新节点是否包含了"已收件"的节点
        boolean isContainEndRoutInfo = false;
        for (Object o : child) {
            Element routinfoe = (Element) o;
            String accept_time = routinfoe.attributeValue("accept_time");
            String accept_address = routinfoe.attributeValue("accept_address");
            String accept_remark = routinfoe.attributeValue("remark");
            String opcode = routinfoe.attributeValue("opcode");
            //和时间集作比对,过滤已存在的
            if(!routAcceptTimeSet.contains(accept_time)){
                WlyyPrescriptionExpressageLogDO newlogobj = new WlyyPrescriptionExpressageLogDO();
                newlogobj.setAcceptTime(DateUtil.strToDate(accept_time));
                newlogobj.setAcceptAddress(accept_address);
                newlogobj.setAcceptRemark(accept_remark);
                newlogobj.setOpCode(opcode);
                newlogobj.setId(UUID.randomUUID().toString().replace("-",""));
                newlogobj.setOutpatientId(sfexpress_obj.getOutpatientId());
                newlogobj.setExpressageId(sfexpress_obj.getId());
                newlogobj.setCreateTime(new Date());
                newroutinfolist.add(newlogobj);
                sfexpresslogList.add(newlogobj);
                //aopcode=80,为已签收
                if("80".equals(opcode)){
                    isContainEndRoutInfo = true;
                }
            }
        }
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        try {
            //如果有新增的路由信息,则添加到数据库
            if(!newroutinfolist.isEmpty()){
                prescriptionExpressageLogDao.save(newroutinfolist);
            }
            //如果路由信息节点包含了"已收件"节点,这修改处方派送状态为完成,增加物流派送日志为完成
            if(isContainEndRoutInfo){
                //修改处方状态为完成
                prescriptionDao.updateStatus(sfexpress_obj.getId(), 100,new Date());
                //保存门诊处方配送成功的日志
                WlyyOutpatientExpressageLogDO outpatiExpressLog = new WlyyOutpatientExpressageLogDO();
                outpatiExpressLog.setOutpatientId(sfexpress_obj.getOutpatientId());
                outpatiExpressLog.setId(UUID.randomUUID().toString());
                outpatiExpressLog.setType(8);
                outpatiExpressLog.setCreateTime(new Date());
                outpatiExpressLog.setFlag(1);
                outpatiExpressLog.setStatus(100);
                outpatientExpressageLogDao.save(outpatiExpressLog);
            }
            //事务提交
            transactionManager.commit(status);
        } catch (Exception ex) {
            //报错事务回滚
            transactionManager.rollback(status);
        }
        return sfexpresslogList;
    }
    /**
     * 解析顺丰推送过来的路由信息,和本地数据匹配并进行增量更新)
     * @param xml
     * @return
     * @throws Exception
     */
    public void SFRoutePushService(String xml) throws Exception{
        Document doc = DocumentHelper.parseText(xml);
        Element root = doc.getRootElement();
        if (root.element("Body") != null)     //包含WaybillRoute节点
        {
            root = root.element("Body");
        }
        List<?> child = root.elements();
        Map<String,List<WlyyPrescriptionExpressageLogDO>> wayroutlsit = new HashMap<>();
        for (Object o : child) {
            Element routinfoe = (Element) o;
            WlyyPrescriptionExpressageLogDO sflog = new WlyyPrescriptionExpressageLogDO();
            String accept_time = routinfoe.attributeValue("accepttime");
            String accept_address = routinfoe.attributeValue("acceptaddress");
            String accept_remark = routinfoe.attributeValue("remark");
            String opcode = routinfoe.attributeValue("opcode");
            String mailno = routinfoe.attributeValue("mailno");
            String orderid = routinfoe.attributeValue("orderid");
            sflog.setAcceptTime(DateUtil.strToDate(accept_time));
            sflog.setAcceptAddress(accept_address);
            sflog.setAcceptRemark(accept_remark);
            sflog.setOpCode(opcode);
            sflog.setExpressageId(orderid);
            sflog.setId(UUID.randomUUID().toString());
            sflog.setCreateTime(new Date());
            if(wayroutlsit.keySet().contains(mailno)){
                wayroutlsit.get(mailno).add(sflog);
            }else{
                List<WlyyPrescriptionExpressageLogDO> newsflogs = new ArrayList<>();
                newsflogs.add(sflog);
                wayroutlsit.put(mailno,newsflogs);
            }
        }
        if(!wayroutlsit.keySet().isEmpty()){
            for (String mailno:wayroutlsit.keySet()) {
                List<WlyyPrescriptionExpressageLogDO> pushSFLogs = wayroutlsit.get(mailno);
                //同一个快递单号的执行一个事务操作
                this.saveSFPushRoutInfos(mailno,pushSFLogs);
            }
        }
    }
    /**
     * 同一个快递单号的执行一个事务操作
     * @param mailno
     * @param pushSFLogs
     */
    public void saveSFPushRoutInfos(String mailno,List<WlyyPrescriptionExpressageLogDO> pushSFLogs){
        //根据快递单号获取处方配送详细信息
        WlyyPrescriptionExpressageDO sfexpress = prescriptionExpressageDao.findByPrescriptionExpressMailno(mailno);
        //根据快递单号获取本地的路由信息
        List<WlyyPrescriptionExpressageLogDO> localroutinfos = prescriptionExpressageLogDao.queryByOutpatientId(sfexpress.getOutpatientId());
        //需要增量更新到本地的路由信息集合
        List<WlyyPrescriptionExpressageLogDO> newroutinfolist = new ArrayList<>();
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事务隔离级别,开启新事务
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        try {
            //用于判断新节点是否包含了"已收件"的节点
            boolean isContainEndRoutInfo = false;
            //获取本地所有路由信息的时间集
            Set<String> routAcceptTimeSet = new HashSet<>();
            for (WlyyPrescriptionExpressageLogDO log: localroutinfos) {
                routAcceptTimeSet.add(DateUtil.dateToStrLong(log.getAcceptTime()));
            }
            for (WlyyPrescriptionExpressageLogDO pushlog: pushSFLogs) {
                //判断是否有已收件的路由节点
                if("80".equals(pushlog.getOpCode())){
                    isContainEndRoutInfo = true;
                }
                if(routAcceptTimeSet.contains(DateUtil.dateToStrLong(pushlog.getAcceptTime()))){
                    continue;
                }else{
                    pushlog.setOutpatientId(sfexpress.getOutpatientId());
                    newroutinfolist.add(pushlog);
                }
            }
            //如果有新增的路由信息,则添加到数据库
            if(!newroutinfolist.isEmpty()){
                prescriptionExpressageLogDao.save(newroutinfolist);
            }
            //如果路由信息节点包含了"已收件"节点,则修改处方状态为完成,增加物流派送日志为完成
            if(isContainEndRoutInfo){
                //修改处方状态为完成
                prescriptionDao.updateStatus(sfexpress.getOutpatientId(), 100,new Date());
                //保存配送成功的日志
                WlyyOutpatientExpressageLogDO outpatiExpressLog = new WlyyOutpatientExpressageLogDO();
                outpatiExpressLog.setOutpatientId(sfexpress.getOutpatientId());
                outpatiExpressLog.setId(UUID.randomUUID().toString());
                outpatiExpressLog.setType(8);
                outpatiExpressLog.setCreateTime(new Date());
                outpatiExpressLog.setFlag(1);
                outpatiExpressLog.setStatus(100);
                outpatientExpressageLogDao.save(outpatiExpressLog);
            }
            //事务提交
            transactionManager.commit(status);
        } catch (Exception ex) {
            //报错事务回滚
            transactionManager.rollback(status);
        }
    }
    /**
     * 根据收寄地址获取快递费用
     * @param d_province 省份名称
     * @param d_city     城市名称
     * @return
     */
    public WlyyExpressagePriceDO getSFExpressPrice(String d_province, String d_city) throws Exception{
        String end_address_name = "";
        if("厦门市".equals(d_city)){
            end_address_name = "同城";
        }else{
            if("福建省".equals(d_province)){
                end_address_name = "省内";
            }else{
                end_address_name = d_province;
            }
        }
        end_address_name = "%"+end_address_name.replaceAll("省","").replaceAll("市","")+"%";
        WlyyExpressagePriceDO sfprice =  expressagePriceDao.getExprePriceByIdAndEndAdressName("shunfeng",end_address_name);
        return sfprice;
    }
    /**
     * 根据处方快递订单号判断是否下单成功
     * 如果下单成功,保存处方物流记录,保存配送日志
     * @param sfexpress_obj
     * @return
     * @throws Exception
     */
    public boolean sfOrderSearchService(WlyyPrescriptionExpressageDO sfexpress_obj)  throws Exception{
        boolean go_on = false;
        String xml = SFUtils.sfOrderSearchService(sfexpress_obj.getId(),sf_code);
        String re = this.SFExpressPost(xml);
        try {
            //xml验证
            verificationResponXml(re,"订单处理失败!");
            Document doc = DocumentHelper.parseText(re);
            String headvalue = doc.selectSingleNode("/Response/Head").getText();
            if(StringUtils.isNotBlank(headvalue) && "OK".equals(headvalue)) {
                //是否能派送:1:人工确认;2:可收派;3:不可以收派
                String filter_result = "";
                String orderid = "";//业务订单号
                String mailno = "";//顺丰运单号
                String destCode = "";//目的地区域代码
                //错误代对应的文字
                Document redoc = doc.selectSingleNode("/Response/Body/Orderresponse").getDocument();
                Element root = redoc.getRootElement();
                List<?> child = root.elements();
                for (Object o : child) {
                    Element e = (Element) o;
                    filter_result = e.attributeValue("filter_result");
                    orderid = e.attributeValue("orderid");
                    mailno = e.attributeValue("mailno");
                    destCode = e.attributeValue("destCode");
                }
                if(StringUtils.isBlank(mailno)){
                    logger.info("顺丰快递下订单失败:未获取到快递单号!"+sfexpress_obj.getOutpatientId());
                    return true;
                }
                if(StringUtils.isNotBlank(filter_result) && "3".equals(filter_result)){
                    logger.info("顺丰快递下订单失败:派送地址不可派送,处方编号:"+sfexpress_obj.getOutpatientId());
                    return true;
                }
                sfexpress_obj.setMailno(mailno);
                sfexpress_obj.setCityCode(destCode);
            }
            //如果成功获取到快递单号,则保存处方物流记录,保存配送日志
            //修改处方状态为配送中
            prescriptionDao.updateStatus(sfexpress_obj.getOutpatientId(),65);
            //保存处方物流记录
            prescriptionExpressageDao.save(sfexpress_obj);
            //保存配送日志
            WlyyOutpatientExpressageLogDO outpatiExpressLog = new WlyyOutpatientExpressageLogDO();
            outpatiExpressLog.setOutpatientId(sfexpress_obj.getOutpatientId());
            outpatiExpressLog.setId(UUID.randomUUID().toString());
            outpatiExpressLog.setType(8);
            outpatiExpressLog.setCreateTime(new Date());
            outpatiExpressLog.setFlag(1);
            outpatiExpressLog.setStatus(100);
            outpatientExpressageLogDao.save(outpatiExpressLog);
        }catch (Exception ex){
            logger.info("顺丰快递下订单失败:派送地址不可派送,处方编号:"+sfexpress_obj.getOutpatientId());
            //如果订单处理失败,则可以继续下单
            go_on = true;
        }
        return go_on;
    }
    public boolean sfOrderSearchServiceJustSearch(WlyyPrescriptionExpressageDO sfexpress_obj)  throws Exception{
        String xml = SFUtils.sfOrderSearchService(sfexpress_obj.getId(),sf_code);
        String re = this.SFExpressPost(xml);
        boolean reslut = false;
        try {
            //xml验证
            verificationResponXml(re,"订单处理失败!");
            Document doc = DocumentHelper.parseText(re);
            String headvalue = doc.selectSingleNode("/Response/Head").getText();
            if(StringUtils.isNotBlank(headvalue) && "OK".equals(headvalue)) {
                Element root = doc.getRootElement();
                if (root.element("Body") != null)     //包含OrderResponse节点
                {
                    root = root.element("Body");
                }
                //是否能派送:1:人工确认;2:可收派;3:不可以收派
                String filter_result = "";
                String orderid = "";//业务订单号
                String mailno = "";//顺丰运单号
                List<?> child = root.elements();
                for (Object o : child) {
                    Element e = (Element) o;
                    filter_result = e.attributeValue("filter_result");
                    orderid = e.attributeValue("orderid");
                    mailno = e.attributeValue("mailno");
                }
                if(StringUtils.isNotBlank(filter_result) && "3".equals(filter_result)){
                    logger.info("顺丰快递下订单失败:派送地址不可派送,处方编号:"+sfexpress_obj.getOutpatientId());
                    throw new Exception("顺丰快递下订单失败:派送地址不可派送");
                }
                if(StringUtils.isBlank(mailno)){
                    logger.info("顺丰快递下订单失败:未获取到快递单号!"+sfexpress_obj.getOutpatientId());
                    throw new Exception("顺丰快递下订单失败:未获取到快递单号!");
                }
            }
        }catch (Exception ex){
            logger.info("顺丰快递下订单失败:派送地址不可派送,处方编号:"+sfexpress_obj.getOutpatientId());
            //如果订单处理失败,则可以继续下单
            throw new Exception(ex.getMessage());
        }
        return reslut;
    }
    public String getRoutInfosSearch(WlyyPrescriptionExpressageDO sfexpress_obj)throws Exception {
        String xml = SFUtils.getRoutInfos(sfexpress_obj,sf_code);
        String re = this.SFExpressPost(xml);
        return xml;
    }
}

+ 22 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/service/WlyyExpressagePriceService.java

@ -0,0 +1,22 @@
package com.yihu.jw.hospital.prescription.service;
import com.yihu.jw.hospital.prescription.dao.WlyyExpressagePriceDao;
import com.yihu.mysql.query.BaseJpaService;
import org.springframework.stereotype.Service;
import com.yihu.jw.entity.hospital.prescription.WlyyExpressagePriceDO;
/**
 * 
 * 服务service
 * 
 * @version 
 * <pre>
 * Author	Version		Date		Changes
 * Administrator    1.0  2019年06月05日 Created
 *
 * </pre>
 * @since 1.
 */
@Service
public class WlyyExpressagePriceService extends BaseJpaService<WlyyExpressagePriceDO, WlyyExpressagePriceDao> {
}

+ 278 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/service/entrance/util/SFUtils.java

@ -0,0 +1,278 @@
package com.yihu.jw.hospital.prescription.service.entrance.util;
import com.yihu.jw.entity.base.org.BaseOrgDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionExpressageDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionInfoDO;
import com.yihu.jw.hospital.prescription.dao.PrescriptionInfoDao;
import com.yihu.jw.hospital.prescription.service.PrescriptionService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import sun.misc.BASE64Encoder;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
 * 顺丰速递接口相关的一些公用方法
 * @author huangwenjie 2017.8.2
 */
@Component
public class SFUtils {
    private static Logger logger = LoggerFactory.getLogger(SFUtils.class);
    @Autowired
    private PrescriptionService prescriptionService;
    @Autowired
    private PrescriptionInfoDao prescriptionInfoDao;
    /**
     * 生成接口校验码
     * 1.先把XML报文与checkword前后连接。
     * 2.把连接后的字符串做 MD5(16位) 编码。
     * 3.把MD5编码后的数据进行 Base64 编码,此时编码后的字符串即为校验码。
     * @param xml   xml报文
     * @param sf_check_word  接口check_word
     * @return
     */
    public String verifyCodeSFXmlStr(String xml,String sf_check_word){
        String verifyCode = xml+sf_check_word;
        verifyCode = md5EncryptAndBase64(verifyCode);
        return verifyCode;
    }
    /**
     * 查询派送地址是否属于顺丰的派送范围
     * @param d_address     派送地址
     * @param sf_code       顺丰接口接入码
     * @param orderid       订单ID
     * @param j_tel         寄方电话
     * @param j_address     寄方地址
     * @param d_tel         收方电话
     * @return
     */
    public String getSFOrderFilterXml(String d_address,String sf_code,String orderid,String j_tel,String j_address,String d_tel){
        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='OrderFilterService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<OrderFilter filter_type='1' ");
        //订单号
        if(StringUtils.isNotBlank(orderid)){
            xml.append("orderid='"+orderid+"' ");
        }
        //派送地址,必填
        xml.append("d_address='"+d_address+"'/>");
        //如果扩张字段有不为空的,则增加扩张字段参数
        if(StringUtils.isNotBlank(j_tel) ||
                StringUtils.isNotBlank(j_address)||
                    StringUtils.isNotBlank(d_tel)){
            xml.append("<OrderFilterOption ");
            //寄方电话
            if(StringUtils.isNotBlank(j_tel)){
                xml.append("j_tel='"+j_tel+"' ");
            }
            //寄方地址
            if(StringUtils.isNotBlank(j_address)){
                xml.append("j_address='"+j_address+"' ");
            }
            //收方电话
            if(StringUtils.isNotBlank(d_tel)){
                xml.append("d_tel='"+d_tel+"' ");
            }
            xml.append("/></OrderFilter>");
        }
        xml.append("</Body></Request>");
        return xml.toString();
    }
    /**
     * 向顺丰快递下订单
     * @param sfexpress_obj
     * @param hospital
     * @return
     */
    public String postSFOrderService(WlyyPrescriptionExpressageDO sfexpress_obj, BaseOrgDO hospital, String sf_code) {
        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='OrderService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<Order ");
        //订单号(快递业务号作为订单号"SF开头的为顺丰快递")
        xml.append("orderid='"+sfexpress_obj.getId()+"' ");
        /**
         * --------寄方参数------
         */
        //寄件方公司名称
        if(StringUtils.isNotBlank(hospital.getName())){
            xml.append("j_company='"+hospital.getName()+"' ");
        }
        //寄方联系人
        if(StringUtils.isNotBlank(hospital.getName())){
            xml.append("j_contact='"+hospital.getName()+"' ");
        }
        //寄件方联系电话
        if(StringUtils.isNotBlank(hospital.getMobile())){
            xml.append("j_tel='"+hospital.getMobile()+"' ");
            xml.append("j_mobile='"+hospital.getMobile()+"' ");
        }
        //寄方所在省份
        if(StringUtils.isNotBlank(hospital.getProvinceName())){
            xml.append("j_province='"+hospital.getProvinceName()+"' ");
        }
        //寄方所在城市
        if(StringUtils.isNotBlank(hospital.getCityName())){
            xml.append("j_city='"+hospital.getCityName()+"' ");
        }
        //寄方所在县/区
        if(StringUtils.isNotBlank(hospital.getTownName())){
            xml.append("j_county='"+hospital.getTownName()+"' ");
        }
        //寄件方详细地址,包括省市县/区
        if(StringUtils.isNotBlank(hospital.getAddress())){
            xml.append("j_address='"+hospital.getAddress()+"' ");
        }
        /**
         * --------收方参数------
         */
        //派送地址,必填
        xml.append("d_address='"+sfexpress_obj.getAddress()+"' ");
        //到件方单位名称,因为接口不能为空,这里默认放到件方联系人
        xml.append("d_company='"+sfexpress_obj.getName()+"' ");
        //到件方联系人
        xml.append("d_contact='"+sfexpress_obj.getName()+"' ");
        //到件方联系电话
        xml.append("d_tel='"+sfexpress_obj.getPhone()+"' ");
        //到件方手机
        if(StringUtils.isNotBlank(sfexpress_obj.getMobile())){
            xml.append("d_mobile='"+sfexpress_obj.getMobile()+"' ");
        }
        xml.append("d_province='"+sfexpress_obj.getProvinceName()+"' ");
        xml.append("d_city='"+sfexpress_obj.getCityName()+"' ");
        xml.append("d_county='"+sfexpress_obj.getTownName()+"' ");
        //是否要求通过是否手持终端;通知顺丰收派员收件:1:要求,其它为不要求
        xml.append("is_docall='1' ");
        //快件产品类别:11,医药常温,1:顺丰标快
        //付款方式:1:寄方付,2:收方付 3:第三方付
        xml.append("express_type='1' pay_method='2' >");
//        xml.append("express_type='11' pay_method='1' custid='9999999999'>");
        //根据快递物流获取门诊信息,根据门诊信息获取处方订单的药品详情
        List<WlyyPrescriptionDO> prescriptionDOList = prescriptionService.findByField("outpatientId",sfexpress_obj.getOutpatientId());
        if(CollectionUtils.isEmpty(prescriptionDOList)){
        }
        Set<String> prescriptionIdSet = new HashSet<>();
        prescriptionDOList.forEach(
               onePrescription -> {
                   prescriptionIdSet.add(onePrescription.getId());
                }
        );
        List<WlyyPrescriptionInfoDO> prescriptionInfolist = prescriptionInfoDao.queryAllByPrescriptionIdInAndDel(prescriptionIdSet,1);
        if(!prescriptionInfolist.isEmpty()){
            for (int i = 0; i < prescriptionInfolist.size(); i++) {
                xml.append("<Cargo name='"+prescriptionInfolist.get(i).getDrugName()+"' count='"+prescriptionInfolist.get(i).getQuantity()+"'></Cargo>");
            }
        }
        xml.append("</Order></Request>");
        return xml.toString();
    }
    /**
     * 顺丰路由查询
     * @param sfexpress_obj
     * @param sf_code
     * @return
     */
    public String getRoutInfos(WlyyPrescriptionExpressageDO sfexpress_obj, String sf_code) {
        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='RouteService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<RouteRequest tracking_type='1' method_type='1' ").append("tracking_number='"+sfexpress_obj.getMailno()+"' />");
        xml.append("</Body></Request>");
        return xml.toString();
    }
    /**
     * 订单结果查询接口
     * @param sfexpress_objCode
     * @param sf_code
     * @return
     */
    public String sfOrderSearchService(String sfexpress_objCode, String sf_code) {
        StringBuilder xml = new StringBuilder("<Request service='OrderSearchService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<OrderSearch orderid='"+sfexpress_objCode+"'/>");
        xml.append("</Body></Request>");
        return xml.toString();
    }
    //-----------顺丰快递验证码加密的相关方法------------------START
    public static String loadFile(String fileName) {
        InputStream fis;
        try {
            fis = new FileInputStream(fileName);
            byte[] bs = new byte[fis.available()];
            fis.read(bs);
            String res = new String(bs);
            fis.close();
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static String md5EncryptAndBase64(String str) {
        return encodeBase64(md5Encrypt(str));
    }
    private static byte[] md5Encrypt(String encryptStr) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(encryptStr.getBytes("utf8"));
            return md5.digest();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static String encodeBase64(byte[] b) {
        BASE64Encoder base64Encode = new BASE64Encoder();
        String str = base64Encode.encode(b);
        return str;
    }
    public static void main(String[] args) {
        String xml = "<Request service='OrderSearchService' lang='zh-cn'><Head>SDDF</Head><Body><OrderSearch orderid='6daa6baec5fd4b65a1b023a8b60e2e76'/></Body></Request>";
        String check_word = "ttzlgGyOQu4L";
        System.out.println(md5EncryptAndBase64(xml + check_word));
//        System.out.println(md5EncryptAndBase64("abc"));
//        System.out.println(md5EncryptAndBase64("中"));
    }
    //-----------顺丰快递验证码加密的相关方法------------------END
}

+ 100 - 0
common/common-entity/src/main/java/com/yihu/jw/entity/hospital/prescription/WlyyExpressagePriceDO.java

@ -0,0 +1,100 @@
package com.yihu.jw.entity.hospital.prescription;
import com.yihu.jw.entity.UuidIdentityEntityWithOperator;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 实体
*
* @author Administrator on  2019年06月05日
*
*/
@Entity
@Table(name = "wlyy_expressage_price")
public class WlyyExpressagePriceDO extends UuidIdentityEntityWithOperator {
    /**
	 * 起始地址名称
	 */
	private String startAddressName;
    /**
	 * 结束地址名称
	 */
	private String endAddressName;
    /**
	 * 首重
	 */
	private Integer firstWeight;
    /**
	 * 首重价格
	 */
	private Integer firstWeightPrice;
    /**
	 * 续重
	 */
	private Integer continueWeight;
    /**
	 * 续重价格
	 */
	private Integer continueWeightPrice;
	@Column(name = "start_address_name")
    public String getStartAddressName() {
        return startAddressName;
    }
    public void setStartAddressName(String startAddressName) {
        this.startAddressName = startAddressName;
    }
	@Column(name = "end_address_name")
    public String getEndAddressName() {
        return endAddressName;
    }
    public void setEndAddressName(String endAddressName) {
        this.endAddressName = endAddressName;
    }
	@Column(name = "first_weight")
    public Integer getFirstWeight() {
        return firstWeight;
    }
    public void setFirstWeight(Integer firstWeight) {
        this.firstWeight = firstWeight;
    }
	@Column(name = "first_weight_price")
    public Integer getFirstWeightPrice() {
        return firstWeightPrice;
    }
    public void setFirstWeightPrice(Integer firstWeightPrice) {
        this.firstWeightPrice = firstWeightPrice;
    }
	@Column(name = "continue_weight")
    public Integer getContinueWeight() {
        return continueWeight;
    }
    public void setContinueWeight(Integer continueWeight) {
        this.continueWeight = continueWeight;
    }
	@Column(name = "continue_weight_price")
    public Integer getContinueWeightPrice() {
        return continueWeightPrice;
    }
    public void setContinueWeightPrice(Integer continueWeightPrice) {
        this.continueWeightPrice = continueWeightPrice;
    }
}

+ 180 - 0
common/common-entity/src/main/java/com/yihu/jw/entity/hospital/prescription/WlyyOutpatientExpressageLogDO.java

@ -0,0 +1,180 @@
package com.yihu.jw.entity.hospital.prescription;
import com.yihu.jw.entity.UuidIdentityEntityWithOperator;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.Date;
/**
* 门诊物流日志表实体
*
* @author Administrator on  2019年06月05日
*
*/
@Entity
@Table(name = "wlyy_outpatient_expressage_log")
public class WlyyOutpatientExpressageLogDO extends UuidIdentityEntityWithOperator {
    /**
	 * 
	 */
	private String saasId;
    /**
	 * 门诊id 关联表wlyy_outpatient id
	 */
	private String outpatientId;
    /**
	 * 创建时间
	 */
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
	private Date createTime;
    /**
	 * 类型: -1 失效 1HIS对接 2易联众对接  3创建处方 4 审核  5付款 6 配送 7完成 8物流对接
	 */
	private Integer type;
    /**
	 * (-2 患者自己取消 -1 审核不通过 , 0 审核中, 10 审核通过/待支付 ,21支付失败  20 配药中/支付成功, 21 等待领药 ,30 配送中 ,100配送成功/已完成)
	 */
	private Integer status;
    /**
	 * 医生或者患者code
	 */
	private String userCode;
    /**
	 * 医生或者患者name
	 */
	private String userName;
    /**
	 * 1 患者 2医生
	 */
	private Integer userType;
    /**
	 * 医院id
	 */
	private String hospital;
    /**
	 * 医院名称
	 */
	private String hospitalName;
    /**
	 * 操作是否成功 1成功 0失败
	 */
	private Integer flag;
    /**
	 * 备注信息
	 */
	private String remark;
	@Column(name = "saas_id")
    public String getSaasId() {
        return saasId;
    }
    public void setSaasId(String saasId) {
        this.saasId = saasId;
    }
	@Column(name = "outpatient_id")
    public String getOutpatientId() {
        return outpatientId;
    }
    public void setOutpatientId(String outpatientId) {
        this.outpatientId = outpatientId;
    }
	@Column(name = "create_time")
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
	@Column(name = "type")
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
	@Column(name = "status")
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
	@Column(name = "user_code")
    public String getUserCode() {
        return userCode;
    }
    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }
	@Column(name = "user_name")
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
	@Column(name = "user_type")
    public Integer getUserType() {
        return userType;
    }
    public void setUserType(Integer userType) {
        this.userType = userType;
    }
	@Column(name = "hospital")
    public String getHospital() {
        return hospital;
    }
    public void setHospital(String hospital) {
        this.hospital = hospital;
    }
	@Column(name = "hospital_name")
    public String getHospitalName() {
        return hospitalName;
    }
    public void setHospitalName(String hospitalName) {
        this.hospitalName = hospitalName;
    }
	@Column(name = "flag")
    public Integer getFlag() {
        return flag;
    }
    public void setFlag(Integer flag) {
        this.flag = flag;
    }
	@Column(name = "remark")
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
}

+ 79 - 0
svr/svr-internet-hospital-entrance/src/main/java/com/yihu/jw/entrance/controller/expressage/ExpressageEndpoint.java

@ -0,0 +1,79 @@
package com.yihu.jw.entrance.controller.expressage;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionExpressageDO;
import com.yihu.jw.hospital.prescription.dao.PrescriptionDao;
import com.yihu.jw.hospital.prescription.service.PrescriptionExpressageService;
import com.yihu.jw.hospital.prescription.service.PrescriptionService;
import com.yihu.jw.restmodel.web.Envelop;
import com.yihu.jw.restmodel.web.endpoint.EnvelopRestEndpoint;
import com.yihu.jw.rm.hospital.BaseHospitalRequestMapping;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.net.URLDecoder;
import java.util.List;
@RestController
@RequestMapping(value = BaseHospitalRequestMapping.Expressage.PREFIX)
@Api(value = "门诊处方快递物流管理器", description = "门诊处方快递物流管理器", tags = {"wlyy基础服务 - 门诊处方快递物流管理服务接口"})
public class ExpressageEndpoint extends EnvelopRestEndpoint {
    private static Logger logger = LoggerFactory.getLogger(ExpressageEndpoint.class);
    @Autowired
    private PrescriptionExpressageService sfexpressService;
    @Autowired
    private PrescriptionExpressageService prescriptionExpressageService;
    private String successxml = "<Response service='RoutePushService'><Head>OK</Head></Response>";
    private String failedxml = "<Response service='RoutePushService'><Head>ERR</Head><ERROR code='-1'>系统发生数据错误或运行时异常</ERROR></Response>";
    @RequestMapping(value="/routepushservice",method = RequestMethod.POST)
    @ApiOperation("接受顺丰推送过来的路由信息")
    public Envelop SFRoutePushService (
            @ApiParam(name="content", value="入参报文") @RequestParam(value = "content",required = true) String content){
        try {
            content = URLDecoder.decode(content,"utf-8");
            logger.info("顺丰路由信息推送,xml="+content);
            sfexpressService.SFRoutePushService(content);
            return success(successxml);
        }catch (Exception e){
            logger.error("接收顺丰路由信息推送失败,入参xml:"+content);
            //日志文件中记录异常信息
            //返回接口异常信息处理结果
            return failed(failedxml);
        }
    }
    @RequestMapping(value="/sfrouteserviceSearch",method = RequestMethod.POST)
    @ApiOperation("通过门诊编号查询顺丰物流派送记录")
    public Envelop SFRouteServiceSearch(@ApiParam(name="outpatientId", value="门诊编号") @RequestParam(value = "outpatientId",required = true) String outpatientId){
        try {
            List<WlyyPrescriptionExpressageDO> expressageDOList = prescriptionExpressageService.findByField("outpatientId",outpatientId);
            if(CollectionUtils.isEmpty(expressageDOList)){
                return failed("当前门诊没有物流信息!");
            }
            WlyyPrescriptionExpressageDO sfexpress_obj = expressageDOList.get(0);
            String result  = sfexpressService.getRoutInfosSearch(sfexpress_obj);
            return success(result);
        }catch (Exception e){
            //日志文件中记录异常信息
            //返回接口异常信息处理结果
            return failed( "查询失败,"+e.getMessage());
        }
    }
}