@@ -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> | |||
@@ -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(); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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"; | |||
// ================= 微信医保支付平台有关 =========================== | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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"; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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(); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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" + | |||
"}"; | |||
} | |||
} |
@@ -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]); | |||
} | |||
} |
@@ -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 | |||
@@ -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("医疗目录规格"); | |||
} | |||
} |