All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.founder.sdk.service.AbsCommonService Maven / Gradle / Ivy

There is a newer version: 3.6.1.9
Show newest version
package com.founder.sdk.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.founder.config.CatalogConfig;
import com.founder.config.ChisFsiConfig;
import com.founder.core.event.FsiActionEvent;
import com.founder.core.log.MyLog;
import com.founder.sdk.exception.FuncRetCode;
import com.founder.sdk.exception.ServerException;
import com.founder.sdk.model.fileupload.*;
import com.founder.sdk.model.hsecfc.LocalQrCodeQueryRequestInputData;
import com.founder.sdk.utils.RSAEncodeUtil;
import com.founder.sdk.utils.SHACoder;
import com.founder.sdk.utils.UniqueUtil;
import com.founder.sdk.vopackage.VoFsiRequest;
import com.founder.sdk.vopackage.VoFsiResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.validation.BindingResult;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;

@RefreshScope
public abstract class AbsCommonService {

    private static final MyLog _log = MyLog.getLog(AbsCommonService.class);

    @Autowired
    ChisFsiConfig chisFsiConfig;

    @Autowired
    CatalogConfig catalogConfig;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    ApplicationEventPublisher eventPublisher;

    public abstract Object validateParams(BindingResult bindingResult);

    /**
     * 错误返回
     * @param errMsg
     * @return
     */
    public VoFsiResponse buildFail(String errMsg) {
        VoFsiResponse response = new VoFsiResponse();
        response.setInfcode(-1);
        response.setInf_refmsgid(chisFsiConfig.getFixmedins_code()+ DateUtil.format(new Date(),"yyyyMMddHHmmssSSS") + "1");
        response.setRefmsg_time(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
        response.setRespond_time(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
        response.setErr_msg(errMsg);
        return response;
    }

    /**
     * 根据httpheader组织入参
     * @param infno 交易编号
     * @param httpHeaders 消息头
     * @return
     */
    public VoFsiRequest buildRequest(String infno, HttpHeaders httpHeaders) {
        VoFsiRequest request = new VoFsiRequest();
        request.setInfno(infno);//1 infno 交易编号 字符型 4 Y 交易编号详见接口列表
        request.setMsgid(chisFsiConfig.getFixmedins_code() + DateUtil.format(new Date(),"yyyyMMddHHmmss") + infno.substring(0,3));//2 msgid 发送方报文 ID 字符型 30 Y定点医药机构编号(12)+时间(14)+顺序号(4)时间格式: yyyyMMddHHmmss
        request.setInsuplc_admdvs(httpHeaders.containsKey("insuplc_admdvs")?httpHeaders.getFirst("insuplc_admdvs"): "");//3 insuplc_admdvs 参保地医保区划 字符型 6如果交易输入中含有人员编号,此项必填, 可通过【 1101】人员信息获取交易取得
        request.setMdtrtarea_admvs(chisFsiConfig.getMdtrtarea_admvs());//4 mdtrtarea_admvs 就医地医保区划 字符型 6 Y
        request.setRecer_sys_code(chisFsiConfig.getRecer_sys_code());//5 recer_sys_code 接收方系统代码 字符型 10 Y 用于多套系统接入,区分不同系统使用
        request.setCainfo("");//6 cainfo 数字签名信息 字符型 1024
        request.setDev_no(chisFsiConfig.getDev_no());//7 dev_no 设备编号 字符型 100
        request.setDev_safe_info("");//8 dev_safe_info 设备安全信息 字符型 2000
        request.setSigntype(httpHeaders.containsKey("signtype")?httpHeaders.getFirst("signtype"):chisFsiConfig.getSigntype());//9 signtype 签名类型 字符型 10 建议使用 SM2、 SM3
        request.setInfver(chisFsiConfig.getInfver());//10 infver 接口版本号 字符型 6 Y 例如:“ V1.0”,版本号由医保下发通知。
        request.setOpter_type(httpHeaders.containsKey("opter_type")?httpHeaders.getFirst("opter_type"): chisFsiConfig.getOpter_type());//11 opter_type 经办人类别 字符型 3 Y Y 1-经办人; 2-自助终端; 3-移动终端
        request.setOpter(httpHeaders.containsKey("opter")?httpHeaders.getFirst("opter"): chisFsiConfig.getOpter());//12 opter 经办人 字符型 30 Y 按地方要求传入经办人/终端编号
        request.setOpter_name(httpHeaders.containsKey("opter_name")? URLDecoder.decode(httpHeaders.getFirst("opter_name")): chisFsiConfig.getOpter_name());//13 opter_name 经办人姓名 字符型 50 Y按地方要求传入经办人姓名/终端名称
        request.setInf_time(DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));//14 inf_time 交易时间日期时间型19 Y
        request.setFixmedins_code(chisFsiConfig.getFixmedins_code());//15 fixmedins_code定点医药机构编号字符型 12 Y
        request.setFixmedins_name(chisFsiConfig.getFixmedins_name());
        request.setSign_no("9001".equals(infno)?"":(httpHeaders.containsKey("sign_no")?httpHeaders.getFirst("sign_no"):""));//16 sign_no 签到流水号 字符型 30 通过签到【 9001】交易获取
        _log.info("根据服务器配置生成通用消息头:" + JSON.toJSONString(request));
        return request;
    }

    /**
     * 构建httpheader
     * @return
     */
    private HttpHeaders buildHeaders() {
        HttpHeaders headers = new HttpHeaders();
        String token = chisFsiConfig.getFsi_token();
        String paasid = chisFsiConfig.getFsi_passid();
        String nonce = UniqueUtil.createUniqueId();//随机字符串
        long timestamp = Instant.now().getEpochSecond();//当前时间戳
        _log.info("当前时间戳:" + timestamp);
        String signature = "";//价签结果
        try {
            signature = SHACoder.encodeSHA256(StringUtils.join(timestamp, token, nonce, timestamp).getBytes());
            _log.info("价签结果:" + signature);
        } catch (Exception e) {
            e.printStackTrace();
            _log.error("签名异常");
            throw new ServerException(FuncRetCode.ERROR_CODE_NET_ERROR);
        }
        String fsi_sign_type = chisFsiConfig.getFsi_sign_type();
        _log.info("签名验证方式:" + fsi_sign_type + "(1、tif 0、rio)");
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        if ("1".equals(fsi_sign_type)) {
            headers.add("x-tif-paasid", paasid);
            headers.add("x-tif-signature", signature);
            headers.add("x-tif-timestamp", String.valueOf(timestamp));
            headers.add("x-tif-nonce", nonce);
        } else {
            headers.add("x-rio-paasid", paasid);
            headers.add("x-rio-signature", signature);
            headers.add("x-rio-timestamp", String.valueOf(timestamp));
            headers.add("x-rio-nonce", nonce);
        }
        return headers;
    }

    /**
     * 验密组织参数
     * @param fsiRequest
     * @param header
     * @return
     */
    private VoFsiRequest buildRequest(VoFsiRequest fsiRequest, HttpHeaders header) {
        _log.debug("打印请求头:" + JSONObject.toJSONString(header));
        Object input = fsiRequest.getInput();
        _log.info("打印入參:" + input);
        String fsi_type = chisFsiConfig.getFsi_type();
        _log.info("公共參數模式:" + fsi_type + ".(1、公共参数采用本地配置 0、公共参数采用客户端传入)");
        if ("1".equals(fsi_type)){
            fsiRequest = buildRequest(fsiRequest.getInfno(),header);
            fsiRequest.setInput(input);
        }
        String infno = fsiRequest.getInfno();
        String password = header.getFirst("password");
        String signtype = header.getFirst("signtype");//request.getSigntype();
        String cainfo = fsiRequest.getCainfo();
        if (StringUtils.isBlank(signtype)) {
            _log.warn("消息头未配置signtype,系统不验签");
        } else {
            if ("2207".equals(infno) || "2207A".equals(infno) || "2304".equals(infno) || "2304A".equals(infno)) {
                _log.info("結算業務:" + infno + "开始結算嚴密。");
                cainfo = sign(signtype, password, cainfo);
                _log.info("密文:" + cainfo);
                fsiRequest.setCainfo(cainfo);
                fsiRequest.setSigntype(signtype);
            }
        }
        return fsiRequest;
    }

    /**
     * 验密算法
     * @param signtype
     * @param password
     * @param cainfo
     * @return
     */
    private String sign(String signtype, String password, String cainfo) {
        String text = password + chisFsiConfig.getFsi_token();
        _log.debug("待加密串串:" + text);
        try {
            _log.info("驗密方式:" + signtype);
            if ("RFID".equals(signtype)){
                _log.info("开始验证RFID电子凭证密码");
                cainfo = RSAEncodeUtil.encrypt(text, RSAEncodeUtil.getPublicKey(chisFsiConfig.getFsi_public_key()));
            } else if ("PRCSSC".equals(signtype)){
                _log.info("开始验证PRCSSC医保卡密码");
                cainfo = RSAEncodeUtil.encrypt(text, RSAEncodeUtil.getPublicKey(chisFsiConfig.getFsi_public_key()));
            } else if ("MOCK".equals(signtype)){
                _log.warn("MOCK不验密(只在测试环境生效)");
                cainfo = "MOCK";
            } else {
                _log.error("無效的驗密方式:" + signtype);
                cainfo = "無效的驗密方式:" + signtype;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return cainfo;
    }

    /**
     * 调医保服务
     * @param url
     * @param infno
     * @param param
     * @return
     */
    private String request(String url, String infno, String param) {
        String result = null;
        HttpHeaders headers = buildHeaders();
        HttpEntity request = new HttpEntity<>(param, headers);
        try {
            ResponseEntity response = restTemplate.postForEntity(url, request, Resource.class);
            HttpStatus statusCode = response.getStatusCode();
            _log.info("医保网关调用状态:" + statusCode);
            InputStream inputStream = Objects.requireNonNull(response.getBody()).getInputStream();
            Resource r = response.getBody();
            //result = IOUtils.toString(inputStream, "UTF-8");
            //System.out.println(result);
            if (r.isFile() || "9102".equals(infno)){
                VoFsiResponse fsiResponse = new VoFsiResponse();
                DownloadRequest requestVo = JSON.parseObject(param,DownloadRequest.class);
                String f = r.getFilename();
                if (StringUtils.isBlank(f)){
                    f = requestVo.getInput().getFsDownloadIn().getFilename();
                }
                String fileName = catalogConfig.getCatalog_path() + f;
                _log.info("文件本地保存路径:" + fileName);
                File file = new File(fileName);
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                inputStream = r.getInputStream();
                int temp;
                while ((temp = inputStream.read()) != -1) {
                    fileOutputStream.write(temp);
                }
                fileOutputStream.close();
                DownloadResponseOutputData outputData = new DownloadResponseOutputData();
                outputData.setFile_qury_no(requestVo.getInput().getFsDownloadIn().getFile_qury_no());
                outputData.setFilename(requestVo.getInput().getFsDownloadIn().getFilename());
                outputData.setFixmedins_code(requestVo.getInput().getFsDownloadIn().getFixmedins_code());
                outputData.setFilecontent(IOUtils.toByteArray(r.getInputStream()));
                fsiResponse.setCainfo(requestVo.getCainfo());
                fsiResponse.setSigntype(requestVo.getSigntype());
                fsiResponse.setErr_msg("ok");
                fsiResponse.setInfcode(0);
                fsiResponse.setInf_refmsgid(requestVo.getMsgid());
                fsiResponse.setRefmsg_time(requestVo.getInf_time());
                fsiResponse.setOutput(outputData);
                _log.info("文件流");
                result = JSON.toJSONString(fsiResponse);
            } else {
                _log.info("字符串");
                result = IOUtils.toString(inputStream, "UTF-8");
                _log.info("发布事件监听");
                try {
                    FsiActionEvent event = new FsiActionEvent(this);
                    event.setInfno(infno);
                    event.setParam(param);
                    event.setResult(result);
                    eventPublisher.publishEvent(event);
                } catch (Exception e) {
                    e.printStackTrace();
                    _log.error("事件发布失败:" + e.getMessage());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            _log.error(e,"核心异常:" + e.getMessage());
            VoFsiResponse response = buildFail(e.getMessage());
            result = JSON.toJSONString(response);
        }
        return result;
    }

    /**
     * 模式② 直接访问不需要验签
     * @param api
     * @param object
     * @return
     */
    public String request(String api, JSONObject object) {
        String param = JSON.toJSONString(object);
        _log.info("【内蒙】原始请求参数:" + param);
        String baseurl = chisFsiConfig.getFsi_baseurl();
        String url = baseurl + api;//"http://inner.getway.ylbzj.hebei.gov.cn/ebus/"
        _log.info("【内蒙】完整请求地址:" + url);
        VoFsiRequest voParam = JSONObject.parseObject(param,VoFsiRequest.class);
        String infno = voParam.getInfno();
        _log.info("【内蒙】交易代码:" + infno);
        String result = request(url,infno,param);
        _log.info("【内蒙】医保返回参数:" + result);
        return result;
    }

    /**
     * 模式① 需要封装httpheader参数,含验密
     * @param api
     * @param object
     * @param header
     * @return
     */
    public String request(String api, JSONObject object, HttpHeaders header) {
        String param = JSON.toJSONString(object);
        _log.info("【河北】原始请求参数:" + param);
        String baseurl = chisFsiConfig.getFsi_baseurl();
        String url = baseurl + api;//"http://inner.getway.ylbzj.hebei.gov.cn/ebus/"
        _log.info("【河北】完整的请求地址:" + url);
        VoFsiRequest fsiRequest = JSONObject.parseObject(param,VoFsiRequest.class);
        fsiRequest = buildRequest(fsiRequest,header);
        param = JSON.toJSONString(fsiRequest, SerializerFeature.PrettyFormat);
        _log.info("【河北】处理后请求参数:" + param);
        String infno = fsiRequest.getInfno();
        _log.info("【河北】交易代码:" + infno);
        String result = request(url,infno,param);
        _log.info("【河北】医保返回参数:" + result);
        return result;
    }

    /**
     * 电子凭证
     * @param api
     * @param inputData
     * @return
     */
    public String request(String api, LocalQrCodeQueryRequestInputData inputData) {
        String baseurl = chisFsiConfig.getFsi_baseurl();
        String url = baseurl + api;//"http://inner.getway.ylbzj.hebei.gov.cn/ebus/"
        _log.info("请求地址:" + url);
        String param = JSON.toJSONString(inputData);
        String result = request(url,"localqrcodequery",param);
        _log.info("【河北】医保返回参数:" + result);
        return result;
    }

    @Deprecated
    public String request(String api, VoFsiRequest fsiRequest, HttpHeaders header) {
        String param = JSON.toJSONString(fsiRequest);
        _log.info("原始请求参数:" + param);
        String baseurl = chisFsiConfig.getFsi_baseurl();
        String url = baseurl + api;//"http://inner.getway.ylbzj.hebei.gov.cn/ebus/"
        _log.info("请求地址:" + url);
        fsiRequest = buildRequest(fsiRequest,header);
        _log.info("处理后请求参数:" + JSON.toJSONString(fsiRequest, SerializerFeature.PrettyFormat));
        String infno = fsiRequest.getInfno();
        _log.info("交易代码:" + infno);
        String result = request(url,infno,param);
        _log.info("医保返回参数:" + result);
        return result;
    }

    @Deprecated
    public VoFsiResponse requestVo(String api, VoFsiRequest fsiRequest, HttpHeaders header) {
        String result = request(api,fsiRequest,header);
        VoFsiResponse fsiResponse = JSON.parseObject(result,VoFsiResponse.class);
        _log.info("处理后返回参数:" + JSON.toJSONString(fsiResponse, SerializerFeature.PrettyFormat));
        return fsiResponse;
    }

//    public VoFsiResponse request(String api, String infno, Object data){
//        String baseurl = chisFsiConfig.getFsi_baseurl();
//        String url = baseurl + api;//"http://inner.getway.ylbzj.hebei.gov.cn/ebus/"
//        _log.info("请求地址:" + url);
//        return null;
//    }

//    public VoFsiResponse request(String api, DownCatalog1301RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1302RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1303RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1305RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1306RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1307RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1308RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1309RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1310RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1311RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1313RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1314RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownCatalog1315RequestInputData inputData) {
//
//        return null;
//    }
//
//    public VoFsiResponse request(String api, DownloadRequestInputData inputData) {
//
//        return null;
//    }

//    /**
//     * 兼容用
//     * @param api
//     * @param jsonParam
//     * @return
//     */
//    public String request(String api, String jsonParam) {
//        VoFsiRequest fsiRequest = JSON.parseObject(jsonParam,VoFsiRequest.class);
//        VoFsiResponse fsiResponse = request(api,fsiRequest);
//        return JSON.toJSONString(fsiResponse);
//    }

//    /**
//     * 河北国家医保
//     * @param api 公开路径
//     * @param fsiRequest 完整JSON参数
//     * @return 返回封装好的对象
//     */
//    @Deprecated
//    public VoFsiResponse request(String api, VoFsiRequest fsiRequest) {
//        VoFsiResponse fsiResponse = new VoFsiResponse();
//        String jsonParam = JSON.toJSONString(fsiRequest);
//        _log.info("请求参数:" + jsonParam);
//        String baseurl = chisFsiConfig.getFsi_baseurl();
//        String url = baseurl + api;//"http://inner.getway.ylbzj.hebei.gov.cn/ebus/"
//        _log.info("请求地址:" + url);
//        HttpHeaders headers = buildHeaders();
//        org.springframework.http.HttpEntity request = new org.springframework.http.HttpEntity(jsonParam, headers);
//        try {
//            String result = "";
//            ResponseEntity response = restTemplate.postForEntity(url, request, Resource.class);
//            org.springframework.http.HttpStatus statusCode = response.getStatusCode();
//            _log.info("" + statusCode);
//            InputStream inputStream = Objects.requireNonNull(response.getBody()).getInputStream();
//            Resource r = response.getBody();
//            String f = r.getFilename();
//            if (r.isFile() || StringUtils.isNotBlank(f) || "9102".equals(fsiRequest.getInfno())){
//                if (StringUtils.isBlank(f)){
//                    if (fsiRequest.getInput() instanceof DownloadRequestInput) {
//                        DownloadRequestInput obj = (DownloadRequestInput) fsiRequest.getInput();
//                        f = obj.getFsDownloadIn().getFilename();
//                    } else if (fsiRequest.getInput() instanceof JSONObject) {
//                        JSONObject obj = (JSONObject) fsiRequest.getInput();
//                        f = obj.getJSONObject("fsDownloadIn").getString("filename");
//                    }
//                }
//                _log.info("文件流");
//                String fileName = catalogConfig.getCatalog_path() + f;
//                _log.info("文件本地保存路径:" + fileName);
//                File file = new File(fileName);
//                FileOutputStream fileOutputStream = new FileOutputStream(file);
//                int temp;
//                while ((temp = inputStream.read()) != -1) {
//                    fileOutputStream.write(temp);
//                }
//                fileOutputStream.close();
//                DownloadRequest requestVo = JSON.parseObject(jsonParam,DownloadRequest.class);
//                DownloadResponse rep = new DownloadResponse();
//                rep.getOutput().getData().setFile_qury_no(requestVo.getInput().getFsDownloadIn().getFile_qury_no());
//                rep.getOutput().getData().setFilename(requestVo.getInput().getFsDownloadIn().getFilename());
//                rep.getOutput().getData().setFixmedins_code(requestVo.getInput().getFsDownloadIn().getFixmedins_code());
//                rep.getOutput().getData().setFilecontent(IOUtils.toByteArray(r.getInputStream()));
//                rep.setCainfo(fsiRequest.getCainfo());
//                rep.setSigntype(fsiRequest.getSigntype());
//                rep.setErr_msg("ok");
//                rep.setInfcode(0);
//                rep.setInf_refmsgid(fsiRequest.getMsgid());
//                rep.setRefmsg_time(fsiRequest.getInf_time());
//                result = JSON.toJSONString(rep);
//            } else {
//                _log.info("字符串");
//                result = IOUtils.toString(inputStream, "UTF-8");
//            }
//            _log.info(result);
//            fsiResponse = JSON.parseObject(result,VoFsiResponse.class);
//        } catch (IOException e) {
//            e.printStackTrace();
//            _log.error(e,e.getMessage());
//            fsiResponse = null;
//        }
//        return fsiResponse;
//    }

    public static  Predicate distinctByKey(Function keyExtractor) {
        Map seen = new ConcurrentHashMap<>();
        System.out.println("这个函数将应用到每一个item");
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy