将密保答案加密后保存
diff --git a/backend/src/main/java/com/supwisdom/dlpay/medical/domain/TBMedicalDtl.java b/backend/src/main/java/com/supwisdom/dlpay/medical/domain/TBMedicalDtl.java
index e8f32b8..bcff4b8 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/medical/domain/TBMedicalDtl.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/medical/domain/TBMedicalDtl.java
@@ -4,11 +4,11 @@
@Entity
@Table(name = "th_medicaldtl", indexes = {
- @Index(name = "medicaldtl_idx", columnList = "uid,emergency,feeno,organizationid"),
+ @Index(name = "medicaldtl_idx", columnList = "emergency,feeno,organizationid,uid"),
@Index(name = "medicaldtl_idx2", columnList = "uid,accdate,organizationid"),
@Index(name = "medicaldtl_idx3", columnList = "medicaldate,paystatus,resultid,organizationid"),
@Index(name = "medicaldtl_idx4", columnList = "patientid,organizationid"),
- @Index(name = "medicaldtl_idx5", columnList = "hisrefundno,organizationid",unique = true)})
+ @Index(name = "medicaldtl_idx5", columnList = "hisrefundno,organizationid", unique = true)})
public class TBMedicalDtl {
@Id
@Column(name = "billno", length = 32)
@@ -35,7 +35,7 @@
/**
* 归并费用名称
*/
- @Column(name = "mergingname",length = 100)
+ @Column(name = "mergingname", length = 100)
private String mergingname;
/**
* 加收费用描述
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBUserSecurity.java b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBUserSecurity.java
index 70a9a83..e15f53f 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBUserSecurity.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBUserSecurity.java
@@ -20,7 +20,7 @@
@Column(name = "uid", nullable = false, length = 32)
private String uid;
- @Column(name = "answer",length = 200)
+ @Column(name = "answer",length = 64)
private String answer;
public String getId() {
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/medical/dao/MedicalDtlDao.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/medical/dao/MedicalDtlDao.kt
index 1709636..372b321 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/medical/dao/MedicalDtlDao.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/medical/dao/MedicalDtlDao.kt
@@ -19,8 +19,14 @@
fun findByMedicaldateBetweenAndPaystatusAndResultidIsNullAndTradeflag(beginTime: String, endTime: String, status: String, tradeflag: String, pageable: Pageable): List<TBMedicalDtl>?
- fun findByUidAndEmergencyAndFeenoAndOrganizationidAndPaystatusNot(
- uid: String, emergency: String, feeNo: String, organizationId: String, payStatus: String): TBMedicalDtl?
+ fun findByEmergencyAndFeenoAndOrganizationidAndUidAndPaystatusNot(
+ emergency: String, feeNo: String, organizationId: String, uid: String, payStatus: String): TBMedicalDtl?
+
+ fun findByEmergencyAndFeenoAndOrganizationidAndUidNotAndPaystatusIn(
+ emergency: String, feeNo: String, organizationId: String, uid: String, payStatus: List<String>): List<TBMedicalDtl>?
+
+ fun findByEmergencyAndFeenoAndOrganizationidAndPaystatus(
+ emergency: String, feeNo: String, organizationId: String, payStatus: String): TBMedicalDtl?
fun findByUidAndOrganizationidAndPaystatusOrderByTransdateDescTranstimeDesc(uid: String, organizationId: String, payStatus: String, pageable: Pageable): List<TBMedicalDtl>?
}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/MedicalService.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/MedicalService.kt
index 464dddd..d8197ab 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/MedicalService.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/MedicalService.kt
@@ -80,5 +80,5 @@
fun refundMedicalDtlConfirm(originBillNo: String, refundMedicalDtl: TBMedicalDtl): TBMedicalDtl
@Transactional
- fun queryrefundResult(bean: PayRefundRequestBean): TBMedicalDtl
+ fun queryRefundResult(bean: PayRefundRequestBean): TBMedicalDtl
}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/impl/MedicalServiceImpl.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/impl/MedicalServiceImpl.kt
index 1d54ab0..f09ba45 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/impl/MedicalServiceImpl.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/medical/service/impl/MedicalServiceImpl.kt
@@ -213,32 +213,42 @@
}
override fun getUnPayedList(uid: String, organizationId: String, data: String, queryType: Int): List<UnPayedDTO> {
- // 根据证件号或医疗卡查询未支付账单
+ // 1.根据证件号或医疗卡查询未支付账单
val unPayedResponse = getUnPayedResponse(organizationId, data, queryType)
val unPayedDTOList = ArrayList<UnPayedDTO>()
val hospital = hospitalDao.findByHospitalcodeAndStatus(organizationId, TradeDict.STATUS_NORMAL)
?: throw MedicineException("未找到该医院")
- // 拆分每次就诊下的每个项目为一条展示数据(一次就诊中可能有几个项目共用一个feeNo,只能一起结算)
+ // 2.拆分每次就诊下的每个项目为一条展示数据(一次就诊中可能有几个项目共用一个feeNo,只能一起结算)
unPayedResponse.medicalInformation.forEach { medicalInformation ->
val map = HashMap<String, TBMedicalDtl>()
for (mergingItems in medicalInformation.mergingItems) {
- // 因为异步通知HIS,HIS中数据有延迟,所以本地扣费成功后的流水仍有可能被查询到
- val localDtl = medicalDtlDao.findByUidAndEmergencyAndFeenoAndOrganizationidAndPaystatusNot(
- uid, medicalInformation.emergencyNumber!!, mergingItems.feeNo!!,
- organizationId, MedicalConstant.DTL_STATUS_FAIL)
+ // 2.1.1因为可通过输入就诊卡号查询医疗账单,同一笔账单可能被多用户支付
+ val payStatus = ArrayList<String>()
+ payStatus.addAll(arrayOf(MedicalConstant.DTL_STATUS_WIP, MedicalConstant.DTL_STATUS_SUCCESS))
+ val payedList = medicalDtlDao.findByEmergencyAndFeenoAndOrganizationidAndUidNotAndPaystatusIn(
+ medicalInformation.emergencyNumber!!, mergingItems.feeNo!!,
+ organizationId, uid, payStatus)
+ // 2.1.2如果有其他用户针对同一笔医疗账单的流水,且支付状态为wip或success,则不展示该条医疗账单
+ if (!payedList.isNullOrEmpty()) {
+ continue
+ }
+
+ // 2.2因为异步通知HIS,HIS中数据有延迟,所以本地扣费成功后的流水仍有可能被查询到
+ val localDtl = medicalDtlDao.findByEmergencyAndFeenoAndOrganizationidAndUidAndPaystatusNot(
+ medicalInformation.emergencyNumber!!, mergingItems.feeNo!!,
+ organizationId, uid, MedicalConstant.DTL_STATUS_FAIL)
var skip = false
if (localDtl != null) {
if (localDtl.paystatus == MedicalConstant.DTL_STATUS_SUCCESS) {
- // 已扣费成功,等待通知HIS成功,此处无须处理
+ // 已扣费成功,等待通知HIS成功,此处无须处理
continue
- } else {
- // 当流水为init或wip时都跳过生成本地流水
- skip = true
}
+ // 当流水为init或wip时都跳过生成本地流水
+ skip = true
}
- // 查看该feeNo的是否已出现过
+ // 2.3查看该feeNo的是否已出现过
if (!map.containsKey(mergingItems.feeNo!!)) {
- // 该feeNo首次出现
+ // 2.3.1该feeNo首次出现
if (!skip) {
val medicalDtl = TBMedicalDtl().apply {
this.billno = systemUtilService.refno
@@ -271,9 +281,9 @@
map[mergingItems.feeNo!!] = localDtl
}
} else {
- // 该feeNo已出现,将该条数据同之前的数据合并成一条流水
+ // 2.3.2该feeNo已出现,将该条数据同之前的数据合并成一条流水
val medicalDtl = map[mergingItems.feeNo!!]!!
- // 如果本地流水已生成,此处无需处理
+ // 2.3.3如果本地流水已生成,此处无需处理
if (!medicalDtl.created) {
// 将金额累加
medicalDtl.mergingsubtotal = MoneyUtil.add(medicalDtl.mergingsubtotal, mergingItems.mergingSubtotal!!)
@@ -282,7 +292,7 @@
}
}
map.forEach { (_, medicalDtl) ->
- // 本地流水未创建,生成本地流水
+ // 本地流水未创建,保存本地流水
if (!medicalDtl.created) {
medicalDtlDao.save(medicalDtl)
}
@@ -368,6 +378,14 @@
override fun medicalPayPreInit(uid: String, bean: PaymentRequestBean) {
val medicalDtl = medicalDtlDao.findByBillnoForUpdate(bean.billno)
?: throw MedicineException("未找到流水为[${bean.billno}]的流水")
+ // 手动输入就诊卡号查询流水,可能存在多个用户支付同一笔医疗账单的情况,查询该账单是否已被支付
+ val payStatus = ArrayList<String>()
+ payStatus.addAll(arrayOf(MedicalConstant.DTL_STATUS_WIP, MedicalConstant.DTL_STATUS_SUCCESS))
+ val payedList = medicalDtlDao.findByEmergencyAndFeenoAndOrganizationidAndUidNotAndPaystatusIn(
+ medicalDtl.emergency, medicalDtl.feeno, medicalDtl.organizationid, uid, payStatus)
+ if (!payedList.isNullOrEmpty()) {
+ throw MedicineException("该流水已被支付,请刷新后再试")
+ }
if (medicalDtl.paystatus != null && medicalDtl.paystatus != MedicalConstant.DTL_STATUS_INIT) {
throw MedicineException("该流水状态异常,请查询后再试")
}
@@ -411,7 +429,7 @@
this.hasJson = true
}
}
-
+
val preFeeResponse = medicalClient.getPreCalculatedFee(preFeeRequest)
if (preFeeResponse.payAmount != medicalDtl.mergingsubtotal || preFeeResponse.totalFee != medicalDtl.mergingsubtotal) {
throw MedicineException("该流水缴费金额异常")
@@ -872,7 +890,7 @@
}
}
- override fun queryrefundResult(bean: PayRefundRequestBean): TBMedicalDtl {
+ override fun queryRefundResult(bean: PayRefundRequestBean): TBMedicalDtl {
val medicalDtl = medicalDtlDao.findByBillnoForUpdate(bean.outOrderNumber)
?: throw MedicineException("未找到订单号为:${bean.outOrderNumber}的订单,请检查订单号是否正确")
if (!medicalDtl.requestbillno.isNullOrEmpty()) {
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
index 743bb7b..982a6a2 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -442,7 +442,7 @@
if (refundToken != bean.token) {
return JsonResult.error("token检验失败,请检查是否正确")
}
- val medicalDtl = medicalService.queryrefundResult(bean)
+ val medicalDtl = medicalService.queryRefundResult(bean)
val map = HashMap<String,String>()
val jsonResult = JsonResult.ok()
if (medicalDtl.paystatus == MedicalConstant.DTL_STATUS_SUCCESS) {
@@ -479,9 +479,6 @@
?: return JsonResult.error("用户不存在")
}
val data = secretSecurityService.getSecretSecurityList(user.uid)
- if (data.isNullOrEmpty()) {
- return JsonResult.error("用户未设置密保问题")
- }
JsonResult.ok().put("data", data)
} catch (e: Exception) {
if (e is PortalBusinessException) {
@@ -1699,7 +1696,7 @@
}
/**
- * 获取密保列表
+ * 获取所有密保问题
*/
@RequestMapping(value = ["/security/all"], method = [RequestMethod.GET])
fun getAllSecretSecurity(): JsonResult? {
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/SecretSecurityServiceImpl.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/SecretSecurityServiceImpl.kt
index 83940d1..9c762df 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/SecretSecurityServiceImpl.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/SecretSecurityServiceImpl.kt
@@ -7,6 +7,7 @@
import com.supwisdom.dlpay.portal.domain.TBSecretSecurity
import com.supwisdom.dlpay.portal.service.SecretSecurityService
import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.stereotype.Service
@Service
@@ -33,8 +34,10 @@
// 先删除用户之前所有的问题再保存
val list = userSecurityDao.findByUid(bean.uid)
if (!list.isNullOrEmpty()) {
- userSecurityDao.deleteAll(list)
+ throw PortalBusinessException("您已设置密保,请先删除后再保存")
}
+ // 对密保答案加密处理
+ val encoder = BCryptPasswordEncoder()
answers.forEach {
if (it.answer.isNullOrEmpty()) {
throw PortalBusinessException("密保答案不能为空")
@@ -43,19 +46,21 @@
throw PortalBusinessException("密保答案长度必须为2-20个字符")
}
it.uid = bean.uid
+ it.answer = encoder.encode(it.answer)
userSecurityDao.save(it)
}
}
- override fun checkUserSecurity(bean: UserSecurityRequestBean):String? {
+ override fun checkUserSecurity(bean: UserSecurityRequestBean): String? {
val answers = bean.answers
if (answers.isNullOrEmpty() || answers.size < 3) {
throw PortalBusinessException("请至少回答三个密保问题")
}
+ val encoder = BCryptPasswordEncoder()
answers.forEach {
val userSecurity = userSecurityDao.findByUidAndSsid(bean.uid, it.ssid)
?: throw PortalBusinessException("未找到密保问题")
- if (it.answer != userSecurity.answer) {
+ if (!encoder.matches(it.answer, userSecurity.answer)) {
return it.ssid
}
}