Przeglądaj źródła

feature : init project

szyx-insurance-payment-no_db_version
王昱 2 miesięcy temu
rodzic
commit
cf7af9f55a
41 zmienionych plików z 5011 dodań i 0 usunięć
  1. +30
    -0
      pom.xml
  2. +6
    -0
      src/main/java/com/szyx/tcm/supervision/config/HttpConfig.java
  3. +78
    -0
      src/main/java/com/szyx/tcm/supervision/config/InsuranceInterceptor.java
  4. +35
    -0
      src/main/java/com/szyx/tcm/supervision/config/WebAppConfigAdapter.java
  5. +78
    -0
      src/main/java/com/szyx/tcm/supervision/constant/WeChatInsurancePayConstant.java
  6. +119
    -0
      src/main/java/com/szyx/tcm/supervision/controller/insurance/HealthInsuranceController.java
  7. +66
    -0
      src/main/java/com/szyx/tcm/supervision/controller/insurance/ProxyController.java
  8. +54
    -0
      src/main/java/com/szyx/tcm/supervision/enums/BannerEnum.java
  9. +66
    -0
      src/main/java/com/szyx/tcm/supervision/enums/ResultEnum.java
  10. +67
    -0
      src/main/java/com/szyx/tcm/supervision/enums/WeekDayEnum.java
  11. +68
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/DiseInfo.java
  12. +131
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/FeeDetail.java
  13. +82
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceAccessTokenRep.java
  14. +30
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceAccessTokenReq.java
  15. +80
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreCommonInputMessage.java
  16. +41
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreCommonOutputMessage.java
  17. +55
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreInputMessage1101.java
  18. +288
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreOutputMessage1101.java
  19. +55
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceGetOrderReq.java
  20. +56
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceMiddleGroundInputMessage.java
  21. +76
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceMiddleGroundOutputMessage.java
  22. +67
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsurancePayOrderInputMessage.java
  23. +65
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsurancePayOrderOutputMessage.java
  24. +80
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceRep.java
  25. +32
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceReq.java
  26. +297
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceUploadRecipeDetailInputMessage.java
  27. +43
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceUploadRecipeDetailOutputMessage.java
  28. +49
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UnifiedOrderRep.java
  29. +68
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UnifiedOrderReq.java
  30. +25
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UserLongitudeLatitude.java
  31. +29
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UserQueryReq.java
  32. +325
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/WechatUnifiedOrderReq.java
  33. +38
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/core/SignIn.java
  34. +32
    -0
      src/main/java/com/szyx/tcm/supervision/model/dto/insurance/core/Signinoutb.java
  35. +102
    -0
      src/main/java/com/szyx/tcm/supervision/service/manager/ClientDemo.java
  36. +1015
    -0
      src/main/java/com/szyx/tcm/supervision/service/manager/HealthInsuranceManager.java
  37. +585
    -0
      src/main/java/com/szyx/tcm/supervision/util/DateUtils.java
  38. +192
    -0
      src/main/java/com/szyx/tcm/supervision/util/InsuranceWechatUtil.java
  39. +187
    -0
      src/main/java/com/szyx/tcm/supervision/util/SZYXAccessUtil.java
  40. +4
    -0
      src/main/resources/application.properties
  41. +215
    -0
      src/test/java/com/szyx/tcm/supervision/InsuranceCoreDemo.java

+ 30
- 0
pom.xml Wyświetl plik

@@ -195,6 +195,36 @@
<version>${fastjson.version}</version>
</dependency>

<!-- ========================== start 只医保中台sdk =========================== -->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>


<dependency>
<groupId>com.tencent.mip</groupId>
<artifactId>med-request-data-sdk</artifactId>
<version>2.1.2</version>
</dependency>

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>

<!-- ========================== end 只医保中台sdk =========================== -->

<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spring-boot-starter</artifactId>
<version>3.7.2</version>
</dependency>


<!-- api doc -->

<dependency>


+ 6
- 0
src/main/java/com/szyx/tcm/supervision/config/HttpConfig.java Wyświetl plik

@@ -4,6 +4,7 @@ import org.asynchttpclient.DefaultAsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/*******************************************************************
* <pre></pre>
@@ -26,5 +27,10 @@ public class HttpConfig {
new DefaultAsyncHttpClientConfig.Builder().setMaxRequestRetry(3).setConnectTimeout(1000).setFollowRedirect(false).setMaxConnections(100).setMaxConnectionsPerHost(10).build());
}

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}


}

+ 78
- 0
src/main/java/com/szyx/tcm/supervision/config/InsuranceInterceptor.java Wyświetl plik

@@ -0,0 +1,78 @@
package com.szyx.tcm.supervision.config;

import com.fiftyonetrust.common.model.exception.CodeException;
import com.szyx.tcm.supervision.enums.ResultEnum;
import com.szyx.tcm.supervision.util.SZYXAccessUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceInterceptor.java
* @包 路 径: com.szyx.tcm.supervision.config
* @Copyright:wy (C) 2024 *
* @Description: 医保系统拦截器 只用满足鉴权的请求才能访问
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/26 16:13
* @Modify:
*/
@Slf4j
@Component
public class InsuranceInterceptor implements HandlerInterceptor {


public static void main(String[] args) {
long timestamp = System.currentTimeMillis();
System.out.println(SZYXAccessUtil.encryptTimeStamp(timestamp));
System.out.println(SZYXAccessUtil.encryptByAES(Long.toString(timestamp)));
}

@Value("${insurance.host}")
private String targetUrl;



@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String requestUrl = request.getRequestURL().toString();
// 医保回调的直接转发
if (requestUrl.startsWith(targetUrl)) {
// If the request URL starts with targetUrl, bypass the interceptor
return true;
}

// 其他请求一律进行请求头校验
String timeStamp = request.getHeader("timestamp");
String accessToken = request.getHeader("accessToken");

if ( StringUtils.isBlank(timeStamp) || StringUtils.isBlank(accessToken) ) {
throw new CodeException(ResultEnum.VERIFY_ERROR.getCode(), ResultEnum.VERIFY_ERROR.getMessage());
}

if(!SZYXAccessUtil.verifyTimeStamp(timeStamp, accessToken)){
throw new CodeException(ResultEnum.VERIFY_ERROR.getCode(), ResultEnum.VERIFY_ERROR.getMessage());
}


return HandlerInterceptor.super.preHandle(request, response, handler);
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

+ 35
- 0
src/main/java/com/szyx/tcm/supervision/config/WebAppConfigAdapter.java Wyświetl plik

@@ -0,0 +1,35 @@
package com.szyx.tcm.supervision.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;

/*******************************************************************
* <pre></pre>
* @文件名称: WebAppConfigAdapter.java
* @包 路 径: com.szyx.tcm.supervision.config
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/26 18:05
* @Modify:
*/
@Configuration
public class WebAppConfigAdapter implements WebMvcConfigurer {

@Resource
private InsuranceInterceptor insuranceInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {

// 走代理转发的接口添加拦截器
registry.addInterceptor(insuranceInterceptor)
.addPathPatterns("/proxy/**");

WebMvcConfigurer.super.addInterceptors(registry);
}
}

+ 78
- 0
src/main/java/com/szyx/tcm/supervision/constant/WeChatInsurancePayConstant.java Wyświetl plik

@@ -0,0 +1,78 @@
package com.szyx.tcm.supervision.constant;

/*******************************************************************
* <pre></pre>
* @文件名称: WeChatInsurancePayConstant.java
* @包 路 径: com.szyx.tcm.common.constant
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/24 14:09
* @Modify:
*/
public interface WeChatInsurancePayConstant {

// ================= 医保核心系统有关 ===========================

/**
* 系统版本号
*/
String INSURANCE_CORE_SYSTEM_VERSION = "V1.0";

/**
* 接收方系统代码
*/
String INSURANCE_CORE_RECEIVER_SYS_CODE = "SH_CLOUD";


/**
* 医保核心交易报文ID 【9001】签到
*/
String INSURANCE_CORE_MSG_ID_SIGN_IN = "9001";



/**
* 医保核心交易报文ID 【1101】人员基本信息获取
*/
String INSURANCE_CORE_BASIC_INFO = "1101";








// ================= 医保支付中台有关 ===========================

/**
* feeType 费用类型 05 互联网医院问诊
*/
String INSURANCE_PAY_FEE_TYPE = "05";












// ================= 微信医保支付平台有关 ===========================











}

+ 119
- 0
src/main/java/com/szyx/tcm/supervision/controller/insurance/HealthInsuranceController.java Wyświetl plik

@@ -0,0 +1,119 @@
package com.szyx.tcm.supervision.controller.insurance;

import com.fiftyonetrust.common.model.result.R;
import com.szyx.tcm.supervision.model.dto.insurance.*;
import com.szyx.tcm.supervision.model.dto.insurance.core.Signinoutb;
import com.szyx.tcm.supervision.service.manager.HealthInsuranceManager;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/*******************************************************************
* <pre></pre>
* @文件名称: HealthInsurenceController.java
* @包 路 径: com.szyx.tcm.web.patient.controller.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 10:12
* @Modify:
*/
@RestController
@RequestMapping("/insurance")
public class HealthInsuranceController {

@Resource
private HealthInsuranceManager healthInsuranceManager;


// 1 根据购药单id生成小程序医保授权链接
@GetMapping("/getAuthUrl/{platformOrderId}")
@ApiOperation(value = "生成小程序医保授权链接")
public R<String> getAuthUrl(@PathVariable("platformOrderId") String medicineOrderId) {
return R.ok(healthInsuranceManager.getAuthUrl(medicineOrderId));
}


// 2 河南医保平台下单,获取订单医保分账

@PostMapping("/getOrder")
@ApiOperation(value = "河南医保平台下单,获取订单医保分账")
public R<InsurancePayOrderOutputMessage> getOrder(@RequestBody InsuranceGetOrderReq req) {
return R.ok(healthInsuranceManager.getOrder(req));
}

// 3 根据医保平台下单分账信息,确认支付,微信统一下单
@PostMapping("/confirmPay")
@ApiOperation(value = "根据医保平台下单分账信息,确认支付,微信统一下单")
public R<UnifiedOrderRep> confirmPay(@RequestBody UnifiedOrderReq req) {
return R.ok(healthInsuranceManager.confirmPay(req));
}



// 根据授权码查询用户的医保电子凭证信息
@PostMapping("/getInsuranceInfo")
@ApiOperation(value = "根据授权码查询用户的医保电子凭证信息")
public R<InsuranceRep> getInsuranceInfo(@RequestBody InsuranceReq req) {
return R.ok(healthInsuranceManager.getInsuranceInfo(req));
}

// 省医保核心系统「9001」 接口签到获取流水号 ,后续接口调用前需先调用此接口获取流水号
@PostMapping("/getSerialNumber")
@ApiOperation(value = "接口签到获取流水号")
public R getSerialNumber() {
return R.ok(healthInsuranceManager.getSerialNumber());
}


// 省医保核心系统「1101」获取医保人员基础信息
@PostMapping("/getBasicInsuranceInfo")
@ApiOperation(value = "获取医保人员基础信息")
public R getBasicInsuranceInfo() {
return R.ok(healthInsuranceManager.getBasicInsuranceInfo(new Signinoutb()));
}


// 省医保平台「6201」上传处方药费明细
@PostMapping("/uploadRecipeDetail")
@ApiOperation(value = "上传处方药费明细")
public R uploadRecipeDetail() {
return R.ok(healthInsuranceManager.uploadRecipeDetail(new InsuranceGetOrderReq(), new InsuranceRep(), new InsuranceCoreOutputMessage1101()));
}


// 省医保平台「6202」支付下单
@PostMapping("/payOrder")
@ApiOperation(value = "支付下单")
public R payOrder() {
return R.ok(healthInsuranceManager.payOrder(new InsuranceGetOrderReq() , new InsuranceRep(), new InsuranceUploadRecipeDetailOutputMessage()));
}


//获取微信医保移动支付access_token 服务商获取方式
@PostMapping("/getInsuranceAccessToken")
@ApiOperation(value = "获取微信医保移动支付access_token")
public R<InsuranceAccessTokenRep> getInsuranceAccessToken(@RequestBody InsuranceAccessTokenReq req) {
return R.ok(healthInsuranceManager.InsuranceAccessToken(req));
}


// 微信医保平台统一下单
@PostMapping("/unifiedOrder")
@ApiOperation(value = "统一下单")
public R unifiedOrder() throws Exception {
return R.ok(healthInsuranceManager.unifiedOrder(new UnifiedOrderReq()));
}


// 读取当前配置信息
@GetMapping("/getInsuranceConfig")
@ApiOperation(value = "读取当前配置信息")
public R getInsuranceConfig() {
return R.ok(healthInsuranceManager.getInsuranceConfig());
}


}

+ 66
- 0
src/main/java/com/szyx/tcm/supervision/controller/insurance/ProxyController.java Wyświetl plik

@@ -0,0 +1,66 @@
package com.szyx.tcm.supervision.controller.insurance;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Objects;

/*******************************************************************
* <pre></pre>
* @文件名称: ProxyController.java
* @包 路 径: com.szyx.tcm.supervision.controller.insurance
* @Copyright:wy (C) 2024 *
* @Description: 用于进行代理转发 所有从云端系统过来的请求都会经过这个controller
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/26 17:34
* @Modify:
*/
@RestController
@RequestMapping("/proxy")
public class ProxyController {

@Value("${insurance.host}")
private String targetUrl;

@Value("${server.servlet.context-path}")
private String contextPath;


private final RestTemplate restTemplate;


public ProxyController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}


@RequestMapping("/**")
public ResponseEntity<String> proxyRequest(HttpServletRequest request, @RequestBody(required = false) String body) {
String url = targetUrl + request.getRequestURI().substring(("/" + contextPath + "/proxy").length());

HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.add(headerName, request.getHeader(headerName));
}

HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(url, Objects.requireNonNull(HttpMethod.resolve(request.getMethod())), entity, String.class);

return new ResponseEntity<>(response.getBody(), responseHeaders,response.getStatusCode());
}



}

+ 54
- 0
src/main/java/com/szyx/tcm/supervision/enums/BannerEnum.java Wyświetl plik

@@ -0,0 +1,54 @@
package com.szyx.tcm.supervision.enums;

/**
* @author cj
*/
public enum BannerEnum {

/**
* banner 状态
*/

PUBLISH(0,"已发布"),
RELEASED(1,"待发布"),
REVOKED(2,"已撤销"),
EXPIRED(3,"已过期"),

PERMANENT(4,"永久");


/**
* 字典类型
*/
private Integer code;

/**
* 字典名称
*/
private String name;




public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

BannerEnum(Integer code, String name){
this.code=code;
this.name=name;
}

}

+ 66
- 0
src/main/java/com/szyx/tcm/supervision/enums/ResultEnum.java Wyświetl plik

@@ -0,0 +1,66 @@
package com.szyx.tcm.supervision.enums;

import com.fiftyonetrust.common.model.pojo.ResultCode;

/**
* <pre></pre>
*
* @文件名称: ResultEnum
* @包 路 径: enums
* @Copyright:北京数字医信科技责任有限公司 (C) 2023 *
* @Description:
* @Version: V1.0
* @Author: hq
* @Date: 2023/08/22 11:01
* @Modify:
*/
public enum ResultEnum implements ResultCode {

FREIGHT_SETTING_ERROR(20001, "获取二维码失败"),
UN_LOGIN_ERROR(20002, "未登录"),
TOKEN_EXPIRED_ERROR(20003, "登录已过期,请重新登录"),
DOCTOR_NOT_EXIST(20004, "账号未绑定!"),
SELECT_ERROR(20005, "查询失败"),
VERIFY_SIGNED_ERR(20006, "验证第三方签名摘要信息signed失败"),
RECIPE_SIGN_NO_EXIST(20007, "处方签名数据不存在"),
YWX_SYN_SIGN(20008, "调用医网信同步待签名数据失败"),
RECIPE_SIGN_UPDATE_ERROR(20009, "处方签名数据更新失败"),
HOS_SIGN_INSERT_ERROR(20010, "医院签章数据插入失败"),
RECIPE_HOSPITAL_SIGN_ERROR(20011, "处方互联网医院签章操作未找到医生已签数据"),
PDF_DOWNLOAD_ERROR(20012, "pdf下载失败"),
PDF_UPLOAD_ERROR(20013, "pdf上传失败"),
RECIPE_PATIENT_NOT_EXIST(20014, "处方患者信息不存在"),
PARAMS_ERROR(20015, "参数异常"),
PDF_PAGES_ERROR(20016, "pdf获取页数异常"),
UPDATE_RECIPE_ERROR(20017, "同步pdf到同仁堂失败"),
UNIQUE_ID_NO_EXIST(20018, "回调signId参数为空"),
SIGNED_PDF_BASE64_NO_EXIST(20019, "回调pdfBase64为空"),
OPEN_ID_NO_EXIST(20020, "openID为空"),
ADD_SIGN_IMAGE(20021,"添加签名图片异常"),
ADD_STAMP_IMAGE(20022,"添加签章图片异常"),

DECRYPT_ERROR(10055, "解密异常"),

REPETITION_ERROR(10056, "请勿重复操作"),

VERIFY_ERROR(10057, "鉴权失败,请检查请求头参数"),
;

private final Integer code;
private final String message;

ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
}

@Override
public int getCode() {
return this.code;
}

@Override
public String getMessage() {
return this.message;
}
}

+ 67
- 0
src/main/java/com/szyx/tcm/supervision/enums/WeekDayEnum.java Wyświetl plik

@@ -0,0 +1,67 @@
package com.szyx.tcm.supervision.enums;

import lombok.Getter;

/**
* <pre></pre>
*
* @文件名称: WeekDayEnum
* @包 路 径: com.szyx.tcm.common.enums
* @Copyright:北京数字医信科技责任有限公司 (C) 2023 *
* @Description:
* @Version: V1.0
* @Author: luzhenjie
* @Date:2023/6/1 12:03
* @Modify:
*/
@Getter
public enum WeekDayEnum {

SUNDAY(1, "SUNDAY", "周日",7),
MONDAY(2, "MONDAY", "周一",1),
TUESDAY(3, "TUESDAY", "周二",2),
WEDNESDAY(4, "WEDNESDAY", "周三",3),
THURSDAY(5, "THURSDAY", "周四",4),
FRIDAY(6, "FRIDAY", "周五",5),
SATURDAY(7, "SATURDAY", "周六",6);

private final Integer code;
private final String name;
private final String desc;
//
private final Integer index;

WeekDayEnum(int code, String name, String desc, Integer index) {
this.code = code;
this.name = name;
this.desc = desc;
this.index = index;
}

public static String getByCode(Integer code) {
for (WeekDayEnum statusEnum : WeekDayEnum.values()) {
if (statusEnum.getCode().equals(code)) {
return statusEnum.desc;
}
}
return "";
}

public static String getByName(String name) {
for (WeekDayEnum statusEnum : WeekDayEnum.values()) {
if (statusEnum.getName().equals(name)) {
return statusEnum.desc;
}
}
return "";
}

public static Integer getIndexByCode(Integer code) {
for (WeekDayEnum statusEnum : WeekDayEnum.values()) {
if (statusEnum.getCode().equals(code)) {
return statusEnum.index;
}
}
return null;
}
}

+ 68
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/DiseInfo.java Wyświetl plik

@@ -0,0 +1,68 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: DiseInfoList.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/17 14:52
* @Modify:
*/
@Data
@ApiModel("省医保平台「6201」上传处方药费明细请求参数诊断或症状明细")
public class DiseInfo {

/**
* diagType 诊断类别 字符型 3 Y 字典诊断类别(diag_type)
* 1 西医主要诊断 3 中医主病诊断
* 2 西医其他诊断 4 中医主证诊断
*/
private String diagType;

/**
* diagSrtNo 诊断排序号 数值型 2 Y
*/
private Integer diagSrtNo;

/**
* diagCode 诊断代码 字符型 20 Y
*/
private String diagCode;

/**
* diagName 诊断名称 字符型 100 Y
*/
private String diagName;

/**
* diagDept 诊断科室 字符型 50 Y
*/
private String diagDept;

/**
* diseDorNo 诊断医生编码 字符型 30 Y
*/
private String diseDorNo;

/**
* diseDorName 诊断医生姓名 字符型 50 Y
*/
private String diseDorName;

/**
* diagTime 诊断时间 字符型 19 Y yyyy-MM-dd HH:mm:ss
*/
private String diagTime;

/**
* valiFlag 有效标志 字符型 3 Y
*/
private String valiFlag;

}

+ 131
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/FeeDetail.java Wyświetl plik

@@ -0,0 +1,131 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.math.BigDecimal;

/*******************************************************************
* <pre></pre>
* @文件名称: FeeDetailList.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/17 14:57
* @Modify:
*/
@Data
@ApiModel("省医保平台「6201」上传处方药费明细请求参数费用明细")
public class FeeDetail {

/**
* feedetlSn 费用明细流水号 字符型 30 Y 单次就诊内唯一
*/
private String feedetlSn;

/**
* mdtrtId 就诊ID 字符型 30 N
*/
private String mdtrtId;

/**
* psnNo 人员编号 字符型 30 Y
*/
private String psnNo;

/**
* chrgBchno 收费批次号 字符型 30 Y 同一收费批次号病种编号必须一致
*/
private String chrgBchno;

/**
* diseCodg 病种编码 字符型 30 N 按照标准编码填写:
* 按病种结算病种目录代码(bydise_setl_list_code)、
* 门诊慢特病病种目录代码(opsp_dise_cod)
*/
private String diseCodg;

/**
* rxno 处方号 字符型 30 N 外购处方时,传入外购处方的处方号;非外购处方,传入医药机构处方号
*/
private String rxno;

/**
* rxCircFlag 外购处方标志 字符型 3 Y
*/
private String rxCircFlag;

// yyyy-MM-dd HH:mm:ss
/**
* feeOcurTime 费用发生时间 日期时间型 Y yyyy-MM-dd HH:mm:ss
*/
private String feeOcurTime;

/**
* medListCodg 医疗目录编码 字符型 50 Y
*/
private String medListCodg;

/**
* medinsListCodg 医药机构目录编码 字符型 150 Y
*/
private String medinsListCodg;

/**
* detItemFeeSumamt 明细项目费用总额 数值型 16,2 Y
*/
private BigDecimal detItemFeeSumamt;

/**
* cnt 数量 数值型 16,4 Y
*/
private BigDecimal cnt;

/**
* pric 单价 数值型 16,6 Y
*/
private BigDecimal pric;

/**
* bilgDeptCodg 开单科室编码 字符型 30 Y
*/
private String bilgDeptCodg;

/**
* bilgDeptName 开单科室名称 字符型 100 Y
*/
private String bilgDeptName;

/**
* bilgDrCodg 开单医生编码 字符型 30 Y 按照标准编码填写
*/
private String bilgDrCodg;

/**
* bilgDrName 开单医师姓名 字符型 50 Y
*/
private String bilgDrName;

/**
*hospApprFlag 医院审批标志 字符型 3 Y
*/
private String hospApprFlag;

/**
* medType 医疗类别 字符型 6 Y
*/
private String medType;

/**
* medListName 医疗目录名称 字符型 50 Y
*/
private String medListName;

/**
* medListSpc 医疗目录规格 字符型 50 Y
*/
private String medListSpc;

}

+ 82
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceAccessTokenRep.java Wyświetl plik

@@ -0,0 +1,82 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceAccessTokenRep.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 11:31
* @Modify:
*/
@Data
@ApiModel("获取AccessToken")
public class InsuranceAccessTokenRep {

/**
* return_code
* 返回状态码
* string16
* Y
* SUCCESS/FAIL
*/
private String returnCode;

/**
* return_msg
* return_msg
* string128
* N
* 返回信息,如非空,为错误原因
*/
private String returnMsg;


/**
* result_code
* 业务结果
* String16
* Y
* SUCCESS/FAIL
*/
private String resultCode;

/**
* err_code
* 错误代码
* String32
* N
*/
private String errCode;

/**
* err_code_des
* 错误代码描述
* String128
* N
*/
private String errCodeDes;

/**
* access_token
* 获取到的凭证
* String256
* Y
*/
private String accessToken;

/**
* expires_in
* 凭证有效时间
* Uint32
* Y
* 单位:秒
*/
private Integer expiresIn;

}

+ 30
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceAccessTokenReq.java Wyświetl plik

@@ -0,0 +1,30 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceAccessTokenReq.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 11:26
* @Modify:
*/
@Data
@ApiModel("获取用户医保参数")
public class InsuranceAccessTokenReq {

private String grant_type = "client_credential";

private String agentappid;

private String agentsecret;

private String appid;


}

+ 80
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreCommonInputMessage.java Wyświetl plik

@@ -0,0 +1,80 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceCoreCommonMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 河南医保核心系统公共报文 v1.4
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 10:18
* @Modify:
*/
@Data
public class InsuranceCoreCommonInputMessage {

// infno 交易编号 字符型 4 Y 交易编号详见接口列表
private String infno;

// msgid 发送方报文ID 字符型 30 Y 定点医药机构编号(12)+时间(14)+顺序号(4)
//时间格式:yyyyMMddHHmmss
private String msgid;

// mdtrtarea_admvs 就医地医保区划 字符型 6 Y
private String mdtrtareaAdmvs;

// insuplc_admdvs 参保地医保区划 字符型 6 如果交易输入中含有人员编号,此项必填,可通过【1101】人员信息获取交易取得
private String insuplcAdmdvs;

// recer_sys_code 接收方系统代码 字符型 10 Y 用于多套系统接入,区分不同系统使用
private String recerSysCode;

// dev_no 设备编号 字符型 100
private String devNo;

// dev_safe_info 设备安全信息 字符型 2000
private String devSafeInfo;

// cainfo 数字签名信息 字符型 1024
private String cainfo;

// signtype 签名类型 字符型 10 建议使用SM2、SM3
private String signtype;

// infver 接口版本号 字符型 6 Y 例如:“V1.0”,版本号由医保下发通知。
private String infver;

// opter_type 经办人类别 3 Y Y 1-经办人;2-自助终端;3-移动终端
private String opterType;

// opter 经办人 字符型 20 Y 按地方要求传入经办人/终端编号
private String opter;

// opter_name 经办人姓名 字符型 50 Y 按地方要求传入经办人姓名/终端名称
private String opterName;

// inf_time 交易时间 日期时间型 19 Y
private String infTime;

// fixmedins_code 定点医药机构编号 字符型 12 Y
private String fixmedinsCode;

// fixmedins_name 定点医药机构名称 字符型 20 Y
private String fixmedinsName;

// sign_no 交易签到流水号 字符型 30 通过签到【9001】交易获取
private String signNo;

// input 交易输入 字符型 40000 Y
private String input;







}

+ 41
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreCommonOutputMessage.java Wyświetl plik

@@ -0,0 +1,41 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceCoreCommonOutputMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 河南医保核心系统公共报文 v1.4
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 10:27
* @Modify:
*/
@Data
public class InsuranceCoreCommonOutputMessage {

// infcode 交易状态码 数值型 4 Y
private Integer infcode;

// inf_refmsgid 接收方报文ID 字符型 30 Y 接收方返回,接收方医保区划代码(6)+时间(14)+流水号(10)
//时间格式:yyyyMMddHHmmss
private String infRefmsgid;

// refmsg_time 接收报文时间 字符型 17 格式:yyyyMMddHHmmssSSS
private String refmsgTime;

// respond_time 响应报文时间 字符型 17 格式:yyyyMMddHHmmssSSS
private String respondTime;

// err_msg 错误信息 字符型 200 交易失败状态下,业务返回的错误信息
private String errMsg;

// output 交易输出 字符型 40000
private String output;




}

+ 55
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreInputMessage1101.java Wyświetl plik

@@ -0,0 +1,55 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceCoreInputMessage1101.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 1101 输入报文
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 14:12
* @Modify:
*/
@Data
public class InsuranceCoreInputMessage1101 {

/**
* mdtrt_cert_type 就诊凭证类型 字符型 3 Y Y
*/
private String mdtrtCertType;

/**
* mdtrt_cert_no 就诊凭证号码 字符型 50 Y Y
*/
private String mdtrtCertNo;

/**
* card_sn 卡识别码 字符型 32 就诊凭证类型为“03”时必填
*/
private String cardSn;

/**
* begntime 开始时间 日期时间型 获取历史参保信息时传入
*/
private String begntime;

/**
* psn_cert_type 人员证件类型 字符型 6 Y 就诊凭证类型为“01”和“03”时必填
*/
private String psnCertType;

/**
* certno 证件号码 字符型 50 就诊凭证类型为“01”和“03”时必填
*/
private String certno;

/**
* psn_name 人员姓名 字符型 50 Y
*/
private String psnName;


}

+ 288
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceCoreOutputMessage1101.java Wyświetl plik

@@ -0,0 +1,288 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;

import java.math.BigDecimal;
import java.util.List;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceCoreOutputMessage1101.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 14:23
* @Modify:
*/
@Data
public class InsuranceCoreOutputMessage1101 {

/**
* 输出-基本信息
*/
private Baseinfo baseinfo;

/**
* 输出-参保信息列表
*/
private Insuinfo insuinfo;

/**
* 输出-身份信息列表
*/
private List<Idetinfo> idetinfo;


@Data
public static class Baseinfo{
/**
* psn_no 人员编号 字符型 30 Y
*/
@JSONField(name = "psn_no")
private String psnNo;

/**
* psn_cert_type 人员证件类型 字符型 6 Y Y
*/
@JSONField(name = "psn_cert_type")
private String psnCertType;

/**
* certno 证件号码 字符型 50 Y
*/
private String certno;

/**
* psn_name 人员姓名 字符型 50 Y
*/
@JSONField(name = "psn_name")
private String psnName;

/**
* gend 性别 字符型 6 Y Y
*/
private String gend;

/**
* naty 民族 字符型 3 Y
*/
private String naty;

/**
* brdy 出生日期 日期型 yyyy-MM-dd
*/
private String brdy;

/**
* age 年龄 数值型 4,1 Y
*/
private String age;

/**
* exp_content 字段扩展 字符型 4000 只有居民返回
* 家庭账户余额
* 门诊统筹累计
* {
* “fm_acct_amt”:0
* “jmmztc_cum”:0
* }
*/
private ExpContent expContent;

@Data
public class ExpContent {

/**
* fm_acct_amt 家庭账户余额 数值型 16,2 只有居民返回
*/
private String fmAcctAmt;

/**
* jmmztc_cum 门诊统筹累计 数值型 16,2 只有居民返回
*/
private String jmmztcCum;

/**
* mat_idet_flag 医疗救助标识 字符型 6 0否,1是
*/
private String matIdetFlag;

/**
* mat_idet_code 救助对象身份 字符型 10 Y
*/
private String matIdetCode;


}





}

@Data
public static class Insuinfo{

/**
* psn_insu_rlts_id 人员参保关系ID 字符型 20
*/
@JSONField(name = "psn_insu_rlts_id")
private String psnInsuRltsId;

/**
* balc 余额 数值型 16,2 Y
*/
private BigDecimal balc;

/**
* insutype 险种类型 字符型 6 Y Y
*/
private String insutype;

/**
* psn_type 人员类别 字符型 6 Y Y
*/
@JSONField(name = "psn_type")
private String psnType;

/**
* psn_insu_stas 人员参保状态 字符型 6 Y
*/
@JSONField(name = "psn_insu_stas")
private String psnInsuStas;

/**
* psn_insu_date 个人参保日期 日期型
*/
private String psnInsuDate;

/**
* paus_insu_date 暂停参保日期 日期型
*/
private String pausInsuDate;

/**
* cvlserv_flag 公务员标志 字符型 3 Y Y
*/
@JSONField(name = "cvlserv_flag")
private String cvlservFlag;

/**
* insuplc_admdvs 参保地医保区划 字符型 6 Y
*/
private String insuplcAdmdvs;

/**
* emp_name 单位名称 字符型 200
*/
@JSONField(name = "emp_name")
private String empName;

}

@Data
public class Idetinfo{

/**
* psn_idet_type 人员身份类别 字符型 10 Y Y
*/
@JSONField(name = "psn_idet_type")
private String psnIdetType;

/**
* psn_type_lv 人员类别等级 字符型 3 Y 详见残疾等级字典
*/
@JSONField(name = "psn_type_lv")
private String psnTypeLv;

/**
* memo 备注 字符型 500
*/
private String memo;

/**
* begntime 开始时间 日期时间型 Y
*/
private String begntime;

/**
* endtime 结束时间 日期时间型
*/
private String endtime;

}


public static void main(String[] args) {

String s = "{\n" +
" \"infcode\": \"1\",\n" +
" \"inf_refmsgid\": \"000000202001041235391234567890\",\n" +
" \"refmsg_time\": \"20200201133411352\",\n" +
" \"respond_time\": \"20200202133731456\",\n" +
" \"err_msg\": \"\",\n" +
" \"output\": {\n" +
" \"baseinfo\": {\n" +
" \"psn_no\": \"131000202001001\",\n" +
" \"psn_cert_type\": \"2\",\n" +
" \"certno\": \"510000202001010000\",\n" +
" \"psn_name\": \"李四\",\n" +
" \"gend\": \"1\",\n" +
" \"naty\": \"01\",\n" +
" \"brdy\": \"2020-01-01\",\n" +
" \"age\": 18\n" +
" },\n" +
" \"insuinfo\": {\n" +
" \"psn_insu_rlts_id\": \"133241523001001\",\n" +
" \"balc\": 5000,\n" +
" \"insutype\": \"310\",\n" +
" \"psn_type\": \"1001\",\n" +
" \"cvlserv_flag\": \"0\",\n" +
" \"insu_admdvs\": \"131002\",\n" +
" \"emp_name\": \"测试单位\"\n" +
" },\n" +
" \"idetinfo\": [\n" +
" {\n" +
" \"psn_idet_type\": \"1\",\n" +
" \"psn_type_lv\": \"1\",\n" +
" \"memo\": \"\",\n" +
" \"begntime\": \"2020-01-01 00:00:00\",\n" +
" \"endtime\": \"\"\n" +
" },\n" +
" {\n" +
" \"psn_idet_type\": \"2\",\n" +
" \"psn_type_lv\": \"1\",\n" +
" \"memo\": \"\",\n" +
" \"begntime\": \"2020-01-01 00:00:00\",\n" +
" \"endtime\": \"\"\n" +
" }\n" +
" ]\n" +
" }\n" +
"}";




InsuranceCoreCommonOutputMessage outputMessage = JSON.parseObject(s, InsuranceCoreCommonOutputMessage.class);

// 收到的1101报文
InsuranceCoreOutputMessage1101 insuranceCoreOutputMessage1101 = JSON.parseObject(outputMessage.getOutput(), InsuranceCoreOutputMessage1101.class);

System.out.println(insuranceCoreOutputMessage1101);

}









}

+ 55
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceGetOrderReq.java Wyświetl plik

@@ -0,0 +1,55 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceGetOrderReq.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/19 10:37
* @Modify:
*/
@Data
@ApiModel("医保下单参数")
public class InsuranceGetOrderReq {


@ApiModelProperty("购药单id 如果是购药单医保支付传购药单id,如果是问诊单医保支付传问诊单id")
private String platformOrderId;


@ApiModelProperty("医保支付订单类型 1: 问诊单 2: 购药单")
private Integer orderType = 1;

@ApiModelProperty("微信医保授权码")
private String authCode;


@ApiModelProperty("订单医疗费总额")
private String medfeeSumamt;


@ApiModelProperty("业务流水号")
private String orgBizSer;

@ApiModelProperty("收费批次号")
private String chrgBchno;

@ApiModelProperty("费用类别")
private String feeType;

@ApiModelProperty("就诊事件ID")
private String mdtrtId;

@ApiModelProperty("医疗机构订单号")
private String medOrgOrd;



}

+ 56
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceMiddleGroundInputMessage.java Wyświetl plik

@@ -0,0 +1,56 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceMiddleGroundInputMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 省移动支付中台 公共请求报文
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 15:08
* @Modify:
*/
@Data
public class InsuranceMiddleGroundInputMessage {

/**
* appId 渠道id String(32) N
*/
private String appId;

/**
* version 版本号 String(6) N 2.0.1
*/
private String version;

/**
* timestamp 当前时间 String(32) N 时间戳
*/
private String timestamp;

/**
* encType 加密方式 String(6) N SM4
*/
private String encType;

/**
* encData 加密数据 String(max) N
*/
private String encData;

/**
* signType 签名方式 String(6) N SM2
*/
private String signType;

/**
* signData 签名串 String(200) N
*/
private String signData;



}

+ 76
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceMiddleGroundOutputMessage.java Wyświetl plik

@@ -0,0 +1,76 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceMiddleGroundOutputMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 省移动支付中台 公共响应报文
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 15:10
* @Modify:
*/
@Data
public class InsuranceMiddleGroundOutputMessage {

/**
* code 响应状态码 int N
*/
private Integer code;

/**
* appId 渠道id String(32) N
*/
private String appId;

/**
* timestamp 当前时间 String(32) N 时间戳
*/
private String timestamp;

/**
* encType 加密方式 String(6) N SM4
*/
private String encType;

/**
* signType 签名方式 String(6) N SM2
*/
private String signType;

/**
* signData 签名串 String(200) N
*/
private String signData;

/**
* encData 加密数据 String(max) N
*/
private String encData;

/**
* message 响应异常信息 String(max) Y
*/
private String message;

/**
* success 响应标识 boolean Y
*/
private Boolean success;

/**
* version 版本号 String(6) N 2.0.1
*/
private String version;


/**
* data 响应数据 Object N
*/
private String data;


}

+ 67
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsurancePayOrderInputMessage.java Wyświetl plik

@@ -0,0 +1,67 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsurancePayOrderInputMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/23 17:26
* @Modify:
*/
@Data
public class InsurancePayOrderInputMessage {

/**
* payAuthNo 支付授权码 字符型 40 Y 电子凭证线上渠道授权返回
*/
private String payAuthNo;

/**
* payOrdId 待支付订单号 字符型 40 Y 费用上传返回
*/
private String payOrdId;

/**
* payToken 支付订单对应的token 字符型 40 Y 费用上传返回
*/
private String payToken;

/**
* orgCodg 定点机构编码 字符型 12 Y
*/
private String orgCodg;

/**
* orgBizSer 业务流水号 字符型 40 Y 每一次请求唯一
*/
private String orgBizSer;

/**
* chrgBchno 收费批次号 字符型 40 Y 与费用上传一致
*/
private String chrgBchno;

/**
* feeType 费用类别 字符型 2 Y 与费用上传一致
*/
private String feeType;

/**
* mdtrtId 就诊事件ID 字符型 40 Y 与费用上传一致
*/
private String mdtrtId;

/**
* acctUsedFlag 个账使用标识 字符型 1 N 为空时默认使用费用上传时的值
*/
private String acctUsedFlag;




}

+ 65
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsurancePayOrderOutputMessage.java Wyświetl plik

@@ -0,0 +1,65 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;

/*******************************************************************
* <pre></pre>
* @文件名称: InsurancePayOrderOutputMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 6202 医保支付订单响应参数
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/23 17:52
* @Modify:
*/
@Data
@ApiModel("医保支付订单响应参数")
public class InsurancePayOrderOutputMessage {

/**
* payOrdId 支付订单号 字符型 40 Y
*/
@ApiModelProperty("支付订单号")
private String payOrdId;

/**
* ordStas 订单状态 字符型 40 Y 字典订单状态(ordStas)
*/
@ApiModelProperty("订单状态")
private String ordStas;

/**
* feeSumamt 费用总额 数值型 12,2 Y
*/
@ApiModelProperty("费用总额")
private BigDecimal feeSumamt;

/**
* ownPayAmt 现金支付 数值型 12,2 Y
*/
@ApiModelProperty("现金支付")
private BigDecimal ownPayAmt;

/**
* psnAcctPay 个人账户支出 数值型 12,2 Y
*/
@ApiModelProperty("个人账户支出")
private BigDecimal psnAcctPay;

/**
* fundPay 医保基金支付 数值型 12,2 Y
*/
@ApiModelProperty("医保基金支付")
private BigDecimal fundPay;

@ApiModelProperty("医保结构体")
private String requestContent;



}

+ 80
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceRep.java Wyświetl plik

@@ -0,0 +1,80 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import com.alibaba.fastjson2.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceRep.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 10:50
* @Modify:
*/
@Data
@ApiModel("获取用户医保参数")
public class InsuranceRep {

/**
* code
* 业务返回码
* int
* Y
* 0成功,小于0系统错误,大于0逻辑错误
*/
private Integer code;

/**
* message
* 业务返回信息
* string
* Y
*/
private String message;

/**
* user_name
* 用户姓名
* string(32)
* N
* 姓名,如张三
*/
private String userName;

/**
* city_id
* 用户参保地代码
* string(12)
* N
* 仅当mi_card_type=CERITIFICATE时,才返回有效值,多地参保用户若未选择主参保地,则该字段未空,并且不可使用后续业务。;
*/
@JSONField(name = "city_id")
private String cityId;

/**
* pay_auth_no
* 医保线上核验payAuthNo
* string(32)
* Y
* 当使用医保线上支付功能时,返回payAuthNo
*/
private String payAuthNo;

/**
* user_longitude_latitude
* 用户经纬度
*
*
*
*
* Y
* 当使用医保线上支付功能时,返回对应的经纬度
*/
private UserLongitudeLatitude userLongitudeLatitude;


}

+ 32
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceReq.java Wyświetl plik

@@ -0,0 +1,32 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceReq.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 10:42
* @Modify:
*/
@Data
@Accessors(chain = true)
@ApiModel("获取用户医保参数")
public class InsuranceReq {

@ApiModelProperty("授权码")
private String qrcode;

@ApiModelProperty("用户openId")
private String openid;



}

+ 297
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceUploadRecipeDetailInputMessage.java Wyświetl plik

@@ -0,0 +1,297 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.math.BigDecimal;
import java.util.List;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceUploadRecipeDetailDTO.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/17 14:36
* @Modify:
*/
@Data
@ApiModel("省医保平台「6201」上传处方药费明细请求参数")
public class InsuranceUploadRecipeDetailInputMessage {

/**
* orgCodg 机构编码 字符型 40 Y 医保分配
*/
private String orgCodg;

/**
* orgId 电子凭证机构号 字符型 40 N 电子凭证中台分配,待机构电子凭证建设完毕后可获取该机构号
*/
private String orgId;

/**
* psnNo 人员编号 字符型 30 Y
*/
private String psnNo;

/**
* insutype 险种类型 字符型 6 Y 字典险种类型
* (insutype)
*/
private String insutype;

/**
* medOrgOrd 医疗机构订单号 字符型 40 Y 院内产生惟一流水,可关联到一次结算记录,结算成功回调入参返回
*/
private String medOrgOrd;

/**
* rxCircFlag 电子处方流转标志 字符型 1 N 1:电子处方 ,0不是电子处方,默认0,非电子处方
*/
private String rxCircFlag = "0";

/**
* begntime 开始时间 字符型 19 Y 挂号时间
* yyyy-MM-dd HH:mm:ss
*/
private String begntime;

/**
* idNo 证件号码 字符型 40 Y
*/
private String idNo;

/**
*userName 用户姓名 字符型 40 Y
*/
private String userName;

/**
* idType 证件类别 字符型 3 Y 字典人员证件类型(psn_cert_type) 01:身份证
*/
private String idType;

/**
* ecToken 电子凭证授权ecToken 字符型 64 Y 电子凭证解码返回
*/
private String ecToken;

/**
* insuCode 就诊参保地行政区划 字符型 6 N 为空(null)时取用户电子凭证默认参保地
*/
private String insuCode;

/**
* iptOtpNo 住院/门诊号 字符型 30 Y 院内唯一流水
*/
private String iptOtpNo;

// ==================非必需字段===================

/**
* atddrNo 医师编码 字符型 30 N
*/
private String atddrNo;

/**
*drName 医师姓名 字符型 50 N
*/
private String drName;

/**
* deptCode 科室编码 字符型 30 N
*/
private String deptCode;


// =====================================

/**
*deptName 科室名称 字符型 100 Y
*/
private String deptName;

/**
* caty 科别 字符型 6 Y
*/
private String caty;

/**
* mdtrtId 就诊ID 字符型 30 N
*/
private String mdtrtId;

/**
*medType 医疗类别 字符型 6 Y 字典医疗类别
* (med_type) 91 其他门诊
*/
private String medType;

/**
* feeType 费用类型 字符型 3 Y 字典费用类型(feeType) 05 互联网医院问诊
*/
private String feeType;

/**
* medfeeSumamt 医疗费总额 数值型 16,2 Y
*/
private BigDecimal medfeeSumamt;

// todo 貌似目前为海南医保的特有字段
/**
* acctUsedFlag 个人账户使用标志 字符型 1 Y 药店上传费用时必填
*/
private String acctUsedFlag;

/**
* mainCondDscr 主要病情描述 字符型 1000 N
*/
private String mainCondDscr;

/**
*diseCodg 病种编码 字符型 30 Y 按照标准编码填写:
* 按病种结算病种目录代码(bydise_setl_list_code)、
* 门诊慢特病病种目录代码(opsp_dise_cod)、
*/
private String diseCodg;

/**
* diseName 病种名称 字符型 500 Y
*/
private String diseName;

// todo 貌似目前为海南医保的特有字段
/**
* psnSetlway 个人结算方式 字符型 6 Y
*/
private String psnSetlway;

/**
* chrgBchno 收费批次号 字符型 30 Y
*/
private String chrgBchno;

/**
* pubHospRfomFlag 公立医院改革标志 字符型 6 Y 可参考FSI的接口要求
*/
private String pubHospRfomFlag;

/**
* diseinfoList 诊断或症状明细 Y 见下方diseinfoList定义
*/
private List<DiseInfo> diseinfoList;

/**
* feedetailList 费用明细 Y 见下方feedetailList定义
*/
private List<FeeDetail> feedetailList;

/**
* payAuthNo 支付授权码 字符型 40 N 线上授权返回
*/
private String payAuthNo;


public static void main(String[] args) {

String s = "{\n" +
"\t\"configId\": \"cs1\",(部分省份无该参数,可去除)\n" +
"\t\"payAuthNo\": \"AUTH430100202206132005090000100\",\n" +
"\t\"uldLatlnt\": \"112.88211,28.230932\",\n" +
"\t\"idType\": \"01\",\n" +
"\t\"mdtrtCertType\": \"02\",\n" +
"\t\"orgCodg\": \"H43010000001\",\n" +
"\t\"orgId\": \"\",\n" +
"\t\"psnNo\": \"430000201000000000\",\n" +
"\t\"insutype\": \"310\",\n" +
"\t\"medOrgOrd\": \"46515950\",\n" +
"\t\"begntime\": \"2022-06-13 17:57:07\",\n" +
"\t\"idNo\": \"430602199111111111\",\n" +
"\t\"userName\": \"刘军\",\n" +
"\t\"ecToken\": \"\",\n" +
"\t\"iptOtpNo\": \"4441829\",\n" +
"\t\"deptCode\": \"2101\",\n" +
"\t\"deptName\": \"心血管内科诊室(一)\",\n" +
"\t\"caty\": \"2101\",\n" +
"\t\"mdtrtId\": \"359999999\",\n" +
"\t\"medType\": \"11\",\n" +
"\t\"feeType\": \"01\",\n" +
"\t\"medfeeSumamt\": 53.69,\n" +
"\t\"acctUsedFlag\": \"\",\n" +
"\t\"diseCodg\": \"J00.x00x002\",\n" +
"\t\"diseName\": \"病毒性感冒\",\n" +
"\t\"psnSetlway\": \"01\",\n" +
"\t\"chrgBchno\": \"4441829694.42\",\n" +
"\t\"pubHospRfomFlag\": \"01\",\n" +
"\t\"fetts\": \"\",\n" +
"\t\"diseinfoList\": [{\n" +
"\t\t\"diagType\": \"0\",\n" +
"\t\t\"diagSrtNo\": 1,\n" +
"\t\t\"diagCode\": \"J00.x00x002\",\n" +
"\t\t\"diagName\": \"病毒性感冒\",\n" +
"\t\t\"diagDept\": \"心血管内科诊室(一)\",\n" +
"\t\t\"diseDorNo\": \"0824\",\n" +
"\t\t\"diseDorName\": \"马丽霞\",\n" +
"\t\t\"diagTime\": \"2022-06-13 17:57:23\",\n" +
"\t\t\"valiFlag\": \"1\"\n" +
"\t}],\n" +
"\t\"feedetailList\": [{\n" +
"\t\t\t\"feedetlSn\": \"97657430\",\n" +
"\t\t\t\"mdtrtId\": \"4441888\",\n" +
"\t\t\t\"psnNo\": \"430000201000000000\",\n" +
"\t\t\t\"chrgBchno\": \"444182920220613175815266\",\n" +
"\t\t\t\"rxCircFlag\": \"0\",\n" +
"\t\t\t\"feeOcurTime\": \"2022-06-13 17:57:08\",\n" +
"\t\t\t\"medListCodg\": \"F00000019080\",\n" +
"\t\t\t\"medinsListCodg\": \"H43010500027\",\n" +
"\t\t\t\"detItemFeeSumamt\": 16,\n" +
"\t\t\t\"cnt\": 1,\n" +
"\t\t\t\"pric\": 16,\n" +
"\t\t\t\"bilgDeptCodg\": \"2101\",\n" +
"\t\t\t\"bilgDeptName\": \"心血管内科诊室(一)\",\n" +
"\t\t\t\"bilgDrCodg\": \"0824\",\n" +
"\t\t\t\"bilgDrName\": \"马丽霞\",\n" +
"\t\t\t\"hospApprFlag\": \"1\",\n" +
"\t\t\t\"medType\": \"11\",\n" +
"\t\t\t\"medListName\": \"副主任医师普通门诊诊查费\",\n" +
"\t\t\t\"medListSpc\": \"\"\n" +
"\t\t},\n" +
"\t\t{\n" +
"\t\t\t\"feedetlSn\": \"97657431\",\n" +
"\t\t\t\"mdtrtId\": \"4441888\",\n" +
"\t\t\t\"psnNo\": \"430000201000000000\",\n" +
"\t\t\t\"chrgBchno\": \"444182920220613175815266\",\n" +
"\t\t\t\"rxCircFlag\": \"0\",\n" +
"\t\t\t\"feeOcurTime\": \"2022-06-13 17:57:36\",\n" +
"\t\t\t\"medListCodg\": \"Y00000020302\",\n" +
"\t\t\t\"medinsListCodg\": \"H43010500027\",\n" +
"\t\t\t\"detItemFeeSumamt\": 678.42,\n" +
"\t\t\t\"cnt\": 18,\n" +
"\t\t\t\"pric\": 37.69,\n" +
"\t\t\t\"bilgDeptCodg\": \"2101\",\n" +
"\t\t\t\"bilgDeptName\": \"心血管内科诊室(一)\",\n" +
"\t\t\t\"bilgDrCodg\": \"0824\",\n" +
"\t\t\t\"bilgDrName\": \"马丽霞\",\n" +
"\t\t\t\"hospApprFlag\": \"1\",\n" +
"\t\t\t\"medType\": \"11\",\n" +
"\t\t\t\"medListName\": \"小儿肺咳颗粒\",\n" +
"\t\t\t\"medListSpc\": \"2g/袋*18袋/盒\"\n" +
"\t\t}\n" +
"\t]\n" +
"}\n";









}



}

+ 43
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/InsuranceUploadRecipeDetailOutputMessage.java Wyświetl plik

@@ -0,0 +1,43 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceUploadRecipeDetailOutputMessage.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 【6201】 上传医保费用明细响应参数
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 15:34
* @Modify:
*/
@Data
public class InsuranceUploadRecipeDetailOutputMessage {

/**
* payOrdId 支付订单号 字符型 40 Y 医保结算中心订单号
*/
private String payOrdId;

/**
* payToken 支付token 字符型 40 Y 下单支付使用
*/
private String payToken;

/**
* cashierUrl 医保支付收银台h5地址 字符型 4000 N 见下方拼接说明
*/
private String cashierUrl;

/**
* extData 医保扩展数据 N 根据各地方医保要求传不同数据内容
*/
private String extData;





}

+ 49
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UnifiedOrderRep.java Wyświetl plik

@@ -0,0 +1,49 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: UnifiedOrderRep.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/24 10:13
* @Modify:
*/
@Data
@ApiModel("统一下单返回参数")
public class UnifiedOrderRep {

/**
*

pay_url
支付链接
String256
Y
下单后跳转到此url,用户完成支付,使用app支付时1.5 APP支付说明

*/
@ApiModelProperty("支付链接")
private String payUrl;

/**
*

pay_appid
支付小程序
String64
N
当使用医院小程序进行下单时,会返回此参数,医院小程序跳转至该支付小程序进行支付
*/
@ApiModelProperty("支付小程序")
private String payAppid;



}

+ 68
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UnifiedOrderReq.java Wyświetl plik

@@ -0,0 +1,68 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: UnifiedOrderReq.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 微信统一下单请求参数
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/23 23:53
* @Modify:
*/
@ApiModel("微信统一下单请求参数")
@Data
public class UnifiedOrderReq {

@ApiModelProperty("支付类型: IntReDiagPay=互联网医院复诊支付\n" +
"IntPscPay=互联网医院处方支付 \n")
private String orderType;

@ApiModelProperty("分账信息")
private InsurancePayOrderOutputMessage insurancePayOrder;

/**
* spbill_create_ip
* 用户端ip
* String16
* Y
* 10.193.0.1
*/
@ApiModelProperty("用户ip")
private String spbillCreateIp;




@ApiModelProperty(hidden = true)
private InsuranceAccessTokenRep accessToken;

@ApiModelProperty(hidden = true)
private String openId;


@ApiModelProperty(hidden = true)
/**
* 证件号码 user_card_no 证件号码的MD5,目前只支持身份证(身份证中如果有字母需要转成大写再做MD5,15位身份证号需要转为18位). 示例:44030019000101123x的MD5为09eb26e839ff3a2e3980352ae45ef09e
*/
private String userCardNo;



@ApiModelProperty(hidden = true)
/**
* 真实姓名 user_name 张三
*/
private String userName;






}

+ 25
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UserLongitudeLatitude.java Wyświetl plik

@@ -0,0 +1,25 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: user_longitude_latitude.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 10:53
* @Modify:
*/
@Data
@ApiModel("获取用户经纬度")
public class UserLongitudeLatitude {

private String longitude;

private String latitude;

}

+ 29
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/UserQueryReq.java Wyświetl plik

@@ -0,0 +1,29 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: UserQueryReq.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 11:12
* @Modify:
*/
@Data
@ApiModel("获取用户信息")
public class UserQueryReq {

@ApiModelProperty("授权码")
private String qrcode;

@ApiModelProperty("openid")
private String openid;


}

+ 325
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/WechatUnifiedOrderReq.java Wyświetl plik

@@ -0,0 +1,325 @@
package com.szyx.tcm.supervision.model.dto.insurance;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: WechatUnifiedOrderReq.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance
* @Copyright:wy (C) 2024 *
* @Description: 微信统一下单请求参数
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/23 23:23
* @Modify:
*/
@Data
public class WechatUnifiedOrderReq {

/**
* order_type
* 支付类型
* String16
* Y
* RegPay=挂号支付
* MedPay=药费支付
* DiagPay=诊间支付
* InHospPay=住院费支付
* PharmacyPay=药店支付
* InsurancePay=保险费支付
* IntRegPay=互联网医院挂号支付
* IntReDiagPay=互联网医院复诊支付
* IntPscPay=互联网医院处方支付
* CovidExamPay=新冠检测费用
* CvidAntigenPay=新冠抗原检测
*/
private String orderType;

/**
* appid
* 公众账号ID
* String32
* Y
* 微信分配的公众账号ID
*/
private String appid;

/**
* mch_id
* 商户号
* String32
* Y
* 微信支付分配的商户号
*/
private String mchId;

/**
* sub_appid
* 子商户公众号ID
* String32
* N
* 微信分配的子商户公众账号ID,如需在支付完成后获取sub_openid则此参数必传。
*/
private String subAppid;

/**
* sub_mch_id
* 子商户号
* String32
* N
* 微信支付分配的子商户号,如果是服务商模式,必填
*/
private String subMchId;

/**
* openid
* 用户标识
* String128
* 二选一
* openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。
*/
private String openid;



/**
* hosp_out_trade_no
* 第三方服务商订单号
* String64
* Y
* 第三方服务商平台自动生成的一个订单号
*/
private String hospOutTradeNo;

/**
* hospital_name
* 医院名称
* string128
* Y
* 医院名称
*/
private String hospitalName;

/**
* nonce_str
* 随机字符串
* String32
* Y
*/
private String nonceStr;

/**
* total_fee
* 总共需要支付现金金额
* Uint64
* Y
* 单位为分>0
* 表示订单总额即全额现金的价格。由于医保局支付有优惠,全额现金的价格可能会大于cash_fee+ insurance_fee的和,不一定等于cash_fee+insurance_fee。
*/
private String totalFee;

/**
* cash_fee
* 现金需要支付的金额
* Uint64
* Y
* 单位为分>=0
* 线上预结算模式金额填0
* 线下预结算模式填实际自费金额
*/
private String cashFee;

/**
* cash_add_fee
* 由医疗机构额外增加的现金金额
* Uint64
* N
* 单位为分,默认0
* 用于医院在医保预结算之外增加现
* 金扣费,举例:原需要
* 支付的是:
* total_ fee 200
* cash_ fee 100
* insurance fee 100。
* 现新增现金50,则入参为:
* total_ _fee 250 ( 总额加上额外现
* 金)
* cash fee 150(自费加上额外现
* 金)
* cash_add_ fee 50 (额外现金)
* insurance_ fee 100
*/

private String cashAddFee;

/**
* cash_add_wording
* 额外现金金额文案
* String16
* N
* 额外现金金额,如:快递费
* 目前不会在前端显示,可不传
*/
private String cashAddWording;

/**
* cash_reduced_wording
* 减免金额文案
* String16
* N
* 减免金额的文案类型,
* 1为:预交金支付
* 2为:医院减免
* 3为:药店优惠
* 4为:优惠金
* 5为:押金抵扣
* 不填则为默认的“机构优惠金额”
*/
private String cashReducedWording;

/**
* allow_fee_change
* 是否允许预结算费用发生变化
* uint8
* Y
* 0:不允许
* 1:允许
* 当医保局返回的预结算金额与医院上传的金额不一致时,此字段为0则直接报错,为1则以医保局金额为准
*/
private String allowFeeChange;

/**
* spbill_create_ip
* 用户端ip
* String16
* Y
* 10.193.0.1
*/
private String spbillCreateIp;

/**
* notify_url
* 回调url
* String256
* Y
* 接收微信支付异步通知回调地址
*/
private String notifyUrl;

/**
* body
* 商品描述
* String128
* Y
* 参照
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2
*/
private String body;

/**
* return_url
* 支付后回跳的页面,不论成功或者失败均会回跳
* string128
* Y
* 调用方可以在链接中加上支付单号,回跳后查询调用方订单状态,如果订单已支付则成功, 如果订单未支付则进行查单操作确认订单结果
*/
private String returnUrl;

/**
* pay_type
* 支付方式
* uint8
* Y
* 1:现金 2:医保 3:现金+医保
* 备注说明:
* 1、当订单要走医保支付时,
* (1)cash_fee>0, paytype填3
* (2)cash_fee=0, paytype填2
* 2、当订单不使用医保支付时 paytype填1。
* 3、当订单有走医保【6201】相关接口时,如果订单为纯自费订单,paytype填3。
*/
private String payType;

/**
* city_id
* 城市ID
* String32
* Y
* 一般为申请接入城市的编码,由腾讯侧对接时提供。
*/
private String cityId;


/**
* consume_type
* 医保部分扣
* 费类型
* int8
* N
* 默认为 0:统筹+个账
* 1:个账
* 2:统筹
*/
private String consumeType;

/**
* insurance_fee
* 医保支付金额
* Uint64
* Y
* 填实际医保金额
*/
private String insuranceFee;

/**
* 证件类型 user_card_type 1 居民身份证 9 户口本 8 外国人护照 5 台湾居民来往大陆通行证 4 澳门居民往来内地通行证 6 香港居民往来内地通行证 7 外国人永久居留证
*/
private String userCardType;

/**
* 证件号码 user_card_no 证件号码的MD5,目前只支持身份证(身份证中如果有字母需要转成大写再做MD5,15位身份证号需要转为18位). 示例:44030019000101123x的MD5为09eb26e839ff3a2e3980352ae45ef09e
*/
private String userCardNo;

/**
* 真实姓名 user_name 张三
*/
private String userName;

/**
* 医保标识 is_dept is_dept=4 医保电子凭证支付;
*/
private String isDept;

/**
* 医院HIS系统订单号 serial_no 医院HIS系统订单号
*/
private String serialNo;

/**
* 医疗机构编码(医保局分配给机构) org_no 医保局局提供的医疗机构编码
*/
private String orgNo;

/**
* 医院下单时间 gmt_out_create 格式为yyyyMMddHHmmss 如20160501163102
*/
private String gmtOutCreate;

/**
* 参考医保结构体(医疗机构透传医保) request_content 示例: {"payAuthNo":"AUTH****","payOrdId":"ORD****","setlLatlnt":"118.096435,24.485407"} payAuthNo:授权码 payOrdId:对应处方上传的出参单号 setlLatlnt:用户地 理定位信息, 经纬 度信息,如“118.096435,24.485407”。未获取到用户定位时,传“0,0”。
*/
private String requestContent;

/**
* 业务单据号 bill_no
*/
private String billNo;

/**
* 签名 sign
*/
private String sign;


}

+ 38
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/core/SignIn.java Wyświetl plik

@@ -0,0 +1,38 @@
package com.szyx.tcm.supervision.model.dto.insurance.core;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: SignIn.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance.core
* @Copyright:wy (C) 2024 *
* @Description: 9001 输入-录入的基本信息
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 10:41
* @Modify:
*/
@Data
public class SignIn {

/**
* opter_no 操作员编号 字符型 20 Y
*/
private String opterNo;

/**
* mac 签到MAC地址 字符型 20 Y
*/
private String mac;

/**
* ip 签到IP地址 字符型 20 Y
*/
private String ip;





}

+ 32
- 0
src/main/java/com/szyx/tcm/supervision/model/dto/insurance/core/Signinoutb.java Wyświetl plik

@@ -0,0 +1,32 @@
package com.szyx.tcm.supervision.model.dto.insurance.core;

import lombok.Data;

/*******************************************************************
* <pre></pre>
* @文件名称: Signinoutb.java
* @包 路 径: com.szyx.tcm.web.patient.dto.insurance.core
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 10:44
* @Modify:
*/
@Data
public class Signinoutb {

/**
* sign_time 签到时间 日期型 Y yyyy-MM-dd HH:mm:ss
*/
private String signTime;

/**
* sign_no 签到编号 字符型 30 Y
*/
private String signNo;




}

+ 102
- 0
src/main/java/com/szyx/tcm/supervision/service/manager/ClientDemo.java Wyświetl plik

@@ -0,0 +1,102 @@
package com.szyx.tcm.supervision.service.manager;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;


/*******************************************************************
* <pre></pre>
* @文件名称: ClientDemo.java
* @包 路 径: com.szyx.tcm.web.patient.service.manager
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/16 11:07
* @Modify:
*/
public class ClientDemo {

private final static String partnerId = "20000011";
private final static String partnerSecret = "5dd6f0926a2e2b2cb19a5bcecb0e2df6";
private final static String urlPath = "https://mip-receiver.tengmed.com/testapi/mipuserquery/userQuery/20000011";
private final static char[] hexArray = "0123456789abcdef".toCharArray();


private String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0Xff;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}

private String createSignature(String partnerSecret, String partnerId, String timestamp)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(partnerSecret.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
return bytesToHex(sha256_HMAC.doFinal((partnerId + timestamp).getBytes("UTF-8")));
}


private String postData(String businessName, String funcName, String partnerId, String data)
throws IOException, NoSuchAlgorithmException, InvalidKeyException {
HttpURLConnection conn = null;
URL url = new URL(urlPath);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(true);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
String timestamp = Long.toString(System.currentTimeMillis());
String signature = createSignature(partnerSecret, partnerId, timestamp);
String requestId = UUID.randomUUID().toString().replaceAll("-", "");
conn.setRequestProperty("god-portal-timestamp", timestamp);
conn.setRequestProperty("god-portal-signature", signature);
conn.setRequestProperty("god-portal-request-id", requestId);
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(data.getBytes());
os.flush();
os.close();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
InputStream inputStream = conn.getInputStream();
byte[] bytes = new byte[1024];
int readBytes;
while ((readBytes = inputStream.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, readBytes);
}
bytes = byteArrayOutputStream.toByteArray();
inputStream.close();
conn.disconnect();
return new String(bytes, "utf-8");

}


public static void main(String[] args) {
ClientDemo demo = new ClientDemo();
try {
System.out.println(demo.postData("test", "test2", demo.partnerId, "{}"));
} catch (Exception e) {
e.printStackTrace();
}
}

}





+ 1015
- 0
src/main/java/com/szyx/tcm/supervision/service/manager/HealthInsuranceManager.java
Plik diff jest za duży
Wyświetl plik


+ 585
- 0
src/main/java/com/szyx/tcm/supervision/util/DateUtils.java Wyświetl plik

@@ -0,0 +1,585 @@
package com.szyx.tcm.supervision.util;


import com.szyx.tcm.supervision.enums.BannerEnum;
import com.szyx.tcm.supervision.enums.WeekDayEnum;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.dromara.hutool.core.date.DateUtil;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
* @author chenjie
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

public static final String PATTERN_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
public static final String PATTERN_DATE_TIME_YEAR = "yyyy-MM-dd HH:mm";
public static final String PATTERN_DATE = "yyyy-MM-dd";
public static final String PATTERN_DATE_SIDE= "yyyyMMdd";
public static final String PATTERN_DATE_HOUR = "HH:mm";
public static final String PATTERN_DATE_HOUR_MS = "HH:mm:ss";
public static final String PATTERN_YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
public static final String PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static final String PATTERN_DATE_YEAR = "yyyy";
public static final String UTC_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss+08:00";

public static final String PATTERN_MONTH_DATE = "MM.dd";

public static final String PATTERN_YEAR_DATE = "yyyy.MM.dd";
public static Date parseDate(String str) {
try {
return parseDate(str, PATTERN_DATE_TIME);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public static Date parseDateHours(String str) {
try {
return parseDate(str, PATTERN_DATE_HOUR_MS);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}


public static String format(Date date) {
return DateFormatUtils.format(date, PATTERN_DATE_TIME);
}

public static String formatString(Date date) {
return DateFormatUtils.format(date, PATTERN_DATE);
}

public static String formatStringToYear(Date date) {
return DateFormatUtils.format(date, PATTERN_DATE_YEAR);
}

public static String formatString1(String date) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(PATTERN_DATE);
return formatString(simpleDateFormat.parse(date));
}

public static String formatStringYear(Date date){
return new SimpleDateFormat("yyyy年MM月dd日").format(date);
}

public static String formatYear(Date date) {
return DateFormatUtils.format(date, PATTERN_DATE_TIME_YEAR);
}

public static String format(Date date, String pattern) {
return DateFormatUtils.format(date, pattern);
}

public static Date parse(String dateStr) throws Exception {
SimpleDateFormat formatter = new SimpleDateFormat(PATTERN_DATE);
return formatter.parse(dateStr);
}

public static Date parse(String dateStr, String pattern_date) throws Exception {
SimpleDateFormat formatter = new SimpleDateFormat(pattern_date);
return formatter.parse(dateStr);
}

/**
* 计算当前日期与{@code endDate}的间隔天数
*
* @param date
* @return 间隔天数
*/
public static long until(Date date) {

LocalDate endDate = dateLocalDate(date);
return LocalDate.now().until(endDate, ChronoUnit.DAYS);
}

/**
* 计算日期{@code startDate}与{@code endDate}的间隔天数
*
* @param startDate
* @param endDate
* @return 间隔天数
*/
public static long until(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.DAYS);
}

/**
* Date转LocalDate
*
* @param date
*/
public static LocalDate dateLocalDate(Date date) {
if (null == date) {
return null;
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}

public static String getDatePoor(Date endDate, Date nowDate, Integer status) {

long nd = 1000 * 24 * 60 * 60;//每天毫秒数

long nh = 1000 * 60 * 60;//每小时毫秒数

long nm = 1000 * 60;//每分钟毫秒数

long diff = endDate.getTime() - nowDate.getTime(); // 获得两个时间的毫秒时间差异

long day = diff / nd; // 计算差多少天

long hour = diff % nd / nh; // 计算差多少小时

long min = diff % nd % nh / nm; // 计算差多少分钟
if (status == 1) {
if (day > 0) {
return day + "天" + hour + "小时";
} else {
return hour + "小时";
}
} else {
if (day == 0 && hour == 0) {
return String.valueOf(min);
} else {
return String.valueOf(100);
}
}
}

/**
* LocalDate转Date
*
* @param localDate
* @return
*/
public static Date localDate2Date(LocalDate localDate) {
if (null == localDate) {
return null;
}
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
return Date.from(zonedDateTime.toInstant());
}

/**
* Date转LocalDate
*
* @param date
*/
public static LocalDate date2LocalDate(Date date) {
if (null == date) {
return null;
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}

/**
* LocalDate 转string
*
* @param localDate
* @return
*/
public static String localDate2String(LocalDate localDate) {
if (null == localDate) {
return null;
}
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(PATTERN_DATE);
return localDate.format(fmt);
}

public static String localDateTimeToString(LocalDateTime localDate, String patternDate) {
if (null == localDate) {
return null;
}

DateTimeFormatter fmt = DateTimeFormatter.ofPattern(patternDate);
return localDate.format(fmt);
}

/**
* 计算当前日期与{@code endDate}的间隔天数
*
* @param endDate
* @return 间隔天数
*/
static long until(LocalDate endDate) {
return LocalDate.now().until(endDate, ChronoUnit.DAYS);
}

/**
* 计算日期{@code startDate}与{@code endDate}的间隔天数
*
* @param startDate
* @param endDate
* @return 间隔天数
*/
static long untilDiffer(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.DAYS);
}

public static String betweenTwoTimes(LocalDate startDate, LocalDate endDate) {
Period p = Period.between(endDate, startDate);
return p.getYears() + "年" + p.getMonths() + "月" + p.getDays() + "日";
}

public final static Map<Character, Integer> digit = new HashMap<>();
public final static Map<Character, Integer> position = new HashMap<>();

static {
digit.put('零', 0);
digit.put('一', 1);
digit.put('二', 2);
digit.put('三', 3);
digit.put('四', 4);
digit.put('五', 5);
digit.put('六', 6);
digit.put('七', 7);
digit.put('八', 8);
digit.put('九', 9);
position.put('十', 1);
position.put('百', 2);
position.put('千', 3);
}

public static int s2(String num) {
//一共八位
char[] nums = new char[8];
int p = 7, now = 7;
char[] c = num.toCharArray();
/**
* 从右到左逐个字符解析
* 通过p控制万位,pp控制万以下的单位,now记录当前单位
*/
for (int i = c.length - 1; i >= 0; i--) {
if (c[i] == '万') {
now = p = 3;
} else {
int d = digit.getOrDefault(c[i], -1);
if (d == 0) {
continue;
}
if (d == -1) {
int pp = position.getOrDefault(c[i], -1);
if (pp == -1) {
throw new RuntimeException("\"" + num + "\"中存在无法解析的字符: " + i + ":" + c[i]);
} else {
now = p - pp;
//允许"一十"省略"一",即"十"
if (now == 6) {
nums[now] = 1;
}
}
} else {
nums[now] = (char)d;
}
}
}
for (int i = 0; i < nums.length; i++) {
nums[i] = (char)(nums[i] + '0');
}
return Integer.parseInt(new String(nums));
}

/**
* 把 Thu Dec 14 00:00:00 CST 2017 转换成自己想要的格式
*
* @param date
* @param pattern
* @return
*/

public static String dateStringFormat(String date, String pattern) {
if (date == null || pattern == null) {
return null;
}
try {
Date formDate = new SimpleDateFormat("MMM dd yyyy", Locale.US).parse(date);
return new SimpleDateFormat(pattern, Locale.CHINA).format(formDate);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}

public static Date dateFormatConvert(String Date, String format, String newFormat) {
try {
SimpleDateFormat newSDF = new SimpleDateFormat(newFormat);
SimpleDateFormat oldSDF = new SimpleDateFormat(format);
Date inDate = oldSDF.parse(Date);
String outDate = newSDF.format(inDate);
return newSDF.parse(outDate);
} catch (Exception e) {
return null;
}
}

public static Date getDate(String sFormat, String sDate) {
SimpleDateFormat sdf = new SimpleDateFormat(sFormat);
Date d = null;
try {
sdf.setLenient(false);
d = sdf.parse(sDate);
} catch (Exception e) {
return null;
}
return d;
}

public static String getDate(String sDate) {
String[] sa =
{"yyyy-MM-dd", "yyyyMMdd", "yyyy.MM.dd", "yyyy/MM/dd", "yyyy年MM月dd日", "dd/MM/yyyy", "d/M/yyyy", "MM-dd-yyyy", "dd-MM-yyyy", "MM/yyyy", "yyyy--M-dd",
"yyyy-MM", "yyyy"};

for (String s : sa) {
Date d = getDate(s, sDate);
if (d != null) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
return simpleDateFormat.format(d);
}
}
return null;
}

/**
* 把 mm/dd/yyyy 转换成
*
* @param date
* @return
*/

public static String dateStringFormat(String date) {
if (StringUtils.isNotBlank(date)) {
String[] split = date.split("/");
if (split.length == 3 && split[2].length() == 4) {
return split[2] + "-" + split[0] + "-" + split[1];
}
return date;
}
return "";
}

public static String dataToUpper(String dateString) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date dateTime = null;
try {
dateTime = simpleDateFormat.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar ca = Calendar.getInstance();
ca.setTime(dateTime);
int year = ca.get(Calendar.YEAR);
int month = ca.get(Calendar.MONTH) + 1;
int day = ca.get(Calendar.DAY_OF_MONTH);
return numToUpper(year) + "年" + monthToUppder(month) + "月" + dayToUppder(day) + "日";
}

// 将数字转化为大写(字体格式可自己定义)
public static String numToUpper(int num) {
//String u[] = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
String[] u = {"零","一","二","三","四","五","六","七","八","九"};
char[] str = String.valueOf(num).toCharArray();
String rstr = "";
for (int i = 0; i < str.length; i++) {
rstr = rstr + u[Integer.parseInt(String.valueOf(str[i]))];
}
return rstr;
}

// 月转化为大写
public static String monthToUppder(int month) {
if(month < 10) {
return numToUpper(month);
} else if(month == 10){
return "十";
} else {
return "十" + numToUpper(month - 10);
}
}

// 日转化为大写
public static String dayToUppder(int day) {
if(day < 20) {
return monthToUppder(day);
} else {
char[] str = String.valueOf(day).toCharArray();
if(str[1] == '0') {
return numToUpper(Integer.parseInt(String.valueOf(str[0]))) + "十";
}else {
return numToUpper(Integer.parseInt(String.valueOf(str[0]))) + "十" + numToUpper(Integer.parseInt(String.valueOf(str[1])));
}
}
}

/**
* 判断当前日期是否在指定日期内
* @param start
* @param end
* @return
*/
public static Integer beforeTimeCalendar(Date start, Date end) {

LocalDate startDate = dateToLocalDate(start);

LocalDate endDate = dateToLocalDate(end);
// 当前日期
LocalDate today = LocalDate.now();
if (today.isAfter(startDate) && today.isBefore(endDate)) {
return BannerEnum.PUBLISH.getCode();
} else {
if(today.isBefore(startDate)) {
return BannerEnum.EXPIRED.getCode();
}
if(today.isAfter(endDate)) {
return BannerEnum.RELEASED.getCode();
}
}
return BannerEnum.PUBLISH.getCode();
}

/**
* JAVA计算两个日期相差多少天
* @param date2
* @param date2
* @return
*/
public static int daysBetween(Date date1,Date date2) {
int count = 0;
try {
if(date1 == null || date2 == null ) {
return 0;
}
count = Math.abs((int) ((date1.getTime() - date2.getTime()) / (1000*3600*24)));
} catch (Exception e) {
e.printStackTrace();
}
return count;
}


/**
* Date 转为 LocalDate
*
* @param date
* @return LocalDate;
*/
public static LocalDate dateToLocalDate(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}

@SneakyThrows
public static Date formatDate(Date date, String pattern) {
if (pattern == null) {
pattern = "yyyy-MM-dd";
}

SimpleDateFormat formatter = new SimpleDateFormat(pattern);
DateFormat dateFormat = new SimpleDateFormat(pattern);
Date formatDate = dateFormat.parse(formatter.format(date));
return formatDate;
}

/**
* 获取年龄
* @param birthday
* @return
*/
public static Integer getAge(Date birthday) {
int compare = DateUtil.compare(birthday, new Date());
if (compare > 0) {
//如果出生日期大于当前时间,返回0
return 0;
} else {
return DateUtil.ageOfNow(birthday);
}
}


/**
* 根据日期获得星期
* @param date
* @return
*/
public static String getWeekOfDate(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int intWeek = calendar.get(Calendar.DAY_OF_WEEK);
return WeekDayEnum.getByCode(intWeek);
}

public static Date getWholeTime(Date date,int addDay){
if (date == null) {
date = new Date();
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_MONTH, addDay);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}

public static Integer dayForWeeks(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
int dayForWeek = 0 ;
if (c.get(Calendar.DAY_OF_WEEK) == 1 ){
dayForWeek = 7 ;
}else {
dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1 ;
}
return dayForWeek;
}

public static int getCompareResult(Date date, Date targetDate) {
return formatDate(date, DateUtils.PATTERN_DATE_TIME_YEAR).compareTo(DateUtils.formatDate(targetDate, DateUtils.PATTERN_DATE_TIME_YEAR));
}

/**
* 方法注释: <br>
* 〈时间增加一个小时〉
* @param hour
* @return java.util.Date
* @author cj 🤡
* @date 2024/1/17 19:15
*/
public static Date timeSubtraction(Integer hour){
// 当前时间
LocalDateTime currentDateTime = LocalDateTime.now();

// 添加小时
LocalDateTime newDateTime = currentDateTime.plusHours(hour);

Date date = Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant());


return date;
}

public static void main(String[] args) {
Date startTime= DateUtils.formatDate(new Date(), DateUtils.PATTERN_DATE_HOUR_MS);
startTime.setDate(new Date().getDate());
Date start= DateUtils.parseDateHours("16:30:00");

Date end= DateUtils.parseDateHours("23:30:00");
if ((start.after(startTime))) {
System.out.println(true);
}

if ((end.before(startTime))) {
System.out.println(true);
}
}
}



+ 192
- 0
src/main/java/com/szyx/tcm/supervision/util/InsuranceWechatUtil.java Wyświetl plik

@@ -0,0 +1,192 @@
package com.szyx.tcm.supervision.util;

import com.tencent.mip.DataHandler;
import org.dromara.hutool.core.util.RandomUtil;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.UUID;

/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceWechatUtil.java
* @包 路 径: com.szyx.tcm.common.utils
* @Copyright:wy (C) 2024 *
* @Description: 医保支付参数封装工具类
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/22 13:42
* @Modify:
*/
public class InsuranceWechatUtil {

// ================= 医保核心系统有关方法 ===========================

/**
* 医保核心系统-生成发送报文ID
*
* @param Code 医院机构编码 K开头
*/
public static String getMsgId(String Code) {

// 时间类型 yyyyMMddHHmmss
// 顺序号 待定 todo
if (Code == null) {
Code = "";
}
return Code + DateUtils.format(new Date(), DateUtils.PATTERN_YYYYMMDDHHMMSS) + RandomUtil.randomNumbers(4);
}


// ================= 医保支付中台有关方法 ===========================

/**
* 根据公私钥和appID生成请求报文
*/
public static String getReqMessageForInsuranceCore(String appid, String appSecret, String publicKey,String privateKey,String plainJSON) throws Exception {
DataHandler dataHandler = DataHandler.newInstance(appid,appSecret,publicKey,privateKey);
dataHandler.setVersion("2.0.1");

return dataHandler.buildReqData(plainJSON);

}






// ================= 微信医保支付平台有关方法 ===========================

/**
*
*/
private final static char[] hexArray = "0123456789abcdef".toCharArray();

//签名工具 获取信息服务接口
private static String createSignature(String partnerSecret, String partnerId, String timestamp)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(partnerSecret.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
return bytesToHex(sha256_HMAC.doFinal((partnerId + timestamp).getBytes("UTF-8")));
}

private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0Xff;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}

/**
* 发送请求
* 微信免密授权请求
* @param businessName 自定义业务名称
* @param funcName 自定义功能名称
* @param urlPath 请求路径
* @param partnerId 合作方ID
* @param data 请求数据
* @return 返回结果
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
public static String postData(String businessName, String funcName, String partnerSecret, String urlPath, String partnerId, String data)
throws IOException, NoSuchAlgorithmException, InvalidKeyException {
HttpURLConnection conn = null;
URL url = new URL(urlPath);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(true);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
String timestamp = Long.toString(System.currentTimeMillis());
String signature = createSignature(partnerSecret, partnerId, timestamp);
String requestId = UUID.randomUUID().toString().replaceAll("-", "");
conn.setRequestProperty("god-portal-timestamp", timestamp);
conn.setRequestProperty("god-portal-signature", signature);
conn.setRequestProperty("god-portal-request-id", requestId);
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(data.getBytes());
os.flush();
os.close();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
InputStream inputStream = conn.getInputStream();
byte[] bytes = new byte[1024];
int readBytes;
while ((readBytes = inputStream.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, readBytes);
}
bytes = byteArrayOutputStream.toByteArray();
inputStream.close();
conn.disconnect();
return new String(bytes, "utf-8");
}


public static void main(String[] args) {
// 收到的1101报文
String s = "{\n" +
" \"infcode\": \"1\",\n" +
" \"inf_refmsgid\": \"000000202001041235391234567890\",\n" +
" \"refmsg_time\": \"20200201133411352\",\n" +
" \"respond_time\": \"20200202133731456\",\n" +
" \"err_msg\": \"\",\n" +
" \"output\": {\n" +
" \"baseinfo\": {\n" +
" \"psn_no\": \"131000202001001\",\n" +
" \"psn_cert_type\": \"2\",\n" +
" \"certno\": \"510000202001010000\",\n" +
" \"psn_name\": \"李四\",\n" +
" \"gend\": \"1\",\n" +
" \"naty\": \"01\",\n" +
" \"brdy\": \"2020-01-01\",\n" +
" \"age\": 18\n" +
" },\n" +
" \"insuinfo\": {\n" +
" \"psn_insu_rlts_id\": \"133241523001001\",\n" +
" \"balc\": 5000,\n" +
" \"insutype\": \"310\",\n" +
" \"psn_type\": \"1001\",\n" +
" \"cvlserv_flag\": \"0\",\n" +
" \"insu_admdvs\": \"131002\",\n" +
" \"emp_name\": \"测试单位\"\n" +
" },\n" +
" \"idetinfo\": [\n" +
" {\n" +
" \"psn_idet_type\": \"1\",\n" +
" \"psn_type_lv\": \"1\",\n" +
" \"memo\": \"\",\n" +
" \"begntime\": \"2020-01-01 00:00:00\",\n" +
" \"endtime\": \"\"\n" +
" },\n" +
" {\n" +
" \"psn_idet_type\": \"2\",\n" +
" \"psn_type_lv\": \"1\",\n" +
" \"memo\": \"\",\n" +
" \"begntime\": \"2020-01-01 00:00:00\",\n" +
" \"endtime\": \"\"\n" +
" }\n" +
" ]\n" +
" }\n" +
"}";


}


}

+ 187
- 0
src/main/java/com/szyx/tcm/supervision/util/SZYXAccessUtil.java Wyświetl plik

@@ -0,0 +1,187 @@
package com.szyx.tcm.supervision.util;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/*******************************************************************
* <pre></pre>
* @文件名称: SZYXAccessUtil.java
* @包 路 径: com.szyx.tcm.supervision.util
* @Copyright:wy (C) 2024 *
* @Description:
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/26 17:02
* @Modify:
*/
public class SZYXAccessUtil {


private static final String[] STAND = {"2", "3", "5", "7"};
private static final String[] CLOCK = {"0", "1", "4", "6", "8", "9"};

private static final String AES_KEY = "szyx6666szyx6666";

// 获取加密时间戳

/**
* 获取加密时间戳
*
* @param timeStamp 时间戳
* @return 加密时间戳
*/
public static String encryptTimeStamp(Long timeStamp) {
String last3 = splitLast3(timeStamp);
String encrypteded = encryptedSwitch(last3);
return timeStamp.toString().substring(0, 10) + encrypteded;
}

// 验证时间戳
public static boolean verifyTimeStamp(final String timeStamp, final String accessToken) {
long ts = Long.parseLong(timeStamp);
long now = System.currentTimeMillis();
if (now - ts > 1000 * 60 * 5) {
return false;
}
return decryptByAES(accessToken).equals(replaceEncryptedLast3(Long.parseLong(timeStamp)));
}

// 使用AES加密时间戳

/**
* 使用AES加密时间戳
*
* @param content 时间戳
* @return aes报文
*/
public static String encryptByAES(final String content) {
byte[] bytes = new byte[0];
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(AES_KEY.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
bytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException
| BadPaddingException e) {
throw new RuntimeException(e);
}
return Base64.getEncoder().encodeToString(bytes);
}

// 使用AES解密获取校验时间戳

/**
* 使用AES解密获取校验时间戳
*
* @param content aes报文
* @return 时间戳
*/
public static String decryptByAES(final String content) {
byte[] bytes = new byte[0];
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(AES_KEY.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
bytes = cipher.doFinal(Base64.getDecoder().decode(content));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
throw new RuntimeException(e);
}
return new String(bytes, StandardCharsets.UTF_8);
}

public static String replaceEncryptedLast3(Long timeStamp) {
String last3 = splitLast3(timeStamp);
String decrypted = decryptedSwitch(last3);
return timeStamp.toString().substring(0, 10) + decrypted;
}

private static String splitLast3(Long timeStamp) {
return timeStamp.toString().substring(10);
}

private static String encryptedSwitch(String num) {
StringBuilder switched = new StringBuilder();
int index = 1;
for (int i = num.length() - 1; i >= 0; i--) {
int digit = Integer.parseInt(String.valueOf(num.charAt(i)));
switched.insert(0, encrypted(digit, index));
index++;
}
return switched.toString();
}

private static String decryptedSwitch(String num) {
StringBuilder switched = new StringBuilder();
int index = 1;
for (int i = num.length() - 1; i >= 0; i--) {
int digit = Integer.parseInt(String.valueOf(num.charAt(i)));
switched.insert(0, decrypted(digit, index));
index++;
}
return switched.toString();
}

private static int encrypted(int n, int index) {
if (isStand(n)) {
return n;
} else {
return index % 2 == 0 ? getClockWise(n, index) : getAntiClockWise(n, index);
}

}

private static int decrypted(int n, int index) {
if (isStand(n)) {
return n;
} else {
return index % 2 == 0 ? getAntiClockWise(n, index) : getClockWise(n, index);

}
}

private static boolean isStand(int n) {
for (String s : STAND) {
if (s.equals(String.valueOf(n))) {
return true;
}
}
return false;
}

private static int getClockWise(int n, int step) {
int len = CLOCK.length;
int index = 0;
for (int i = 0; i < len; i++) {
if (CLOCK[i].equals(String.valueOf(n))) {
index = i;
break;
}
}
int newIndex = (index + step) % len;
return Integer.parseInt(CLOCK[newIndex]);
}

private static int getAntiClockWise(int n, int step) {
int len = CLOCK.length;
int index = 0;
for (int i = 0; i < len; i++) {
if (CLOCK[i].equals(String.valueOf(n))) {
index = i;
break;
}
}
int newIndex = (index - step + len) % len;
return Integer.parseInt(CLOCK[newIndex]);
}



}

+ 4
- 0
src/main/resources/application.properties Wyświetl plik

@@ -12,6 +12,10 @@ spring.servlet.multipart.max-request-size=150MB
spring.servlet.multipart.enabled=true
spring.main.allow-bean-definition-overriding=true
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
arthas.slient-init=true

# \u533B\u4FDD\u4E13\u7F51\u914D\u7F6E
insurance.host =http://localhost:9345/


## \u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014 mysql \u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014


+ 215
- 0
src/test/java/com/szyx/tcm/supervision/InsuranceCoreDemo.java Wyświetl plik

@@ -0,0 +1,215 @@
package com.szyx.tcm.supervision;


import com.alibaba.fastjson.JSONObject;

import com.szyx.tcm.supervision.model.dto.insurance.DiseInfo;
import com.szyx.tcm.supervision.model.dto.insurance.FeeDetail;
import com.szyx.tcm.supervision.model.dto.insurance.InsuranceCoreOutputMessage1101;
import com.szyx.tcm.supervision.model.dto.insurance.InsuranceUploadRecipeDetailInputMessage;
import com.szyx.tcm.supervision.util.DateUtils;
import com.szyx.tcm.supervision.util.InsuranceWechatUtil;
import com.tencent.mip.DataHandler;
import com.tencent.mip.MIPayInvoker;
import com.tencent.mip.model.DetailUploadReq;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;


/*******************************************************************
* <pre></pre>
* @文件名称: InsuranceCoreDemo.java
* @包 路 径: org.szyx.tcm.applet
* @Copyright:wy (C) 2024 *
* @Description: 河南医保局 医保核心系统调用demo
* @Version: V1.0
* @Author: wy
* @Date: 2024/7/17 16:41
* @Modify:
*/
public class InsuranceCoreDemo {

private static final String url = "http://localhost:8097/fsi/api/rsfComIfsService/callService";

// private static final

private static String appSecret = "cb5405c1053da6e27ac2e6c5ea63c25b"; // 应⽤密钥
private static String appId = "wx988658e383760cea"; // 应⽤ID
private static String publicKey = "IYNKr8u66CDfzTkChz44e7AocWNqLTEO"; // 平台公钥
private static String privateKey = "IYNKr8u66CDfzTkChz44e7AocWNqLTEO"; // 渠道私钥
private static String reqUrl = "********************";

private static String fixmedinsCode = "H41148100267"; // 定点医疗机构编码

private static String mdtrtareaAdmvs = "411401"; // 就诊地医保区划

private static String authCode = "AUTH410100202205241618510007210"; // 授权码





public static void main(String[] args) throws IOException {
// 6201、6202 签名sdk
// 请求报文
DataHandler dataHandler = DataHandler.newInstance(appId,appSecret,publicKey,privateKey);
dataHandler.setVersion("2.0.1");

MIPayInvoker miPayInvoker = MIPayInvoker.newInstance(dataHandler);
DetailUploadReq detailUploadReq = new DetailUploadReq();




}


@Test
public void test1() throws Exception {
System.out.println("test1");


InsuranceUploadRecipeDetailInputMessage uploadData = new InsuranceUploadRecipeDetailInputMessage();
buildText(uploadData);



String reqMessageForInsuranceCore = InsuranceWechatUtil
.getReqMessageForInsuranceCore(appId, appSecret, publicKey, privateKey, JSONObject.toJSONString(uploadData));

System.out.println(reqMessageForInsuranceCore);


}

private void buildText(InsuranceUploadRecipeDetailInputMessage uploadData){

// 医保核心系统患者基本信息
InsuranceCoreOutputMessage1101.Baseinfo baseinfo = new InsuranceCoreOutputMessage1101.Baseinfo();
baseinfo.setPsnNo("131000202001001");
baseinfo.setPsnCertType("2");
baseinfo.setCertno("510000202001010000");
baseinfo.setPsnName("李四");
baseinfo.setGend("1");
baseinfo.setNaty("01");
baseinfo.setBrdy("2020-01-01");
baseinfo.setAge("18");


// 医保核心系统保信息
InsuranceCoreOutputMessage1101.Insuinfo insuinfo = new InsuranceCoreOutputMessage1101.Insuinfo();
insuinfo.setPsnInsuRltsId("133241523001001");
insuinfo.setBalc(new BigDecimal("5000"));
insuinfo.setInsutype("310");
insuinfo.setPsnType("1001");
insuinfo.setCvlservFlag("0");
insuinfo.setInsuplcAdmdvs("131002");
insuinfo.setEmpName("测试单位");





// 费用明细
List<FeeDetail> feedetailList = new ArrayList<>();
// 诊断或状态明细
List<DiseInfo> diseinfoList = new ArrayList<>();


uploadData.setOrgCodg(fixmedinsCode);
// uploadData.setOrgId();
uploadData.setPsnNo(baseinfo.getPsnNo());
uploadData.setIdType(insuinfo.getInsutype());
uploadData.setMedOrgOrd(UUID.randomUUID().toString().replace("-", ""));
// 电子处方流转标志 todo 目前河南省并未测试过电子处方线上医保支付
uploadData.setRxCircFlag("0");
uploadData.setBegntime(DateUtils.format(new Date(), DateUtils.PATTERN_DATE_TIME));
uploadData.setIdNo(baseinfo.getCertno());
uploadData.setUserName(baseinfo.getPsnName());
uploadData.setIdType("01");
uploadData.setEcToken(authCode);
uploadData.setInsuCode(mdtrtareaAdmvs);
uploadData.setIptOtpNo(UUID.randomUUID().toString().replace("-", ""));
// 字典 dept
uploadData.setDeptName("预防保健科");
uploadData.setCaty("A01");
uploadData.setMedType("91");
uploadData.setFeeType("05");
uploadData.setMedfeeSumamt(new BigDecimal("0.01"));
// uploadData.setAcctUsedFlag("0");
uploadData.setDiseCodg("A01.001");
uploadData.setDiseName("感冒");
uploadData.setPsnSetlway("01");
// 公立医院内容 todo 疑问点 互联网医院是否为公立医院 公立医院改革标志 如何传参
uploadData.setChrgBchno(UUID.randomUUID().toString().replace("-", ""));
uploadData.setDiseinfoList(diseinfoList);
uploadData.setFeedetailList(feedetailList);

// ========组装诊断数据========
DiseInfo diseInfo = new DiseInfo();
diseinfoList.add(diseInfo);
// 西医诊断
diseInfo.setDiagType("1");
// todo 确认诊断排序号
diseInfo.setDiagSrtNo(1);
diseInfo.setDiagCode("A01.001");
diseInfo.setDiagName("感冒");
diseInfo.setDiagDept("预防保健科");
diseInfo.setDiseDorNo("wy");
diseInfo.setDiseDorName("wy");
diseInfo.setDiagTime(DateUtils.format(new Date(), DateUtils.PATTERN_DATE_TIME));
diseInfo.setValiFlag("1");

//========组装费用数据========
FeeDetail feeDetail = new FeeDetail();

feedetailList.add(feeDetail);
// 如果是诊疗 传问诊单号
feeDetail.setFeedetlSn("10086");
feeDetail.setMdtrtId(UUID.randomUUID().toString().replace("-", ""));
feeDetail.setPsnNo(baseinfo.getPsnNo());
feeDetail.setChrgBchno(uploadData.getChrgBchno());
// 同一收费批次号病种编号必须一致 todo 确认 多药品多问题
feeDetail.setDiseCodg("A01.001");
feeDetail.setRxno("100866");
feeDetail.setRxCircFlag("0");
feeDetail.setFeeOcurTime(DateUtils.format(new Date(), DateUtils.PATTERN_DATE_TIME));
// 医疗目录编码 todo 确认互联网医院处方的医疗目录编码
feeDetail.setMedListCodg("A01.001");
// 医药机构目录编码 todo 确认互联网医院处方的医药机构目录编码
feeDetail.setMedinsListCodg("A01.001");
feeDetail.setDetItemFeeSumamt(new BigDecimal("0.01"));
feeDetail.setCnt(new BigDecimal("1"));
feeDetail.setPric(new BigDecimal("0.01"));
feeDetail.setBilgDeptCodg("A01.001");
feeDetail.setBilgDeptName("预防保健科");
feeDetail.setBilgDrCodg("wy");
feeDetail.setBilgDrName("wy");
feeDetail.setHospApprFlag("1");
// todo 确认互联网医院处方的医疗类别
feeDetail.setMedType("医疗类别");
feeDetail.setMedListName("医疗目录名称");
feeDetail.setMedListSpc("医疗目录规格");









}






}

Ładowanie…
Anuluj
Zapisz