diff --git a/pom.xml b/pom.xml index 2d63ba8..e776c35 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ 1.18.4 3.0.3 2.7.1 + 0.4.4 @@ -235,6 +236,13 @@ simple-xml ${simple-xml.version} + + + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + ${wechatpay-apiv3.version} + diff --git a/xinelu-admin/src/main/resources/application.yml b/xinelu-admin/src/main/resources/application.yml index 8f26272..14d25aa 100644 --- a/xinelu-admin/src/main/resources/application.yml +++ b/xinelu-admin/src/main/resources/application.yml @@ -243,7 +243,7 @@ xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) - excludes: /system/notice + excludes: /system/notice,/system/station/add,/system/station/edit,/system/stationItem/add,/system/stationItem/edit,/system/operateGoodInfo/add,/system/operateGoodInfo/edit,/system/goodsInfo/add,/system/goodsInfo/edit,/system/hospital/add,/system/hospital/edit,/system/informationInfo/add,/system/informationInfo/edit,/system/trainingItem/edit,/system/trainingItem/add # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* @@ -276,21 +276,6 @@ applet-chat-config: # 微信小程序事件回调消息加密密钥 encoding-aes-key: 5rbyhMBpdnxTEVT54zeHMNcXi3ccilQZ209QqGi89EW -# 护理员微信小程序参数配置信息 -nurse-applet-chat-config: - # 微信小程序id,wxa4f2b43d2ccb9908 - applet-id: wxa4f2b43d2ccb9908 - # 微信小程序密钥, - secret: faeba9fc043cfdcb088f43be1747e054 - # 微信小程序返回国家语言 - lang: zh_CN - # 微信小程序授权类型 - grant-type: authorization_code - # 微信小程序事件回调令牌 - token: Yw3vfW1ILpc34qAVDtTpB2hesAMCpvW0 - # 微信小程序事件回调消息加密密钥 - encoding-aes-key: Lr2uq0F3ds36ZA4AUv1h3Pki0JO1Ql0QeG0z1r4A3at - # 小程序首页路径 applet-page-config: # 首页跳转路径 @@ -305,3 +290,37 @@ applet-page-config: integral-page-url: pages/integral/integral # 护理结构详情页面跳转路径 nursestation-details-page-url: pages/nursestation/nursestation + +# 新医路微信商户号配置参数 +xyl-we-chat-config: + xyl-mch-id: 1633348407 + xyl-mch-serial-no: 7C6A18FC8E1F0445901B1BE1C4DD1ACE284C3D79 + xyl-private-key-path: xinyilu_apiclient_key.pem + xyl-payment-key: Xyl699003981qazVFR4xsw23edcASDFG + xyl-wechat-notify-url: https://1608.xinelu.cn + +# 医路优品微信商户号配置参数 +ylyp-we-chat-config: + ylyp-mch-id: 1633506981 + ylyp-mch-serial-no: 7840E8CE4B9B1F0F19D5DD2AB7BC159E007F9D90 + ylyp-private-key-path: yiluyoupin_apiclient_key.pem + ylyp-payment-key: Xyk699003981qazxsw23edcvfr4bgt56 + ylyp-we-chat-notify-url: https://1608.xinelu.cn + +# 微信支付接口地址,包含小程序和App支付接口地址 +we-chat-payment-url-config: + jsapi-palce-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi + query-order-no-url: https://api.mch.weixin.qq.com/v3/pay/transactions/id/%s + query-mch-id-url: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s + close-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s/close + refund-apply-url: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds + refund-query-order-url: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/%s + trade-apply-bill-url: https://api.mch.weixin.qq.com/v3/bill/tradebill + capital-apply-bill-url: https://api.mch.weixin.qq.com/v3/bill/fundflowbill + app-place-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/app + +# 快递鸟物流查询参数配置 +logistics-config: + e-business-id: 1781371 + api-key: 998b273d-c926-4659-a9d5-ae0613782d70 + express-bird-url: https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx diff --git a/xinelu-admin/src/main/resources/xinyilu_apiclient_key.pem b/xinelu-admin/src/main/resources/xinyilu_apiclient_key.pem new file mode 100644 index 0000000..9cf8337 --- /dev/null +++ b/xinelu-admin/src/main/resources/xinyilu_apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDFgFmuT17PjBIN +B0wSGnchCCsB9ZRZZFpcpvBpO+VLspmTSM//zV621uTzZeWNONEBzwO4C7VCsbHW +gu7R5AQj9FYSzTKdycvs+097qQcQAvMr3VwrX0/dtH2U0iFX6zr3ztDKv2eQBegu +wEcZsoOEgEW1rsjs/t2MTJJLPYWfzDDUbDBJi2hKFzSGAPfpqeOz0+loKNUz/i7V +/dg5TXlbWfe0gdf4SI04sdrUkNsbQKabc7hWoPSVaRnX4ywfgzW8fHaIP+vuTzHr +p7h5dnFNUuA5CdobDnIl0sz+ekLfCFuX4pCYNE6uR/58uknmXW0jfrK/WPU5T+F7 +sGDIsuJHAgMBAAECggEADIrkJx+/Q6r/kng+KoAnxJ9CK/OuoiavXmbzqZs2KqKD +AkmDfBlMxIvNKm/0Lg3HqDe/YrbLohqq0paqGAZFBQuFU9hYOJESNFCZcZ8AZdHq +I4UBT3fUGJ5Xw1W87Fpx+j7WH6ocJ5dYcW+glE8z7vw+cRVSiUp+Q2SxfbnAfK9c +anqJLWA8pxkGRcXzE/tcB4JAkPsluWslFPDeKVOZ5/NRs8oE5ppmQKxqx2KFK7rh +S0irhlJ/6t1jiI3t+syYXJILwbutJ9PUFaS1Uu3CErcvmBwWiLRZEkNa7xMlzEk+ +R2dplVhT0W++Ku1cjtU4q7V+paea+/YZj3mtos45YQKBgQDsFc4KM8/Lm146dNJX +TOK1pDjZD5rfEpgtHCEm6dBRbueOYjb/D1Lo/JU4L6Yl2fGsJNtTX4a8i38nxTuI +6b+SEQoLinEyr8JQtBFMvU4vYOIiA5oCHaZIXn0WLLFbUBkOhq/dXC4xDT6MOyNd +2rDTSwvLqVE8K8sbupcvRP/RLwKBgQDWKVayVKGHz3cT+YyPhGTD19yBM0w6AGBR +MLNKdKek7/BnKXe009fxDg/gCtGUBmE+umFbEBLStg7zD31JXLm5/LyT2NBkJYRl +neO9UW8tWbnL6DOGgNvQTqDN650Od39R8rVoRSH4H4az6A/B1qrJReyrGw7xDXOz +0eAq9vnKaQKBgH1IDPDJEepAZr6qo7yEJoKxxSEa8NqT6YF2vfkCdvPf4K1kXT75 +CMxuzVjloEvR3je1z1XtCXkgpbebKL69HFYNCMGbE/sL3hgplkyc4NKvnRDjzGR3 +C3i3+7U6vltwo/tbahQUCMcq+hg8gcYaeV+HIZlQHrXJn5z1ZalF+mMtAoGAKVgZ +sJu+A2X96xFGHX7FpTlLDHZGxPvFnGb2de1HYAQiOQg8X+B108ePMQVlqFoC9AUv +PlFAEQWspSfcXAlWoZ01GqXEtVC42pU8nhPWjr6/q6nMKK8/wFstmBNgYqaXIc7l +TpfqEuijLKAkSpuSpQCmy/GRVN/v8ksWJ7U+S+ECgYB+e/GAdxHOdMGOFbrqZ3Dx +jmPshaFFj/3UEsBZ6lBBTbdlMI7wFrSsqxCe1KGh0yG2GnOXE2useggeJyDVuaEY +7/CNalD9w158WS9Zb7pPOm6QQpKUeIEXvpQbKi6FjKZKaFlUDk2auFT+d1lOga0T +QRowjmcym1p+moKlqdiXGw== +-----END PRIVATE KEY----- diff --git a/xinelu-admin/src/main/resources/yiluyoupin_apiclient_key.pem b/xinelu-admin/src/main/resources/yiluyoupin_apiclient_key.pem new file mode 100644 index 0000000..cf65f27 --- /dev/null +++ b/xinelu-admin/src/main/resources/yiluyoupin_apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC3rkr2Mp+Xb31y +xfTOJPSmjQkG5/Eko6cyJcb8e6fGrrtsPVM9kExpVIor61oWTS1gyKYLwCQ92xmh +qjKtazzd6KvqjKdxFknxxH9R1L+n7LnSEfK2KNaxIL17h2vdXOJatuinX0+7A9Ct +5ZnKb5O5HVctQH0xCca6C6yyuF0q11BFquKyGPVwhqVwQnt+qIeQ/VCKFD5AYf1r +ebkaHwKCg0rbzPFWeZfVI0z3j6M71DLxdIHV40xDn31ygQYlBeuTOUxFvKnri8m+ +BalcSUhocS9VAIyuPyDXCAdujm3hKz/WgqVtvgB3OOiIeGVppbgDlW+JWgR7lizM +TzMYfhjPAgMBAAECggEBAJbB6SjVOAO1MEOpklo4Hs0saMJQUK3/3FTeiMnmPDho +ZdBbLR0UeILjLl0J2HEBe0M6rH5sf9J9KDZ2WQ3ZPKXuOFxUgYHiB2L2IoHpmjyb +oZB3xrwYHM5Yzuy6o5+Wgvptsdrd8bTPVtHD50wt9BM1r72mdppvKbq9pksx4tYr +apw4WXfjO2zbdOngY4T5pCk5NZgXrlBfY0/vXsP/3SR+52KXGre/lSt35A4SjNe6 +voI1vZLDNlqzRaEZqBC0tLyvMH3NaYpRhwyEHtoABE9AQvVaQNt+fN1qhbhjtVdQ +lR64Dqdc6jjIhuUhs1umYswf2umA3duZox8RTLZo1UECgYEA4oM2gLsX7dVNiDI4 +bZsMBdm8cb+N3/npiZBlDL9UL4tWCzLQP8sR/HJH3OZHQ1iLk+7QXi2g0YR5VtNx +tLvECK1+Cd3sGt2zyFcrSpeYAnvbsMqB9F/K3grCCnvzKKmHJS27c9EVGr+sRTbx +6hSqQyEAYTP1yRLnLVmWzkCBXh8CgYEAz5eqFmfou3U7B04tK739HTJGAaHTxVAR +C4u4x0HGUP+NhPKZzySc70vWHoNgyP/QBUgzf5gTEnGCJ7Rk6Y2YZxCLyPksEDFc +meW9ENSOQMwTWM1PAF+XLr4wXbyojMqlI7vWimTMOPK7WMVt4jYCoaN9lBS+McYj +e1ZpB5yEj1ECgYEAiSXLXVxq2604GYvW0L59JBm22OSTwZZuycUs+e/qyDLEcVld +8BJDnKeRTXX8lhFJydNiRHO6GMHuOh0ijrzVsC9jzhOZvpaYIWhuJObuuipGVZ/3 +2YAatCCtZm2wR+GFm4Q6KKDi92QwqWPgS8whXy3fLfupCQsyACprfgxeiB8CgYBF +pfjm843d9wMK/GujVWbquMdMHONUO/y8BvDDyYmj+1mb1VlNaldM4gDA1AtQ5KMC +YqsEkB01/udQMvH4eg075w0/LHpgJG+RIsdAMlBX5SBIlvl+gpPSlvTbPkS+l+64 +AnmEjTUHlkjNC9BGKSDQ4m1rlVoKkROuedtbNmQzQQKBgQCQdmmWy2Nr9NRmy5+r +3FKymUVGujww+R7IiFGnFiBBhec8hUPaBp1xG5d8XVIcLt6nleOX5ZunXBwTOmp6 +XH6tQuup+hjFiNpRLmbVkTv8uQVy5sWEqiGp0i7Jhb+0QEOSEshOr8sQDDAFwWXl +FyCbC1amAeC1i1knzGrNOdppUw== +-----END PRIVATE KEY----- diff --git a/xinelu-common/src/main/java/com/xinelu/common/config/LogisticsConfig.java b/xinelu-common/src/main/java/com/xinelu/common/config/LogisticsConfig.java new file mode 100644 index 0000000..af39e48 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/config/LogisticsConfig.java @@ -0,0 +1,23 @@ +package com.xinelu.common.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Description 快递鸟物流接口配置参数类 + * @Author 纪寒 + * @Date 2022-11-01 13:30:47 + * @Version 1.0 + */ +@Data +@Component +@ConfigurationProperties(prefix = "logistics-config") +public class LogisticsConfig { + + private String eBusinessId; + + private String apiKey; + + private String expressBirdUrl; +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/config/NurseAppletChatConfig.java b/xinelu-common/src/main/java/com/xinelu/common/config/NurseAppletChatConfig.java deleted file mode 100644 index eb05253..0000000 --- a/xinelu-common/src/main/java/com/xinelu/common/config/NurseAppletChatConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.xinelu.common.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 护理员小程序配置类 - * - * @author ljh - * @version 1.0 - * Create by 2023/3/29 15:40 - */ -@Data -@Component -@ConfigurationProperties(prefix = "nurse-applet-chat-config") -public class NurseAppletChatConfig { - - /** - * 小程序id - */ - private String appletId; - - /** - * 小程序secret - */ - private String secret; - - /** - * 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 - */ - private String lang; - - /** - * 授权类型 - */ - private String grantType; - - /** - * 微信小程序事件回调令牌 - */ - private String token; - - /** - * 微信小程序事件回调消息加密密钥 - */ - private String encodingAesKey; - - /** - * 护理站运营人员-服务派单通知-模板id - */ - private String serviceDispatchOperationsTemplateId; - - /** - * 护理站运营人员-接单提醒-模板id - */ - private String receivingOrdersOperationsTemplateId; - - /** - * 护理站运营人员-师傅拒绝接单通知-模板id - */ - private String refusalOrdersOperationsTemplateId; - - /** - * 护理站运营人员和护理员-订单回池通知-模板id - */ - private String overtimeOrdersOperationsTemplateId; - - /** - * 护理站运营人员-订单完成通知-模板id - */ - private String orderCompletionOperationsTemplateId; - - /** - * 护理员-接单提醒-模板id - */ - private String receivingOrdersNurseTemplateId; - -} diff --git a/xinelu-common/src/main/java/com/xinelu/common/config/WeChatPaymentUrlConfig.java b/xinelu-common/src/main/java/com/xinelu/common/config/WeChatPaymentUrlConfig.java new file mode 100644 index 0000000..efe2237 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/config/WeChatPaymentUrlConfig.java @@ -0,0 +1,35 @@ +package com.xinelu.common.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Description 微信支付接口地址 + * @Author 纪寒 + * @Date 2022-10-17 17:56:25 + * @Version 1.0 + */ +@Component +@Data +@ConfigurationProperties(prefix = "we-chat-payment-url-config") +public class WeChatPaymentUrlConfig { + + private String jsapiPalceOrderUrl; + + private String queryOrderNoUrl; + + private String queryMchIdUrl; + + private String closeOrderUrl; + + private String refundApplyUrl; + + private String refundQueryOrderUrl; + + private String tradeApplyBillUrl; + + private String capitalApplyBillUrl; + + private String appPlaceOrderUrl; +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/config/XylWeChatPaymentConfig.java b/xinelu-common/src/main/java/com/xinelu/common/config/XylWeChatPaymentConfig.java new file mode 100644 index 0000000..097ef16 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/config/XylWeChatPaymentConfig.java @@ -0,0 +1,27 @@ +package com.xinelu.common.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Description 新医路商户号微信支付参数配置类 + * @Author 纪寒 + * @Date 2022-10-17 16:55:04 + * @Version 1.0 + */ +@Data +@Component +@ConfigurationProperties(prefix = "xyl-we-chat-config") +public class XylWeChatPaymentConfig { + + private String xylMchId; + + private String xylMchSerialNo; + + private String xylPrivateKeyPath; + + private String xylPaymentKey; + + private String xylWeChatNotifyUrl; +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/config/YlypWeChatPaymentConfig.java b/xinelu-common/src/main/java/com/xinelu/common/config/YlypWeChatPaymentConfig.java new file mode 100644 index 0000000..ea976a4 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/config/YlypWeChatPaymentConfig.java @@ -0,0 +1,27 @@ +package com.xinelu.common.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Description 医路优品商户号微信支付参数配置类 + * @Author 纪寒 + * @Date 2022-10-17 16:55:04 + * @Version 1.0 + */ +@Data +@Component +@ConfigurationProperties(prefix = "ylyp-we-chat-config") +public class YlypWeChatPaymentConfig { + + private String ylypMchId; + + private String ylypMchSerialNo; + + private String ylypPrivateKeyPath; + + private String ylypPaymentKey; + + private String ylypWeChatNotifyUrl; +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/enums/OrderSourceEnum.java b/xinelu-common/src/main/java/com/xinelu/common/enums/OrderSourceEnum.java new file mode 100644 index 0000000..ea7ae23 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/enums/OrderSourceEnum.java @@ -0,0 +1,29 @@ +package com.xinelu.common.enums; + +import lombok.Getter; + +/** + * @Description 订单来源枚举 + * @Author 纪寒 + * @Date 2023-10-16 + */ +@Getter +public enum OrderSourceEnum { + + /** + * 泉医模块 + */ + SPRING_DOCTOR("SPRING_DOCTOR"), + + /** + * 家医模块 + */ + FAMILY_DOCTOR("FAMILY_DOCTOR"), + ; + + final private String info; + + OrderSourceEnum(String info) { + this.info = info; + } +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/enums/PayTypeEnum.java b/xinelu-common/src/main/java/com/xinelu/common/enums/PayTypeEnum.java new file mode 100644 index 0000000..4679dbd --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/enums/PayTypeEnum.java @@ -0,0 +1,30 @@ +package com.xinelu.common.enums; + +import lombok.Getter; + +/** + * @Description 支付了类型枚举 + * @Author 纪寒 + * @Date 2022-10-18 15:16:02 + * @Version 1.0 + */ +@Getter +public enum PayTypeEnum { + + /** + * 微信 + */ + WECHAT_PAY("WECHAT_PAY"), + + /** + * 支付宝 + */ + ALI_PAY("ALI_PAY"), + ; + + final private String info; + + PayTypeEnum(String info) { + this.info = info; + } +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/enums/PaymentMerchantTypeEnum.java b/xinelu-common/src/main/java/com/xinelu/common/enums/PaymentMerchantTypeEnum.java new file mode 100644 index 0000000..9a2f4d6 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/enums/PaymentMerchantTypeEnum.java @@ -0,0 +1,30 @@ +package com.xinelu.common.enums; + +import lombok.Getter; + +/** + * @Description 支付账户枚举 + * @Author 纪寒 + * @Date 2022-10-20 17:48:32 + * @Version 1.0 + */ +@Getter +public enum PaymentMerchantTypeEnum { + + /** + * 新医路 + */ + XINYILU("XINYILU"), + + /** + * 医路优品 + */ + YILUYOUPIN("YILUYOUPIN"), + ; + + final private String info; + + PaymentMerchantTypeEnum(String info) { + this.info = info; + } +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/enums/RefundStatusEnum.java b/xinelu-common/src/main/java/com/xinelu/common/enums/RefundStatusEnum.java new file mode 100644 index 0000000..7df7d78 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/enums/RefundStatusEnum.java @@ -0,0 +1,41 @@ +package com.xinelu.common.enums; + +import lombok.Getter; + +/** + * @Description 微信退款通知枚举 + * @Author 纪寒 + * @Date 2022-10-25 13:12:03 + * @Version 1.0 + */ +@Getter +public enum RefundStatusEnum { + /** + * 退款成功 + */ + SUCCESS("SUCCESS"), + + /** + * 退款关闭 + */ + CLOSED("CLOSED"), + + /** + * 退款处理中 + */ + PROCESSING("PROCESSING"), + + /** + * 退款异常,退款到银行发现用户的卡作废或者冻结了, + * 导致原路退款银行卡失败,可前往【商户平台—>交易中心】,手动处理此笔退款 + */ + ABNORMAL("ABNORMAL"), + + ; + + final private String info; + + RefundStatusEnum(String info) { + this.info = info; + } +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/enums/RefundTypeEnum.java b/xinelu-common/src/main/java/com/xinelu/common/enums/RefundTypeEnum.java new file mode 100644 index 0000000..bc049d3 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/enums/RefundTypeEnum.java @@ -0,0 +1,30 @@ +package com.xinelu.common.enums; + +import lombok.Getter; + +/** + * @Description 退款类型枚举 + * @Author 纪寒 + * @Date 2022-10-18 15:16:02 + * @Version 1.0 + */ +@Getter +public enum RefundTypeEnum { + + /** + * 微信 + */ + WE_CHAT("WE_CHAT"), + + /** + * 支付宝 + */ + ALI_PAY("ALI_PAY"), + ; + + final private String info; + + RefundTypeEnum(String info) { + this.info = info; + } +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/enums/WeChatTradeStateEnum.java b/xinelu-common/src/main/java/com/xinelu/common/enums/WeChatTradeStateEnum.java new file mode 100644 index 0000000..009a8b5 --- /dev/null +++ b/xinelu-common/src/main/java/com/xinelu/common/enums/WeChatTradeStateEnum.java @@ -0,0 +1,52 @@ +package com.xinelu.common.enums; + +import lombok.Getter; + +/** + * 微信支付回调通知状态 + */ +@Getter +public enum WeChatTradeStateEnum { + + /** + * 支付成功 + */ + SUCCESS("SUCCESS"), + + /** + * 未支付 + */ + NOTPAY("NOTPAY"), + + /** + * 已关闭 + */ + CLOSED("CLOSED"), + + /** + * 转入退款 + */ + REFUND("REFUND"), + + /** + * 已撤销(付款码支付) + */ + REVOKED("REVOKED"), + + /** + * 用户支付中(付款码支付) + */ + USERPAYING("USERPAYING"), + + /** + * 支付失败(其他原因,如银行返回失败) + */ + PAYERROR("PAYERROR") + ; + + final private String info; + + WeChatTradeStateEnum(String info) { + this.info = info; + } +} diff --git a/xinelu-common/src/main/java/com/xinelu/common/utils/http/HttpUtils.java b/xinelu-common/src/main/java/com/xinelu/common/utils/http/HttpUtils.java index 5b3a8d3..c25a523 100644 --- a/xinelu-common/src/main/java/com/xinelu/common/utils/http/HttpUtils.java +++ b/xinelu-common/src/main/java/com/xinelu/common/utils/http/HttpUtils.java @@ -16,6 +16,7 @@ import org.apache.http.HttpEntity; import org.apache.http.impl.client.CloseableHttpClient; import javax.net.ssl.*; +import javax.servlet.http.HttpServletRequest; import java.io.*; import java.net.ConnectException; import java.net.SocketTimeoutException; @@ -253,4 +254,35 @@ public class HttpUtils { } return result; } + + /** + * 将通知参数转化为字符串 + * + * @param request 请求信息 + * @return 请求参数信息 + */ + public static String readRequestData(HttpServletRequest request) { + BufferedReader br = null; + try { + StringBuilder result = new StringBuilder(); + br = request.getReader(); + for (String line; (line = br.readLine()) != null; ) { + if (result.length() > 0) { + result.append("\n"); + } + result.append(line); + } + return result.toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } } diff --git a/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/mapper/ResidentPatientInfoMapper.java b/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/mapper/ResidentPatientInfoMapper.java index 8eb0e0c..1a5eccc 100644 --- a/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/mapper/ResidentPatientInfoMapper.java +++ b/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/mapper/ResidentPatientInfoMapper.java @@ -95,5 +95,12 @@ public interface ResidentPatientInfoMapper { **/ PatientInfo getByCardNo(String cardNo); - int selectPatientInfoByPhone(String phone); + List selectPatientInfoByPhone(String phone); + /** + *根据用户编号查询 + * + *@param patientCode 用户编号 + *@return PatientInfo + **/ + PatientInfo getPatientInfoByPatientCode(String patientCode); } diff --git a/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/service/impl/ResidentPatientInfoServiceImpl.java b/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/service/impl/ResidentPatientInfoServiceImpl.java index 55d4889..b0c3424 100644 --- a/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/service/impl/ResidentPatientInfoServiceImpl.java +++ b/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/service/impl/ResidentPatientInfoServiceImpl.java @@ -152,16 +152,18 @@ public class ResidentPatientInfoServiceImpl implements IResidentPatientInfoServi if (ObjectUtils.isNotEmpty(body.getCardNo())) { // 修改 if(!StringUtils.isBlank(body.getPatientCode())) { - PatientInfo patientInfo = residentPatientInfoMapper.getByCardNo(body.getCardNo()); - BeanUtils.copyBeanProp(patientInfo, body); - if(body.getDiseaseList() != null) { - patientInfo.setDisease(body.getDiseaseList().stream().collect(Collectors.joining(","))); - } else { - patientInfo.setDisease("0"); + PatientInfo patientInfo = residentPatientInfoMapper.getPatientInfoByPatientCode(body.getPatientCode()); + if (ObjectUtils.isNotEmpty(patientInfo)) { + BeanUtils.copyBeanProp(patientInfo, body); + if (body.getDiseaseList() != null) { + patientInfo.setDisease(body.getDiseaseList().stream().collect(Collectors.joining(","))); + } else { + patientInfo.setDisease("0"); + } + patientInfo.setLoginFlag(Long.valueOf(1)); + updatePatientInfo(patientInfo); + // 注册 } - patientInfo.setLoginFlag(Long.valueOf(1)); - updatePatientInfo(patientInfo); - // 注册 } else { // 获取当前微信绑定的居民 List list = residentPatientInfoMapper.getList(body.getOpenid(), body.getCityCode()); @@ -340,12 +342,22 @@ public class ResidentPatientInfoServiceImpl implements IResidentPatientInfoServi } catch (Exception e) { throw new ServiceException(e.getMessage()); } + //获取手机号 String code; + String cityCode = ""; AppletPhoneVO phone = getPhone(phoneCode); String phoneNumber = phone.getPhoneInfo().getPhoneNumber(); HashMap.put("phone",phoneNumber); - code = residentPatientInfoMapper.selectPatientInfoByPhone(phoneNumber) == 0 ? "0" : "1"; + List infoList = residentPatientInfoMapper.selectPatientInfoByPhone(phoneNumber); + code = infoList.size()== 0 ? "0" : "1"; + //返回绑定城市 + if ("1".equals(code)){ + for (PatientInfo patientInfo : infoList) { + cityCode = patientInfo.getCityCode(); + } + } HashMap.put("code",code); + HashMap.put("cityCode",cityCode); return HashMap; } } diff --git a/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/utils/AppletAccessTokenUtils.java b/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/utils/AppletAccessTokenUtils.java index b126972..24318f5 100644 --- a/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/utils/AppletAccessTokenUtils.java +++ b/xinelu-familydoctor/src/main/java/com/xinelu/familydoctor/applet/utils/AppletAccessTokenUtils.java @@ -1,7 +1,6 @@ package com.xinelu.familydoctor.applet.utils; import com.xinelu.common.config.AppletChatConfig; -import com.xinelu.common.config.NurseAppletChatConfig; import com.xinelu.common.constant.Constants; import com.xinelu.common.entity.AppletAccessToken; import com.xinelu.common.exception.ServiceException; @@ -27,8 +26,7 @@ public class AppletAccessTokenUtils { private RedisTemplate redisTemplate; @Resource private AppletChatConfig appletChatConfig; - @Resource - private NurseAppletChatConfig nurseAppletChatConfig; + /** * 返回成功状态码 */ @@ -65,34 +63,4 @@ public class AppletAccessTokenUtils { return accessToken; } - /** - * 护理员小程序获取小程序AccessToken方法 - * - * @return 小程序的AccessToken - */ - public String getPersonAppletAccessToken() { - String accessToken; - String accessTokenKey = Constants.NURSE_STATION_PERSON_APPLET_ACCESS_TOKEN + "accessToken"; - //从Redis中取出accessToken - Object object = redisTemplate.opsForValue().get(accessTokenKey); - if (Objects.isNull(object)) { - //没有,获取accessToken - AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(nurseAppletChatConfig.getAppletId(), nurseAppletChatConfig.getSecret()); - if (Objects.isNull(appletAccessToken)) { - throw new ServiceException("获取微信小程序accessToken信息失败"); - } - if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != SUCCESS_CODE) { - throw new ServiceException("获取微信小程序accessToken信息失败,失败信息为:" + appletAccessToken.getErrmsg(), 201); - } - if (StringUtils.isBlank(appletAccessToken.getAccessToken())) { - throw new ServiceException("accessToken信息为空"); - } - //存入Redis中 - redisTemplate.opsForValue().set(accessTokenKey, appletAccessToken.getAccessToken(), 3600, TimeUnit.SECONDS); - accessToken = appletAccessToken.getAccessToken(); - } else { - accessToken = (String) object; - } - return accessToken; - } } \ No newline at end of file diff --git a/xinelu-familydoctor/src/main/resources/mapper/register/ResidentPatientInfoMapper.xml b/xinelu-familydoctor/src/main/resources/mapper/register/ResidentPatientInfoMapper.xml index e7c3870..e06f9b6 100644 --- a/xinelu-familydoctor/src/main/resources/mapper/register/ResidentPatientInfoMapper.xml +++ b/xinelu-familydoctor/src/main/resources/mapper/register/ResidentPatientInfoMapper.xml @@ -479,10 +479,15 @@ - + where phone = #{pnone} and login_flag = '1' + diff --git a/xinelu-framework/pom.xml b/xinelu-framework/pom.xml index 7de84ec..e9bf62a 100644 --- a/xinelu-framework/pom.xml +++ b/xinelu-framework/pom.xml @@ -78,6 +78,11 @@ ${knife4j.version} + + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + diff --git a/xinelu-framework/src/main/java/com/xinelu/framework/config/AsyncExecutorConfig.java b/xinelu-framework/src/main/java/com/xinelu/framework/config/AsyncExecutorConfig.java index a8c4058..70434bd 100644 --- a/xinelu-framework/src/main/java/com/xinelu/framework/config/AsyncExecutorConfig.java +++ b/xinelu-framework/src/main/java/com/xinelu/framework/config/AsyncExecutorConfig.java @@ -26,7 +26,6 @@ public class AsyncExecutorConfig { */ @Bean public Executor asyncThreadServiceExecutor() { - log.info("异步线程池配置执行"); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(20); diff --git a/xinelu-framework/src/main/java/com/xinelu/framework/config/XylWeChatPaymentUtilConfig.java b/xinelu-framework/src/main/java/com/xinelu/framework/config/XylWeChatPaymentUtilConfig.java new file mode 100644 index 0000000..f39008d --- /dev/null +++ b/xinelu-framework/src/main/java/com/xinelu/framework/config/XylWeChatPaymentUtilConfig.java @@ -0,0 +1,97 @@ +package com.xinelu.framework.config; + +import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; +import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; +import com.wechat.pay.contrib.apache.httpclient.auth.Verifier; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; +import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import com.xinelu.common.config.XylWeChatPaymentConfig; +import com.xinelu.common.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.impl.client.CloseableHttpClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; + +/** + * @Description 新医路商户号微信支付核心配置类 + * @Author 纪寒 + * @Date 2022-10-17 18:56:22 + * @Version 1.0 + */ +@Configuration +@Slf4j +public class XylWeChatPaymentUtilConfig { + + @Resource + private XylWeChatPaymentConfig xylWeChatPaymentConfig; + + /** + * 获取新医路签名信息 + * + * @return 签名信息 + * @throws Exception 异常信息 + */ + @Bean(name = "xylVerifier") + public Verifier getXylVerifier() throws Exception { + PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath()); + PrivateKeySigner privateKeySigner = new PrivateKeySigner(xylWeChatPaymentConfig.getXylMchSerialNo(), privateKey); + WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(xylWeChatPaymentConfig.getXylMchId(), privateKeySigner); + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + certificatesManager.putMerchant(xylWeChatPaymentConfig.getXylMchId(), wechatPay2Credentials, xylWeChatPaymentConfig.getXylPaymentKey().getBytes(StandardCharsets.UTF_8)); + return certificatesManager.getVerifier(xylWeChatPaymentConfig.getXylMchId()); + } + + /** + * 获取新医路商户号带有签名的http请求对象 + * + * @return CloseableHttpClient对象 + */ + @Bean(name = "xinYiLuWeChatPayClient") + public CloseableHttpClient getXinYiLuWeChatPayClient(Verifier xylVerifier) { + PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath()); + CloseableHttpClient closeableHttpClient = null; + try { + closeableHttpClient = WechatPayHttpClientBuilder.create() + .withMerchant(xylWeChatPaymentConfig.getXylMchId(), xylWeChatPaymentConfig.getXylMchSerialNo(), privateKey) + .withValidator(new WechatPay2Validator(xylVerifier)).build(); + } catch (Exception e) { + log.error("新医路验证签名信息失败,失败信息:{}", e.getMessage()); + } + return closeableHttpClient; + } + + /** + * 获取新医路商户号无签名的http请求对象 + * + * @return CloseableHttpClient对象 + */ + @Bean(name = "xinYiLuWeChatPayNoSignClient") + public CloseableHttpClient getXinYiLuWeChatPayNoSignClient() { + PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath()); + return WechatPayHttpClientBuilder.create() + .withMerchant(xylWeChatPaymentConfig.getXylMchId(), xylWeChatPaymentConfig.getXylMchSerialNo(), privateKey) + .withValidator((response) -> true).build(); + } + + /** + * 获取商户的私钥文件 + * + * @param filename 获取商户的私钥文件 + * @return 商户私钥 + */ + private PrivateKey getPrivateKey(String filename) { + try { + return PemUtil.loadPrivateKey(new ClassPathResource(filename).getInputStream()); + } catch (Exception e) { + log.error("新医路商户私钥文件不存在,错误原因:{}", e.getMessage()); + throw new ServiceException("新医路商户私钥文件不存在,请联系管理员!"); + } + } +} diff --git a/xinelu-framework/src/main/java/com/xinelu/framework/config/YlypWeChatPaymentUtilConfig.java b/xinelu-framework/src/main/java/com/xinelu/framework/config/YlypWeChatPaymentUtilConfig.java new file mode 100644 index 0000000..0507f18 --- /dev/null +++ b/xinelu-framework/src/main/java/com/xinelu/framework/config/YlypWeChatPaymentUtilConfig.java @@ -0,0 +1,97 @@ +package com.xinelu.framework.config; + +import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; +import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; +import com.wechat.pay.contrib.apache.httpclient.auth.Verifier; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; +import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import com.xinelu.common.config.YlypWeChatPaymentConfig; +import com.xinelu.common.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.impl.client.CloseableHttpClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; + +/** + * @Description 医路优品微信支付核心配置类 + * @Author 纪寒 + * @Date 2022-10-17 18:56:22 + * @Version 1.0 + */ +@Configuration +@Slf4j +public class YlypWeChatPaymentUtilConfig { + + @Resource + private YlypWeChatPaymentConfig ylypWeChatPaymentConfig; + + /** + * 获取新医路签名信息 + * + * @return 签名信息 + * @throws Exception 异常信息 + */ + @Bean(name = "ylypVerifier") + public Verifier getYlypVerifier() throws Exception { + PrivateKey privateKey = getPrivateKey(ylypWeChatPaymentConfig.getYlypPrivateKeyPath()); + PrivateKeySigner privateKeySigner = new PrivateKeySigner(ylypWeChatPaymentConfig.getYlypMchSerialNo(), privateKey); + WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(ylypWeChatPaymentConfig.getYlypMchId(), privateKeySigner); + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + certificatesManager.putMerchant(ylypWeChatPaymentConfig.getYlypMchId(), wechatPay2Credentials, ylypWeChatPaymentConfig.getYlypPaymentKey().getBytes(StandardCharsets.UTF_8)); + return certificatesManager.getVerifier(ylypWeChatPaymentConfig.getYlypMchId()); + } + + /** + * 获取医路优品商户带有签名信息的http请求对象 + * + * @return CloseableHttpClient对象 + */ + @Bean(name = "yiLuYouPinWeChatPayClient") + public CloseableHttpClient getYiLuYouPinWeChatPayClient(Verifier ylypVerifier) { + PrivateKey privateKey = getPrivateKey(ylypWeChatPaymentConfig.getYlypPrivateKeyPath()); + CloseableHttpClient closeableHttpClient = null; + try { + closeableHttpClient = WechatPayHttpClientBuilder.create() + .withMerchant(ylypWeChatPaymentConfig.getYlypMchId(), ylypWeChatPaymentConfig.getYlypMchSerialNo(), privateKey) + .withValidator(new WechatPay2Validator(ylypVerifier)).build(); + } catch (Exception e) { + log.error("医路优品验证签名信息失败,失败信息:{}", e.getMessage()); + } + return closeableHttpClient; + } + + /** + * 获取HttpClient,无需进行应答签名验证,跳过验签的流程 + * + * @return CloseableHttpClient对象 + */ + @Bean(name = "yiLuYouPinWeChatPayNoSignClient") + public CloseableHttpClient getYiLuYouPinWeChatPayNoSignClient() { + PrivateKey privateKey = getPrivateKey(ylypWeChatPaymentConfig.getYlypPrivateKeyPath()); + return WechatPayHttpClientBuilder.create() + .withMerchant(ylypWeChatPaymentConfig.getYlypMchId(), ylypWeChatPaymentConfig.getYlypMchSerialNo(), privateKey) + .withValidator((response) -> true).build(); + } + + /** + * 获取商户的私钥文件 + * + * @param filename 获取商户的私钥文件 + * @return 商户私钥 + */ + private PrivateKey getPrivateKey(String filename) { + try { + return PemUtil.loadPrivateKey(new ClassPathResource(filename).getInputStream()); + } catch (Exception e) { + log.error("医路优品商户私钥文件不存在,错误原因:{}", e.getMessage()); + throw new ServiceException("医路优品商户私钥文件不存在,请联系管理员!"); + } + } +} diff --git a/xinelu-nurse-applet/pom.xml b/xinelu-nurse-applet/pom.xml index 7567c88..db781b7 100644 --- a/xinelu-nurse-applet/pom.xml +++ b/xinelu-nurse-applet/pom.xml @@ -46,5 +46,11 @@ org.simpleframework simple-xml + + + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + - \ No newline at end of file + diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/healthconsultation/HealthConsultationController.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/healthconsultation/HealthConsultationController.java new file mode 100644 index 0000000..bd1551d --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/healthconsultation/HealthConsultationController.java @@ -0,0 +1,93 @@ +package com.xinelu.applet.controller.healthconsultation; + +import com.xinelu.applet.service.healthconsultation.HealthConsultationService; +import com.xinelu.applet.vo.healthconsultation.HealthConsultationOrderDTO; +import com.xinelu.common.annotation.MobileRequestAuthorization; +import com.xinelu.common.annotation.RepeatSubmit; +import com.xinelu.common.core.controller.BaseController; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.core.page.TableDataInfo; +import com.xinelu.common.custominterface.Insert; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.manage.domain.hospitalpersoninfo.HospitalPersonInfo; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; + +/** + * @Description APP及小程序健康咨询接口 + * @Author zh + * @Date 2023-03-07 + */ +@RestController +@RequestMapping("/nurseApp/healthConsultation") +public class HealthConsultationController extends BaseController { + @Resource + private HealthConsultationService healthConsultationService; + + /** + * 健康咨询-预约医生 + */ + @MobileRequestAuthorization + @GetMapping("/selectDepartment") + public TableDataInfo selectDepartment() { + return healthConsultationService.selectDepartment(); + } + + /** + * 健康咨询-预约医生(无分页) + */ + @MobileRequestAuthorization + @GetMapping("/selectDepartmentNoPage") + public AjaxResult selectDepartmentNoPage() { + return AjaxResult.success(healthConsultationService.selectDepartmentNoPage()); + } + + /** + * 健康咨询-预约医生-单查科室人员 + */ + @MobileRequestAuthorization + @GetMapping("/selectHospitalPerson") + public TableDataInfo selectHospitalPerson(Long departmentId) { + startPage(); + List list = healthConsultationService.selectHospitalPerson(departmentId); + return getDataTable(list); + } + + /** + * 健康咨询-信息确认 + */ + @MobileRequestAuthorization + @GetMapping("/informationConfirmation") + public AjaxResult informationConfirmation(Long patientId) { + if (Objects.isNull(patientId)) { + return AjaxResult.error("用户信息为空!"); + } + return healthConsultationService.informationConfirmation(patientId); + } + + + /** + * 手机App和微信小程序健康咨询确认订单方法 + * + * @param healthConsultationOrderDTO 健康咨询订单 + * @return 结果 + */ + @MobileRequestAuthorization + @RepeatSubmit + @PostMapping("/addHealthConsultationOrder") + public AjaxResult addHealthConsultationOrder(@Validated(Insert.class) @RequestBody HealthConsultationOrderDTO healthConsultationOrderDTO, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new ServiceException(bindingResult.getAllErrors().get(0).getDefaultMessage()); + } + if (Objects.nonNull(healthConsultationOrderDTO.getTotalPrice()) && healthConsultationOrderDTO.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) { + return AjaxResult.error("预约金额不正确,无法下单,请输入正确的预约金额!"); + } + return healthConsultationService.insertHealthConsultationOrder(healthConsultationOrderDTO); + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/logistics/LogisticsController.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/logistics/LogisticsController.java new file mode 100644 index 0000000..10705f6 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/logistics/LogisticsController.java @@ -0,0 +1,46 @@ +package com.xinelu.applet.controller.logistics; + +import com.xinelu.applet.service.logistics.LogisticsService; +import com.xinelu.common.annotation.MobileRequestAuthorization; +import com.xinelu.common.core.controller.BaseController; +import com.xinelu.common.core.domain.AjaxResult; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @Description 快递鸟物流查询接口控制器 + * @Author 纪寒 + * @Date 2022-11-01 13:33:31 + * @Version 1.0 + */ +@RestController +@RequestMapping("/nurseApp/logistics") +public class LogisticsController extends BaseController { + + @Resource + private LogisticsService logisticsService; + + /** + * 根据快递单号查询物流信息 + * + * @param orderNo 订单单号 + * @param expressNo 快递单号 + * @return 物流信息 + * @throws Exception 异常信息 + */ + @MobileRequestAuthorization + @GetMapping("/queryLogisticsInfo") + public AjaxResult queryLogisticsInfo(String orderNo, String expressNo) throws Exception { + if (StringUtils.isBlank(orderNo)) { + return AjaxResult.error("请选择要查询的订单信息!"); + } + if (StringUtils.isBlank(expressNo)) { + return AjaxResult.error("请选择要查询的快递单号!"); + } + return logisticsService.queryLogisticsInfo(orderNo, expressNo); + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/nursingorder/NursingOrderController.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/nursingorder/NursingOrderController.java new file mode 100644 index 0000000..35a1960 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/nursingorder/NursingOrderController.java @@ -0,0 +1,96 @@ +package com.xinelu.applet.controller.nursingorder; + +import com.xinelu.applet.service.nursingorder.INursingOrderService; +import com.xinelu.applet.vo.nursingorder.AppletGoodsOrderVO; +import com.xinelu.applet.vo.nursingorder.NursingOrderInfoVO; +import com.xinelu.common.annotation.MobileRequestAuthorization; +import com.xinelu.common.core.controller.BaseController; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.core.domain.entity.SysDictData; +import com.xinelu.common.core.page.TableDataInfo; +import com.xinelu.common.enums.OrderTypeEnum; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Objects; + +/** + * @Description 个人中心订单页面 + * @Author zhangheng + * @Date 2022-09-06 + * @Version 1.0 + */ +@RestController +@RequestMapping("/nurseApplet/nursingOrder") +public class NursingOrderController extends BaseController { + + @Resource + private INursingOrderService nursingOrderService; + + /** + * 根据登录id查询订单列表 + */ + @GetMapping("/userPage") + public TableDataInfo page(Long parentId) { + startPage(); + List nursingOrderByPatientId = nursingOrderService.getNursingOrderByPatientId(parentId); + return getDataTable(nursingOrderByPatientId); + } + + /** + * 根据护理人id以及订单状态查询订单信息 + */ + @MobileRequestAuthorization + @GetMapping("/goodsOrder") + public TableDataInfo goodsOrder(AppletGoodsOrderVO goodsOrderVO) { + startPage(); + List goodsOrder = nursingOrderService.getGoodsOrder(goodsOrderVO); + return getDataTable(goodsOrder); + } + + /** + * 查询退款原因 + */ + @MobileRequestAuthorization + @GetMapping("/refundReason") + public TableDataInfo refundReason(SysDictData sysDictData) { + startPage(); + List refundReason = nursingOrderService.getRefundReason(sysDictData); + return getDataTable(refundReason); + } + + /** + * 修改商品订单(退款售后记录信息) + */ + @MobileRequestAuthorization + @PostMapping("/edit") + public AjaxResult edit(@RequestBody GoodsOrder goodsOrder) { + if (Objects.isNull(goodsOrder.getId())) { + return AjaxResult.error("订单id不能为空!"); + } + if (StringUtils.isNotBlank(goodsOrder.getOrderType()) && !OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(goodsOrder.getOrderType())) { + if (Objects.isNull(goodsOrder.getRefundReasonDictId())) { + return AjaxResult.error("请选择退款原因!"); + } + } + return toAjax(nursingOrderService.updateGoodsOrder(goodsOrder)); + } + + /** + * 根据预约订单编号查询对应得订单详情信息 + * + * @param orderNo 订单编号 + * @return 详情信息 + */ + @MobileRequestAuthorization + @GetMapping("/getAppointmentDetailsInfo") + public AjaxResult getAppointmentDetailsInfo(String orderNo) { + if (StringUtils.isBlank(orderNo)) { + return AjaxResult.error("请选择要查询的预约订单信息!"); + } + return nursingOrderService.getAppointmentDetailsInfo(orderNo); + } +} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/personappletlogin/PersonAppletLoginController.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/personappletlogin/PersonAppletLoginController.java deleted file mode 100644 index 8d64c91..0000000 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/personappletlogin/PersonAppletLoginController.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.xinelu.applet.controller.personappletlogin; - - -import com.xinelu.applet.service.personappletlogin.PersonAppletLoginService; -import com.xinelu.common.core.controller.BaseController; -import com.xinelu.common.core.domain.AjaxResult; -import org.apache.commons.lang3.StringUtils; -import org.apache.ibatis.annotations.Param; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * @Description 护理员微信小程序登录注册控制器 - * @Author zh - * @Date 2023-03-30 - */ -@RestController -@RequestMapping("/nurseApplet/personLogin") -public class PersonAppletLoginController extends BaseController { - - @Resource - private PersonAppletLoginService personAppletLoginService; - - /** - * 护理员根据登录凭证获取用户的登录信息 - * - * @param loginCode 登录凭证 - * @param phoneCode 手机号凭证 - * @return 微信用户登录信息 - */ - @GetMapping("/getPersonWeChatUserInfo") - public AjaxResult appletLogin(@RequestParam("loginCode") String loginCode, @Param("phoneCode") String phoneCode) { - if (StringUtils.isBlank(loginCode)) { - return AjaxResult.error("登录凭证编码不能为空!"); - } - if (StringUtils.isBlank(phoneCode)) { - return AjaxResult.error("获取手机号凭证不存在"); - } - return personAppletLoginService.personAppletLogin(loginCode, phoneCode); - } -} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/wechatpaymentinfo/WeChatPaymentController.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/wechatpaymentinfo/WeChatPaymentController.java new file mode 100644 index 0000000..e40adef --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/controller/wechatpaymentinfo/WeChatPaymentController.java @@ -0,0 +1,159 @@ +package com.xinelu.applet.controller.wechatpaymentinfo; + +import com.xinelu.applet.service.wechatpaymentinfo.WeChatPayNotifyService; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatPaymentService; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatRefundService; +import com.xinelu.applet.vo.wechatpaymentinfo.dto.PaymentDTO; +import com.xinelu.applet.vo.wechatpaymentinfo.dto.RefundDTO; +import com.xinelu.common.annotation.MobileRequestAuthorization; +import com.xinelu.common.core.controller.BaseController; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.custominterface.Insert; +import com.xinelu.common.enums.BuySourceEnum; +import com.xinelu.common.exception.ServiceException; +import org.apache.commons.lang3.StringUtils; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; +import java.util.Objects; + +/** + * @Description 微信小程序和App支付控制器 + * @Author 纪寒 + * @Date 2022-10-18 14:47:11 + * @Version 1.0 + */ +@RestController +@RequestMapping("/nurseApp/weChatPayment") +public class WeChatPaymentController extends BaseController { + + @Resource + private WeChatPaymentService weChatPaymentService; + @Resource + private WeChatPayNotifyService weChatPayNotifyService; + @Resource + private WeChatRefundService weChatRefundService; + + /** + * 微信小程序购买商品和健康咨询支付接口 + * + * @param paymentDTO 输入参数 + * @return 支付返回结果 + * @throws Exception 异常信息 + */ + @MobileRequestAuthorization + @PostMapping("/appletGoodsOrderPay") + public AjaxResult appletGoodsOrderPay(@Validated(Insert.class) @RequestBody PaymentDTO paymentDTO, BindingResult bindingResult) throws Exception { + if (bindingResult.hasErrors()) { + throw new ServiceException(bindingResult.getAllErrors().get(0).getDefaultMessage()); + } + if (StringUtils.isBlank(paymentDTO.getOpenid())) { + return AjaxResult.error("微信openid不能为空!"); + } + if (Objects.nonNull(paymentDTO.getPaymentPrice()) && paymentDTO.getPaymentPrice().compareTo(BigDecimal.ZERO) < 0) { + return AjaxResult.error("订单支付金额不能为负数,无法支付!"); + } + if (Objects.nonNull(paymentDTO.getPaymentPrice()) && paymentDTO.getPaymentPrice().compareTo(BigDecimal.ZERO) == 0) { + return AjaxResult.error("订单支付金额不能为零,无法支付!"); + } + return weChatPaymentService.appletGoodsOrderPay(paymentDTO); + } + + /** + * 微信小程序预约服务订单支付接口 + * + * @param paymentDTO 输入参数 + * @return 支付返回结果信息 + * @throws Exception 异常信息 + */ + @MobileRequestAuthorization + @PostMapping("/appletAppointmentOrderPay") + public AjaxResult appletAppointmentOrderPay(@Validated(Insert.class) @RequestBody PaymentDTO paymentDTO, BindingResult bindingResult) throws Exception { + if (bindingResult.hasErrors()) { + throw new ServiceException(bindingResult.getAllErrors().get(0).getDefaultMessage()); + } + if (StringUtils.isBlank(paymentDTO.getOpenid())) { + return AjaxResult.error("微信openid不能为空!"); + } + if (!BuySourceEnum.NURSE_STATION.getInfo().equals(paymentDTO.getBuySource())) { + return AjaxResult.error("当前订单非预约服务项,请重新预约!"); + } + if (Objects.nonNull(paymentDTO.getPaymentPrice()) && paymentDTO.getPaymentPrice().compareTo(BigDecimal.ZERO) < 0) { + return AjaxResult.error("订单支付金额不能为负数,无法支付!"); + } + return weChatPaymentService.appletAppointmentOrderPay(paymentDTO); + } + + /** + * 新医路微信支付回调通知接口 + * + * @param request 请求头信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @PostMapping("/xylWeChatPayNotify") + public String xylWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + return weChatPayNotifyService.xylWeChatPayNotify(request, response); + } + + /** + * 医路优品微信支付回调通知接口 + * + * @param request 请求头信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @PostMapping("/ylypWeChatPayNotify") + public String ylypWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + return weChatPayNotifyService.ylypWeChatPayNotify(request, response); + } + + /** + * 微信确认退款接口 + * + * @param refundDTO 退款参数 + * @return 退款申请结果 + * @throws Exception 异常信息 + */ + @PostMapping("/weChatRefundOrderApply") + public AjaxResult weChatRefundOrderApply(@Validated(Insert.class) @RequestBody RefundDTO refundDTO) throws Exception { + return weChatRefundService.weChatRefundOrderApply(refundDTO); + } + + /** + * 新医路微信退款回调通知接口 + * + * @param request 请求头信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @PostMapping("/xylWeChatRefundNotify") + public String xylWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + return weChatPayNotifyService.xylWeChatRefundNotify(request, response); + } + + /** + * 医路优品微信退款回调通知接口 + * + * @param request 请求头信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @PostMapping("/ylypWeChatRefundNotify") + public String ylypWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + return weChatPayNotifyService.ylypWeChatRefundNotify(request, response); + } + +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/mapper/healthconsultation/HealthConsultationMapper.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/mapper/healthconsultation/HealthConsultationMapper.java new file mode 100644 index 0000000..27769d8 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/mapper/healthconsultation/HealthConsultationMapper.java @@ -0,0 +1,30 @@ +package com.xinelu.applet.mapper.healthconsultation; + +import com.xinelu.applet.vo.healthconsultation.HealthConsultationVO; +import com.xinelu.manage.domain.patientinfo.PatientInfo; + +import java.util.List; + +/** + * 健康咨询Mapper接口 + * + * @author 张恒 + * @date 2023-03-07 + */ +public interface HealthConsultationMapper { + + /** + * 健康咨询-信息确认 + * + * @param patientId 用户信息 + * @return PatientInfo + */ + PatientInfo selectPatientById(Long patientId); + + /** + * 查询科室信息管理列表 + * + * @return 科室信息管理集合 + */ + List selectHospitalDepartmentList(); +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/mapper/nursingorder/NursingOrderMapper.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/mapper/nursingorder/NursingOrderMapper.java new file mode 100644 index 0000000..bd37450 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/mapper/nursingorder/NursingOrderMapper.java @@ -0,0 +1,66 @@ +package com.xinelu.applet.mapper.nursingorder; + + +import com.xinelu.applet.vo.nursingorder.AppletGoodsOrderVO; +import com.xinelu.applet.vo.nursingorder.NursingOrderInfoVO; +import com.xinelu.applet.vo.specialdisease.AppointmentOrderDetailsInfoVO; +import com.xinelu.common.core.domain.entity.SysDictData; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; + +import java.util.List; + +/** + * 功能描述: 护理站订单信息 + * + * @author zhangheng + */ +public interface NursingOrderMapper { + + /** + * 根据被护理人patientId查询订单信息 + * + * @param patientId 会员id + * @return 订单列表 + */ + List getNursingOrderVOByPatientId(Long patientId); + + /** + * 根据护理人id以及订单状态查询订单信息 + * + * @param goodsOrderVO 订单信息 + * @return AppletGoodsOrderVO + **/ + List getGoodsOrder(AppletGoodsOrderVO goodsOrderVO); + + /** + * 查询退款原因 + * + * @param sysDictData 退款原因 + * @return com.xinyilu.common.core.domain.entity.SysDictData + **/ + List getRefundReason(SysDictData sysDictData); + + /** + * 修改商品订单(退款售后记录信息) + * + * @param goodsOrder 商品订单 + * @return 结果 + */ + int updateGoodsOrder(GoodsOrder goodsOrder); + + /** + * 根据预约订单编号查询对应得详情信息 + * + * @param orderNo 订单编号 + * @return 详情信息 + */ + AppointmentOrderDetailsInfoVO getAppointmentOrderDetailsInfo(String orderNo); + + /** + * 查询护理站信息 + * + * @param nurseStationItemId 护理站项目id + * @return 护理站信息 + */ + AppointmentOrderDetailsInfoVO getNurseStationByItemId(Long nurseStationItemId); +} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/goodstock/GoodsStockService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/goodstock/GoodsStockService.java new file mode 100644 index 0000000..e781d9b --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/goodstock/GoodsStockService.java @@ -0,0 +1,27 @@ +package com.xinelu.applet.service.goodstock; + +/** + * @Description 库存公共服务业务层 + * @Author 纪寒 + * @Date 2022-10-24 13:56:40 + * @Version 1.0 + */ +public interface GoodsStockService { + + /** + * 新增库存数量服务 + * + * @param orderNo 订单编号 + * @param goodsAttributeDetailsId 商品属性明细id + * @param stockNum 商品数量 + */ + void addGoodsStockInfo(String orderNo, Long goodsAttributeDetailsId, Integer stockNum); + + /** + * 减少库存数量服务 + * + * @param orderNo 订单编号 + * @param goodsAttributeDetailsId 商品属性明细id + */ + void reduceGoodsStockInfo(String orderNo, Long goodsAttributeDetailsId); +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/goodstock/impl/GoodsStockServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/goodstock/impl/GoodsStockServiceImpl.java new file mode 100644 index 0000000..8b919e0 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/goodstock/impl/GoodsStockServiceImpl.java @@ -0,0 +1,102 @@ +package com.xinelu.applet.service.goodstock.impl; + +import com.xinelu.applet.service.goodstock.GoodsStockService; +import com.xinelu.common.constant.Constants; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.common.utils.RedisDistributedLockUtils; +import com.xinelu.manage.domain.goodsOrderDetails.GoodsOrderDetails; +import com.xinelu.manage.mapper.goodsAttributeDetails.GoodsAttributeDetailsMapper; +import com.xinelu.manage.mapper.goodsOrderDetails.GoodsOrderDetailsMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Objects; + +/** + * @Description 商品库存公共服务业务层实现类 + * @Author 纪寒 + * @Date 2022-10-24 13:57:28 + * @Version 1.0 + */ +@Slf4j +@Service +public class GoodsStockServiceImpl implements GoodsStockService { + + @Resource + private RedisDistributedLockUtils redisDistributedLockUtils; + @Resource + private GoodsOrderDetailsMapper goodsOrderDetailsMapper; + @Resource + private GoodsAttributeDetailsMapper goodsAttributeDetailsMapper; + + /** + * 新增库存数量服务 + * + * @param orderNo 订单编号 + * @param goodsAttributeDetailsId 商品属性明细id + * @param stockNum 商品数量 + */ + @Override + public void addGoodsStockInfo(String orderNo, Long goodsAttributeDetailsId, Integer stockNum) { + if (StringUtils.isBlank(orderNo)) { + throw new ServiceException("订单编号不能为空!"); + } + if (Objects.isNull(goodsAttributeDetailsId)) { + throw new ServiceException("商品属性明细id不能为空!"); + } + String orderNoLockKey = Constants.ADD_GOODS_STOCK_KEY + orderNo + "_" + goodsAttributeDetailsId; + boolean tryLock = redisDistributedLockUtils.tryLock(orderNoLockKey, 5); + if (!tryLock) { + return; + } + try { + int updateCount = goodsAttributeDetailsMapper.addGoodsStockCount(goodsAttributeDetailsId, stockNum); + if (updateCount < 1) { + log.info("新增库存数量失败,订单编号:{},商品属性明细id:{},数量数量:{}", orderNo, goodsAttributeDetailsId, stockNum); + } + } catch (Exception e) { + log.error("新增库存信息失败,失败原因为 ====> {}", e.getMessage()); + throw new ServiceException(e.getMessage()); + } finally { + redisDistributedLockUtils.unlock(orderNoLockKey); + } + } + + /** + * 减少库存数量服务 + * + * @param orderNo 订单编号 + * @param goodsAttributeDetailsId 商品属性明细id + */ + @Override + public void reduceGoodsStockInfo(String orderNo, Long goodsAttributeDetailsId) { + if (StringUtils.isBlank(orderNo)) { + throw new ServiceException("订单编号不能为空!"); + } + if (Objects.isNull(goodsAttributeDetailsId)) { + throw new ServiceException("商品属性明细id不能为空!"); + } + GoodsOrderDetails goodsOrderDetailInfo = goodsOrderDetailsMapper.getGoodsOrderDetailInfo(orderNo, goodsAttributeDetailsId); + if (Objects.isNull(goodsOrderDetailInfo)) { + return; + } + String orderNoLockKey = Constants.REDUCE_GOODS_STOCK_KEY + orderNo + "_" + goodsAttributeDetailsId; + boolean tryLock = redisDistributedLockUtils.tryLock(orderNoLockKey, 5); + if (!tryLock) { + return; + } + try { + int updateCount = goodsAttributeDetailsMapper.reduceGoodsStockCount(goodsAttributeDetailsId, goodsOrderDetailInfo.getGoodsCount()); + if (updateCount < 1) { + log.info("减少库存数量失败,订单编号:{},商品属性明细id:{},数量数量:{}", orderNo, goodsAttributeDetailsId, goodsOrderDetailInfo.getGoodsCount()); + } + } catch (Exception e) { + log.error("减少库存信息失败,失败原因为 ====> {}", e.getMessage()); + throw new ServiceException(e.getMessage()); + } finally { + redisDistributedLockUtils.unlock(orderNoLockKey); + } + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/healthconsultation/HealthConsultationService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/healthconsultation/HealthConsultationService.java new file mode 100644 index 0000000..b12a7a1 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/healthconsultation/HealthConsultationService.java @@ -0,0 +1,58 @@ +package com.xinelu.applet.service.healthconsultation; + + + +import com.xinelu.applet.vo.healthconsultation.HealthConsultationOrderDTO; +import com.xinelu.applet.vo.healthconsultation.HealthConsultationVO; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.core.page.TableDataInfo; +import com.xinelu.manage.domain.hospitalpersoninfo.HospitalPersonInfo; + +import java.util.List; + +/** + * @Description 健康咨询接口业务层 + * @Author zh + * @Date 2023-03-07 + */ +public interface HealthConsultationService { + + /** + * 健康咨询-预约医生 + * + * @return AjaxResult + */ + TableDataInfo selectDepartment(); + + /** + * 健康咨询-预约医生(无分页) + * + * @return AjaxResult + */ + List selectDepartmentNoPage(); + + /** + * 单查科室人员 + * + * @param departmentId 科室id + * @return AjaxResult + */ + List selectHospitalPerson(Long departmentId); + + /** + * 健康咨询-信息确认 + * + * @param patientId 用户信息 + * @return AjaxResult + */ + AjaxResult informationConfirmation(Long patientId); + + + /** + * 手机App和微信小程序健康咨询确认订单方法 + * + * @param healthConsultationOrderDTO 健康咨询订单 + * @return 结果 + */ + AjaxResult insertHealthConsultationOrder(HealthConsultationOrderDTO healthConsultationOrderDTO); +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/healthconsultation/impl/HealthConsultationServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/healthconsultation/impl/HealthConsultationServiceImpl.java new file mode 100644 index 0000000..d86f3da --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/healthconsultation/impl/HealthConsultationServiceImpl.java @@ -0,0 +1,188 @@ +package com.xinelu.applet.service.healthconsultation.impl; + +import com.xinelu.applet.service.healthconsultation.HealthConsultationService; +import com.xinelu.applet.utils.AppointmentTimeUtil; +import com.xinelu.applet.vo.healthconsultation.HealthConsultationOrderDTO; +import com.xinelu.applet.vo.healthconsultation.HealthConsultationVO; +import com.xinelu.applet.vo.healthconsultation.PatientAndTimeVO; +import com.xinelu.applet.vo.specialdisease.WeekDaysVO; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.core.page.TableDataInfo; +import com.xinelu.common.enums.BuySourceEnum; +import com.xinelu.common.enums.GooodsOrderStatusEnum; +import com.xinelu.common.enums.OrderTypeEnum; +import com.xinelu.common.enums.PoserModuleTypeEnum; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.common.utils.PageServiceUtil; +import com.xinelu.common.utils.StringUtils; +import com.xinelu.common.utils.bean.BeanUtils; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import com.xinelu.manage.domain.goodsOrderDetails.GoodsOrderDetails; +import com.xinelu.manage.domain.hospitalpersoninfo.HospitalPersonInfo; +import com.xinelu.manage.domain.patientinfo.PatientInfo; +import com.xinelu.manage.domain.poserInfo.PoserInfo; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import com.xinelu.manage.mapper.goodsOrderDetails.GoodsOrderDetailsMapper; +import com.xinelu.applet.mapper.healthconsultation.HealthConsultationMapper; +import com.xinelu.manage.mapper.hospitalpersoninfo.HospitalPersonInfoMapper; +import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper; +import com.xinelu.manage.mapper.poserInfo.PoserInfoMapper; +import com.xinelu.manage.vo.patientinfo.PatientInfoVO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.compress.utils.Lists; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @Description 健康咨询接口业务层实现类 + * @Author zh + * @Date 2023-03-07 + */ +@Slf4j +@Service +public class HealthConsultationServiceImpl implements HealthConsultationService { + + @Resource + private PatientInfoMapper patientInfoMapper; + @Resource + private GoodsOrderMapper goodsOrderMapper; + @Resource + private GoodsOrderDetailsMapper goodsOrderDetailsMapper; + @Resource + private HealthConsultationMapper healthConsultationMapper; + @Resource + private PoserInfoMapper poserInfoMapper; + @Resource + private HospitalPersonInfoMapper hospitalPersonInfoMapper; + @Resource + private AppointmentTimeUtil appointmentTimeUtil; + @Resource + private PageServiceUtil pageServiceUtil; + + /** + * 健康咨询-预约医生 + * + * @return AjaxResult + */ + @Override + public TableDataInfo selectDepartment() { + //查询海报及科室 + List poserList = poserInfoMapper.selectPoserListByModuleTyp(PoserModuleTypeEnum.HEALTH_CONSUTION_MODULE.getInfo()); + pageServiceUtil.startPage(); + List healthConsultation = healthConsultationMapper.selectHospitalDepartmentList(); + if (CollectionUtils.isNotEmpty(healthConsultation)) { + healthConsultation.get(0).setPoserInfoList(poserList); + } + return pageServiceUtil.getDataTable(healthConsultation); + } + + /** + * 健康咨询-预约医生(无分页) + * + * @return AjaxResult + */ + @Override + public List selectDepartmentNoPage() { + //查询海报及科室 + List poserList = poserInfoMapper.selectPoserListByModuleTyp(PoserModuleTypeEnum.HEALTH_CONSUTION_MODULE.getInfo()); + List healthConsultation = healthConsultationMapper.selectHospitalDepartmentList(); + if (CollectionUtils.isNotEmpty(healthConsultation)) { + healthConsultation.get(0).setPoserInfoList(poserList); + } + return healthConsultation; + } + + /** + * 单查科室人员 + * + * @param departmentId 科室id + * @return AjaxResult + */ + @Override + public List selectHospitalPerson(Long departmentId) { + if (Objects.isNull(departmentId)) { + return new ArrayList<>(); + } + return hospitalPersonInfoMapper.selectHospitalPerson(departmentId); + } + + /** + * 健康咨询-信息确认 + * + * @param patientId 用户信息 + * @return AjaxResult + */ + @Override + public AjaxResult informationConfirmation(Long patientId) { + PatientAndTimeVO patientAndTime = new PatientAndTimeVO(); + PatientInfo patientInfo = healthConsultationMapper.selectPatientById(patientId); + if (Objects.isNull(patientInfo)) { + return AjaxResult.error("用户信息不存在!"); + } + LocalDate nowTime = LocalDate.now(); + //近七天的预约时间点数据集合 + List weekDaysList = Lists.newArrayList(); + appointmentTimeUtil.setWeekDayAndWeekDate(nowTime, weekDaysList); + patientAndTime.setAppointmentTimeList(weekDaysList); + patientAndTime.setPatientName(patientInfo.getPatientName()); + patientAndTime.setPhone(patientInfo.getPhone()); + return AjaxResult.success(patientAndTime); + } + + /** + * 手机App和微信小程序健康咨询确认订单方法 + * + * @param healthConsultationOrderDTO 健康咨询订单 + * @return 结果 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public AjaxResult insertHealthConsultationOrder(HealthConsultationOrderDTO healthConsultationOrderDTO) { + //判断当前会员信息是否存在 + PatientInfoVO patientInfo = patientInfoMapper.getPatientInfoById(healthConsultationOrderDTO.getPatientId()); + if (Objects.isNull(patientInfo)) { + return AjaxResult.error("用户信息不存在,无法预约专家!"); + } + //根据id查询当前专家是否存在 + HospitalPersonInfo hospitalPersonInfo = hospitalPersonInfoMapper.selectHospitalPersonInfoById(healthConsultationOrderDTO.getHospitalPersonId()); + if (Objects.isNull(hospitalPersonInfo)) { + return AjaxResult.error("当前专家信息不存在,请重新预约!"); + } + //生成订单信息 + GoodsOrder goodsOrder = new GoodsOrder(); + BeanUtils.copyProperties(healthConsultationOrderDTO, goodsOrder); + String goodOrderNo = StringUtils.fillZeroByPatientId(healthConsultationOrderDTO.getPatientId(), 5) + System.nanoTime(); + goodsOrder.setOrderNo(goodOrderNo); + goodsOrder.setOrderStatus(GooodsOrderStatusEnum.WAIT_PAY.getInfo()); + goodsOrder.setDelFlag(0); + goodsOrder.setOrderType(OrderTypeEnum.HEALTH_CONSULTATION.getInfo()); + goodsOrder.setBuySource(BuySourceEnum.HEALTH_CONSULTATION.getInfo()); + goodsOrder.setCreateTime(LocalDateTime.now()); + goodsOrder.setOrderTime(LocalDateTime.now()); + goodsOrder.setOriginalTotalPrice(healthConsultationOrderDTO.getTotalPrice()); + int insertGoodsOrder = goodsOrderMapper.insertGoodsOrder(goodsOrder); + if (insertGoodsOrder <= 0) { + throw new ServiceException("预约订单新增信息失败,请联系管理员!"); + } + GoodsOrderDetails goodsOrderDetails = new GoodsOrderDetails(); + goodsOrderDetails.setGoodsOrderId(goodsOrder.getId()); + goodsOrderDetails.setOrderNo(goodOrderNo); + goodsOrderDetails.setGoodsName("健康咨询"); + goodsOrderDetails.setTotalPrice(healthConsultationOrderDTO.getTotalPrice()); + goodsOrderDetails.setDelFlag(0); + goodsOrderDetails.setCreateTime(LocalDateTime.now()); + int insertGoodsOrderDetails = goodsOrderDetailsMapper.insertGoodsOrderDetails(goodsOrderDetails); + if (insertGoodsOrderDetails <= 0) { + throw new ServiceException("预约订单明细新增信息失败,请联系管理员!"); + } + return AjaxResult.success(goodsOrderMapper.getGoodsOrderByOrderNo(goodOrderNo)); + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/logistics/LogisticsService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/logistics/LogisticsService.java new file mode 100644 index 0000000..1ceac46 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/logistics/LogisticsService.java @@ -0,0 +1,22 @@ +package com.xinelu.applet.service.logistics; + +import com.xinelu.common.core.domain.AjaxResult; + +/** + * @Description 快递鸟物流查询接口业务层 + * @Author 纪寒 + * @Date 2022-11-01 13:35:04 + * @Version 1.0 + */ +public interface LogisticsService { + + /** + * 根据快递快递单号查询物流信息 + * + * @param orderNo 订单单号 + * @param expressNo 快递单号 + * @return 物流信息结果 + * @throws Exception 异常信息 + */ + AjaxResult queryLogisticsInfo(String orderNo, String expressNo) throws Exception; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/logistics/impl/LogisticsServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/logistics/impl/LogisticsServiceImpl.java new file mode 100644 index 0000000..797c4c9 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/logistics/impl/LogisticsServiceImpl.java @@ -0,0 +1,172 @@ +package com.xinelu.applet.service.logistics.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.xinelu.applet.service.logistics.LogisticsService; +import com.xinelu.applet.utils.LogisticsUtil; +import com.xinelu.applet.vo.logistics.DistinguishResultVO; +import com.xinelu.applet.vo.logistics.SearchMonitorResultVO; +import com.xinelu.common.config.LogisticsConfig; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description 快递鸟物流查询接口业务层实现类 + * @Author 纪寒 + * @Date 2022-11-01 13:35:38 + * @Version 1.0 + */ +@Slf4j +@Service +public class LogisticsServiceImpl implements LogisticsService { + + @Resource + private LogisticsConfig logisticsConfig; + @Resource + private GoodsOrderMapper goodsOrderMapper; + + /** + * 编码格式 + */ + private static final String CHARSET = "UTF-8"; + + /** + * 识别单号接口指令 + */ + private static final String DISTINGUISH_REQUEST_TYPE = "2002"; + + /** + * DataType=2,请求、返回数据类型均为JSON格式 + */ + private static final String DATA_TYPE = "2"; + + /** + * 即时查询接口指令 + */ + private static final String SEARCH_MONITOR_REQUEST_TYPE = "8001"; + + /** + * 顺丰快递编码 + */ + private static final String SF_SHIPPER_CODE_TYPE = "SF"; + + /** + * 根据快递快递单号查询物流信息 + * + * @param orderNo 订单单号 + * @param expressNo 快递单号 + * @return 物流信息结果 + * @throws Exception 异常信息 + */ + @Override + public AjaxResult queryLogisticsInfo(String orderNo, String expressNo) throws Exception { + GoodsOrder goodsOrder = goodsOrderMapper.getGoodsOrderByOrderNo(orderNo); + if (Objects.isNull(goodsOrder) || StringUtils.isBlank(goodsOrder.getPhone())) { + return AjaxResult.error("当前订单信息不存在!"); + } + if (StringUtils.isBlank(goodsOrder.getExpressNo())) { + return AjaxResult.error("当前订单未发货,暂无订物流信息!"); + } + //用户id、API KEY、正式地址等参数信息 + String eBusinessId = logisticsConfig.getEBusinessId(); + String apiKey = logisticsConfig.getApiKey(); + String expressBirdUrl = logisticsConfig.getExpressBirdUrl(); + Map distinguishParam = buildDistinguishParam(expressNo, eBusinessId, apiKey); + String distinguishResult = LogisticsUtil.sendPost(expressBirdUrl, distinguishParam); + if (StringUtils.isBlank(distinguishResult)) { + log.info("调用快递鸟识别单号返回结果为空,请求参数 ====> {}", distinguishParam.toString()); + return AjaxResult.error("当前订单暂无物流信息!"); + } + DistinguishResultVO vo = JSONObject.parseObject(distinguishResult, DistinguishResultVO.class); + if (Objects.isNull(vo) || BooleanUtils.isFalse(vo.getSuccess())) { + log.info("调用快递鸟识别单号返回结果为空,请求参数 ====> {}", distinguishParam.toString()); + return AjaxResult.error("当前订单暂无物流信息!"); + } + List shipperCodeList = vo.getShippers().stream().filter(item -> StringUtils.isNotBlank(item.getShipperCode())).map(DistinguishResultVO.ShippersDTO::getShipperCode).distinct().collect(Collectors.toList()); + //循环查询快递信息 + SearchMonitorResultVO monitorResultVO = null; + for (String shipperCode : shipperCodeList) { + if (StringUtils.isBlank(shipperCode)) { + continue; + } + //构建在途查询中即时查询接口参数信息 + Map searchMonitorParam = buildSearchMonitorParam(expressNo, eBusinessId, apiKey, shipperCode, goodsOrder.getPhone()); + String searchMonitorResult = LogisticsUtil.sendPost(expressBirdUrl, searchMonitorParam); + monitorResultVO = JSONObject.parseObject(searchMonitorResult, SearchMonitorResultVO.class); + if (Objects.nonNull(monitorResultVO) && BooleanUtils.isTrue(monitorResultVO.getSuccess())) { + List sortTraces = monitorResultVO.getTraces().stream() + .filter(item -> Objects.nonNull(item.getAcceptTime())) + .sorted(Comparator.comparing(SearchMonitorResultVO.TracesDTO::getAcceptTime).reversed()).collect(Collectors.toList()); + monitorResultVO.setTraces(sortTraces); + monitorResultVO.setShipperName(vo.getShippers().stream().filter(item -> StringUtils.isNotBlank(item.getShipperName())) + .filter(item -> shipperCode.equals(item.getShipperCode())).map(DistinguishResultVO.ShippersDTO::getShipperName).findFirst().orElse("")); + break; + } + } + return AjaxResult.success(monitorResultVO); + } + + /** + * 构建识别单号参数信息 + * + * @param expressNo 快递单号 + * @param eBusinessId 用户id + * @param apiKey API key + * @return 参数信息 + * @throws Exception 异常信息 + */ + private Map buildDistinguishParam(String expressNo, String eBusinessId, + String apiKey) throws Exception { + String requestData = "{'LogisticCode': '" + expressNo + "'}"; + Map params = new LinkedHashMap<>(); + params.put("RequestData", LogisticsUtil.urlEncoder(requestData, CHARSET)); + params.put("EBusinessID", eBusinessId); + params.put("RequestType", DISTINGUISH_REQUEST_TYPE); + String dataSign = LogisticsUtil.encrypt(requestData, apiKey, CHARSET); + params.put("DataSign", LogisticsUtil.urlEncoder(dataSign, CHARSET)); + params.put("DataType", DATA_TYPE); + return params; + } + + /** + * 构建即时查询物流单号信息 + * + * @param expressNo 快递单号 + * @param eBusinessId 用户id + * @param apiKey API key + * @param shipperCode 快递公司编码 + * @param phone 联系电话 + * @return 参数信息 + * @throws Exception 异常信息 + */ + private Map buildSearchMonitorParam(String expressNo, String eBusinessId, String apiKey, + String shipperCode, String phone) throws Exception { + Map sysParamMap = new LinkedHashMap<>(); + sysParamMap.put("OrderCode", ""); + if (SF_SHIPPER_CODE_TYPE.equals(shipperCode)) { + sysParamMap.put("CustomerName", phone.substring(7, 11)); + } else { + sysParamMap.put("CustomerName", ""); + } + sysParamMap.put("ShipperCode", shipperCode); + sysParamMap.put("LogisticCode", expressNo); + String requestData = JSON.toJSONString(sysParamMap); + Map params = new LinkedHashMap<>(); + params.put("RequestData", LogisticsUtil.urlEncoder(requestData, CHARSET)); + params.put("EBusinessID", eBusinessId); + params.put("RequestType", SEARCH_MONITOR_REQUEST_TYPE); + String dataSign = LogisticsUtil.encrypt(requestData, apiKey, CHARSET); + params.put("DataSign", LogisticsUtil.urlEncoder(dataSign, CHARSET)); + params.put("DataType", DATA_TYPE); + return params; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseappletpersonworkorder/Impl/NurseAppletPersonWorkOrderServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseappletpersonworkorder/Impl/NurseAppletPersonWorkOrderServiceImpl.java index bdf26ed..5983d71 100644 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseappletpersonworkorder/Impl/NurseAppletPersonWorkOrderServiceImpl.java +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseappletpersonworkorder/Impl/NurseAppletPersonWorkOrderServiceImpl.java @@ -8,7 +8,6 @@ import com.xinelu.common.enums.OrderStatusEnum; import com.xinelu.common.exception.ServiceException; import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; import com.xinelu.manage.mapper.appointmentorderdetails.AppointmentOrderDetailsMapper; -import com.xinelu.manage.service.stationmessagepush.StationMessagePushService; import com.xinelu.manage.vo.appointmentorder.AppointmentReceivingOrderVO; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -29,8 +28,6 @@ public class NurseAppletPersonWorkOrderServiceImpl implements NurseAppletPersonW @Resource private AppointmentOrderMapper appointmentOrderMapper; @Resource - private StationMessagePushService stationMessagePushService; - @Resource private AppointmentOrderDetailsMapper appointmentOrderDetailsMapper; /** @@ -50,8 +47,6 @@ public class NurseAppletPersonWorkOrderServiceImpl implements NurseAppletPersonW if (update < 0) { throw new ServiceException("接单失败,请联系管理员!"); } - //异步发送消息 - stationMessagePushService.receivingOrdersOperationsPush(appointmentReceivingOrder); return AjaxResult.success(); } } diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseapplogin/impl/NurseAppLoginServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseapplogin/impl/NurseAppLoginServiceImpl.java index ba9bce0..414e087 100644 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseapplogin/impl/NurseAppLoginServiceImpl.java +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nurseapplogin/impl/NurseAppLoginServiceImpl.java @@ -177,7 +177,9 @@ public class NurseAppLoginServiceImpl implements NurseAppLoginService { patientDisease.setAge(AgeUtil.getAgeMonth(String.valueOf(patientDisease.getBirthDate()))); } if (Objects.nonNull(patientDisease) && StringUtils.isNotBlank(patientDisease.getDisease())) { - patientDisease.setDiseaseList(patientDisease.getDisease().split("")); + patientDisease.setDiseaseList(Arrays.stream(patientDisease.getDisease().split(",")) + .map(Integer::valueOf) + .toArray(Integer[]::new)); } if (Objects.nonNull(patientDisease) && StringUtils.isNotBlank(patientDisease.getAreaCode())) { SysAreaVO codeName = sysAreaMapper.getSubordinateRegionsFindSuperiorRegions(patientDisease.getAreaCode()); diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursepersonapplogin/impl/NursePersonAppLoginServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursepersonapplogin/impl/NursePersonAppLoginServiceImpl.java index 31e4fd1..3869f7e 100644 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursepersonapplogin/impl/NursePersonAppLoginServiceImpl.java +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursepersonapplogin/impl/NursePersonAppLoginServiceImpl.java @@ -23,7 +23,6 @@ import com.xinelu.manage.mapper.nursestation.NurseStationMapper; import com.xinelu.manage.mapper.nursestationperson.NurseStationPersonMapper; import com.xinelu.manage.mapper.nursestationpersonrevenue.NurseStationPersonRevenueMapper; import com.xinelu.manage.mapper.patientdiseaseinfo.PatientDiseaseInfoMapper; -import com.xinelu.manage.service.stationmessagepush.StationMessagePushService; import com.xinelu.manage.vo.appointmentorder.AppointmentOrderRecordVO; import com.xinelu.manage.vo.appointmentorder.AppointmentReceivingOrderVO; import com.xinelu.manage.vo.nursestation.NurseStationSysUserVO; @@ -71,8 +70,6 @@ public class NursePersonAppLoginServiceImpl implements INursePersonAppLoginServi private NurseStationPersonRevenueMapper nurseStationPersonRevenueMapper; @Resource private PatientDiseaseInfoMapper patientDiseaseInfoMapper; - @Resource - private StationMessagePushService stationMessagePushService; /** * 工单首页查询已完成以及未完成数量 @@ -168,8 +165,6 @@ public class NursePersonAppLoginServiceImpl implements INursePersonAppLoginServi if (update <= 0) { throw new ServiceException("任务退回失败,请联系管理员!"); } - //异步发送信息 - stationMessagePushService.refusalOrdersOperationsPush(appointmentReceivingOrder); return AjaxResult.success(); } @@ -213,8 +208,6 @@ public class NursePersonAppLoginServiceImpl implements INursePersonAppLoginServi Long nurseStationPersonId = Objects.isNull(orderDetails.getNurseStationPersonId()) ? 0 : orderDetails.getNurseStationPersonId(); BigDecimal orderCommissionAmount = Objects.isNull(orderDetails.getOrderCommissionAmount()) ? BigDecimal.ZERO : orderDetails.getOrderCommissionAmount(); nurseStationPersonMapper.updateTotalRevenueAmountById(nurseStationPersonId, orderCommissionAmount); - //异步发送信息 - stationMessagePushService.orderCompletionOperationsPush(orderDetails); return AjaxResult.success(); } diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursingorder/INursingOrderService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursingorder/INursingOrderService.java new file mode 100644 index 0000000..1ea42de --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursingorder/INursingOrderService.java @@ -0,0 +1,58 @@ +package com.xinelu.applet.service.nursingorder; + + +import com.xinelu.applet.vo.nursingorder.AppletGoodsOrderVO; +import com.xinelu.applet.vo.nursingorder.NursingOrderInfoVO; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.core.domain.entity.SysDictData; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; + +import java.util.List; + +/** + * 订单列表Service接口 + * + * @author zhangheng + * @date 2022-09-06 + */ +public interface INursingOrderService { + /** + * 根据被护理人patientId查询订单信息 + * + * @param patientId 被护理人id + * @return 订单列表 + */ + List getNursingOrderByPatientId(Long patientId); + + /** + * 根据护理人id以及订单状态查询订单信息 + * + * @param goodsOrderVO 订单信息 + * @return java.util.List + **/ + List getGoodsOrder(AppletGoodsOrderVO goodsOrderVO); + + /** + * 查询退款原因 + * + * @param sysDictData 退款原因 + * @return com.xinyilu.common.core.domain.entity.SysDictData + **/ + List getRefundReason(SysDictData sysDictData); + + /** + * 修改商品订单(退款售后记录信息) + * + * @param goodsOrder 商品订单 + * @return 结果 + */ + int updateGoodsOrder(GoodsOrder goodsOrder); + + /** + * 根据预约订单编号查询对应得订单详情信息 + * + * @param orderNo 订单编号 + * @return 详情信息 + */ + AjaxResult getAppointmentDetailsInfo(String orderNo); +} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursingorder/impl/NursingOrderServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursingorder/impl/NursingOrderServiceImpl.java new file mode 100644 index 0000000..6756490 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/nursingorder/impl/NursingOrderServiceImpl.java @@ -0,0 +1,110 @@ +package com.xinelu.applet.service.nursingorder.impl; + + +import com.xinelu.applet.mapper.nursingorder.NursingOrderMapper; +import com.xinelu.applet.service.nursingorder.INursingOrderService; +import com.xinelu.applet.vo.nursingorder.AppletGoodsOrderVO; +import com.xinelu.applet.vo.nursingorder.NursingOrderInfoVO; +import com.xinelu.applet.vo.specialdisease.AppointmentOrderDetailsInfoVO; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.core.domain.entity.SysDictData; +import com.xinelu.common.enums.ConfirmRefundStatusEnum; +import com.xinelu.common.enums.GooodsOrderStatusEnum; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +/** + * @Description 订单分页 + * @Author ZhangHeng + * @Date 2022-09-06 + * @Version + */ +@Service +public class NursingOrderServiceImpl implements INursingOrderService { + + @Resource + private NursingOrderMapper nursingOrderMapper; + + /** + * 查询个人订单列表并分页 + * + * @param patientId 被护理人id + * @return 结果 + */ + @Override + public List getNursingOrderByPatientId(Long patientId) { + return nursingOrderMapper.getNursingOrderVOByPatientId(patientId); + } + + /** + * 根据护理人id以及订单状态查询订单信息 + * + * @param goodsOrderVO 订单信息 + * @return java.util.List + **/ + @Override + public List getGoodsOrder(AppletGoodsOrderVO goodsOrderVO) { + return nursingOrderMapper.getGoodsOrder(goodsOrderVO); + } + + /** + * 查询退款原因 + * + * @param sysDictData 退款原因 + * @return com.xinyilu.common.core.domain.entity.SysDictData + **/ + @Override + public List getRefundReason(SysDictData sysDictData) { + //dict_type 字典类型refund_reason + sysDictData.setDictType("refund_reason"); + return nursingOrderMapper.getRefundReason(sysDictData); + } + + /** + * 修改商品订单(退款售后记录信息) + * + * @param goodsOrder 商品订单 + * @return 结果 + */ + @Override + public int updateGoodsOrder(GoodsOrder goodsOrder) { + //设置修改人以及修改时间 + goodsOrder.setUpdateTime(LocalDateTime.now()); + //订单状态 退款中 WAIT_REFUND + goodsOrder.setOrderStatus(GooodsOrderStatusEnum.WAIT_REFUND.getInfo()); + //确认退款状态 未确认 NOT_CONFIRM + goodsOrder.setConfirmRefundStatus(ConfirmRefundStatusEnum.NOT_CONFIRM.getInfo()); + return nursingOrderMapper.updateGoodsOrder(goodsOrder); + } + + /** + * 根据预约订单编号查询对应得订单详情信息 + * + * @param orderNo 订单编号 + * @return 详情信息 + */ + @Override + public AjaxResult getAppointmentDetailsInfo(String orderNo) { + //查询预约服务订单信息 + AppointmentOrderDetailsInfoVO detailsInfoVO = nursingOrderMapper.getAppointmentOrderDetailsInfo(orderNo); + if (Objects.isNull(detailsInfoVO)) { + return AjaxResult.success(); + } + //查询护理站相关信息 + AppointmentOrderDetailsInfoVO nurseStationInfo = nursingOrderMapper.getNurseStationByItemId(Objects.isNull(detailsInfoVO.getNurseStationItemId()) ? 0L : detailsInfoVO.getNurseStationItemId()); + if (Objects.nonNull(nurseStationInfo)) { + detailsInfoVO.setNurseStationName(StringUtils.isBlank(nurseStationInfo.getNurseStationName()) ? "" : nurseStationInfo.getNurseStationName()); + detailsInfoVO.setStationPhone(StringUtils.isBlank(nurseStationInfo.getStationPhone()) ? "" : nurseStationInfo.getStationPhone()); + detailsInfoVO.setAddress(StringUtils.isBlank(nurseStationInfo.getAddress()) ? "" : nurseStationInfo.getAddress()); + detailsInfoVO.setStationPictureUrl(StringUtils.isBlank(nurseStationInfo.getStationPictureUrl()) ? "" : nurseStationInfo.getStationPictureUrl()); + detailsInfoVO.setItemPictureUrl(StringUtils.isBlank(nurseStationInfo.getItemPictureUrl()) ? "" : nurseStationInfo.getItemPictureUrl()); + } + return AjaxResult.success(detailsInfoVO); + } +} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/personappletlogin/Impl/PersonAppletLoginServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/personappletlogin/Impl/PersonAppletLoginServiceImpl.java deleted file mode 100644 index 5562b62..0000000 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/personappletlogin/Impl/PersonAppletLoginServiceImpl.java +++ /dev/null @@ -1,231 +0,0 @@ -package com.xinelu.applet.service.personappletlogin.Impl; - - -import com.xinelu.applet.mapper.nursemanagepersonwechatinfo.NurseManagePersonWechatInfoMapper; -import com.xinelu.applet.mapper.personappletlogin.PersonAppletLoginMapper; -import com.xinelu.applet.service.personappletlogin.PersonAppletLoginService; -import com.xinelu.applet.utils.AppletAccessTokenUtil; -import com.xinelu.applet.vo.personappletlogin.PersonAppletVO; -import com.xinelu.applet.vo.personappletlogin.UserAndRole; -import com.xinelu.common.config.NurseAppletChatConfig; -import com.xinelu.common.constant.Constants; -import com.xinelu.common.core.domain.AjaxResult; -import com.xinelu.common.entity.AppletLoginVO; -import com.xinelu.common.entity.AppletPhoneVO; -import com.xinelu.common.exception.ServiceException; -import com.xinelu.common.utils.AppletChatUtil; -import com.xinelu.manage.domain.nursemanagepersonwechatinfo.NurseManagePersonWechatInfo; -import com.xinelu.manage.mapper.nursestationperson.NurseStationPersonMapper; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * @Description 护理员微信小程序登录注册业务层实现类 - * @Author zh - * @Date 2023-03-30 - * @Version 1.0 - */ -@Slf4j -@Service -public class PersonAppletLoginServiceImpl implements PersonAppletLoginService { - @Resource - private RedisTemplate redisTemplate; - @Resource - private NurseAppletChatConfig nurseAppletChatConfig; - @Resource - private AppletAccessTokenUtil appletAccessTokenUtil; - @Resource - private NurseStationPersonMapper nurseStationPersonMapper; - @Resource - private PersonAppletLoginMapper personAppletLoginMapper; - @Resource - private NurseManagePersonWechatInfoMapper nurseManagePersonWechatInfoMapper; - - /** - * 返回成功状态码 - */ - private static final int SUCCESS_CODE = 0; - - /** - * 获取微信小程序access_token错误码 - */ - private static final int ERROR_ACCESS_CODE = 40001; - - /** - * 返回成功状态码 - */ - private static final String OK = "ok"; - - /** - * 根据登录凭证获取用户的登录信息 - * - * @param loginCode 登录凭证 - * @return 微信用户登录信息 - */ - @Transactional(rollbackFor = Exception.class) - @Override - public AjaxResult personAppletLogin(String loginCode, String phoneCode) { - //根据code获取用户的微信unionId以及openId等信息 - AppletLoginVO appletLoginInfo = AppletChatUtil.getAppletLoginInfo(nurseAppletChatConfig.getAppletId(), nurseAppletChatConfig.getSecret(), loginCode, nurseAppletChatConfig.getGrantType()); - if (Objects.isNull(appletLoginInfo)) { - return AjaxResult.error("获取微信小程序用户信息失败"); - } - if (Objects.nonNull(appletLoginInfo.getErrcode()) && appletLoginInfo.getErrcode() != SUCCESS_CODE) { - return AjaxResult.error("获取微信小程序用户信息失败,失败信息为:" + appletLoginInfo.getErrmsg()); - } - //获取微信accessToken,从Redis中取出accessToken - String accessToken; - String accessTokenKey = Constants.NURSE_STATION_PERSON_APPLET_ACCESS_TOKEN + "accessToken"; - Object object = redisTemplate.opsForValue().get(accessTokenKey); - if (Objects.isNull(object)) { - accessToken = appletAccessTokenUtil.getPersonAppletAccessToken(); - } else { - accessToken = (String) object; - } - //获取用户手机号 - AppletPhoneVO appletPhoneInfo = AppletChatUtil.getAppletPhoneInfo(phoneCode, accessToken); - if (Objects.isNull(appletPhoneInfo)) { - return AjaxResult.error("获取用户手机号失败"); - } - if (Objects.nonNull(appletPhoneInfo.getErrcode()) && appletPhoneInfo.getErrcode() == ERROR_ACCESS_CODE) { - //当前Redis缓存中的access_token无效直接删除 - if (Objects.nonNull(object)) { - redisTemplate.delete(accessTokenKey); - accessToken = appletAccessTokenUtil.getPersonAppletAccessToken(); - appletPhoneInfo = AppletChatUtil.getAppletPhoneInfo(phoneCode, accessToken); - if (Objects.isNull(appletPhoneInfo)) { - return AjaxResult.error("获取用户手机号失败"); - } - if (Objects.nonNull(appletPhoneInfo.getErrcode()) && appletPhoneInfo.getErrcode() == ERROR_ACCESS_CODE) { - return AjaxResult.error("登录失败!"); - } - } - } - if (StringUtils.isNotBlank(appletPhoneInfo.getErrmsg()) && !OK.equals(appletPhoneInfo.getErrmsg())) { - return AjaxResult.error("获取用户手机号失败,失败信息为:" + appletPhoneInfo.getErrmsg()); - } - PersonAppletVO personAppletVO = getPersonApplet(appletPhoneInfo, appletLoginInfo); - return AjaxResult.success(personAppletVO); - } - - /** - * 护理站管理人员微信个人信息对象 - * - * @param phone 护理员手机号 - * @param openid 用户的信息 - * @param sysUser 管理员信息 - */ - private void getNurseManagePersonWechat(String phone, String openid, List sysUser) { - //护理站管理人员微信个人信息对象 - NurseManagePersonWechatInfo nurseManagePersonWechat = nurseManagePersonWechatInfoMapper.selectNurseManagePersonWechatInfoByPhone(phone); - NurseManagePersonWechatInfo nurseManagePersonWechatInfo = new NurseManagePersonWechatInfo(); - if (Objects.isNull(nurseManagePersonWechat)) { - nurseManagePersonWechatInfo.setOpenid(openid); - nurseManagePersonWechatInfo.setPhone(phone); - nurseManagePersonWechatInfo.setNurseStationId(StringUtils.isBlank(sysUser.get(0).getNurseStationIds()) ? "" : sysUser.get(0).getNurseStationIds()); - nurseManagePersonWechatInfo.setUserId(Objects.isNull(sysUser.get(0).getUserId()) ? null : sysUser.get(0).getUserId()); - nurseManagePersonWechatInfo.setCreateTime(LocalDateTime.now()); - int count = nurseManagePersonWechatInfoMapper.insertNurseManagePersonWechatInfo(nurseManagePersonWechatInfo); - if (count <= 0) { - throw new ServiceException("新增护理站管理人员微信个人信息失败,请联系管理员!"); - } - } - if (Objects.nonNull(nurseManagePersonWechat)) { - nurseManagePersonWechatInfo.setId(Objects.isNull(nurseManagePersonWechat.getId()) ? null : nurseManagePersonWechat.getId()); - nurseManagePersonWechatInfo.setOpenid(openid); - nurseManagePersonWechatInfo.setPhone(phone); - nurseManagePersonWechatInfo.setNurseStationId(StringUtils.isBlank(sysUser.get(0).getNurseStationIds()) ? "" : sysUser.get(0).getNurseStationIds()); - nurseManagePersonWechatInfo.setUserId(Objects.isNull(sysUser.get(0).getUserId()) ? null : sysUser.get(0).getUserId()); - int update = nurseManagePersonWechatInfoMapper.updateNurseManagePersonWechatInfo(nurseManagePersonWechatInfo); - if (update <= 0) { - throw new ServiceException("新增护理站管理人员微信个人信息失败,请联系管理员!"); - } - } - } - - /** - * 护理员登录接口方法抽取 - * - * @param appletPhoneInfo 微信用户信息 - * @param appletLoginInfo 手机号信息 - * @return 登录标识 - */ - private PersonAppletVO getPersonApplet(AppletPhoneVO appletPhoneInfo, AppletLoginVO appletLoginInfo) { - PersonAppletVO appletParent = new PersonAppletVO(); - String phone = StringUtils.isBlank(appletPhoneInfo.getPhoneInfo().getPhoneNumber()) ? "" : appletPhoneInfo.getPhoneInfo().getPhoneNumber(); - String openid = StringUtils.isBlank(appletLoginInfo.getOpenid()) ? "" : appletLoginInfo.getOpenid(); - PersonAppletVO nurseStationPerson = personAppletLoginMapper.getNurseStationPersonByPhone(phone); - List sysUser = personAppletLoginMapper.selectSysUser(phone); - //说明当前用户角色即是:护理员又是护理站运营人员 - if (Objects.nonNull(nurseStationPerson) && CollectionUtils.isNotEmpty(sysUser)) { - //更新用户的openid等微信标识信息 - this.updateNurseStationPerson(appletParent, nurseStationPerson, openid); - appletParent.setPersonRoleLoginFlag(Constants.PERSON_ROLE_NAME); - //护理站管理人员微信个人信息对象 - List roleKeyList = sysUser.stream().filter(Objects::nonNull).map(UserAndRole::getRoleKey).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(roleKeyList) && (String.join((","), roleKeyList).contains(Constants.STATION_ROLE_NAME))) { - this.getNurseManagePersonWechat(phone, openid, sysUser); - appletParent.setPersonRoleLoginFlag(Constants.STATION_AND_PERSON_ROLE_NAME); - } - } - //说明当前用户角色即是:护理员 - if (Objects.nonNull(nurseStationPerson) && Objects.isNull(sysUser)) { - //更新用户的openid等微信标识信息 - this.updateNurseStationPerson(appletParent, nurseStationPerson, openid); - appletParent.setPersonRoleLoginFlag(Constants.PERSON_ROLE_NAME); - } - //说明当前用户角色即是:护理站运营人员 - if (Objects.isNull(nurseStationPerson) && Objects.nonNull(sysUser)) { - List roleKeyList = sysUser.stream().filter(Objects::nonNull).map(UserAndRole::getRoleKey).collect(Collectors.toList()); - appletParent.setPersonRoleLoginFlag(Constants.NOT_ROLE_NAME); - if (CollectionUtils.isNotEmpty(roleKeyList) && (String.join((","), roleKeyList).contains(Constants.STATION_ROLE_NAME))) { - this.getNurseManagePersonWechat(phone, openid, sysUser); - appletParent.setPersonRoleLoginFlag(Constants.STATION_ROLE_NAME); - } - appletParent.setPhone(phone); - } - //说明当前用户角色即是:即不是护理员又是不是护理站运营人员 - if (Objects.isNull(nurseStationPerson) && Objects.isNull(sysUser)) { - appletParent.setPhone(phone); - appletParent.setPersonRoleLoginFlag(Constants.NOT_ROLE_NAME); - } - //当前用户角色只要包含护理员,那么将护理员的信息返回给前端 - if (Objects.nonNull(nurseStationPerson)) { - appletParent.setNurseStationId(Objects.isNull(nurseStationPerson.getNurseStationId()) ? null : nurseStationPerson.getNurseStationId()); - appletParent.setNurseStationPersonId(Objects.isNull(nurseStationPerson.getNurseStationPersonId()) ? null : nurseStationPerson.getNurseStationPersonId()); - appletParent.setNursePersonName(StringUtils.isBlank(nurseStationPerson.getNursePersonName()) ? "" : nurseStationPerson.getNursePersonName()); - } - return appletParent; - } - - /** - * 修改护理人员信息 - * - * @param appletParent 护理员信息 - * @param nurseStationPerson 护理员信息 - * @param openid 护理员信息 - */ - private void updateNurseStationPerson(PersonAppletVO appletParent, PersonAppletVO nurseStationPerson, String openid) { - appletParent.setId(nurseStationPerson.getNurseStationPersonId()); - appletParent.setNurseStationPersonId(nurseStationPerson.getNurseStationPersonId()); - appletParent.setOpenid(openid); - appletParent.setPhone(StringUtils.isBlank(nurseStationPerson.getPhone()) ? "" : nurseStationPerson.getPhone()); - appletParent.setUpdateTime(LocalDateTime.now()); - int updateCount = nurseStationPersonMapper.updateNurseStationPerson(appletParent); - if (updateCount <= 0) { - throw new ServiceException("修改护理人员信息失败,请联系管理员!"); - } - } -} - - diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/personappletlogin/PersonAppletLoginService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/personappletlogin/PersonAppletLoginService.java deleted file mode 100644 index 5d1bd1b..0000000 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/personappletlogin/PersonAppletLoginService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.xinelu.applet.service.personappletlogin; - -import com.xinelu.common.core.domain.AjaxResult; -import org.springframework.web.bind.annotation.RequestParam; - -/** - * @Description 护理员微信小程序登录注册业务层 - * @Author zh - * @Date 2023-03-30 - */ -public interface PersonAppletLoginService { - - /** - * 护理员根据登录凭证获取用户的登录信息 - * - * @param loginCode 登录凭证 - * @param phoneCode 手机号凭证 - * @return 微信用户登录信息 - */ - AjaxResult personAppletLogin(@RequestParam("loginCode") String loginCode, String phoneCode); -} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatPayNotifyService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatPayNotifyService.java new file mode 100644 index 0000000..1ede360 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatPayNotifyService.java @@ -0,0 +1,53 @@ +package com.xinelu.applet.service.wechatpaymentinfo; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @Description 微信支付回调业务层 + * @Author 纪寒 + * @Date 2022-10-20 14:00:21 + * @Version 1.0 + */ +public interface WeChatPayNotifyService { + + /** + * 新医路支付回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + String xylWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception; + + /** + * 医路优品支付回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + String ylypWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception; + + /** + * 新医路退款回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + String xylWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception; + + /** + * 医路优品退款回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + String ylypWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatPaymentService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatPaymentService.java new file mode 100644 index 0000000..75bdf05 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatPaymentService.java @@ -0,0 +1,82 @@ +package com.xinelu.applet.service.wechatpaymentinfo; + +import com.xinelu.applet.vo.wechatpaymentinfo.dto.PaymentDTO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.OrderStatusInfoVO; +import com.xinelu.common.core.domain.AjaxResult; + +/** + * @Description 微信小程序和App支付业务层 + * @Author 纪寒 + * @Date 2022-10-18 15:02:27 + * @Version 1.0 + */ +public interface WeChatPaymentService { + + /** + * 微信小程序购买商品和健康咨询支付接口 + * + * @param paymentDTO 输入参数 + * @return 支付结果 + * @throws Exception 异常信息 + */ + AjaxResult appletGoodsOrderPay(PaymentDTO paymentDTO) throws Exception; + + /** + * 微信小程序预约服务订单支付接口 + * + * @param paymentDTO 输入参数 + * @return 支付结果 + * @throws Exception 异常信息 + */ + AjaxResult appletAppointmentOrderPay(PaymentDTO paymentDTO) throws Exception; + + /** + * 取消订单接口 + * + * @param orderNo 点单编号 + * @param buySource 购买来源 + * @return 取消结果信息 + * @throws Exception 异常信息 + */ + AjaxResult cancelOrderInfo(String orderNo, String buySource) throws Exception; + + /** + * 查询订单状态信息 + * + * @param orderNo 点单编号 + * @param buySource 购买来源 + * @return 结果信息 + * @throws Exception 异常信息 + */ + AjaxResult getOrderStatusInfo(String orderNo, String buySource) throws Exception; + + /** + * 微信关闭订单方法 + * + * @param orderNo 订单编号 + * @param buySource 购买来源 + * @return 状态码 + * @throws Exception 异常信息 + */ + int closeWeChatOrderInfo(String orderNo, String buySource) throws Exception; + + /** + * 查询预约服务订单信息 + * + * @param orderNo 订单编号 + * @param vo 返回值信息 + * @return 订单状态标识 + */ + OrderStatusInfoVO queryAppointmentOrderStatus(String orderNo, OrderStatusInfoVO vo); + + /** + * 查询上商品订单信息 + * + * @param orderNo 订单编号 + * @param buySource 购买来源 + * @param vo 返回值信息 + * @return 订单状态标识 + * @throws Exception 异常信息 + */ + OrderStatusInfoVO queryGoodsOrderStatus(String orderNo, OrderStatusInfoVO vo, String buySource) throws Exception; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatRefundService.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatRefundService.java new file mode 100644 index 0000000..966dd61 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/WeChatRefundService.java @@ -0,0 +1,41 @@ +package com.xinelu.applet.service.wechatpaymentinfo; + +import com.xinelu.applet.vo.wechatpaymentinfo.dto.RefundDTO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundInfoVO; +import com.xinelu.common.core.domain.AjaxResult; + +/** + * @Description 微信退款业务层 + * @Author 纪寒 + * @Date 2022-10-24 15:22:49 + * @Version 1.0 + */ +public interface WeChatRefundService { + + /** + * 微信确认退款接口 + * + * @param refundDTO 退款参数 + * @return 返回信息 + * @throws Exception 异常信息 + */ + AjaxResult weChatRefundOrderApply(RefundDTO refundDTO) throws Exception; + + /** + * 调用微信查询单笔退款接口查询预约订单状态信息 + * + * @param refundNo 退款单号 + * @return 退款信息 + */ + WeChatRefundInfoVO queryAppointmentOrderRefundStatus(String refundNo); + + /** + * 调用微信查询单笔退款接口查询商品订单状态信息 + * + * @param refundNo 退单编号 + * @param buySource 购买来源 + * @return 退款信息 + * @throws Exception 异常信息 + */ + WeChatRefundInfoVO queryGoodsOrderRefundStatus(String refundNo, String buySource) throws Exception; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatPayNotifyServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatPayNotifyServiceImpl.java new file mode 100644 index 0000000..c530ea7 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatPayNotifyServiceImpl.java @@ -0,0 +1,486 @@ +package com.xinelu.applet.service.wechatpaymentinfo.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.wechat.pay.contrib.apache.httpclient.auth.Verifier; +import com.wechat.pay.contrib.apache.httpclient.notification.Notification; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; +import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatPayNotifyService; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatPayNotifyPlaintextVO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundNotifyVO; +import com.xinelu.common.config.XylWeChatPaymentConfig; +import com.xinelu.common.config.YlypWeChatPaymentConfig; +import com.xinelu.common.constant.Constants; +import com.xinelu.common.enums.*; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.common.utils.RedisDistributedLockUtils; +import com.xinelu.common.utils.http.HttpUtils; +import com.xinelu.manage.domain.appointmentorder.AppointmentOrder; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import com.xinelu.manage.domain.paymentinfo.PaymentInfo; +import com.xinelu.manage.domain.refundinfo.RefundInfo; +import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; +import com.xinelu.manage.mapper.goodsAttributeDetails.GoodsAttributeDetailsMapper; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import com.xinelu.manage.mapper.patientcouponreceive.PatientCouponReceiveMapper; +import com.xinelu.manage.mapper.paymentinfo.PaymentInfoMapper; +import com.xinelu.manage.mapper.refundinfo.RefundInfoMapper; +import com.xinelu.manage.vo.AppointOrderAndDetailsInfo; +import com.xinelu.manage.vo.appointmentorder.AppointmentOrderInfoVO; +import com.xinelu.manage.vo.goods.GoodsOrderAndDetailsInfo; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.support.atomic.RedisAtomicLong; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @Description 微信支付回调业务层实现类 + * @Author 纪寒 + * @Date 2022-10-20 14:00:52 + * @Version 1.0 + */ +@Slf4j +@Service +public class WeChatPayNotifyServiceImpl implements WeChatPayNotifyService { + + @Resource + private XylWeChatPaymentConfig xylWeChatPaymentConfig; + @Resource + private GoodsOrderMapper goodsOrderMapper; + @Resource + private AppointmentOrderMapper appointmentOrderMapper; + @Resource + private YlypWeChatPaymentConfig ylypWeChatPaymentConfig; + @Resource + private PaymentInfoMapper paymentInfoMapper; + @Resource + private RedisDistributedLockUtils redisDistributedLockUtils; + @Resource(name = "transactionManager") + private DataSourceTransactionManager transactionManager; + @Resource + private GoodsAttributeDetailsMapper goodsAttributeDetailsMapper; + @Resource + private RefundInfoMapper refundInfoMapper; + @Resource(name = "xylVerifier") + private Verifier xylVerifier; + @Resource(name = "ylypVerifier") + private Verifier ylypVerifier; + @Resource + private RedisTemplate redisTemplate; + @Resource + private PatientCouponReceiveMapper patientCouponReceiveMapper; + + /** + * 新医路账户标识 + */ + private static final String XINYILU_ACCOUNT = "XINYILU"; + + /** + * 新医路账户标识 + */ + private static final String YILUYOUPIN_ACCOUNT = "YILUYOUPIN"; + + /** + * 支付回调标识 + */ + private static final String PAY = "PAY"; + + /** + * 退款回调标识 + */ + private static final String REFUND = "REFUND"; + + /** + * 新医路支付回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + */ + @Override + public String xylWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + log.info("新医路微信支付回调开始执行"); + return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.XINYILU.getInfo(), PAY); + } + + /** + * 医路优品支付回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @Override + public String ylypWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + log.info("医路优品微信支付回调开始执行"); + return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.YILUYOUPIN.getInfo(), PAY); + } + + /** + * 新医路退款回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @Override + public String xylWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + log.info("新医路微信退款回调开始执行"); + return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.XINYILU.getInfo(), REFUND); + } + + /** + * 医路优品退款回调接口 + * + * @param request 请求信息 + * @param response 响应信息 + * @return 应答信息,避免微信平台重复发送回调通知 + * @throws Exception 异常信息 + */ + @Override + public String ylypWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + log.info("医路优品微信退款回调开始执行"); + return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.YILUYOUPIN.getInfo(), REFUND); + } + + /** + * 微信支付回调通知公共方法 + * + * @param request 请求信息 + * @param response 响应信息 + * @param accountFlag 账户标识,用于区分是新医路还是医路优品 + * @param refundAndPaymentFlag 支付和回调标识 + * @return 返回信息 + * @throws Exception 异常信息 + */ + private String weChatPayNotifyInfo(HttpServletRequest request, HttpServletResponse response, + String accountFlag, String refundAndPaymentFlag) throws Exception { + Map resultMap = new HashMap<>(); + String body = HttpUtils.readRequestData(request); + if (StringUtils.isBlank(body)) { + log.error(accountFlag + "微信回调通知失败,请求体 ====> {}", body); + response.setStatus(500); + resultMap.put("code", "ERROR"); + resultMap.put("message", "通知验签失败"); + return JSON.toJSONString(resultMap); + } + String nonce = request.getHeader("Wechatpay-Nonce"); + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String signature = request.getHeader("Wechatpay-Signature"); + String serialNo = request.getHeader("Wechatpay-Serial"); + Notification notification = null; + if (XINYILU_ACCOUNT.equals(accountFlag)) { + NotificationRequest notificationRequest = new NotificationRequest.Builder().withSerialNumber(serialNo) + .withNonce(nonce).withTimestamp(timestamp).withSignature(signature).withBody(body).build(); + NotificationHandler handler = new NotificationHandler(xylVerifier, xylWeChatPaymentConfig.getXylPaymentKey().getBytes(StandardCharsets.UTF_8)); + notification = handler.parse(notificationRequest); + } + if (YILUYOUPIN_ACCOUNT.equals(accountFlag)) { + NotificationRequest notificationRequest = new NotificationRequest.Builder().withSerialNumber(serialNo) + .withNonce(nonce).withTimestamp(timestamp).withSignature(signature).withBody(body).build(); + NotificationHandler handler = new NotificationHandler(ylypVerifier, ylypWeChatPaymentConfig.getYlypPaymentKey().getBytes(StandardCharsets.UTF_8)); + notification = handler.parse(notificationRequest); + } + if (Objects.isNull(notification)) { + log.error(accountFlag + "微信通知验签失败,请求体 ====> {}", body); + response.setStatus(500); + resultMap.put("code", "ERROR"); + resultMap.put("message", "通知验签失败"); + return JSON.toJSONString(resultMap); + } + String ciphertext = StringUtils.isBlank(notification.getResource().getCiphertext()) ? "" : notification.getResource().getCiphertext(); + String nonceTwo = StringUtils.isBlank(notification.getResource().getNonce()) ? "" : notification.getResource().getNonce(); + String associatedData = StringUtils.isBlank(notification.getResource().getAssociatedData()) ? "" : notification.getResource().getAssociatedData(); + String plainText = ""; + if (XINYILU_ACCOUNT.equals(accountFlag)) { + AesUtil aesUtil = new AesUtil(xylWeChatPaymentConfig.getXylPaymentKey().getBytes(StandardCharsets.UTF_8)); + plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonceTwo.getBytes(StandardCharsets.UTF_8), ciphertext); + } + if (YILUYOUPIN_ACCOUNT.equals(accountFlag)) { + AesUtil aesUtil = new AesUtil(ylypWeChatPaymentConfig.getYlypPaymentKey().getBytes(StandardCharsets.UTF_8)); + plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonceTwo.getBytes(StandardCharsets.UTF_8), ciphertext); + } + if (StringUtils.isBlank(plainText)) { + response.setStatus(500); + resultMap.put("code", "ERROR"); + resultMap.put("message", "解密失败!"); + return JSON.toJSONString(resultMap); + } + //记录支付日志和修改订单状态 + if (Constants.PAY_NOTIFY.equals(refundAndPaymentFlag)) { + this.processPaymentInfo(plainText); + } + //修改订单状态以及增加库存以及退还用户所使用的优惠券信息 + if (Constants.REFUND_NOTIFY.equals(refundAndPaymentFlag)) { + this.processRefundInfo(plainText); + } + response.setStatus(200); + resultMap.put("code", "SUCCESS"); + resultMap.put("message", "成功"); + log.info("微信回调方法执行完成!"); + return JSON.toJSONString(resultMap); + } + + /** + * 记录支付信息和修改订单状态 + * + * @param plainText 支付验签以后的通知内容 + */ + private void processPaymentInfo(String plainText) { + WeChatPayNotifyPlaintextVO notifyPlaintext = JSONObject.parseObject(plainText, WeChatPayNotifyPlaintextVO.class); + if (StringUtils.isBlank(notifyPlaintext.getOutTradeNo())) { + return; + } + String orderNoLockKey = Constants.WE_CHAT_NOTIFY_KEY + notifyPlaintext.getOutTradeNo(); + boolean tryLock = redisDistributedLockUtils.tryLock(orderNoLockKey, 5); + if (!tryLock) { + return; + } + TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + //商品订单信息 + GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(notifyPlaintext.getOutTradeNo()); + if (Objects.nonNull(goodsOrderInfo)) { + insertPaymentInfo(notifyPlaintext, goodsOrderInfo, null, plainText); + if (WeChatTradeStateEnum.SUCCESS.getInfo().equals(notifyPlaintext.getTradeState())) { + goodsOrderMapper.updateGoodsOrderStatus(GooodsOrderStatusEnum.WAIT_RECEIVED_GOODS.getInfo(), goodsOrderInfo.getOrderNo()); + } else { + log.info("商品订单微信订单状态异常,订单状态为 ====> {}", notifyPlaintext.getTradeState()); + } + transactionManager.commit(transactionStatus); + return; + } + AppointmentOrderInfoVO appointmentOrderInfo = appointmentOrderMapper.getAppointmentOrderInfoByOrderNo(notifyPlaintext.getOutTradeNo()); + if (Objects.isNull(appointmentOrderInfo)) { + return; + } + //预约服务订单信息 + insertPaymentInfo(notifyPlaintext, null, appointmentOrderInfo, plainText); + if (WeChatTradeStateEnum.SUCCESS.getInfo().equals(notifyPlaintext.getTradeState())) { + appointmentOrderMapper.updateAppointmentOrderStatus(OrderStatusEnum.WAIT_DISPATCH.getInfo(), appointmentOrderInfo.getOrderNo()); + } else { + log.info("预约服务微信订单状态异常,订单状态为 ====> {}", notifyPlaintext.getTradeState()); + } + transactionManager.commit(transactionStatus); + } catch (Exception e) { + transactionManager.rollback(transactionStatus); + log.error("微信支付回调失败,失败原因:{}", e.getMessage()); + throw e; + } finally { + redisDistributedLockUtils.unlock(orderNoLockKey); + log.info("支付回调释放锁完成..........."); + } + } + + /** + * 记录支付日志信息 + * + * @param notifyPlaintext 回调信息 + * @param goodsOrderInfo 商品订单信息 + * @param appointmentOrder 预约订单信息 + * @param plainText 回调明文 + */ + private void insertPaymentInfo(WeChatPayNotifyPlaintextVO notifyPlaintext, GoodsOrder goodsOrderInfo, + AppointmentOrder appointmentOrder, String plainText) { + int paymentInfoCount = paymentInfoMapper.getPaymentInfoByOrderNo(notifyPlaintext.getOutTradeNo()); + if (paymentInfoCount <= 0) { + PaymentInfo paymentInfo = buildPaymentInfo(notifyPlaintext, goodsOrderInfo, appointmentOrder, plainText); + int insertCount = paymentInfoMapper.insertPaymentInfo(paymentInfo); + if (insertCount <= 0) { + log.error("记录支付日志出错,参数为 ====> [{}]", paymentInfo); + throw new ServiceException("记录支付日志出错,请联系管理员!"); + } + } + } + + /** + * 构建支付信息参数 + * + * @param notifyPlaintext 通知明文信息 + * @param goodsOrderInfo 商品订单信息 + * @param appointmentOrderInfo 预约订单信息 + */ + private PaymentInfo buildPaymentInfo(WeChatPayNotifyPlaintextVO notifyPlaintext, GoodsOrder goodsOrderInfo, + AppointmentOrder appointmentOrderInfo, String plainText) { + PaymentInfo paymentInfo = new PaymentInfo(); + if (Objects.nonNull(goodsOrderInfo)) { + paymentInfo.setPatientId(Objects.isNull(goodsOrderInfo.getPatientId()) ? null : goodsOrderInfo.getPatientId()); + paymentInfo.setOrderNo(StringUtils.isBlank(goodsOrderInfo.getOrderNo()) ? "" : goodsOrderInfo.getOrderNo()); + paymentInfo.setPayChannel(StringUtils.isBlank(goodsOrderInfo.getOrderChannel()) ? "" : goodsOrderInfo.getOrderChannel()); + } else if (Objects.nonNull(appointmentOrderInfo)) { + paymentInfo.setPatientId(Objects.isNull(appointmentOrderInfo.getPatientId()) ? null : appointmentOrderInfo.getPatientId()); + paymentInfo.setOrderNo(StringUtils.isBlank(appointmentOrderInfo.getOrderNo()) ? "" : appointmentOrderInfo.getOrderNo()); + paymentInfo.setPayChannel(StringUtils.isBlank(appointmentOrderInfo.getOrderChannel()) ? "" : appointmentOrderInfo.getOrderChannel()); + } + paymentInfo.setTransactionNo(StringUtils.isBlank(notifyPlaintext.getTransactionId()) ? "" : notifyPlaintext.getTransactionId()); + paymentInfo.setPayPrice(BigDecimal.valueOf(Objects.isNull(notifyPlaintext.getAmount().getPayerTotal()) ? 0 : notifyPlaintext.getAmount().getPayerTotal()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN)); + paymentInfo.setPayType(PayTypeEnum.WECHAT_PAY.getInfo()); + paymentInfo.setWechatTradeState(StringUtils.isBlank(notifyPlaintext.getTradeState()) ? "" : notifyPlaintext.getTradeState()); + paymentInfo.setPayNotifyContent(plainText); + paymentInfo.setPayTime(LocalDateTime.parse(StringUtils.isBlank(notifyPlaintext.getSuccessTime()) ? "" : notifyPlaintext.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME)); + if (notifyPlaintext.getMchid().equals(xylWeChatPaymentConfig.getXylMchId())) { + paymentInfo.setPaymentMerchantType(PaymentMerchantTypeEnum.XINYILU.getInfo()); + } + if (notifyPlaintext.getMchid().equals(ylypWeChatPaymentConfig.getYlypMchId())) { + paymentInfo.setPaymentMerchantType(PaymentMerchantTypeEnum.YILUYOUPIN.getInfo()); + } + paymentInfo.setDelFlag(0); + paymentInfo.setCreateTime(LocalDateTime.now()); + return paymentInfo; + } + + /** + * 修改订单状态以及减少库存信息 + * + * @param plainText 支付验签以后的通知内容 + */ + private void processRefundInfo(String plainText) { + WeChatRefundNotifyVO refundNotifyVO = JSONObject.parseObject(plainText, WeChatRefundNotifyVO.class); + if (StringUtils.isBlank(refundNotifyVO.getOutTradeNo())) { + return; + } + String orderNoLockKey = Constants.WE_CHAT_REFUND_KEY + refundNotifyVO.getOutTradeNo(); + boolean tryLock = redisDistributedLockUtils.tryLock(orderNoLockKey, 5); + if (!tryLock) { + return; + } + TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + RedisAtomicLong redisAtomicLong = null; + try { + GoodsOrderAndDetailsInfo detailsOrderInfo = goodsOrderMapper.getGoodsAndDetailsOrderInfo(refundNotifyVO.getOutTradeNo()); + AppointOrderAndDetailsInfo appointmentOrderInfo = appointmentOrderMapper.getAppointOrderAndDetailsInfo(refundNotifyVO.getOutTradeNo()); + if (Objects.isNull(detailsOrderInfo) && Objects.isNull(appointmentOrderInfo)) { + return; + } + if (Objects.nonNull(appointmentOrderInfo)) { + updateAppointmentInfo(appointmentOrderInfo, plainText, refundNotifyVO); + if (Objects.nonNull(appointmentOrderInfo.getAppointmentLimitCount()) && StringUtils.equals(AppointmentOrderTypeEnum.OTHER.getInfo(), appointmentOrderInfo.getOrderType())) { + String appointLimitCountKey = Constants.PRE_APPOINTMENT_LIMIT_COUNT_KEY + appointmentOrderInfo.getNurseStationItemId() + "_" + appointmentOrderInfo.getServiceDate() + "_" + appointmentOrderInfo.getServiceStartTime(); + redisAtomicLong = new RedisAtomicLong(appointLimitCountKey, Objects.requireNonNull(redisTemplate.getConnectionFactory())); + if (redisAtomicLong.get() >= 0 && redisAtomicLong.get() < appointmentOrderInfo.getAppointmentLimitCount()) { + redisAtomicLong.incrementAndGet(); + } + } + } + if (Objects.nonNull(detailsOrderInfo)) { + updateGoodsInfo(detailsOrderInfo, plainText, refundNotifyVO); + } + transactionManager.commit(transactionStatus); + } catch (Exception e) { + transactionManager.rollback(transactionStatus); + log.error("微信退款回调通知失败,失败信息为:{}", e.getMessage()); + if (Objects.nonNull(redisAtomicLong) && redisAtomicLong.get() > 0) { + redisAtomicLong.decrementAndGet(); + } + throw e; + } finally { + redisDistributedLockUtils.unlock(orderNoLockKey); + log.info("退款回调释放锁完成............."); + } + } + + /** + * 处理预约服务订单信息 + * + * @param appointmentOrderInfo 预约订单信息 + * @param plainText 明文 + * @param refundNotifyVO 退款回调信息 + */ + private void updateAppointmentInfo(AppointmentOrder appointmentOrderInfo, String plainText, WeChatRefundNotifyVO refundNotifyVO) { + if (RefundStatusEnum.SUCCESS.getInfo().equals(refundNotifyVO.getRefundStatus()) + && StringUtils.isNotBlank(appointmentOrderInfo.getOrderStatus()) + && !(OrderStatusEnum.REFUNDED.getInfo().equals(appointmentOrderInfo.getOrderStatus()))) { + int updateCount = appointmentOrderMapper.updateAppointmentOrderStatus(OrderStatusEnum.REFUNDED.getInfo(), appointmentOrderInfo.getOrderNo()); + if (updateCount < 1) { + log.info("微信退款通知,修改预约订单状态失败,订单编号 =====> {}", refundNotifyVO.getOutTradeNo()); + } + RefundInfo refundInfo = buildRefundInfo(plainText, refundNotifyVO); + int refundCount = refundInfoMapper.updateRefundInfoByNo(refundInfo); + if (refundCount < 1) { + log.info("微信退款通知,记录预约订单微信退款单信息失败,订单编号 =====> {}", refundNotifyVO.getOutTradeNo()); + } + } + if (RefundStatusEnum.CLOSED.getInfo().equals(refundNotifyVO.getRefundStatus())) { + log.info("当前预约退款单已经关闭,订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo()); + } + if (RefundStatusEnum.ABNORMAL.getInfo().equals(refundNotifyVO.getRefundStatus())) { + log.info("预约订单退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往【商户平台—>交易中心】,手动处理此笔退款,订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo()); + } + } + + /** + * 处理商品订单信息 + * + * @param detailsOrderInfo 商品订单信息 + * @param plainText 明文 + * @param refundNotifyVO 退款回调信息 + */ + private void updateGoodsInfo(GoodsOrderAndDetailsInfo detailsOrderInfo, String plainText, WeChatRefundNotifyVO refundNotifyVO) { + if (RefundStatusEnum.SUCCESS.getInfo().equals(refundNotifyVO.getRefundStatus()) + && StringUtils.isNotBlank(detailsOrderInfo.getOrderStatus()) + && !(GooodsOrderStatusEnum.REFUNDED.getInfo().equals(detailsOrderInfo.getOrderStatus()))) { + int updateGoodsOrderCount = goodsOrderMapper.updateGoodsOrderStatus(OrderStatusEnum.REFUNDED.getInfo(), detailsOrderInfo.getOrderNo()); + if (updateGoodsOrderCount < 1) { + log.info("微信退款通知,修改商品单状态失败,订单编号 =====> {}", refundNotifyVO.getOutTradeNo()); + } + if (StringUtils.isNotBlank(detailsOrderInfo.getOrderType()) && !OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(detailsOrderInfo.getOrderType())) { + if (!GooodsOrderStatusEnum.REFUNDED.getInfo().equals(detailsOrderInfo.getOrderStatus())) { + int updateStockCount = goodsAttributeDetailsMapper.addGoodsStockCount(detailsOrderInfo.getGoodsAttributeDetailsId(), detailsOrderInfo.getGoodsCount()); + if (updateStockCount < 1) { + log.info("新增库存数量失败,订单编号:{},商品属性明细id:{},数量数量:{}", detailsOrderInfo.getOrderNo(), detailsOrderInfo.getGoodsAttributeDetailsId(), detailsOrderInfo.getGoodsCount()); + } + } + if (Objects.nonNull(detailsOrderInfo.getCouponId()) && Objects.nonNull(detailsOrderInfo.getPatientId())) { + patientCouponReceiveMapper.updatePatientCouponUseStatus(detailsOrderInfo.getPatientId(), detailsOrderInfo.getCouponId(), CouponUseStatusEnum.NOT_USED.getInfo()); + } + } + RefundInfo refundInfo = buildRefundInfo(plainText, refundNotifyVO); + int refundCount = refundInfoMapper.updateRefundInfoByNo(refundInfo); + if (refundCount < 1) { + log.info("微信退款通知,记录商品订单微信退款单信息失败,订单编号 =====> {}", refundNotifyVO.getOutTradeNo()); + } + } + if (RefundStatusEnum.CLOSED.getInfo().equals(refundNotifyVO.getRefundStatus())) { + log.info("当前商品退款单已经关闭,订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo()); + } + if (RefundStatusEnum.ABNORMAL.getInfo().equals(refundNotifyVO.getRefundStatus())) { + log.info("商品订单退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往【商户平台—>交易中心】,手动处理此笔退款,订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo()); + } + } + + /** + * 构建退款单信息 + * + * @param plainText 退款通知解密的明文信息 + * @param refundNotifyVO 通知参数 + * @return 结果 + */ + private RefundInfo buildRefundInfo(String plainText, WeChatRefundNotifyVO refundNotifyVO) { + RefundInfo refundInfo = new RefundInfo(); + refundInfo.setWechatRefundStatus(StringUtils.isBlank(refundNotifyVO.getRefundStatus()) ? "" : refundNotifyVO.getRefundStatus()); + refundInfo.setSuccessTime(LocalDateTime.parse(StringUtils.isBlank(refundNotifyVO.getSuccessTime()) ? "" : refundNotifyVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME)); + refundInfo.setRefundNotifyContent(plainText); + refundInfo.setOrderNo(StringUtils.isBlank(refundNotifyVO.getOutTradeNo()) ? "" : refundNotifyVO.getOutTradeNo()); + refundInfo.setOutRefundNo(StringUtils.isBlank(refundNotifyVO.getOutRefundNo()) ? "" : refundNotifyVO.getOutRefundNo()); + return refundInfo; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatPaymentServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatPaymentServiceImpl.java new file mode 100644 index 0000000..fcb03dd --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatPaymentServiceImpl.java @@ -0,0 +1,565 @@ +package com.xinelu.applet.service.wechatpaymentinfo.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatPaymentService; +import com.xinelu.applet.utils.WeChatUtil; +import com.xinelu.applet.vo.wechatpaymentinfo.dto.PaymentDTO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.OrderStatusInfoVO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatAppletSignVO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatQueryOrderVO; +import com.xinelu.common.config.AppletChatConfig; +import com.xinelu.common.config.WeChatPaymentUrlConfig; +import com.xinelu.common.config.XylWeChatPaymentConfig; +import com.xinelu.common.config.YlypWeChatPaymentConfig; +import com.xinelu.common.constant.Constants; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.enums.BuySourceEnum; +import com.xinelu.common.enums.GooodsOrderStatusEnum; +import com.xinelu.common.enums.OrderStatusEnum; +import com.xinelu.common.enums.WeChatTradeStateEnum; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.manage.domain.appointmentorder.AppointmentOrder; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Base64Utils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.security.Signature; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @Description 微信小程序和App支付业务层实现类 + * @Author 纪寒 + * @Date 2022-10-18 15:02:40 + * @Version 1.0 + */ +@Service +@Slf4j +public class WeChatPaymentServiceImpl implements WeChatPaymentService { + + @Resource + private GoodsOrderMapper goodsOrderMapper; + @Resource + private AppointmentOrderMapper appointmentOrderMapper; + @Resource + private AppletChatConfig appletChatConfig; + @Resource + private XylWeChatPaymentConfig xylWeChatPaymentConfig; + @Resource + private YlypWeChatPaymentConfig ylypWeChatPaymentConfig; + @Resource(name = "xinYiLuWeChatPayClient") + private CloseableHttpClient xinYiLuWeChatPayClient; + @Resource(name = "yiLuYouPinWeChatPayClient") + private CloseableHttpClient yiLuYouPinWeChatPayClient; + @Resource + private WeChatPaymentUrlConfig weChatPaymentUrlConfig; + @Resource + private RedisTemplate redisTemplate; + @Resource + private WeChatUtil weChatUtil; + + /** + * 新医路支付商品描述 + */ + private static final String XIN_YI_LU_DESCRIPTION = "山东新医路信息科技有限公司"; + + /** + * 医路优品支付商品描述 + */ + private static final String YI_LU_YOU_PIN_DESCRIPTION = "医路优品信息科技有限公司"; + + /** + * JsApi下单成功状态码 + */ + private static final int HAVE_BODY_SUCCESS_CODE = 200; + + /** + * JsApi下单成功状态码 + */ + private static final int NO_HAVE_BODY_SUCCESS_CODE = 204; + + /** + * 签名算法 + */ + private static final String SIGNATURE_ALGORITHM = "SHA256withRSA"; + + /** + * 签名方式 + */ + private static final String SIGN_TYPE = "RSA"; + + /** + * 新医路支付回调接口地址 + */ + private static final String XINYILU_WE_CHAT_NOTIFY_URL = "/nurseApp/weChatPayment/xylWeChatPayNotify"; + + /** + * 医路优品支付回调接口地址 + */ + private static final String YINLUYOUPIN_WE_CHAT_NOTIFY_URL = "/nurseApp/weChatPayment/ylypWeChatPayNotify"; + + /** + * 微信小程序购买商品和健康咨询支付接口 + * + * @param paymentDTO 输入参数 + * @return 支付结果 + * @throws Exception 常信息 + */ + @Override + public AjaxResult appletGoodsOrderPay(PaymentDTO paymentDTO) throws Exception { + String prepayId = redisTemplate.opsForValue().get(Constants.PREPAY_ID_KEY + paymentDTO.getOrderNo()); + if (StringUtils.isBlank(prepayId)) { + GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(paymentDTO.getOrderNo()); + if (Objects.isNull(goodsOrderInfo) || StringUtils.isBlank(goodsOrderInfo.getOrderStatus())) { + return AjaxResult.error("未查询到当前订单信息,请选择正确的订单信息!"); + } + if (!goodsOrderInfo.getOrderStatus().equals(GooodsOrderStatusEnum.WAIT_PAY.getInfo())) { + return AjaxResult.error("订单状态异常,无法支付,请联系管理员!"); + } + if (StringUtils.isBlank(goodsOrderInfo.getBuySource()) + || !paymentDTO.getBuySource().equals(goodsOrderInfo.getBuySource())) { + log.info("购买来源不一致,请进行确认!"); + return AjaxResult.error("订单状态异常,无法支付,请联系管理员!"); + } + String jsApiParams = this.buildGoodsOrderJsApiParams(paymentDTO, goodsOrderInfo); + prepayId = this.requestJsApiInterface(jsApiParams, paymentDTO, prepayId); + } else { + prepayId = redisTemplate.opsForValue().get(Constants.PREPAY_ID_KEY + paymentDTO.getOrderNo()); + } + return AjaxResult.success(getSignInfo(prepayId, paymentDTO.getBuySource())); + } + + /** + * 微信小程序预约服务订单支付接口 + * + * @param paymentDTO 输入参数 + * @return 支付结果 + * @throws Exception 异常信息 + */ + @Override + public AjaxResult appletAppointmentOrderPay(PaymentDTO paymentDTO) throws Exception { + String prepayId = redisTemplate.opsForValue().get(Constants.PREPAY_ID_KEY + paymentDTO.getOrderNo()); + if (StringUtils.isBlank(prepayId)) { + AppointmentOrder appointmentOrderInfo = appointmentOrderMapper.getAppointmentOrderByOrderNo(paymentDTO.getOrderNo()); + if (Objects.isNull(appointmentOrderInfo) || StringUtils.isBlank(appointmentOrderInfo.getOrderStatus())) { + return AjaxResult.error("未查询到当前预约订单信息,请选择重新预约!"); + } + if (!appointmentOrderInfo.getOrderStatus().equals(OrderStatusEnum.WAIT_PAY.getInfo())) { + return AjaxResult.error("订单状态异常,无法支付,请联系管理员!"); + } + String jsApiParams = this.buildAppointmentOrderJsApiParams(paymentDTO, appointmentOrderInfo); + prepayId = this.requestJsApiInterface(jsApiParams, paymentDTO, prepayId); + } else { + prepayId = redisTemplate.opsForValue().get(Constants.PREPAY_ID_KEY + paymentDTO.getOrderNo()); + } + return AjaxResult.success(getSignInfo(prepayId, paymentDTO.getBuySource())); + } + + /** + * 取消订单接口 + * + * @param orderNo 点单编号 + * @param buySource 购买来源 + * @return 取消结果信息 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public AjaxResult cancelOrderInfo(String orderNo, String buySource) throws Exception { + GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(orderNo); + AppointmentOrder appointmentOrderInfo = appointmentOrderMapper.getAppointmentOrderByOrderNo(orderNo); + if (Objects.isNull(goodsOrderInfo) && Objects.isNull(appointmentOrderInfo)) { + return AjaxResult.error("当前订单信息不存在,请重新选择!"); + } + //商品订单 + if (Objects.nonNull(goodsOrderInfo)) { + if (StringUtils.isBlank(goodsOrderInfo.getOrderStatus()) + || !GooodsOrderStatusEnum.WAIT_PAY.getInfo().equals(goodsOrderInfo.getOrderStatus())) { + log.info("订单状态为:====> {}", StringUtils.isBlank(goodsOrderInfo.getOrderStatus()) ? "不存在" : goodsOrderInfo.getOrderStatus()); + return AjaxResult.error("当前订单状态异常,请联系管理员!"); + } + LocalDateTime tenAfterTime = goodsOrderInfo.getOrderTime().plusMinutes(10); + if (LocalDateTime.now().isBefore(tenAfterTime)) { + return AjaxResult.error("10分钟以后才能取消当前订单,请耐心等待!"); + } + OrderStatusInfoVO orderStatusInfoVO = new OrderStatusInfoVO(); + OrderStatusInfoVO vo = this.queryGoodsOrderStatus(goodsOrderInfo.getOrderNo(), orderStatusInfoVO, buySource); + if (BooleanUtils.isTrue(vo.getPayFlag())) { + int statusCode = this.closeWeChatOrderInfo(goodsOrderInfo.getOrderNo(), goodsOrderInfo.getBuySource()); + if (!(statusCode == HAVE_BODY_SUCCESS_CODE || statusCode == NO_HAVE_BODY_SUCCESS_CODE)) { + return AjaxResult.error("取消订单失败,请联系管理员!"); + } + goodsOrderMapper.updateGoodsOrderStatus(GooodsOrderStatusEnum.CANCEL.getInfo(), orderNo); + } + } + //预约服务订单信息 + if (Objects.nonNull(appointmentOrderInfo)) { + if (StringUtils.isBlank(appointmentOrderInfo.getOrderStatus()) + || !OrderStatusEnum.WAIT_PAY.getInfo().equals(appointmentOrderInfo.getOrderStatus())) { + log.info("订单状态为:====> {}", StringUtils.isBlank(appointmentOrderInfo.getOrderStatus()) ? "不存在" : appointmentOrderInfo.getOrderStatus()); + return AjaxResult.error("当前订单状态异常,请联系管理员!"); + } + LocalDateTime tenAfterTime = appointmentOrderInfo.getCreateTime().plusMinutes(10); + if (LocalDateTime.now().isBefore(tenAfterTime)) { + return AjaxResult.error("10分钟以后才能取消当前订单,请耐心等待!"); + } + OrderStatusInfoVO orderStatusInfoVO = new OrderStatusInfoVO(); + OrderStatusInfoVO vo = this.queryAppointmentOrderStatus(appointmentOrderInfo.getOrderNo(), orderStatusInfoVO); + if (BooleanUtils.isTrue(vo.getPayFlag())) { + int statusCode = this.closeWeChatOrderInfo(appointmentOrderInfo.getOrderNo(), BuySourceEnum.NURSE_STATION.getInfo()); + if (!(statusCode == HAVE_BODY_SUCCESS_CODE || statusCode == NO_HAVE_BODY_SUCCESS_CODE)) { + return AjaxResult.error("取消订单失败,请联系管理员!"); + } + appointmentOrderMapper.updateAppointmentOrderStatus(OrderStatusEnum.CANCEL.getInfo(), orderNo); + } + } + return AjaxResult.success("取消订单成功!"); + } + + /** + * 查询订单状态信息 + * + * @param orderNo 点单编号 + * @param buySource 购买来源 + * @return 结果信息 + * @throws Exception 异常信息 + */ + @Override + public AjaxResult getOrderStatusInfo(String orderNo, String buySource) throws Exception { + OrderStatusInfoVO vo = new OrderStatusInfoVO(); + GoodsOrder goodsOrder = goodsOrderMapper.getGoodsOrderByOrderNo(orderNo); + AppointmentOrder appointmentOrder = appointmentOrderMapper.getAppointmentOrderByOrderNo(orderNo); + if (Objects.isNull(goodsOrder) && Objects.isNull(appointmentOrder)) { + vo.setPayFlag(true); + return AjaxResult.success(vo); + } + //预约服务订单不为空,调用微信查单接口确认订单状态 + if (Objects.nonNull(appointmentOrder)) { + OrderStatusInfoVO order = new OrderStatusInfoVO(); + vo = this.queryAppointmentOrderStatus(appointmentOrder.getOrderNo(), order); + } + //商品订单不为空,调用微信查单接口确认订单状态 + if (Objects.nonNull(goodsOrder)) { + OrderStatusInfoVO order = new OrderStatusInfoVO(); + vo = this.queryGoodsOrderStatus(goodsOrder.getOrderNo(), order, buySource); + } + return AjaxResult.success(vo); + } + + /** + * 微信关闭订单方法 + * + * @param orderNo 订单编号 + * @param buySource 购买来源 + * @return 状态码 + * @throws Exception 异常信息 + */ + @Override + public int closeWeChatOrderInfo(String orderNo, String buySource) throws Exception { + String closeUrl = String.format(weChatPaymentUrlConfig.getCloseOrderUrl(), orderNo); + HttpPost httpPost = new HttpPost(closeUrl); + Map paramMap = new HashMap<>(); + String jsonParams; + CloseableHttpResponse response = null; + if (BuySourceEnum.NURSE_STATION.getInfo().equals(buySource)) { + paramMap.put("mchid", xylWeChatPaymentConfig.getXylMchId()); + jsonParams = JSON.toJSONString(paramMap); + StringEntity entity = new StringEntity(jsonParams, "utf-8"); + entity.setContentType("application/json"); + httpPost.setEntity(entity); + httpPost.setHeader("Accept", "application/json"); + response = xinYiLuWeChatPayClient.execute(httpPost); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(buySource) + || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(buySource) || BuySourceEnum.TRAINING.getInfo().equals(buySource)) { + paramMap.put("mchid", ylypWeChatPaymentConfig.getYlypMchId()); + jsonParams = JSON.toJSONString(paramMap); + StringEntity entity = new StringEntity(jsonParams, "utf-8"); + entity.setContentType("application/json"); + httpPost.setEntity(entity); + httpPost.setHeader("Accept", "application/json"); + response = yiLuYouPinWeChatPayClient.execute(httpPost); + } + try { + if (response == null) { + throw new ServiceException("获取微信HttpClient对象失败,请联系管理员!"); + } + int statusCode = response.getStatusLine().getStatusCode(); + switch (statusCode) { + case HAVE_BODY_SUCCESS_CODE: + log.info("微信关闭订单成功!"); + break; + case NO_HAVE_BODY_SUCCESS_CODE: + log.info("微信关闭订单成功,无返回体!"); + break; + default: + throw new ServiceException("微信关闭订单失败!"); + } + return statusCode; + } finally { + if (response != null) { + response.close(); + } + } + } + + /** + * 查询预约服务订单状态 + * + * @param orderNo 订单编号 + * @param vo 返回值信息 + */ + @Override + public OrderStatusInfoVO queryAppointmentOrderStatus(String orderNo, OrderStatusInfoVO vo) { + String requestUrl = String.format(weChatPaymentUrlConfig.getQueryMchIdUrl(), orderNo); + requestUrl = requestUrl.concat("?mchid=").concat(xylWeChatPaymentConfig.getXylMchId()); + HttpGet httpGet = new HttpGet(requestUrl); + httpGet.setHeader("Accept", "application/json"); + try (CloseableHttpResponse response = xinYiLuWeChatPayClient.execute(httpGet)) { + String responseBody = EntityUtils.toString(response.getEntity()); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HAVE_BODY_SUCCESS_CODE) { + WeChatQueryOrderVO weChatQueryOrderVO = JSONObject.parseObject(responseBody, WeChatQueryOrderVO.class); + vo.setPayFlag(StringUtils.isNotBlank(weChatQueryOrderVO.getTradeState()) + && WeChatTradeStateEnum.NOTPAY.getInfo().equals(weChatQueryOrderVO.getTradeState())); + vo.setTradeStatus(weChatQueryOrderVO.getTradeState()); + vo.setWeChatQueryOrderVO(weChatQueryOrderVO); + } else if (statusCode == NO_HAVE_BODY_SUCCESS_CODE) { + log.warn("请求微信查单接口成功,无返回信息!"); + } else { + throw new ServiceException("调用微信查询订单接口异常,响应码为:" + statusCode + ", 查询订单返回结果 = " + responseBody); + } + return vo; + } catch (Exception e) { + log.error("请求微信查单接口异常,异常信息为 ====> {}", e.getMessage()); + throw new ServiceException("查询预约订单状态失败,请联系管理员!"); + } + } + + /** + * 查询上商品订单状态 + * + * @param orderNo 订单编号 + * @param vo 返回值信息 + */ + @Override + public OrderStatusInfoVO queryGoodsOrderStatus(String orderNo, OrderStatusInfoVO vo, + String buySource) throws Exception { + String requestUrl = ""; + if (BuySourceEnum.NURSE_STATION.getInfo().equals(buySource)) { + requestUrl = String.format(weChatPaymentUrlConfig.getQueryMchIdUrl(), orderNo).concat("?mchid=").concat(xylWeChatPaymentConfig.getXylMchId()); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(buySource) + || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(buySource) || BuySourceEnum.TRAINING.getInfo().equals(buySource)) { + requestUrl = String.format(weChatPaymentUrlConfig.getQueryMchIdUrl(), orderNo).concat("?mchid=").concat(ylypWeChatPaymentConfig.getYlypMchId()); + } + HttpGet httpGet = new HttpGet(requestUrl); + httpGet.setHeader("Accept", "application/json"); + CloseableHttpResponse response = null; + try { + if (BuySourceEnum.NURSE_STATION.getInfo().equals(buySource)) { + response = xinYiLuWeChatPayClient.execute(httpGet); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(buySource) + || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(buySource) || BuySourceEnum.TRAINING.getInfo().equals(buySource)) { + response = yiLuYouPinWeChatPayClient.execute(httpGet); + } + if (response == null) { + throw new ServiceException("获取微信HttpClient对象失败,请联系管理员!"); + } + String responseBody = EntityUtils.toString(response.getEntity()); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HAVE_BODY_SUCCESS_CODE) { + WeChatQueryOrderVO weChatQueryOrderVO = JSONObject.parseObject(responseBody, WeChatQueryOrderVO.class); + vo.setPayFlag(StringUtils.isNotBlank(weChatQueryOrderVO.getTradeState()) + && WeChatTradeStateEnum.NOTPAY.getInfo().equals(weChatQueryOrderVO.getTradeState())); + vo.setTradeStatus(weChatQueryOrderVO.getTradeState()); + vo.setWeChatQueryOrderVO(weChatQueryOrderVO); + } + if (statusCode == NO_HAVE_BODY_SUCCESS_CODE) { + log.warn("请求微信查单接口成功,无返回信息!"); + } + return vo; + } catch (Exception e) { + log.error("请求微信查单接口异常,异常信息为 ====> {}", e.getMessage()); + throw new ServiceException("查询商品订单状态失败,请联系管理员!"); + } finally { + if (response != null) { + response.close(); + } + } + } + + /** + * 构建商品订单JsApi微信下单参数 + * + * @param paymentDTO 前端传值 + * @param goodsOrderInfo 订单信息 + * @return 下单参数json串 + */ + private String buildGoodsOrderJsApiParams(PaymentDTO paymentDTO, GoodsOrder goodsOrderInfo) { + Map paramMap = new LinkedHashMap<>(); + if (BuySourceEnum.NURSE_STATION.getInfo().equals(paymentDTO.getBuySource())) { + paramMap.put("mchid", xylWeChatPaymentConfig.getXylMchId()); + paramMap.put("out_trade_no", goodsOrderInfo.getOrderNo()); + paramMap.put("appid", appletChatConfig.getAppletId()); + paramMap.put("description", XIN_YI_LU_DESCRIPTION); + paramMap.put("notify_url", xylWeChatPaymentConfig.getXylWeChatNotifyUrl() + XINYILU_WE_CHAT_NOTIFY_URL); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(paymentDTO.getBuySource()) || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(paymentDTO.getBuySource())) { + paramMap.put("mchid", ylypWeChatPaymentConfig.getYlypMchId()); + paramMap.put("out_trade_no", goodsOrderInfo.getOrderNo()); + paramMap.put("appid", appletChatConfig.getAppletId()); + paramMap.put("description", YI_LU_YOU_PIN_DESCRIPTION); + paramMap.put("notify_url", ylypWeChatPaymentConfig.getYlypWeChatNotifyUrl() + YINLUYOUPIN_WE_CHAT_NOTIFY_URL); + } + Map amountParamMap = new LinkedHashMap<>(); + int totalPrice = paymentDTO.getPaymentPrice().multiply(BigDecimal.valueOf(100)).intValue(); + amountParamMap.put("total", totalPrice); + amountParamMap.put("currency", "CNY"); + paramMap.put("amount", amountParamMap); + Map payerParamMap = new LinkedHashMap<>(); + payerParamMap.put("openid", paymentDTO.getOpenid()); + paramMap.put("payer", payerParamMap); + return JSON.toJSONString(paramMap); + } + + /** + * 请求JsApi下单接口方法 + * + * @param jsApiParams 下单参数 + * @param paymentDTO 输入参数 + * @param prepayId JsAp下单接口返回值 + * @return 结果 + * @throws Exception 异常信息 + */ + private String requestJsApiInterface(String jsApiParams, PaymentDTO paymentDTO, String prepayId) throws Exception { + StringEntity stringEntity = new StringEntity(jsApiParams, StandardCharsets.UTF_8); + stringEntity.setContentType("application/json"); + HttpPost httpPost = new HttpPost(weChatPaymentUrlConfig.getJsapiPalceOrderUrl()); + httpPost.setEntity(stringEntity); + httpPost.setHeader("Accept", "application/json"); + CloseableHttpResponse response = null; + String payAccount = ""; + try { + if (BuySourceEnum.NURSE_STATION.getInfo().equals(paymentDTO.getBuySource())) { + response = xinYiLuWeChatPayClient.execute(httpPost); + payAccount = "山东新医路信息科技有限公司"; + } + //泉医会员小程序中的商城订单、健康咨询订单、泉医助手学习培训订单都使用医路优品账户进行支付 + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(paymentDTO.getBuySource()) + || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(paymentDTO.getBuySource()) + || BuySourceEnum.TRAINING.getInfo().equals(paymentDTO.getBuySource())) { + response = yiLuYouPinWeChatPayClient.execute(httpPost); + payAccount = "医路优品信息科技有限公司"; + } + if (Objects.isNull(response)) { + log.error("JsApi下单接口执行错误, 执行账户为 ====> {}", payAccount); + throw new ServiceException("JsApi下单接口执行异常,请联系管理员!"); + } + int statusCode = response.getStatusLine().getStatusCode(); + String result = EntityUtils.toString(response.getEntity()); + if (statusCode == HAVE_BODY_SUCCESS_CODE) { + Map resultMap = JSONObject.parseObject(result); + prepayId = resultMap.getOrDefault("prepay_id", "").toString(); + redisTemplate.opsForValue().set(Constants.PREPAY_ID_KEY + paymentDTO.getOrderNo(), prepayId, 5400, TimeUnit.SECONDS); + } else if (statusCode == NO_HAVE_BODY_SUCCESS_CODE) { + log.info("JsApi下单成功,无返回值信息!"); + } else { + log.error("JsApi下单失败,失败原因为 ====> {}", result); + throw new ServiceException("JsApi下单失败,失败原因为:" + result); + } + } catch (Exception e) { + log.error("JsApi下单失败,失败原因 =====> {}", e.getMessage()); + throw new ServiceException("JsApi下单失败,请联系管理员!"); + } finally { + if (response != null) { + response.close(); + } + } + return prepayId; + } + + /** + * 构建微信小程序调起支付参数设置 + * + * @param prepayId jsapi下单返回参数信息 + * @param buySource 购买来源 + * @return 参数信息 + * @throws Exception 异常信息 + */ + private WeChatAppletSignVO getSignInfo(String prepayId, String buySource) throws Exception { + String appId = appletChatConfig.getAppletId(); + String nonceStr = UUID.randomUUID().toString().replace("-", ""); + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + PrivateKey privateKey = null; + //泉医到家小程序中的护理站模块的支付账户均使用新医路账户进行支付 + if (BuySourceEnum.NURSE_STATION.getInfo().equals(buySource)) { + privateKey = weChatUtil.getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath()); + } + //泉医到家小程序中的商城模块和健康咨询模块以及泉医助手中的学习培训模块使用医路优品账户进行支付 + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(buySource) + || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(buySource) + || BuySourceEnum.TRAINING.getInfo().equals(buySource)) { + privateKey = weChatUtil.getPrivateKey(ylypWeChatPaymentConfig.getYlypPrivateKeyPath()); + } + if (privateKey == null) { + throw new ServiceException("获取商户私钥失败,请联系管理员!"); + } + prepayId = "prepay_id=" + prepayId; + String signatureStr = Stream.of(appId, timestamp, nonceStr, prepayId) + .collect(Collectors.joining("\n", "", "\n")); + log.info("计算签名认证信息 =====> {}", signatureStr); + Signature sign = Signature.getInstance(SIGNATURE_ALGORITHM); + sign.initSign(privateKey); + sign.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + String paySign = Base64Utils.encodeToString(sign.sign()); + return WeChatAppletSignVO.builder().appId(appId).timeStamp(timestamp).nonceStr(nonceStr).prepayId(prepayId) + .signType(SIGN_TYPE).paySign(paySign).build(); + } + + /** + * 构建预约订单JsApi微信下单参数 + * + * @param paymentDTO 前端传值 + * @param appointmentOrder 预约订单信息 + * @return 下单参数json串 + */ + private String buildAppointmentOrderJsApiParams(PaymentDTO paymentDTO, AppointmentOrder appointmentOrder) { + Map paramMap = new LinkedHashMap<>(); + paramMap.put("mchid", xylWeChatPaymentConfig.getXylMchId()); + paramMap.put("out_trade_no", appointmentOrder.getOrderNo()); + paramMap.put("appid", appletChatConfig.getAppletId()); + paramMap.put("description", XIN_YI_LU_DESCRIPTION); + paramMap.put("notify_url", xylWeChatPaymentConfig.getXylWeChatNotifyUrl() + XINYILU_WE_CHAT_NOTIFY_URL); + Map amountParamMap = new LinkedHashMap<>(); + int totalPrice = appointmentOrder.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue(); + amountParamMap.put("total", totalPrice); + amountParamMap.put("currency", "CNY"); + paramMap.put("amount", amountParamMap); + Map payerParamMap = new LinkedHashMap<>(); + payerParamMap.put("openid", paymentDTO.getOpenid()); + paramMap.put("payer", payerParamMap); + return JSON.toJSONString(paramMap); + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatRefundServiceImpl.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatRefundServiceImpl.java new file mode 100644 index 0000000..c275f33 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/service/wechatpaymentinfo/impl/WeChatRefundServiceImpl.java @@ -0,0 +1,451 @@ +package com.xinelu.applet.service.wechatpaymentinfo.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.xinelu.applet.service.goodstock.GoodsStockService; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatRefundService; +import com.xinelu.applet.vo.wechatpaymentinfo.dto.RefundDTO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundInfoVO; +import com.xinelu.common.config.WeChatPaymentUrlConfig; +import com.xinelu.common.config.XylWeChatPaymentConfig; +import com.xinelu.common.config.YlypWeChatPaymentConfig; +import com.xinelu.common.core.domain.AjaxResult; +import com.xinelu.common.enums.*; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.manage.domain.appointmentorder.AppointmentOrder; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import com.xinelu.manage.domain.patientintegralchange.PatientIntegralChange; +import com.xinelu.manage.domain.refundinfo.RefundInfo; +import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper; +import com.xinelu.manage.mapper.patientintegralchange.PatientIntegralChangeMapper; +import com.xinelu.manage.mapper.refundinfo.RefundInfoMapper; +import com.xinelu.manage.vo.goodsorder.GoodsInfoRedemptionVO; +import com.xinelu.manage.vo.patientinfo.PatientInfoVO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @Description 微信退款业务层实现类 + * @Author 纪寒 + * @Date 2022-10-24 15:23:16 + * @Version 1.0 + */ +@Slf4j +@Service +public class WeChatRefundServiceImpl implements WeChatRefundService { + + @Resource + private GoodsOrderMapper goodsOrderMapper; + @Resource + private AppointmentOrderMapper appointmentOrderMapper; + @Resource + private XylWeChatPaymentConfig xylWeChatPaymentConfig; + @Resource + private YlypWeChatPaymentConfig ylypWeChatPaymentConfig; + @Resource(name = "xinYiLuWeChatPayClient") + private CloseableHttpClient xinYiLuWeChatPayClient; + @Resource(name = "yiLuYouPinWeChatPayClient") + private CloseableHttpClient yiLuYouPinWeChatPayClient; + @Resource + private WeChatPaymentUrlConfig weChatPaymentUrlConfig; + @Resource + private RefundInfoMapper refundInfoMapper; + @Resource + private GoodsStockService goodsStockService; + @Resource + private PatientIntegralChangeMapper patientIntegralChangeMapper; + @Resource + private PatientInfoMapper patientInfoMapper; + + /** + * 成功状态码 + */ + private static final int HAVE_BODY_SUCCESS_CODE = 200; + + /** + * 成功状态码 + */ + private static final int NO_HAVE_BODY_SUCCESS_CODE = 204; + + /** + * 新医路退款回调接口地址 + */ + private static final String XINYILU_WE_CHAT_REFUND_URL = "/nurseApp/weChatPayment/xylWeChatRefundNotify"; + + /** + * 医路优品退款回调接口地址 + */ + private static final String YINLUYOUPIN_WE_CHAT_REFUND_URL = "/nurseApp/weChatPayment/ylypWeChatRefundNotify"; + + /** + * 微信确认退款接口 + * + * @param refundDTO 退款参数 + * @return 退款申请结果 + * @throws Exception 异常信息 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public AjaxResult weChatRefundOrderApply(RefundDTO refundDTO) throws Exception { + if (StringUtils.isNotBlank(refundDTO.getOrderType()) && StringUtils.equals(OrderTypeEnum.INTEGRAL_EXCHANGE.getInfo(), refundDTO.getOrderType())) { + return refundPointsRedemption(refundDTO); + } + AppointmentOrder appointmentOrderInfo = appointmentOrderMapper.getAppointmentOrderByOrderNo(refundDTO.getOrderNo()); + if (Objects.nonNull(appointmentOrderInfo)) { + AjaxResult ajaxResult = judgeRefundInfo(appointmentOrderInfo.getCreateTime(), refundDTO.getRefundPrice(), appointmentOrderInfo.getTotalPrice()); + if (Objects.nonNull(ajaxResult)) { + return ajaxResult; + } + if (StringUtils.isBlank(appointmentOrderInfo.getConfirmRefundStatus()) + || !(ConfirmRefundStatusEnum.NOT_CONFIRM.getInfo().equals(appointmentOrderInfo.getConfirmRefundStatus()))) { + return AjaxResult.error("当前预约订单未进行退款确认,请先进行确认!"); + } + if (StringUtils.isBlank(appointmentOrderInfo.getOrderStatus()) + || !OrderStatusEnum.WAIT_REFUND.getInfo().equals(appointmentOrderInfo.getOrderStatus()) + || OrderStatusEnum.REFUNDED.getInfo().equals(appointmentOrderInfo.getOrderStatus())) { + return AjaxResult.error("当前预约订单正在退款中或者已退款,无法进行退款处理!"); + } + Long patientId = Objects.isNull(appointmentOrderInfo.getPatientId()) ? 0 : appointmentOrderInfo.getPatientId(); + String outRefundNo = com.xinelu.common.utils.StringUtils.fillZeroByPatientId(patientId, 5) + System.nanoTime(); + String refundParam = buildRefundParam(null, appointmentOrderInfo, refundDTO, outRefundNo); + this.applyWeRefund(refundParam, appointmentOrderInfo, null, patientId, refundDTO); + return AjaxResult.success(); + } + GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(refundDTO.getOrderNo()); + if (Objects.nonNull(goodsOrderInfo)) { + AjaxResult ajaxResult = judgeRefundInfo(goodsOrderInfo.getOrderTime(), refundDTO.getRefundPrice(), goodsOrderInfo.getTotalPrice()); + if (Objects.nonNull(ajaxResult)) { + return ajaxResult; + } + if (StringUtils.isBlank(goodsOrderInfo.getConfirmRefundStatus()) + || !(ConfirmRefundStatusEnum.NOT_CONFIRM.getInfo().equals(goodsOrderInfo.getConfirmRefundStatus()))) { + return AjaxResult.error("当前商品订单未进行退款确认,请先进行确认!"); + } + if (StringUtils.isBlank(goodsOrderInfo.getOrderStatus()) + || !GooodsOrderStatusEnum.WAIT_REFUND.getInfo().equals(goodsOrderInfo.getOrderStatus()) + || GooodsOrderStatusEnum.REFUNDED.getInfo().equals(goodsOrderInfo.getOrderStatus())) { + return AjaxResult.error("当前商品订单非退款中或者已退款,无法进行退款处理!"); + } + Long patientId = Objects.isNull(goodsOrderInfo.getPatientId()) ? 0 : goodsOrderInfo.getPatientId(); + String outRefundNo = com.xinelu.common.utils.StringUtils.fillZeroByPatientId(patientId, 5) + System.nanoTime(); + String refundParam = buildRefundParam(goodsOrderInfo, null, refundDTO, outRefundNo); + this.applyWeRefund(refundParam, null, goodsOrderInfo, patientId, refundDTO); + return AjaxResult.success(); + } + return AjaxResult.success(); + } + + /** + * 调用微信查询单笔退款接口查询预约订单状态信息 + * + * @param refundNo 退款单号 + * @return 退款信息 + */ + @Override + public WeChatRefundInfoVO queryAppointmentOrderRefundStatus(String refundNo) { + WeChatRefundInfoVO weChatRefundInfoVO = new WeChatRefundInfoVO(); + String requestUrl = String.format(weChatPaymentUrlConfig.getRefundQueryOrderUrl(), refundNo); + HttpGet httpGet = new HttpGet(requestUrl); + httpGet.setHeader("Accept", "application/json"); + try (CloseableHttpResponse response = xinYiLuWeChatPayClient.execute(httpGet)) { + String body = EntityUtils.toString(response.getEntity()); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HAVE_BODY_SUCCESS_CODE) { + weChatRefundInfoVO = JSONObject.parseObject(body, WeChatRefundInfoVO.class); + } else if (statusCode == NO_HAVE_BODY_SUCCESS_CODE) { + log.warn("请求微信查询单笔退款接口成功,无返回信息!"); + } else { + throw new ServiceException("调用微信查询单笔退款接口异常,响应码为:" + statusCode + ", 查询退款返回结果 = " + body); + } + return weChatRefundInfoVO; + } catch (Exception e) { + log.error("请求微信查询单笔退款接口异常,异常信息为 ====> {}", e.getMessage()); + throw new ServiceException("查询预约订单状态失败,请联系管理员!"); + } + } + + /** + * 调用微信查询单笔退款接口查询商品订单状态信息 + * + * @param refundNo 退单编号 + * @param buySource 购买来源 + * @return 退款信息 + * @throws Exception 异常信息 + */ + @Override + public WeChatRefundInfoVO queryGoodsOrderRefundStatus(String refundNo, String buySource) throws Exception { + WeChatRefundInfoVO weChatRefundInfoVO = new WeChatRefundInfoVO(); + String requestUrl = String.format(weChatPaymentUrlConfig.getRefundQueryOrderUrl(), refundNo); + HttpGet httpGet = new HttpGet(requestUrl); + httpGet.setHeader("Accept", "application/json"); + CloseableHttpResponse response = null; + try { + if (BuySourceEnum.NURSE_STATION.getInfo().equals(buySource)) { + response = xinYiLuWeChatPayClient.execute(httpGet); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(buySource) + || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(buySource) || BuySourceEnum.TRAINING.getInfo().equals(buySource)) { + response = yiLuYouPinWeChatPayClient.execute(httpGet); + } + if (response == null) { + throw new ServiceException("获取微信HttpClient对象失败,请联系管理员!"); + } + String body = EntityUtils.toString(response.getEntity()); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HAVE_BODY_SUCCESS_CODE) { + weChatRefundInfoVO = JSONObject.parseObject(body, WeChatRefundInfoVO.class); + } else if (statusCode == NO_HAVE_BODY_SUCCESS_CODE) { + log.warn("请求微信查询单笔退款接口成功,无返回信息!"); + } else { + throw new ServiceException("调用微信查询单笔退款接口异常,响应码为:" + statusCode + ", 查询退款返回结果 = " + body); + } + return weChatRefundInfoVO; + } catch (Exception e) { + log.error("请求微信查询单笔退款接口,异常信息为 ====> {}", e.getMessage()); + throw new ServiceException("查询商品订单状态失败,请联系管理员!"); + } finally { + if (response != null) { + response.close(); + } + } + } + + /** + * 退款参数检验 + * + * @param orderTime 下单时间 + * @param refundPrice 退款金额 + * @param totalPrice 支付总金额 + * @return 返回结果信息 + */ + private AjaxResult judgeRefundInfo(LocalDateTime orderTime, BigDecimal refundPrice, BigDecimal totalPrice) { + LocalDateTime localDateTime = orderTime.plusYears(1); + if (LocalDateTime.now().isAfter(localDateTime)) { + return AjaxResult.error("当前订单超过一年,无法进行退款处理!"); + } + if (refundPrice.compareTo(totalPrice) > 0) { + return AjaxResult.error("当前退款金额大于订单支付金额,无法进行退款处理!"); + } + return null; + } + + /** + * 构建微信退款参数信息 + * + * @param goodsOrderInfo 商品订单信息 + * @param appointmentOrderInfo 预约服务订单信息 + * @param refundDTO 退款参数信息 + * @return 退款申请Json串 + */ + private String buildRefundParam(GoodsOrder goodsOrderInfo, AppointmentOrder appointmentOrderInfo, + RefundDTO refundDTO, String outRefundNo) { + Map paramMap = new LinkedHashMap<>(); + paramMap.put("out_trade_no", refundDTO.getOrderNo()); + paramMap.put("out_refund_no", outRefundNo); + Map amountMap = new LinkedHashMap<>(); + //回调通知地址和退款金额,预约订单使用新医路账户 + if (Objects.nonNull(appointmentOrderInfo) && Objects.isNull(goodsOrderInfo)) { + paramMap.put("notify_url", xylWeChatPaymentConfig.getXylWeChatNotifyUrl() + XINYILU_WE_CHAT_REFUND_URL); + amountMap.put("refund", refundDTO.getRefundPrice().multiply(BigDecimal.valueOf(100)).intValue()); + amountMap.put("total", appointmentOrderInfo.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue()); + } + //护理站商品购买订单使用新医路账户,商城商品订单和健康咨询订单使用医路优品账户 + if (Objects.nonNull(goodsOrderInfo) && Objects.isNull(appointmentOrderInfo)) { + if (BuySourceEnum.NURSE_STATION.getInfo().equals(goodsOrderInfo.getBuySource())) { + paramMap.put("notify_url", xylWeChatPaymentConfig.getXylWeChatNotifyUrl() + XINYILU_WE_CHAT_REFUND_URL); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(goodsOrderInfo.getBuySource()) || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(goodsOrderInfo.getBuySource())) { + paramMap.put("notify_url", ylypWeChatPaymentConfig.getYlypWeChatNotifyUrl() + YINLUYOUPIN_WE_CHAT_REFUND_URL); + } + amountMap.put("refund", refundDTO.getRefundPrice().multiply(BigDecimal.valueOf(100)).intValue()); + amountMap.put("total", goodsOrderInfo.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue()); + } + amountMap.put("currency", "CNY"); + paramMap.put("amount", amountMap); + return JSON.toJSONString(paramMap); + } + + /** + * 发起退款申请 + * + * @param refundParam 请求参数 + * @param appointmentOrderInfo 预约服务订单信息 + * @param goodsOrderInfo 商品订单信息 + * @param patientId 会员id + * @param refundDTO 申请信息 + * @throws Exception 异常信息 + */ + public void applyWeRefund(String refundParam, AppointmentOrder appointmentOrderInfo, GoodsOrder goodsOrderInfo, + Long patientId, RefundDTO refundDTO) throws Exception { + String requestUrl = weChatPaymentUrlConfig.getRefundApplyUrl(); + HttpPost httpPost = new HttpPost(requestUrl); + StringEntity entity = new StringEntity(refundParam, "utf-8"); + entity.setContentType("application/json"); + httpPost.setEntity(entity); + httpPost.setHeader("Accept", "application/json"); + CloseableHttpResponse response = null; + String refundMerchantType = ""; + try { + //预约订单使用新医路账户 + if (Objects.nonNull(appointmentOrderInfo) && Objects.isNull(goodsOrderInfo)) { + response = xinYiLuWeChatPayClient.execute(httpPost); + refundMerchantType = PaymentMerchantTypeEnum.XINYILU.getInfo(); + } + //护理站商品购买订单使用新医路账户,商城商品订单和健康咨询订单使用医路优品账户 + if (Objects.nonNull(goodsOrderInfo) && Objects.isNull(appointmentOrderInfo)) { + if (BuySourceEnum.NURSE_STATION.getInfo().equals(goodsOrderInfo.getBuySource())) { + response = xinYiLuWeChatPayClient.execute(httpPost); + refundMerchantType = PaymentMerchantTypeEnum.XINYILU.getInfo(); + } + if (BuySourceEnum.SHOPPING_MALL.getInfo().equals(goodsOrderInfo.getBuySource()) || BuySourceEnum.HEALTH_CONSULTATION.getInfo().equals(goodsOrderInfo.getBuySource())) { + response = yiLuYouPinWeChatPayClient.execute(httpPost); + refundMerchantType = PaymentMerchantTypeEnum.YILUYOUPIN.getInfo(); + } + } + if (Objects.isNull(response)) { + throw new ServiceException("获取httpclient对象失败!"); + } + int statusCode = response.getStatusLine().getStatusCode(); + String body = EntityUtils.toString(response.getEntity()); + if (statusCode != HAVE_BODY_SUCCESS_CODE && statusCode != NO_HAVE_BODY_SUCCESS_CODE) { + throw new ServiceException("微信申请退款异常, 响应码:" + statusCode + ", 退款返回结果:" + body); + } + if (Objects.nonNull(appointmentOrderInfo)) { + appointmentOrderMapper.updateAppointConfirmRefundStatus(appointmentOrderInfo.getOrderNo(), ConfirmRefundStatusEnum.CONFIRMED.getInfo()); + } + if (Objects.nonNull(goodsOrderInfo)) { + goodsOrderMapper.updateGoodsConfirmRefundStatus(goodsOrderInfo.getOrderNo(), ConfirmRefundStatusEnum.CONFIRMED.getInfo()); + } + WeChatRefundInfoVO weChatRefundInfoVO = JSONObject.parseObject(body, WeChatRefundInfoVO.class); + int refundInfoCount = refundInfoMapper.getRefundInfoByOrderNo(weChatRefundInfoVO.getOutTradeNo()); + if (refundInfoCount <= 0) { + RefundInfo refundInfo = buildRefundInfo(patientId, weChatRefundInfoVO, refundDTO, body, refundMerchantType); + int insertCunt = refundInfoMapper.insertRefundInfo(refundInfo); + if (insertCunt <= 0) { + throw new ServiceException("记录退款信息失败,请联系管理员!"); + } + } + } catch (Exception e) { + log.error("微信申请退款接口出错,原因:{}", e.getMessage()); + } finally { + if (response != null) { + response.close(); + } + } + } + + /** + * 构建微信退款信息 + * + * @param patientId 会员id + * @param refundInfoVO 退款信息参数 + * @param refundDTO 退款申请参数 + * @param refundBody 返回体 + * @param refundMerchantType 退款账户类型,新医路或者医路优品 + */ + private RefundInfo buildRefundInfo(Long patientId, WeChatRefundInfoVO refundInfoVO, + RefundDTO refundDTO, String refundBody, String refundMerchantType) { + RefundInfo refundInfo = new RefundInfo(); + refundInfo.setPatientId(patientId); + refundInfo.setOrderNo(refundInfoVO.getOutTradeNo()); + refundInfo.setRefundNo(refundInfoVO.getRefundId()); + refundInfo.setOutRefundNo(refundInfoVO.getOutRefundNo()); + refundInfo.setTransactionNo(StringUtils.isBlank(refundInfoVO.getTransactionId()) ? "" : refundInfoVO.getTransactionId()); + refundInfo.setRefundReason(StringUtils.isBlank(refundDTO.getRefundReason()) ? "" : refundDTO.getRefundReason()); + refundInfo.setRefundType(RefundTypeEnum.WE_CHAT.getInfo()); + refundInfo.setWechatRefundStatus(RefundStatusEnum.PROCESSING.getInfo()); + refundInfo.setOrderTotalPrice(BigDecimal.valueOf(refundInfoVO.getAmount().getTotal()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN)); + refundInfo.setRefundPrice(BigDecimal.valueOf(refundInfoVO.getAmount().getRefund()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN)); + refundInfo.setCurrency(refundInfoVO.getAmount().getCurrency()); + refundInfo.setChannel(refundInfoVO.getChannel()); + refundInfo.setUserreceivedaccount(refundInfoVO.getUserReceivedAccount()); + refundInfo.setSuccessTime(StringUtils.isBlank(refundInfoVO.getSuccessTime()) ? null : LocalDateTime.parse(refundInfoVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME)); + refundInfo.setApplyRefundReturnContent(refundBody); + refundInfo.setRefundMerchantType(refundMerchantType); + refundInfo.setDelFlag(0); + refundInfo.setCreateTime(LocalDateTime.parse(refundInfoVO.getCreateTime(), DateTimeFormatter.ISO_DATE_TIME)); + return refundInfo; + } + + /** + * 会员积分兑换商品确认退款接口 + * + * @param refundDTO 退款参数 + * @return com.xinyilu.common.core.domain.AjaxResult + **/ + public AjaxResult refundPointsRedemption(RefundDTO refundDTO) { + GoodsInfoRedemptionVO goodsOrderInfo = goodsOrderMapper.getGoodOrder(refundDTO.getOrderNo()); + if (Objects.isNull(goodsOrderInfo)) { + return AjaxResult.error("当前订单信息不存在,请重新选择!"); + } + PatientInfoVO patientInfo = patientInfoMapper.getPatientInfoById(goodsOrderInfo.getPatientId()); + if (Objects.isNull(patientInfo)) { + return AjaxResult.error("当前用户信息不存在,无法退款!"); + } + AjaxResult ajaxResult = goodIntegralVerification(goodsOrderInfo); + if (Objects.nonNull(ajaxResult)) { + return ajaxResult; + } + goodsOrderMapper.updateConfirmRefundStatusAndOrderStatus(refundDTO.getOrderNo(), ConfirmRefundStatusEnum.CONFIRMED.getInfo(), OrderStatusEnum.REFUNDED.getInfo()); + Integer stockNum = Objects.isNull(goodsOrderInfo.getIntegralExchangeCount()) ? 0 : goodsOrderInfo.getIntegralExchangeCount(); + goodsStockService.addGoodsStockInfo(goodsOrderInfo.getOrderNo(), goodsOrderInfo.getGoodsAttributeDetailsId(), stockNum); + int stockIntegralNum = Objects.isNull(goodsOrderInfo.getIntegralExchangeSill()) ? 0 : goodsOrderInfo.getIntegralExchangeSill(); + patientInfoMapper.addPatientIntegralCount(goodsOrderInfo.getPatientId(), stockIntegralNum); + PatientIntegralChange patientIntegralChange = new PatientIntegralChange(); + patientIntegralChange.setPatientId(goodsOrderInfo.getPatientId()); + patientIntegralChange.setOriginalIntegral(Objects.isNull(patientInfo.getIntegral()) ? 0 : patientInfo.getIntegral()); + patientIntegralChange.setChangeIntegral(stockIntegralNum); + patientIntegralChange.setChangeTime(LocalDateTime.now()); + patientIntegralChange.setChangeType(IntegralChangeType.COMMODITY_EXCHANGE.getInfo()); + patientIntegralChange.setChangeRemark("积分兑换商品订单新增积分变更"); + patientIntegralChange.setChangeIntegralChannel(StringUtils.isBlank(goodsOrderInfo.getOrderChannel()) ? "" : goodsOrderInfo.getOrderChannel()); + patientIntegralChange.setCreateTime(LocalDateTime.now()); + int integralChange = patientIntegralChangeMapper.insertPatientIntegralChange(patientIntegralChange); + if (integralChange <= 0) { + log.error("积分兑换商品-生成积分变更记录表信息失败,积分变更信息:{}", integralChange); + throw new ServiceException("确认退款失败,请联系管理员!"); + } + return AjaxResult.success(); + } + + + /** + * 校验积分兑换商品订单状态以及订单时间等下信息 + * + * @return 返回结果信息 + */ + private AjaxResult goodIntegralVerification(GoodsInfoRedemptionVO goodsOrderInfo) { + LocalDateTime localDateTime = goodsOrderInfo.getOrderTime().plusYears(1); + if (LocalDateTime.now().isAfter(localDateTime)) { + return AjaxResult.error("当前订单超过一年,无法进行退款处理!"); + } + if (StringUtils.isBlank(goodsOrderInfo.getConfirmRefundStatus()) + || !ConfirmRefundStatusEnum.NOT_CONFIRM.getInfo().equals(goodsOrderInfo.getConfirmRefundStatus())) { + return AjaxResult.error("当前商品订单未进行退款确认,请先进行确认!"); + } + if (StringUtils.isBlank(goodsOrderInfo.getOrderStatus()) + || !GooodsOrderStatusEnum.WAIT_REFUND.getInfo().equals(goodsOrderInfo.getOrderStatus()) + || GooodsOrderStatusEnum.REFUNDED.getInfo().equals(goodsOrderInfo.getOrderStatus())) { + return AjaxResult.error("当前商品订单非退款中或者已退款,无法进行退款处理!"); + } + return null; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/AppletAccessTokenUtil.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/AppletAccessTokenUtil.java index 8cdaa33..7454651 100644 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/AppletAccessTokenUtil.java +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/AppletAccessTokenUtil.java @@ -1,7 +1,6 @@ package com.xinelu.applet.utils; import com.xinelu.common.config.AppletChatConfig; -import com.xinelu.common.config.NurseAppletChatConfig; import com.xinelu.common.constant.Constants; import com.xinelu.common.entity.AppletAccessToken; import com.xinelu.common.exception.ServiceException; @@ -27,8 +26,7 @@ public class AppletAccessTokenUtil { private RedisTemplate redisTemplate; @Resource private AppletChatConfig appletChatConfig; - @Resource - private NurseAppletChatConfig nurseAppletChatConfig; + /** * 返回成功状态码 */ @@ -65,34 +63,4 @@ public class AppletAccessTokenUtil { return accessToken; } - /** - * 护理员小程序获取小程序AccessToken方法 - * - * @return 小程序的AccessToken - */ - public String getPersonAppletAccessToken() { - String accessToken; - String accessTokenKey = Constants.NURSE_STATION_PERSON_APPLET_ACCESS_TOKEN + "accessToken"; - //从Redis中取出accessToken - Object object = redisTemplate.opsForValue().get(accessTokenKey); - if (Objects.isNull(object)) { - //没有,获取accessToken - AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(nurseAppletChatConfig.getAppletId(), nurseAppletChatConfig.getSecret()); - if (Objects.isNull(appletAccessToken)) { - throw new ServiceException("获取微信小程序accessToken信息失败"); - } - if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != SUCCESS_CODE) { - throw new ServiceException("获取微信小程序accessToken信息失败,失败信息为:" + appletAccessToken.getErrmsg(), 201); - } - if (StringUtils.isBlank(appletAccessToken.getAccessToken())) { - throw new ServiceException("accessToken信息为空"); - } - //存入Redis中 - redisTemplate.opsForValue().set(accessTokenKey, appletAccessToken.getAccessToken(), 3600, TimeUnit.SECONDS); - accessToken = appletAccessToken.getAccessToken(); - } else { - accessToken = (String) object; - } - return accessToken; - } } \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/LogisticsUtil.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/LogisticsUtil.java new file mode 100644 index 0000000..1a8d276 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/LogisticsUtil.java @@ -0,0 +1,145 @@ +package com.xinelu.applet.utils; + +import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import com.xinelu.common.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.Map; + +/** + * @Description 快递鸟物流查询工具类 + * @Author 纪寒 + * @Date 2022-11-01 13:43:03 + * @Version 1.0 + */ +@Slf4j +public class LogisticsUtil { + + /** + * 发送POST请求 + * + * @param url 请求地址 + * @param params 请求参数 + * @return 返回结果信息 + * @throws Exception 异常信息 + */ + public static String sendPost(String url, Map params) throws Exception { + OutputStreamWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + URL realUrl = new URL(url); + HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); + //发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + //设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + conn.connect(); + //获取URLConnection对象对应的输出流 + out = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8); + StringBuilder param = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (param.length() > 0) { + param.append("&"); + } + param.append(entry.getKey()); + param.append("="); + param.append(entry.getValue()); + } + out.write(param.toString()); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + } catch (Exception e) { + log.error("调用快递鸟识别单号异常,异常信息:{}", e.getMessage()); + throw new ServiceException("查询物流信息出错,请联系管理员!"); + } finally { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } + return result.toString(); + } + + /** + * sign签名生成 + * + * @param content 内容 + * @param keyValue ApiKey + * @param charset 编码方式 + * @return 签名信息 + * @throws Exception 异常信息 + */ + public static String encrypt(String content, String keyValue, String charset) throws Exception { + if (keyValue != null) { + return base64(logisticsMd5(content + keyValue, charset), charset); + } + return base64(logisticsMd5(content, charset), charset); + } + + /** + * 编码格式信息 + * + * @param content 内容 + * @param charset 字符集 + * @return 编码结果信息 + * @throws Exception 异常信息 + */ + public static String urlEncoder(String content, String charset) throws Exception { + return URLEncoder.encode(content, charset); + } + + /** + * base64编码 + * + * @param content 内容 + * @param charset 编码方式 + * @return 编码结果信息 + * @throws Exception 异常信息 + */ + public static String base64(String content, String charset) throws Exception { + return Base64.encode(content.getBytes(charset)); + } + + /** + * MD5加密 + * + * @param content 内容 + * @param charset 编码方式 + * @return 结果 + * @throws Exception 异常信息 + */ + public static String logisticsMd5(String content, String charset) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(content.getBytes(charset)); + byte[] result = md.digest(); + StringBuilder sb = new StringBuilder(32); + for (byte b : result) { + int val = b & 0xff; + if (val <= 0xf) { + sb.append("0"); + } + sb.append(Integer.toHexString(val)); + } + return sb.toString().toLowerCase(); + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/WeChatUtil.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/WeChatUtil.java new file mode 100644 index 0000000..af2a86b --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/utils/WeChatUtil.java @@ -0,0 +1,35 @@ +package com.xinelu.applet.utils; + +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import com.xinelu.common.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Component; + +import java.security.PrivateKey; + +/** + * @Description 微信工具类 + * @Author 纪寒 + * @Date 2022-10-20 10:11:38 + * @Version 1.0 + */ +@Component +@Slf4j +public class WeChatUtil { + + /** + * 获取商户的私钥文件 + * + * @param filename 获取商户的私钥文件 + * @return 商户私钥 + */ + public PrivateKey getPrivateKey(String filename) { + try { + return PemUtil.loadPrivateKey(new ClassPathResource(filename).getInputStream()); + } catch (Exception e) { + log.error("商户私钥文件不存在,错误原因:{}", e.getMessage()); + throw new ServiceException("商户私钥文件不存在,请联系管理员!"); + } + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/HealthConsultationOrderDTO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/HealthConsultationOrderDTO.java new file mode 100644 index 0000000..dc05cfa --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/HealthConsultationOrderDTO.java @@ -0,0 +1,131 @@ +package com.xinelu.applet.vo.healthconsultation; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xinelu.common.custominterface.Insert; +import com.xinelu.common.custominterface.Update; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * @author ljh + * @version 1.0 + * Create by 2023/3/8 13:59 + */ +@Data +public class HealthConsultationOrderDTO implements Serializable { + private static final long serialVersionUID = 8664995394794180987L; + + /** + * 主键id + */ + private Long id; + + /** + * 商品订单表id + */ + private Long goodsOrderId; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 0:否,1:是 + */ + private Integer delFlag; + + /** + * 会员id + */ + @NotNull(message = "咨询人员信息不能为空!", groups = {Insert.class, Update.class}) + private Long patientId; + + /** + * 订单状态,待付款:WAIT_PAY,已付款:PAY,已取消:CANCEL,待收货:WAIT_RECEIVED,已收货:RECEIVED,待退款:WAIT_REFUND,已退款:REFUNDED,待退货:WAIT_RETURNED,已退货:RETURNED + */ + private String orderStatus; + + /** + * 订单总金额 + */ + @NotNull(message = "金额不能为空", groups = {Insert.class, Update.class}) + private BigDecimal totalPrice; + + /** + * 收货人 + */ + @NotBlank(message = "姓名不能为空", groups = {Insert.class, Update.class}) + @Length(max = 20, message = "姓名不能超过20位", groups = {Insert.class, Update.class}) + private String receiver; + + /** + * 联系电话 + */ + @NotBlank(message = "联系电话不能为空", groups = {Insert.class, Update.class}) + @Length(max = 11, message = "联系电话不能超过11位", groups = {Insert.class, Update.class}) + private String phone; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime orderTime; + /** + * 下单方式,手机App:MOBILE_APP,微信小程序:WECHAT_APPLET,支付宝小程序:ALI_PAY_APPLET + */ + @NotNull(message = "下单方式不能为空", groups = {Insert.class, Update.class}) + private String orderChannel; + + /** + * 护理站:NURSE_STATION,商城:SHOPPING_MALL,健康咨询:HEALTH_CONSULTATION + */ + private String buySource; + + /** + * 订单类型,积分兑换:INTEGRAL_EXCHANGE,直接购买:DIRECT_BUY,健康咨询:HEALTH_CONSULTATION + */ + private String orderType; + + /** + * 健康咨询人员表id,记录咨询订单中选择的医生,健康咨询订单使用 + */ + @NotNull(message = "请选择咨询的专家!", groups = {Insert.class, Update.class}) + private Long hospitalPersonId; + + /** + * 商品原始金额,即:商品数量 * 商品单价 + */ + private BigDecimal originalTotalPrice; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** + * 健康咨询预约时间,健康咨询订单使用 + **/ + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "服务日期不能为空", groups = {Insert.class, Update.class}) + private Date healthAppointDate; + + /** + * 健康咨询内容,健康咨询类型的订单使用 + */ + private String healthConsultationContent; + + /** + * 健康咨询专家,记录咨询订单中选择的医生姓名,健康咨询订单使用 + */ + @NotBlank(message = "请选择咨询的专家!", groups = {Insert.class, Update.class}) + private String hospitalPersonName; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/HealthConsultationVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/HealthConsultationVO.java new file mode 100644 index 0000000..73f412b --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/HealthConsultationVO.java @@ -0,0 +1,30 @@ +package com.xinelu.applet.vo.healthconsultation; + +import com.xinelu.manage.domain.poserInfo.PoserInfo; +import lombok.Data; + +import java.util.List; + +/** + * @Description 健康咨询返回值实体类 + * @Author zh + * @Date 2023-03-07 + */ +@Data +public class HealthConsultationVO { + + /** + * 科室id + */ + private Long departmentId; + + /** + * 科室名称 + */ + private String departmentName; + + /** + * 海报集合 + */ + List poserInfoList; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/PatientAndTimeVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/PatientAndTimeVO.java new file mode 100644 index 0000000..f42770e --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/healthconsultation/PatientAndTimeVO.java @@ -0,0 +1,30 @@ +package com.xinelu.applet.vo.healthconsultation; + +import com.xinelu.applet.vo.specialdisease.WeekDaysVO; +import lombok.Data; + +import java.util.List; + +/** + * @Description 信息确认返回值实体类 + * @Author zh + * @Date 2023-03-07 + */ +@Data +public class PatientAndTimeVO { + + /** + * 用户姓名 + */ + private String patientName; + + /** + * 手机号码 + */ + private String phone; + + /** + * 近七天的预约时间点集合 + */ + List appointmentTimeList; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/logistics/DistinguishResultVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/logistics/DistinguishResultVO.java new file mode 100644 index 0000000..3c8e57e --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/logistics/DistinguishResultVO.java @@ -0,0 +1,44 @@ +package com.xinelu.applet.vo.logistics; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Description 快递鸟单号识别接口返回值实体类 + * @Author 纪寒 + * @Date 2022-11-01 14:44:06 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class DistinguishResultVO implements Serializable { + + private static final long serialVersionUID = 5858502009039750987L; + + @JsonProperty("EBusinessID") + private String eBusinessID; + + @JsonProperty("Success") + private Boolean success; + + @JsonProperty("LogisticCode") + private String logisticCode; + + @JsonProperty("Shippers") + private List shippers; + + @NoArgsConstructor + @Data + public static class ShippersDTO { + + @JsonProperty("ShipperCode") + private String shipperCode; + + @JsonProperty("ShipperName") + private String shipperName; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/logistics/SearchMonitorResultVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/logistics/SearchMonitorResultVO.java new file mode 100644 index 0000000..2d513ed --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/logistics/SearchMonitorResultVO.java @@ -0,0 +1,66 @@ +package com.xinelu.applet.vo.logistics; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @Description 快递鸟即时查询接口返回值实体类 + * @Author 纪寒 + * @Date 2022-11-01 15:21:32 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class SearchMonitorResultVO implements Serializable { + private static final long serialVersionUID = -3109050110048632561L; + + @JsonProperty("EBusinessID") + private String eBusinessID; + + @JsonProperty("ShipperCode") + private String shipperCode; + + private String shipperName; + + @JsonProperty("Success") + private Boolean success; + + @JsonProperty("LogisticCode") + private String logisticCode; + + @JsonProperty("State") + private String state; + + @JsonProperty("StateEx") + private String stateEx; + + @JsonProperty("Location") + private String location; + + @JsonProperty("Traces") + private List traces; + + @NoArgsConstructor + @Data + public static class TracesDTO { + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonProperty("AcceptTime") + private LocalDateTime acceptTime; + + @JsonProperty("AcceptStation") + private String acceptStation; + + @JsonProperty("Location") + private String location; + + @JsonProperty("Action") + private String action; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nurseapplogin/PatientAndDiseaseVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nurseapplogin/PatientAndDiseaseVO.java index 97ee956..faa5201 100644 --- a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nurseapplogin/PatientAndDiseaseVO.java +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nurseapplogin/PatientAndDiseaseVO.java @@ -163,5 +163,5 @@ public class PatientAndDiseaseVO implements Serializable { /** * 基础疾病信息 */ - private String[] diseaseList; + private Integer[] diseaseList; } diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nursingorder/AppletGoodsOrderVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nursingorder/AppletGoodsOrderVO.java new file mode 100644 index 0000000..12b5735 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nursingorder/AppletGoodsOrderVO.java @@ -0,0 +1,249 @@ +package com.xinelu.applet.vo.nursingorder; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; + + +/** + * @author ljh + * @version 1.0 + * Create by 2022/10/25 15:49 + */ +@Data +public class AppletGoodsOrderVO implements Serializable { + private static final long serialVersionUID = -1046127024688630443L; + + /** + * 商品订单表id + */ + private Long goodsOrderId; + + /** + * 护理站id + */ + private Long nurseStationId; + + /** + * 会员id + */ + private Long patientId; + + /** + * 订单编号 + */ + private String goOrderNo; + /** + * 订单编号 + */ + private String godOrderNo; + + /** + * 订单状态,待付款:WAIT_PAY,已付款:PAY,已取消:CANCEL,待收货:WAIT_RECEIVED,已收货:RECEIVED,待退款:WAIT_REFUND,已退款:REFUNDED,待退货:WAIT_RETURNED,已退货:RETURNED + */ + private String orderStatus; + + /** + * 订单总金额 + */ + private BigDecimal totalPrice; + /** + * 收货人 + */ + private String receiver; + /** + * 收货地址 + */ + private String receiveAddress; + /** + * 联系电话 + */ + private String phone; + + /** + * 订单总金额 + */ + private BigDecimal godTotalPrice; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime orderTime; + + /** + * 主键id + */ + private Long goodsOrderDetailsId; + + + /** + * 商品名称 + */ + private String goodsName; + + /** + * 商品数量 + */ + private Integer goodsCount; + + /** + * 商品属性名称 + */ + private String goodsAttributeName; + + /** + * 商品属性内容 + */ + private String goodsAttributeContent; + + /** + * 商品单价(元) + */ + private BigDecimal goodsPrice; + + + /** + * 优惠金额(元) + */ + private BigDecimal discountPrice; + + /** + * 运费金额(元) + */ + private BigDecimal transportPrice; + + /** + * 赠送积分 + */ + private Integer giveIntegral; + + + /** + * 退款退货类型:REFUND_MONEY_GOODS,仅退款:ONLY_REFUND_MONEY + */ + private String refundType; + + /** + * 退款原因类型字典表id + */ + private Long refundReasonDictId; + + /** + * 退货原因具体描述 + */ + private String refundReasonRemark; + + /** + * 确认退款状态,未确认:NOT_CONFIRM,已确认:CONFIRMED + */ + private String confirmRefundStatus; + + /** + * 商品属性图片地址 + */ + private String attributePitureUrl; + + /** + * 退款时间时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + + /** + * 字典标签 + */ + private String dictLabel; + + /** + * 快递单号 + */ + private String expressNo; + + /** + * 购买来源 + */ + private String buySource; + + /** + * 订单类型,积分兑换:INTEGRAL_EXCHANGE,直接购买:DIRECT_BUY,健康咨询:HEALTH_CONSULTATION + */ + private String orderType; + + + /** + * 积分抵扣数量 + */ + private Integer integralDeductionCount; + + /** + * 退款详情-申请时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime appleTime; + + /** + * 积分兑换标识,0:否,1:是 + */ + private Integer integralExchangeFlag; + + /** + * 积分兑换门槛值 + */ + private Integer integralExchangeSill; + + /** + * 积分兑换商品数量 + */ + private Integer integralExchangeCount; + + /** + * 订单原始总金额(优惠券之前的价格,即:商品数量*商品单价) + */ + private BigDecimal originalTotalPrice; + + /** + * 优惠券名称 + */ + private String couponTitle; + + /** + * 优惠券id + */ + private Long couponId; + + /** + * 健康咨询人员表id,记录咨询订单中选择的医生 + */ + private Long hospitalPersonId; + + /** + * 下单方式,手机App:MOBILE_APP,微信小程序:WECHAT_APPLET,支付宝小程序:ALI_PAY_APPLET + */ + private String orderChannel; + + /** + * 健康咨询内容,健康咨询类型的订单使用 + */ + private String healthConsultationContent; + + /** + * 健康咨询预约时间,健康咨询订单使用 + **/ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date healthAppointDate; + + /** + * 健康咨询专家名称,健康咨询类型的订单使用 + */ + private String hospitalPersonName; + + /** + * 科室人员头像地址 + */ + private String personPictureUrl; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nursingorder/NursingOrderInfoVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nursingorder/NursingOrderInfoVO.java new file mode 100644 index 0000000..065ed8a --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/nursingorder/NursingOrderInfoVO.java @@ -0,0 +1,103 @@ +package com.xinelu.applet.vo.nursingorder; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xinelu.common.core.domain.BaseDomain; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalTime; + +/** + * 个人中心订单Controller + * + * @author zhangheng + * @date 2022-09-06 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class NursingOrderInfoVO extends BaseDomain implements Serializable { + + private static final long serialVersionUID = -2337545308977415936L; + + /** + * 预约订单编号 + */ + private String orderNo; + /** + * 订单数量 + */ + private Long orderCount; + + /** + * 服务日期,格式:yyyy-MM-dd + */ + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate serviceDate; + + /** + * 服务开始时间,格式:HH:mm + */ + + @JsonFormat(pattern = "HH:mm:ss") + private LocalTime serviceStartTime; + + /** + * 服务结束时间,格式:HH:mm + */ + @JsonFormat(pattern = "HH:mm:ss") + private LocalTime serviceEndTime; + + /** + * 预约订单状态,代付款:WAIT_PAY,待派单:WAIT_DISPATCH,未完成:NOT_FINISH,服务完成:COMPLETE + */ + private String orderStatus; + + /** + * 预约状态,0:可以预约,1:不可以预约 + */ + private Integer appointmentStatus; + + /** + * 预约总价格,单位:元 + */ + private BigDecimal totalPrice; + + /** + * 护理项目名称 + */ + private String nurseItemName; + + /** + * 护理项目价格 + */ + private BigDecimal nurseItemPrice; + + + /** + * 是否删除标识,0:否,1:是 + */ + private Integer delFlag; + + /** + * 提前预约时长,单位小时 + */ + private Integer advanceAppointDuration; + + /** + * 护理站图片路径 + */ + private String itemPictureUrl; + + /** + * 护理站图片路径 + */ + private String nurseStationName; + + /** + * 服务时长和单位 + */ + private String itemServeDurationUnit; +} \ No newline at end of file diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/specialdisease/AppointmentOrderDetailsInfoVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/specialdisease/AppointmentOrderDetailsInfoVO.java new file mode 100644 index 0000000..219c62b --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/specialdisease/AppointmentOrderDetailsInfoVO.java @@ -0,0 +1,208 @@ +package com.xinelu.applet.vo.specialdisease; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xinelu.manage.domain.appointmentorderconsumable.AppointmentOrderConsumable; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; + +/** + * @Description 预约服务订单详情返回值实体类 + * @Author 纪寒 + * @Date 2022-11-11 14:48:01 + * @Version 1.0 + */ +@Data +public class AppointmentOrderDetailsInfoVO implements Serializable { + private static final long serialVersionUID = 7042842920314984169L; + + /** + * 订单主表id + */ + private Long appointmentOrderId; + + /** + * 会员id + */ + private Long patientId; + + /** + * 护理项目id + */ + private Long nurseStationItemId; + + /** + * 护理站名称 + */ + private String nurseStationName; + + /** + * 护理站头像 + */ + private String stationPictureUrl; + + /** + * 护理站地址 + */ + private String address; + + /** + * 护理站联系电话 + */ + private String stationPhone; + + /** + * 护理人联系电话 + */ + private String patientPhone; + + /** + * 服务项目名称 + */ + private String nurseItemName; + + /** + * 服务时长 + */ + private String itemServeDurationUnit; + + /** + * 护理人名称即:会员名称 + */ + private String patientName; + + /** + * 服务地址 + */ + private String serviceAddress; + + /** + * 服务时间 + */ + private LocalDate serviceDate; + + /** + * 服务开始时间 + */ + private LocalTime serviceStartTime; + + /** + * 服务结束时间 + */ + private LocalTime serviceEndTime; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 备注信息 + */ + private String remark; + + /** + * 服务项目价格 + */ + private BigDecimal nurseItemPrice; + + /** + * 耗材总价格 + */ + private BigDecimal consumableTotalPrice; + + /** + * 订单总价格 + */ + private String totalPrice; + + /** + * 订单状态 + */ + private String orderStatus; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** + * 服务项目图片 + */ + private String itemPictureUrl; + /** + * 预约订单耗材信息 + */ + private List itemConsumableList; + + /** + * 失能情况,NOT_DISABLED:未失能,DISABLED:已失能 + */ + private String disablingCondition; + + /** + * 失能原因 + */ + private String disablingReason; + + /** + * 订单类型,院内陪护:COMPANION_IN_HOSPITAL,其它:OTHER + */ + private String orderType; + + /** + * 陪护开始时间,院内陪护订单使用,格式:yyyy-MM-dd + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate companionStartDate; + + /** + * 陪护结束时间,院内陪护订单使用,格式:yyyy-MM-dd + */ + @JsonFormat(pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate companionEndDate; + + /** + * 陪护天数,院内陪护订单使用 + */ + private Integer companionDays; + + /** + * 订单填写人姓名,院内陪护订单使用 + */ + private String orderWriteName; + + /** + * 护理人姓名,院内陪护订单使用 + */ + private String caregiverName; + + /** + * 护理人电话,院内陪护订单使用 + */ + private String caregiverPhone; + + /** + * 医院名称,院内陪护订单使用 + */ + private String hospitalName; + + /** + * 科室名称,院内陪护订单使用 + */ + private String departmentName; + + /** + * 病床号,院内陪护订单使用 + */ + private String hospitalBedNumber; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/dto/PaymentDTO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/dto/PaymentDTO.java new file mode 100644 index 0000000..99e2a7c --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/dto/PaymentDTO.java @@ -0,0 +1,67 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.dto; + +import com.xinelu.common.custominterface.Insert; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @Description 微信支付参数接受实体类 + * @Author 纪寒 + * @Date 2022-10-18 15:12:51 + * @Version 1.0 + */ +@Data +public class PaymentDTO implements Serializable { + private static final long serialVersionUID = 4090244715734558969L; + + /** + * 会员id + */ + @NotNull(message = "会员id不能为空!", groups = {Insert.class}) + private Long patientId; + + /** + * 微信用户openid + */ + private String openid; + + /** + * 订单编号 + */ + @NotBlank(message = "订单编号不能为空!", groups = {Insert.class}) + private String orderNo; + + /** + * 支付类型,微信支付:WECHAT_PAY,支付宝支付:ALI_PAY + */ + @NotBlank(message = "支付类型不能为空!", groups = {Insert.class}) + private String payType; + + /** + * 支付渠道,手机App:MOBILE_APP,微信小程序:WECHAT_APPLET,支付宝小程序:ALI_PAY_APPLE + */ + @NotBlank(message = "支付渠道不能为空!", groups = {Insert.class}) + private String orderChannel; + + /** + * 购买来源,用于判断使用那个商户进行支付 + * 护理站:NURSE_STATION,商城:SHOPPING_MAL, 健康咨询:HEALTH_CONSULTATION,学习培训:TRAINING + */ + @NotBlank(message = "购买来源不能为空!", groups = {Insert.class}) + private String buySource; + + /** + * 支付金额 + */ + @NotNull(message = "支付金额不能为空!", groups = {Insert.class}) + private BigDecimal paymentPrice; + + /** + * 护理员id + */ + private Long nurseStationPersonId; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/dto/RefundDTO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/dto/RefundDTO.java new file mode 100644 index 0000000..2ec9808 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/dto/RefundDTO.java @@ -0,0 +1,57 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.dto; + +import com.xinelu.common.custominterface.Insert; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @Description + * @Author 纪寒 + * @Date 2022-10-24 16:15:44 + * @Version 1.0 + */ +@Data +public class RefundDTO implements Serializable { + private static final long serialVersionUID = -1990509784850994288L; + + /** + * 订单编号,必传字段 + */ + @NotBlank(message = "订单编号不能为空!", groups = {Insert.class}) + private String orderNo; + + /** + * 退款原因 + */ + private String refundReason; + + /** + * 退款金额,必传字段 + */ + @NotNull(message = "退款金额不能为空!", groups = {Insert.class}) + private BigDecimal refundPrice; + + /** + * 补充描述和凭证 + */ + private String remark; + + /** + * 货物到货状态,目前用不到 + */ + private String goodsStatus; + + /** + * 订单类型(健康咨询订单退款使用),积分兑换:INTEGRAL_EXCHANGE,直接购买:DIRECT_BUY,健康咨询:HEALTH_CONSULTATION + */ + private String orderType; + + /** + * 学习培训订单标识(学习培训订单退款使用) + */ + private String trainingOrderFlag; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/OrderStatusInfoVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/OrderStatusInfoVO.java new file mode 100644 index 0000000..a8d1067 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/OrderStatusInfoVO.java @@ -0,0 +1,22 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description 订单状态返回值实体类 + * @Author 纪寒 + * @Date 2022-10-21 10:47:20 + * @Version 1.0 + */ +@Data +public class OrderStatusInfoVO implements Serializable { + private static final long serialVersionUID = -8522003863208703215L; + + private Boolean payFlag; + + private String tradeStatus; + + WeChatQueryOrderVO weChatQueryOrderVO; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatAppSignVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatAppSignVO.java new file mode 100644 index 0000000..39a9b1b --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatAppSignVO.java @@ -0,0 +1,34 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description 微信App调起支付参数信息 + * @Author 纪寒 + * @Date 2022-10-31 09:59:19 + * @Version 1.0 + */ +@Builder +@Data +public class WeChatAppSignVO implements Serializable { + private static final long serialVersionUID = 6921828781484230912L; + + private String appId; + + private String partnerId; + + private String prepayId; + + private String packageValue; + + private String nonceStr; + + private String timeStamp; + + private String sign; + + +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatAppletSignVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatAppletSignVO.java new file mode 100644 index 0000000..710273a --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatAppletSignVO.java @@ -0,0 +1,30 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description 微信小程序调起支付参数信息 + * @Author 纪寒 + * @Date 2022-10-20 09:59:19 + * @Version 1.0 + */ +@Builder +@Data +public class WeChatAppletSignVO implements Serializable { + private static final long serialVersionUID = -2527792374746553807L; + + private String appId; + + private String timeStamp; + + private String nonceStr; + + private String prepayId; + + private String signType; + + private String paySign; +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatPayNotifyCiphertextVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatPayNotifyCiphertextVO.java new file mode 100644 index 0000000..1982a33 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatPayNotifyCiphertextVO.java @@ -0,0 +1,57 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Description 微信只顾回调密文参数实体类 + * @Author 纪寒 + * @Date 2022-10-20 14:10:15 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class WeChatPayNotifyCiphertextVO implements Serializable { + private static final long serialVersionUID = -3000851624508762861L; + + @JsonProperty("id") + private String id; + + @JsonProperty("create_time") + private String createTime; + + @JsonProperty("resource_type") + private String resourceType; + + @JsonProperty("event_type") + private String eventType; + + @JsonProperty("summary") + private String summary; + + @JsonProperty("resource") + private ResourceDTO resource; + + @NoArgsConstructor + @Data + public static class ResourceDTO { + + @JsonProperty("original_type") + private String originalType; + + @JsonProperty("algorithm") + private String algorithm; + + @JsonProperty("ciphertext") + private String ciphertext; + + @JsonProperty("associated_data") + private String associatedData; + + @JsonProperty("nonce") + private String nonce; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatPayNotifyPlaintextVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatPayNotifyPlaintextVO.java new file mode 100644 index 0000000..0bd85c0 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatPayNotifyPlaintextVO.java @@ -0,0 +1,146 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Description 微信支付回调通知明文参数实体类 + * @Author 纪寒 + * @Date 2022-10-20 14:08:07 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class WeChatPayNotifyPlaintextVO implements Serializable { + private static final long serialVersionUID = -3950813376227389879L; + + @JsonProperty("transaction_id") + private String transactionId; + + @JsonProperty("amount") + private AmountDTO amount; + + @JsonProperty("mchid") + private String mchid; + + @JsonProperty("trade_state") + private String tradeState; + + @JsonProperty("bank_type") + private String bankType; + + @JsonProperty("promotion_detail") + private List promotionDetail; + + @JsonProperty("success_time") + private String successTime; + + @JsonProperty("payer") + private PayerDTO payer; + + @JsonProperty("out_trade_no") + private String outTradeNo; + + @JsonProperty("appid") + private String appid; + + @JsonProperty("trade_state_desc") + private String tradeStateDesc; + + @JsonProperty("trade_type") + private String tradeType; + + @JsonProperty("attach") + private String attach; + + @JsonProperty("scene_info") + private SceneInfoDTO sceneInfo; + + @NoArgsConstructor + @Data + public static class AmountDTO { + + @JsonProperty("payer_total") + private Integer payerTotal; + + @JsonProperty("total") + private Integer total; + + @JsonProperty("currency") + private String currency; + + @JsonProperty("payer_currency") + private String payerCurrency; + } + + @NoArgsConstructor + @Data + public static class PayerDTO { + @JsonProperty("openid") + private String openid; + } + + @NoArgsConstructor + @Data + public static class SceneInfoDTO { + @JsonProperty("device_id") + private String deviceId; + } + + @NoArgsConstructor + @Data + public static class PromotionDetailDTO { + @JsonProperty("amount") + private Integer amount; + + @JsonProperty("wechatpay_contribute") + private Integer wechatpayContribute; + + @JsonProperty("coupon_id") + private String couponId; + + @JsonProperty("scope") + private String scope; + + @JsonProperty("merchant_contribute") + private Integer merchantContribute; + + @JsonProperty("name") + private String name; + + @JsonProperty("other_contribute") + private Integer otherContribute; + + @JsonProperty("currency") + private String currency; + + @JsonProperty("stock_id") + private String stockId; + + @JsonProperty("goods_detail") + private List goodsDetail; + + @NoArgsConstructor + @Data + public static class GoodsDetailDTO { + @JsonProperty("goods_remark") + private String goodsRemark; + + @JsonProperty("quantity") + private Integer quantity; + + @JsonProperty("discount_amount") + private Integer discountAmount; + + @JsonProperty("goods_id") + private String goodsId; + + @JsonProperty("unit_price") + private Integer unitPrice; + } + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatQueryOrderVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatQueryOrderVO.java new file mode 100644 index 0000000..54f3179 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatQueryOrderVO.java @@ -0,0 +1,82 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Description 微信查单接口返回值实体类 + * @Author 纪寒 + * @Date 2022-10-21 11:26:12 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class WeChatQueryOrderVO implements Serializable { + + private static final long serialVersionUID = 8467953500266751257L; + @JsonProperty("amount") + private AmountDTO amount; + + @JsonProperty("appid") + private String appid; + + @JsonProperty("attach") + private String attach; + + @JsonProperty("bank_type") + private String bankType; + + @JsonProperty("mchid") + private String mchid; + + @JsonProperty("out_trade_no") + private String outTradeNo; + + @JsonProperty("payer") + private PayerDTO payer; + + @JsonProperty("promotion_detail") + private List promotionDetail; + + @JsonProperty("success_time") + private String successTime; + + @JsonProperty("trade_state") + private String tradeState; + + @JsonProperty("trade_state_desc") + private String tradeStateDesc; + + @JsonProperty("trade_type") + private String tradeType; + + @JsonProperty("transaction_id") + private String transactionId; + + @NoArgsConstructor + @Data + public static class AmountDTO { + @JsonProperty("currency") + private String currency; + + @JsonProperty("payer_currency") + private String payerCurrency; + + @JsonProperty("payer_total") + private Integer payerTotal; + + @JsonProperty("total") + private Integer total; + } + + @NoArgsConstructor + @Data + public static class PayerDTO { + @JsonProperty("openid") + private String openid; + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatRefundInfoVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatRefundInfoVO.java new file mode 100644 index 0000000..60af7a9 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatRefundInfoVO.java @@ -0,0 +1,140 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @Description 微信申请退款返回值实体类 + * @Author 纪寒 + * @Date 2022-10-24 17:50:40 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class WeChatRefundInfoVO implements Serializable { + private static final long serialVersionUID = -7834783600438774698L; + @JsonProperty("refund_id") + private String refundId; + + @JsonProperty("out_refund_no") + private String outRefundNo; + + @JsonProperty("transaction_id") + private String transactionId; + + @JsonProperty("out_trade_no") + private String outTradeNo; + + @JsonProperty("channel") + private String channel; + + @JsonProperty("user_received_account") + private String userReceivedAccount; + + @JsonProperty("success_time") + private String successTime; + + @JsonProperty("create_time") + private String createTime; + + @JsonProperty("status") + private String status; + + @JsonProperty("funds_account") + private String fundsAccount; + + @JsonProperty("amount") + private AmountDTO amount; + + @JsonProperty("promotion_detail") + private List promotionDetail; + + @NoArgsConstructor + @Data + public static class AmountDTO { + @JsonProperty("total") + private Integer total; + + @JsonProperty("refund") + private Integer refund; + + @JsonProperty("from") + private List from; + + @JsonProperty("payer_total") + private Integer payerTotal; + + @JsonProperty("payer_refund") + private Integer payerRefund; + + @JsonProperty("settlement_refund") + private Integer settlementRefund; + + @JsonProperty("settlement_total") + private Integer settlementTotal; + + @JsonProperty("discount_refund") + private Integer discountRefund; + + @JsonProperty("currency") + private String currency; + + @NoArgsConstructor + @Data + public static class FromDTO { + @JsonProperty("account") + private String account; + + @JsonProperty("amount") + private Integer amount; + } + } + + @NoArgsConstructor + @Data + public static class PromotionDetailDTO { + @JsonProperty("promotion_id") + private String promotionId; + + @JsonProperty("scope") + private String scope; + + @JsonProperty("type") + private String type; + + @JsonProperty("amount") + private Integer amount; + + @JsonProperty("refund_amount") + private Integer refundAmount; + + @JsonProperty("goods_detail") + private List goodsDetail; + + @NoArgsConstructor + @Data + public static class GoodsDetailDTO { + @JsonProperty("merchant_goods_id") + private String merchantGoodsId; + + @JsonProperty("wechatpay_goods_id") + private String wechatpayGoodsId; + + @JsonProperty("goods_name") + private String goodsName; + + @JsonProperty("unit_price") + private Integer unitPrice; + + @JsonProperty("refund_amount") + private Integer refundAmount; + + @JsonProperty("refund_quantity") + private Integer refundQuantity; + } + } +} diff --git a/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatRefundNotifyVO.java b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatRefundNotifyVO.java new file mode 100644 index 0000000..2586f22 --- /dev/null +++ b/xinelu-nurse-applet/src/main/java/com/xinelu/applet/vo/wechatpaymentinfo/vo/WeChatRefundNotifyVO.java @@ -0,0 +1,61 @@ +package com.xinelu.applet.vo.wechatpaymentinfo.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Description 微信退款回调通知参数实体类 + * @Author 纪寒 + * @Date 2022-10-25 11:38:39 + * @Version 1.0 + */ +@NoArgsConstructor +@Data +public class WeChatRefundNotifyVO implements Serializable { + private static final long serialVersionUID = -2553550636560311860L; + @JsonProperty("mchid") + private String mchid; + + @JsonProperty("transaction_id") + private String transactionId; + + @JsonProperty("out_trade_no") + private String outTradeNo; + + @JsonProperty("refund_id") + private String refundId; + + @JsonProperty("out_refund_no") + private String outRefundNo; + + @JsonProperty("refund_status") + private String refundStatus; + + @JsonProperty("success_time") + private String successTime; + + @JsonProperty("user_received_account") + private String userReceivedAccount; + + @JsonProperty("amount") + private AmountDTO amount; + + @NoArgsConstructor + @Data + public static class AmountDTO { + @JsonProperty("total") + private Integer total; + + @JsonProperty("refund") + private Integer refund; + + @JsonProperty("payer_total") + private Integer payerTotal; + + @JsonProperty("payer_refund") + private Integer payerRefund; + } +} diff --git a/xinelu-nurse-applet/src/main/resources/mapper/applet/healthconsultation/HealthConsultationMapper.xml b/xinelu-nurse-applet/src/main/resources/mapper/applet/healthconsultation/HealthConsultationMapper.xml new file mode 100644 index 0000000..f96089d --- /dev/null +++ b/xinelu-nurse-applet/src/main/resources/mapper/applet/healthconsultation/HealthConsultationMapper.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/xinelu-nurse-applet/src/main/resources/mapper/applet/nursingorder/NusringOrderMapper.xml b/xinelu-nurse-applet/src/main/resources/mapper/applet/nursingorder/NusringOrderMapper.xml new file mode 100644 index 0000000..b5b9772 --- /dev/null +++ b/xinelu-nurse-applet/src/main/resources/mapper/applet/nursingorder/NusringOrderMapper.xml @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + update goods_order + + + nurse_station_id = + #{nurseStationId}, + + + patient_id = + #{patientId}, + + + order_no = + #{orderNo}, + + + order_status = + #{orderStatus}, + + + total_price = + #{totalPrice}, + + + receiver = + #{receiver}, + + + receive_address = + #{receiveAddress}, + + + phone = + #{phone}, + + + order_time = + #{orderTime}, + + + order_channel = + #{orderChannel}, + + + buy_source = + #{buySource}, + + + remark = + #{remark}, + + + del_flag = + #{delFlag}, + + + create_by = + #{createBy}, + + + create_time = + #{createTime}, + + + update_by = + #{updateBy}, + + + update_time = + #{updateTime}, + + + refund_type = + #{refundType}, + + + refund_reason_dict_id = + #{refundReasonDictId}, + + + refund_reason_remark = + #{refundReasonRemark}, + + + confirm_refund_status = + #{confirmRefundStatus}, + + + where id = #{id} + + + + + + \ No newline at end of file diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/goodsOrder/GoodsOrder.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/goodsOrder/GoodsOrder.java index f6568e8..3d06ecc 100644 --- a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/goodsOrder/GoodsOrder.java +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/goodsOrder/GoodsOrder.java @@ -179,6 +179,11 @@ public class GoodsOrder extends BaseDomain implements Serializable { */ private String hospitalPersonName; + /** + * 专家咨询信息表id + */ + private Long consultationInfoId; + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/patientinfo/PatientInfo.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/patientinfo/PatientInfo.java index 860ef8c..7999fe7 100644 --- a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/patientinfo/PatientInfo.java +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/patientinfo/PatientInfo.java @@ -19,6 +19,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDate; +import java.time.LocalDateTime; /** * 被护理人基本信息对象 patient_info @@ -247,6 +248,23 @@ public class PatientInfo extends BaseDomain implements Serializable { */ private String disease; + /** + * 绑定城市(1:德州 2:东营) + */ + private String cityCode; + + /** + * 小程序绑定时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime bindingTime; + + /** + * 当前是否选中(0: 否 1:是) + */ + private String isChecked; + + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) @@ -275,6 +293,9 @@ public class PatientInfo extends BaseDomain implements Serializable { .append("loginFlag", getLoginFlag()) .append("primaryAccountFlag", getPrimaryAccountFlag()) .append("delFlag", getDelFlag()) + .append("cityCode", getCityCode()) + .append("bindingTime", getBindingTime()) + .append("isChecked", getIsChecked()) .toString(); } } diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/paymentinfo/PaymentInfo.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/paymentinfo/PaymentInfo.java new file mode 100644 index 0000000..c3b2104 --- /dev/null +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/paymentinfo/PaymentInfo.java @@ -0,0 +1,156 @@ +package com.xinelu.manage.domain.paymentinfo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xinelu.common.annotation.Excel; +import com.xinelu.common.core.domain.BaseDomain; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 支付记录信息对象 payment_info + * + * @author xinyilu + * @date 2022-10-18 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "支付记录信息对象", description = "payment_info") +public class PaymentInfo extends BaseDomain implements Serializable { + private static final long serialVersionUID = 3272597744303067026L; + /** + * 主键id + */ + private Long id; + + /** + * 会员id + */ + @ApiModelProperty(value = "会员id") + @Excel(name = "会员id") + private Long patientId; + + /** + * 护理员表id + */ + private Long nurseStationPersonId; + + /** + * 商品订单编号,系统自动生成 + */ + @ApiModelProperty(value = "商品订单编号,系统自动生成") + @Excel(name = "商品订单编号,系统自动生成") + private String orderNo; + + /** + * 支付标题 + */ + @ApiModelProperty(value = "支付标题") + @Excel(name = "支付标题") + private String paymentTitle; + + /** + * 交易流水号 + */ + @ApiModelProperty(value = "交易流水号") + @Excel(name = "交易流水号") + private String transactionNo; + + /** + * 支付金额(分) + */ + @ApiModelProperty(value = "支付金额") + @Excel(name = "支付金额", readConverterExp = "分=") + private BigDecimal payPrice; + + /** + * 支付类型,微信支付:WECHAT_PAY,支付宝支付:ALI_PAY + */ + @ApiModelProperty(value = "支付类型,微信支付:WECHAT_PAY,支付宝支付:ALI_PAY") + @Excel(name = "支付类型,微信支付:WECHAT_PAY,支付宝支付:ALI_PAY") + private String payType; + + /** + * 支付渠道,手机App:MOBILE_APP,微信小程序:WECHAT_APPLET,支付宝小程序:ALI_PAY_APPLET + */ + @ApiModelProperty(value = "支付渠道,手机App:MOBILE_APP,微信小程序:WECHAT_APPLET,支付宝小程序:ALI_PAY_APPLET") + @Excel(name = "支付渠道,手机App:MOBILE_APP,微信小程序:WECHAT_APPLET,支付宝小程序:ALI_PAY_APPLET") + private String payChannel; + + /** + * 微信支付交易状态,支付成功:SUCCESS,转入退款:REFUND,未支付:NOTPAY,已关闭:CLOSED,已撤销(付款码支付):REVOKED,用户支付中(付款码支付):USERPAYING,支付失败(其他原因,如银行返回失败):PAYERROR + */ + @ApiModelProperty(value = "微信支付交易状态,支付成功:SUCCESS,转入退款:REFUND,未支付:NOTPAY,已关闭:CLOSED,已撤销") + @Excel(name = "微信支付交易状态,支付成功:SUCCESS,转入退款:REFUND,未支付:NOTPAY,已关闭:CLOSED,已撤销", readConverterExp = "付=款码支付") + private String wechatTradeState; + + /** + * 支付宝交易状态,支付成功:SUCCESS,转入退款:REFUND,未支付:NOTPAY,已关闭:CLOSED,已撤销(付款码支付):REVOKED,用户支付中(付款码支付):USERPAYING,支付失败(其他原因,如银行返回失败):PAYERROR + */ + @ApiModelProperty(value = "支付宝交易状态,支付成功:SUCCESS,转入退款:REFUND,未支付:NOTPAY,已关闭:CLOSED,已撤销") + @Excel(name = "支付宝交易状态,支付成功:SUCCESS,转入退款:REFUND,未支付:NOTPAY,已关闭:CLOSED,已撤销", readConverterExp = "付=款码支付") + private String alipayTradeState; + + /** + * 支付通知参数内容,微信或者支付宝支付回调通知信息 + */ + @ApiModelProperty(value = "支付通知参数内容,微信或者支付宝支付回调通知信息") + @Excel(name = "支付通知参数内容,微信或者支付宝支付回调通知信息") + private String payNotifyContent; + + /** + * 支付时间 + */ + @ApiModelProperty(value = "支付时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime payTime; + + /** + * 支付账户类型,新医路账户:XINYILU,医路优品:YILUYOUPIN + */ + @ApiModelProperty(value = "支付账户类型,新医路账户:XINYILU,医路优品:YILUYOUPIN") + @Excel(name = "支付账户类型,新医路账户:XINYILU,医路优品:YILUYOUPIN") + private String paymentMerchantType; + + /** + * 是否删除,0:否,1:是 + */ + private Integer delFlag; + + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("patientId", getPatientId()) + .append("orderNo", getOrderNo()) + .append("paymentTitle", getPaymentTitle()) + .append("transactionNo", getTransactionNo()) + .append("payPrice", getPayPrice()) + .append("payType", getPayType()) + .append("payChannel", getPayChannel()) + .append("wechatTradeState", getWechatTradeState()) + .append("alipayTradeState", getAlipayTradeState()) + .append("payNotifyContent", getPayNotifyContent()) + .append("payTime", getPayTime()) + .append("paymentMerchantType", getPaymentMerchantType()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/refundinfo/RefundInfo.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/refundinfo/RefundInfo.java new file mode 100644 index 0000000..d87fd12 --- /dev/null +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/domain/refundinfo/RefundInfo.java @@ -0,0 +1,205 @@ +package com.xinelu.manage.domain.refundinfo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xinelu.common.annotation.Excel; +import com.xinelu.common.core.domain.BaseDomain; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 退款记录信息对象 refund_info + * + * @author xinyilu + * @date 2022-10-18 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "退款记录信息对象", description = "refund_info") +public class RefundInfo extends BaseDomain implements Serializable { + + private static final long serialVersionUID = -3202049270867033957L; + /** + * 主键id + */ + private Long id; + + /** + * 会员id + */ + @ApiModelProperty(value = "会员id") + @Excel(name = "会员id") + private Long patientId; + + /** + * 护理员表id + */ + private Long nurseStationPersonId; + + /** + * 商品订单号 + */ + @ApiModelProperty(value = "商品订单号") + @Excel(name = "商品订单号") + private String orderNo; + + /** + * 支付退款单号,多种支付方式共用 + */ + @ApiModelProperty(value = "支付退款单号,多种支付方式共用") + @Excel(name = "支付退款单号,多种支付方式共用") + private String refundNo; + + /** + * 商户退款单号,系统自动生成 + */ + @ApiModelProperty(value = "商户退款单号,系统自动生成") + @Excel(name = "商户退款单号,系统自动生成") + private String outRefundNo; + + /** + * 支付交易订单号,多种支付方式共用 + */ + @ApiModelProperty(value = "支付交易订单号,多种支付方式共用") + @Excel(name = "支付交易订单号,多种支付方式共用") + private String transactionNo; + + /** + * 退款原因 + */ + @ApiModelProperty(value = "退款原因") + @Excel(name = "退款原因") + private String refundReason; + + /** + * 退款方式,微信:WE_CHAT,支付宝:ALI_PAY + */ + @ApiModelProperty(value = "退款方式,微信:WE_CHAT,支付宝:ALI_PAY") + @Excel(name = "退款方式,微信:WE_CHAT,支付宝:ALI_PAY") + private String refundType; + + /** + * 微信退款状态,退款成功:SUCCESS,退款关闭:CLOSED,退款处理中:PROCESSING,退款异常:ABNORMAL + */ + @ApiModelProperty(value = "微信退款状态,退款成功:SUCCESS,退款关闭:CLOSED,退款处理中:PROCESSING,退款异常:ABNORMAL") + @Excel(name = "微信退款状态,退款成功:SUCCESS,退款关闭:CLOSED,退款处理中:PROCESSING,退款异常:ABNORMAL") + private String wechatRefundStatus; + + /** + * 支付宝退款状态,退款成功:SUCCESS,退款关闭:CLOSED,退款处理中:PROCESSING,退款异常:ABNORMAL + */ + @ApiModelProperty(value = "支付宝退款状态,退款成功:SUCCESS,退款关闭:CLOSED,退款处理中:PROCESSING,退款异常:ABNORMAL") + @Excel(name = "支付宝退款状态,退款成功:SUCCESS,退款关闭:CLOSED,退款处理中:PROCESSING,退款异常:ABNORMAL") + private String alipayRefundStatus; + + /** + * 订单金额(分) + */ + @ApiModelProperty(value = "订单金额") + @Excel(name = "订单金额", readConverterExp = "分=") + private BigDecimal orderTotalPrice; + + /** + * 退款金额(分) + */ + @ApiModelProperty(value = "退款金额") + @Excel(name = "退款金额", readConverterExp = "分=") + private BigDecimal refundPrice; + + /** + * 退款币种,人民币:CNY + */ + @ApiModelProperty(value = "退款币种,人民币:CNY") + @Excel(name = "退款币种,人民币:CNY") + private String currency; + + /** + * ORIGINAL:原路退款,BALANCE:退回到余额,OTHER_BALANCE:原账户异常退到其他余额账户,OTHER_BANKCARD:原银行卡异常退到其他银行卡 + */ + @ApiModelProperty(value = "ORIGINAL:原路退款,BALANCE:退回到余额,OTHER_BALANCE:原账户异常退到其他余额账户,OTHER_BANKCARD:原银行卡异常退到其他银行卡") + @Excel(name = "ORIGINAL:原路退款,BALANCE:退回到余额,OTHER_BALANCE:原账户异常退到其他余额账户,OTHER_BANKCARD:原银行卡异常退到其他银行卡") + private String channel; + + /** + * 退款入账账户 + */ + @ApiModelProperty(value = "退款入账账户") + @Excel(name = "退款入账账户") + private String userreceivedaccount; + + /** + * 退款成功时间 + */ + @ApiModelProperty(value = "退款成功时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "退款成功时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime successTime; + + /** + * 退款回调通知内容,微信或者支付款退款通知内容 + */ + @ApiModelProperty(value = "退款回调通知内容,微信或者支付款退款通知内容") + @Excel(name = "退款回调通知内容,微信或者支付款退款通知内容") + private String refundNotifyContent; + + /** + * 申请退款返回参数内容 + */ + @ApiModelProperty(value = "申请退款返回参数内容") + @Excel(name = "申请退款返回参数内容") + private String applyRefundReturnContent; + + /** + * 退款账户类型,新医路账户:XINYILU,医路优品:YILUYOUPIN + */ + @ApiModelProperty(value = "退款账户类型,新医路账户:XINYILU,医路优品:YILUYOUPIN") + @Excel(name = "退款账户类型,新医路账户:XINYILU,医路优品:YILUYOUPIN") + private String refundMerchantType; + + /** + * 是否删除,0:否,1:是 + */ + private Integer delFlag; + + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("patientId", getPatientId()) + .append("orderNo", getOrderNo()) + .append("refundNo", getRefundNo()) + .append("outRefundNo", getOutRefundNo()) + .append("transactionNo", getTransactionNo()) + .append("refundReason", getRefundReason()) + .append("refundType", getRefundType()) + .append("wechatRefundStatus", getWechatRefundStatus()) + .append("alipayRefundStatus", getAlipayRefundStatus()) + .append("orderTotalPrice", getOrderTotalPrice()) + .append("refundPrice", getRefundPrice()) + .append("currency", getCurrency()) + .append("channel", getChannel()) + .append("userreceivedaccount", getUserreceivedaccount()) + .append("successTime", getSuccessTime()) + .append("refundNotifyContent", getRefundNotifyContent()) + .append("applyRefundReturnContent", getApplyRefundReturnContent()) + .append("refundMerchantType", getRefundMerchantType()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/mapper/paymentinfo/PaymentInfoMapper.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/mapper/paymentinfo/PaymentInfoMapper.java new file mode 100644 index 0000000..39e5bc5 --- /dev/null +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/mapper/paymentinfo/PaymentInfoMapper.java @@ -0,0 +1,70 @@ +package com.xinelu.manage.mapper.paymentinfo; + +import com.xinelu.manage.domain.paymentinfo.PaymentInfo; + +import java.util.List; + + +/** + * 支付记录信息Mapper接口 + * + * @author xinyilu + * @date 2022-10-18 + */ +public interface PaymentInfoMapper { + /** + * 查询支付记录信息 + * + * @param id 支付记录信息主键 + * @return 支付记录信息 + */ + PaymentInfo selectPaymentInfoById(Long id); + + /** + * 查询支付记录信息列表 + * + * @param paymentInfo 支付记录信息 + * @return 支付记录信息集合 + */ + List selectPaymentInfoList(PaymentInfo paymentInfo); + + /** + * 新增支付记录信息 + * + * @param paymentInfo 支付记录信息 + * @return 结果 + */ + int insertPaymentInfo(PaymentInfo paymentInfo); + + /** + * 修改支付记录信息 + * + * @param paymentInfo 支付记录信息 + * @return 结果 + */ + int updatePaymentInfo(PaymentInfo paymentInfo); + + /** + * 删除支付记录信息 + * + * @param id 支付记录信息主键 + * @return 结果 + */ + int deletePaymentInfoById(Long id); + + /** + * 批量删除支付记录信息 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + int deletePaymentInfoByIds(Long[] ids); + + /** + * 根据订单查询支付记录表信息 + * + * @param orderNo 订单编号 + * @return 数量 + */ + int getPaymentInfoByOrderNo(String orderNo); +} diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/mapper/refundinfo/RefundInfoMapper.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/mapper/refundinfo/RefundInfoMapper.java new file mode 100644 index 0000000..60186c7 --- /dev/null +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/mapper/refundinfo/RefundInfoMapper.java @@ -0,0 +1,90 @@ +package com.xinelu.manage.mapper.refundinfo; + +import com.xinelu.manage.domain.refundinfo.RefundInfo; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 退款记录信息Mapper接口 + * + * @author xinyilu + * @date 2022-10-18 + */ +public interface RefundInfoMapper { + /** + * 查询退款记录信息 + * + * @param id 退款记录信息主键 + * @return 退款记录信息 + */ + RefundInfo selectRefundInfoById(Long id); + + /** + * 查询退款记录信息列表 + * + * @param refundInfo 退款记录信息 + * @return 退款记录信息集合 + */ + List selectRefundInfoList(RefundInfo refundInfo); + + /** + * 新增退款记录信息 + * + * @param refundInfo 退款记录信息 + * @return 结果 + */ + int insertRefundInfo(RefundInfo refundInfo); + + /** + * 修改退款记录信息 + * + * @param refundInfo 退款记录信息 + * @return 结果 + */ + int updateRefundInfo(RefundInfo refundInfo); + + /** + * 删除退款记录信息 + * + * @param id 退款记录信息主键 + * @return 结果 + */ + int deleteRefundInfoById(Long id); + + /** + * 批量删除退款记录信息 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + int deleteRefundInfoByIds(Long[] ids); + + /** + * 修改退款单信息 + * + * @param refundInfo 退款单信息 + * @return 更新数量 + */ + int updateRefundInfoByNo(RefundInfo refundInfo); + + /** + * 批量更新支付订单状态 + * + * @param orderNo 订单编号 + * @param successTime 退款成功时间 + * @param weChatRefundStatus 订单状态 + * @return 更新数量 + */ + int updateBatchRefundStatus(@Param("orderNo") String orderNo, @Param("successTime") LocalDateTime successTime, + @Param("weChatRefundStatus") String weChatRefundStatus); + + /** + * 根据订单编号查询支付退款表信息 + * + * @param orderNo 订单编号 + * @return 数量 + */ + int getRefundInfoByOrderNo(String orderNo); +} diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/appointmentorder/impl/AppointmentOrderServiceImpl.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/appointmentorder/impl/AppointmentOrderServiceImpl.java index e019e27..bc37003 100644 --- a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/appointmentorder/impl/AppointmentOrderServiceImpl.java +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/appointmentorder/impl/AppointmentOrderServiceImpl.java @@ -13,7 +13,6 @@ import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; import com.xinelu.manage.mapper.appointmentorderconsumable.AppointmentOrderConsumableMapper; import com.xinelu.manage.mapper.appointmentorderdetails.AppointmentOrderDetailsMapper; import com.xinelu.manage.service.appointmentorder.IAppointmentOrderService; -import com.xinelu.manage.service.stationmessagepush.StationMessagePushService; import com.xinelu.manage.vo.appointmentorder.AppointmentOrderVO; import com.xinelu.manage.vo.appointmentorder.PersonAndDepartmentVO; import lombok.extern.slf4j.Slf4j; @@ -42,8 +41,6 @@ public class AppointmentOrderServiceImpl implements IAppointmentOrderService { private AppointmentOrderDetailsMapper appointmentOrderDetailsMapper; @Resource private AppointmentOrderConsumableMapper appointmentOrderConsumableMapper; - @Resource - private StationMessagePushService stationMessagePushService; /** * 查询预约订单信息 @@ -178,7 +175,6 @@ public class AppointmentOrderServiceImpl implements IAppointmentOrderService { if (updateAppointmentOrderStatus <= 0) { throw new ServiceException("派单失败,请联系管理员!"); } - stationMessagePushService.waitReceiveMessagePush(appointmentOrder); return AjaxResult.success(); } diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/information/IInformationService.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/information/IInformationService.java index 3cb9498..c7ee467 100644 --- a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/information/IInformationService.java +++ b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/information/IInformationService.java @@ -61,4 +61,4 @@ public interface IInformationService { * @return 结果 */ int deleteInformationById(Long id); -} +} \ No newline at end of file diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/stationmessagepush/Impl/StationMessagePushServiceImpl.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/stationmessagepush/Impl/StationMessagePushServiceImpl.java deleted file mode 100644 index 8d06e5f..0000000 --- a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/stationmessagepush/Impl/StationMessagePushServiceImpl.java +++ /dev/null @@ -1,408 +0,0 @@ -package com.xinelu.manage.service.stationmessagepush.Impl; - -import com.alibaba.fastjson2.JSON; -import com.xinelu.common.config.NurseAppletChatConfig; -import com.xinelu.common.config.NurseAppletPageConfig; -import com.xinelu.common.constant.Constants; -import com.xinelu.common.entity.AppletAccessToken; -import com.xinelu.common.entity.MessageValueEntity; -import com.xinelu.common.enums.AppletSubscriptionMessageEnum; -import com.xinelu.common.enums.SubscribeStatusEnum; -import com.xinelu.common.utils.AppletChatUtil; -import com.xinelu.common.utils.http.HttpUtils; -import com.xinelu.manage.domain.appointmentorder.AppointmentOrder; -import com.xinelu.manage.domain.personsubscribemessage.PersonSubscribeMessage; -import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; -import com.xinelu.manage.mapper.personsubscribemessage.PersonSubscribeMessageMapper; -import com.xinelu.manage.service.stationmessagepush.StationMessagePushService; -import com.xinelu.manage.vo.appointmentorder.AppointmentOrderInfoVO; -import com.xinelu.manage.vo.appointmentorder.AppointmentOrderRecordVO; -import com.xinelu.manage.vo.appointmentorder.AppointmentReceivingOrderVO; -import com.xinelu.manage.vo.personsubscribemessage.PersonSubscribeMessageVO; -import com.xinelu.manage.vo.stationmessagepush.WaitReceiveMessagePushVO; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.math.BigDecimal; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import java.util.*; - -/** - * 派单消息推送业务层 - * - * @author zh - */ -@Slf4j -@Service -public class StationMessagePushServiceImpl implements StationMessagePushService { - - @Resource - private NurseAppletChatConfig nurseAppletChatConfig; - @Resource - private PersonSubscribeMessageMapper personSubscribeMessageMapper; - @Resource - private AppointmentOrderMapper appointmentOrderMapper; - @Resource - private NurseAppletPageConfig nurseAppletPageConfig; - - /** - * 微信消息推送url - */ - private static final String MESSAGE_PUSH_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="; - - /** - * 派单后提醒护理员接单消息推送 - * - * @param appointmentOrder 订单信息 - */ - @Override - @Async("asyncThreadServiceExecutor") - public void waitReceiveMessagePush(AppointmentOrder appointmentOrder) { - log.info("待接单消息提醒,订单参数:{}", appointmentOrder); - //获取AppletAccessToken的值 - AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(nurseAppletChatConfig.getAppletId(), nurseAppletChatConfig.getSecret()); - if (Objects.isNull(appletAccessToken)) { - log.error("获取微信小程序accessToken信息失败!"); - return; - } - if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != AppletSubscriptionMessageEnum.SUCCESS_ERRCODE.getValue()) { - log.error("获取微信小程序accessToken信息失败,失败信息为:" + appletAccessToken.getErrmsg(), 201); - return; - } - if (StringUtils.isBlank(appletAccessToken.getAccessToken())) { - log.error("accessToken信息为空!"); - return; - } - //获取用户信息、订阅消息记录、规则信息 - PersonSubscribeMessage personSubscribeMessage = personSubscribeMessageMapper - .selectPersonSubscribeMessageByPatientId(appointmentOrder.getNurseStationPersonId(), null, nurseAppletChatConfig.getReceivingOrdersNurseTemplateId()); - if (Objects.isNull(personSubscribeMessage) || StringUtils.isBlank(personSubscribeMessage.getOpenid()) || StringUtils.isBlank(personSubscribeMessage.getSubscribeStatus()) || !SubscribeStatusEnum.ACCEPT.getInfo().equals(personSubscribeMessage.getSubscribeStatus())) { - return; - } - WaitReceiveMessagePushVO waitReceiveOrderDetails = appointmentOrderMapper.selectOrderDetailsAndPatientBy(appointmentOrder.getOrderNo()); - if (Objects.isNull(waitReceiveOrderDetails)) { - return; - } - this.waitReceiveMessage(waitReceiveOrderDetails, personSubscribeMessage, appletAccessToken); - } - - - /** - * 待接单消息推送 - * - * @param appletAccessToken 令牌 - * @param dispatchOrderDetails 订单信息 - * @param personSubscribeMessage 订阅消息记录 - */ - @Override - public void waitReceiveMessage(WaitReceiveMessagePushVO dispatchOrderDetails, PersonSubscribeMessage personSubscribeMessage, AppletAccessToken appletAccessToken) { - //模板参数、用户openid、推送消息模板id - Map paramsMap = new LinkedHashMap<>(); - paramsMap.put("touser", personSubscribeMessage.getOpenid()); - paramsMap.put("template_id", nurseAppletChatConfig.getReceivingOrdersNurseTemplateId()); - paramsMap.put("page", nurseAppletPageConfig.getWorkPageUrl()); - String serviceDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(Objects.isNull(dispatchOrderDetails.getServiceDate()) ? LocalDate.now() : dispatchOrderDetails.getServiceDate()); - LocalTime serviceStartTime = Objects.isNull(dispatchOrderDetails.getServiceStartTime()) ? LocalTime.now() : dispatchOrderDetails.getServiceStartTime(); - //模板内容 - Map messageValueEntityMap = new LinkedHashMap<>(); - messageValueEntityMap.put("thing2", new MessageValueEntity(StringUtils.isBlank(dispatchOrderDetails.getNurseItemName()) ? "" : dispatchOrderDetails.getNurseItemName())); - String serviceAddress = StringUtils.isBlank(dispatchOrderDetails.getServiceAddress()) ? "" : dispatchOrderDetails.getServiceAddress(); - if (StringUtils.isNotBlank(serviceAddress) && dispatchOrderDetails.getServiceAddress().length() > 20) { - serviceAddress = dispatchOrderDetails.getServiceAddress().substring(0, 19); - } - messageValueEntityMap.put("thing6", new MessageValueEntity(serviceAddress)); - messageValueEntityMap.put("time16", new MessageValueEntity(serviceDate + " " + serviceStartTime)); - messageValueEntityMap.put("thing7", new MessageValueEntity(StringUtils.isBlank(dispatchOrderDetails.getPatientName()) ? "" : dispatchOrderDetails.getPatientName())); - messageValueEntityMap.put("phone_number8", new MessageValueEntity(StringUtils.isBlank(dispatchOrderDetails.getPhone()) ? "" : dispatchOrderDetails.getPhone())); - paramsMap.put("data", messageValueEntityMap); - this.sendPosts(appletAccessToken, paramsMap); - } - - - /** - * 服务派单通知运营人员 - * - * @param appointmentOrderInfo 订单信息表 - **/ - @Override - @Async("asyncThreadServiceExecutor") - public void serviceDispatchOperationsPush(AppointmentOrderInfoVO appointmentOrderInfo) { - log.info("预定订单下单派单消息提醒,订单参数:{}", appointmentOrderInfo); - //根据护理人员id去查询护理人员角色是否是护理站管理人员 - List personSubscribe = personSubscribeMessageMapper.selectPersonSubscribeMessageByPersonWechatId(appointmentOrderInfo.getNurseStationId(), null, null, nurseAppletChatConfig.getServiceDispatchOperationsTemplateId()); - if (CollectionUtils.isEmpty(personSubscribe)) { - return; - } - //循环发送 - AppletAccessToken appletAccessToken = getAppletAccessToken(); - for (PersonSubscribeMessageVO personSubscribeMessage : personSubscribe) { - boolean subscribeMessage = Objects.nonNull(personSubscribeMessage) - && StringUtils.isNotBlank(personSubscribeMessage.getSubscribeStatus()) - && SubscribeStatusEnum.ACCEPT.getInfo().equals(personSubscribeMessage.getSubscribeStatus()); - if (BooleanUtils.isTrue(subscribeMessage)) { - //构建微信小程序消息推送参数 - Map paramsMap = new LinkedHashMap<>(); - paramsMap.put("template_id", StringUtils.isBlank(personSubscribeMessage.getTemplateId()) ? "" : personSubscribeMessage.getTemplateId()); - paramsMap.put("page", nurseAppletPageConfig.getNursePageUrl()); - paramsMap.put("touser", StringUtils.isBlank(personSubscribeMessage.getOpenid()) ? "" : personSubscribeMessage.getOpenid()); - paramsMap.put("lang", "zh_CN"); - //构建微信小程序消息推送内容参数 - Map amountParamMap = new HashMap<>(); - //服务项目 - amountParamMap.put("thing2", new MessageValueEntity(StringUtils.isBlank(appointmentOrderInfo.getNurseItemName()) ? "" : appointmentOrderInfo.getNurseItemName())); - //服务信息 - amountParamMap.put("thing3", new MessageValueEntity(StringUtils.isBlank(appointmentOrderInfo.getItemServeDurationUnit()) ? "" : appointmentOrderInfo.getItemServeDurationUnit())); - //订单编号 - amountParamMap.put("character_string13", new MessageValueEntity(StringUtils.isBlank(appointmentOrderInfo.getOrderNo()) ? "" : appointmentOrderInfo.getOrderNo())); - //上门时间 - String serviceDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(Objects.isNull(appointmentOrderInfo.getServiceDate()) ? LocalDate.now() : appointmentOrderInfo.getServiceDate()); - LocalTime serviceStartTime = Objects.isNull(appointmentOrderInfo.getServiceStartTime()) ? LocalTime.now() : appointmentOrderInfo.getServiceStartTime(); - amountParamMap.put("time24", new MessageValueEntity(serviceDate + " " + serviceStartTime)); - //上门地址 - String serviceAddress = StringUtils.isBlank(appointmentOrderInfo.getServiceAddress()) ? "" : appointmentOrderInfo.getServiceAddress(); - if (StringUtils.isNotBlank(serviceAddress) && appointmentOrderInfo.getServiceAddress().length() > 20) { - serviceAddress = appointmentOrderInfo.getServiceAddress().substring(0, 19); - } - amountParamMap.put("thing25", new MessageValueEntity(serviceAddress)); - paramsMap.put("data", amountParamMap); - //发送 - this.sendPosts(appletAccessToken, paramsMap); - } - } - } - - /** - * 接单提醒通知运营人员 - * - * @param appointmentReceivingOrder 订单信息表 - **/ - @Override - @Async("asyncThreadServiceExecutor") - public void receivingOrdersOperationsPush(AppointmentReceivingOrderVO appointmentReceivingOrder) { - //根据护理人员id去查询护理人员角色是否是护理站管理人员 - log.info("预约订单接单消息提醒,订单参数:{}", appointmentReceivingOrder); - List personSubscribe = personSubscribeMessageMapper.selectPersonSubscribeMessageByPersonWechatId(appointmentReceivingOrder.getNurseStationId(), null, null, nurseAppletChatConfig.getReceivingOrdersOperationsTemplateId()); - if (CollectionUtils.isEmpty(personSubscribe)) { - return; - } - //循环发送 - AppletAccessToken appletAccessToken = getAppletAccessToken(); - for (PersonSubscribeMessageVO personSubscribeMessage : personSubscribe) { - boolean subscribeMessage = Objects.nonNull(personSubscribeMessage) - && StringUtils.isNotBlank(personSubscribeMessage.getSubscribeStatus()) - && SubscribeStatusEnum.ACCEPT.getInfo().equals(personSubscribeMessage.getSubscribeStatus()); - if (BooleanUtils.isTrue(subscribeMessage)) { - //构建微信小程序消息推送参数 - Map paramsMap = new LinkedHashMap<>(); - paramsMap.put("template_id", StringUtils.isBlank(personSubscribeMessage.getTemplateId()) ? "" : personSubscribeMessage.getTemplateId()); - paramsMap.put("page", nurseAppletPageConfig.getNursePageUrl()); - paramsMap.put("touser", StringUtils.isBlank(personSubscribeMessage.getOpenid()) ? "" : personSubscribeMessage.getOpenid()); - paramsMap.put("lang", "zh_CN"); - //构建微信小程序消息推送内容参数 - Map amountParamMap = new HashMap<>(); - //服务师傅 - amountParamMap.put("thing15", new MessageValueEntity(StringUtils.isBlank(appointmentReceivingOrder.getNursePersonName()) ? "" : appointmentReceivingOrder.getNursePersonName())); - //预约时间 - String serviceDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(Objects.isNull(appointmentReceivingOrder.getServiceDate()) ? LocalDate.now() : appointmentReceivingOrder.getServiceDate()); - LocalTime serviceStartTime = Objects.isNull(appointmentReceivingOrder.getServiceStartTime()) ? LocalTime.now() : appointmentReceivingOrder.getServiceStartTime(); - amountParamMap.put("time11", new MessageValueEntity(serviceDate + " " + serviceStartTime)); - //地点 - String serviceAddress = StringUtils.isBlank(appointmentReceivingOrder.getServiceAddress()) ? "" : appointmentReceivingOrder.getServiceAddress(); - if (StringUtils.isNotBlank(serviceAddress) && appointmentReceivingOrder.getServiceAddress().length() > 20) { - serviceAddress = appointmentReceivingOrder.getServiceAddress().substring(0, 19); - } - amountParamMap.put("thing9", new MessageValueEntity(serviceAddress)); - //电话 - amountParamMap.put("phone_number8", new MessageValueEntity(StringUtils.isBlank(appointmentReceivingOrder.getPhone()) ? "" : appointmentReceivingOrder.getPhone())); - //业主 - amountParamMap.put("thing7", new MessageValueEntity(StringUtils.isBlank(appointmentReceivingOrder.getPatientName()) ? "" : appointmentReceivingOrder.getPatientName())); - paramsMap.put("data", amountParamMap); - //发送 - this.sendPosts(appletAccessToken, paramsMap); - } - } - } - - /** - * 拒单通知运营人员 - * - * @param appointmentReceivingOrder 订单信息表 - **/ - @Override - @Async("asyncThreadServiceExecutor") - public void refusalOrdersOperationsPush(AppointmentReceivingOrderVO appointmentReceivingOrder) { - //根据护理人员id去查询护理人员角色是否是护理站管理人员 - log.info("预约订单拒单消息提醒,订单参数:{}", appointmentReceivingOrder); - List personSubscribe = personSubscribeMessageMapper.selectPersonSubscribeMessageByPersonWechatId(appointmentReceivingOrder.getNurseStationId(), null, null, nurseAppletChatConfig.getRefusalOrdersOperationsTemplateId()); - if (CollectionUtils.isEmpty(personSubscribe)) { - return; - } - //循环发送 - AppletAccessToken appletAccessToken = getAppletAccessToken(); - for (PersonSubscribeMessageVO personSubscribeMessage : personSubscribe) { - boolean subscribeMessage = Objects.nonNull(personSubscribeMessage) - && StringUtils.isNotBlank(personSubscribeMessage.getSubscribeStatus()) - && SubscribeStatusEnum.ACCEPT.getInfo().equals(personSubscribeMessage.getSubscribeStatus()); - if (BooleanUtils.isTrue(subscribeMessage)) { - //构建微信小程序消息推送参数 - Map paramsMap = new LinkedHashMap<>(); - paramsMap.put("template_id", StringUtils.isBlank(personSubscribeMessage.getTemplateId()) ? "" : personSubscribeMessage.getTemplateId()); - paramsMap.put("page", nurseAppletPageConfig.getNursePageUrl()); - paramsMap.put("touser", StringUtils.isBlank(personSubscribeMessage.getOpenid()) ? "" : personSubscribeMessage.getOpenid()); - paramsMap.put("lang", "zh_CN"); - //构建微信小程序消息推送内容参数 - Map amountParamMap = new HashMap<>(); - //订单编号 - amountParamMap.put("character_string3", new MessageValueEntity(StringUtils.isBlank(appointmentReceivingOrder.getOrderNo()) ? "" : appointmentReceivingOrder.getOrderNo())); - //服务内容 - amountParamMap.put("thing1", new MessageValueEntity(StringUtils.isBlank(appointmentReceivingOrder.getNurseItemName()) ? "" : appointmentReceivingOrder.getNurseItemName())); - //服务时间 - String serviceDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(Objects.isNull(appointmentReceivingOrder.getServiceDate()) ? LocalDate.now() : appointmentReceivingOrder.getServiceDate()); - LocalTime serviceStartTime = Objects.isNull(appointmentReceivingOrder.getServiceStartTime()) ? LocalTime.now() : appointmentReceivingOrder.getServiceStartTime(); - amountParamMap.put("time4", new MessageValueEntity(serviceDate + " " + serviceStartTime)); - //服务地点 - String serviceAddress = StringUtils.isBlank(appointmentReceivingOrder.getServiceAddress()) ? "" : appointmentReceivingOrder.getServiceAddress(); - if (StringUtils.isNotBlank(serviceAddress) && appointmentReceivingOrder.getServiceAddress().length() > 20) { - serviceAddress = appointmentReceivingOrder.getServiceAddress().substring(0, 19); - } - amountParamMap.put("thing5", new MessageValueEntity(serviceAddress)); - //拒单理由 - String taskReturnReason = StringUtils.isBlank(appointmentReceivingOrder.getTaskReturnReason()) ? "" : appointmentReceivingOrder.getTaskReturnReason(); - String[] split = StringUtils.split(taskReturnReason, ";"); - if (split.length > 0) { - taskReturnReason = split[0]; - if (StringUtils.isNotBlank(taskReturnReason) && taskReturnReason.length() > 20) { - taskReturnReason = taskReturnReason.substring(0, 19); - } - } - amountParamMap.put("thing6", new MessageValueEntity(taskReturnReason)); - paramsMap.put("data", amountParamMap); - //发送 - this.sendPosts(appletAccessToken, paramsMap); - } - } - } - - /** - * 订单完成通知运营人员 - * - * @param appointmentOrderRecordVO 订单信息表 - **/ - @Override - @Async("asyncThreadServiceExecutor") - public void orderCompletionOperationsPush(AppointmentOrderRecordVO appointmentOrderRecordVO) { - //根据护理人员id去查询护理人员角色是否是护理站管理人员 - log.info("预约订单完成消息提醒,订单参数:{}", appointmentOrderRecordVO); - List personSubscribe = personSubscribeMessageMapper.selectPersonSubscribeMessageByPersonWechatId(appointmentOrderRecordVO.getNurseStationId(), null, null, nurseAppletChatConfig.getOrderCompletionOperationsTemplateId()); - if (CollectionUtils.isEmpty(personSubscribe)) { - return; - } - //循环发送 - AppletAccessToken appletAccessToken = getAppletAccessToken(); - for (PersonSubscribeMessageVO personSubscribeMessage : personSubscribe) { - boolean subscribeMessage = Objects.nonNull(personSubscribeMessage) - && StringUtils.isNotBlank(personSubscribeMessage.getSubscribeStatus()) - && SubscribeStatusEnum.ACCEPT.getInfo().equals(personSubscribeMessage.getSubscribeStatus()); - if (BooleanUtils.isTrue(subscribeMessage)) { - //构建微信小程序消息推送参数 - Map paramsMap = new LinkedHashMap<>(); - paramsMap.put("template_id", StringUtils.isBlank(personSubscribeMessage.getTemplateId()) ? "" : personSubscribeMessage.getTemplateId()); - paramsMap.put("page", nurseAppletPageConfig.getNursePageUrl()); - paramsMap.put("touser", StringUtils.isBlank(personSubscribeMessage.getOpenid()) ? "" : personSubscribeMessage.getOpenid()); - paramsMap.put("lang", "zh_CN"); - //构建微信小程序消息推送内容参数 - Map amountParamMap = new HashMap<>(); - //订单编号 - amountParamMap.put("character_string5", new MessageValueEntity(StringUtils.isBlank(appointmentOrderRecordVO.getOrderNo()) ? "" : appointmentOrderRecordVO.getOrderNo())); - //服务内容 - amountParamMap.put("thing6", new MessageValueEntity(StringUtils.isBlank(appointmentOrderRecordVO.getNurseItemName()) ? "" : appointmentOrderRecordVO.getNurseItemName())); - //服务金额 - BigDecimal totalPrice = Objects.isNull(appointmentOrderRecordVO.getTotalPrice()) ? BigDecimal.ZERO : appointmentOrderRecordVO.getTotalPrice(); - amountParamMap.put("amount8", new MessageValueEntity(totalPrice + "元")); - //骑手和电话 - amountParamMap.put("thing21", new MessageValueEntity((StringUtils.isBlank(appointmentOrderRecordVO.getNursePersonName()) ? "" : appointmentOrderRecordVO.getNursePersonName()) + " " + (StringUtils.isBlank(appointmentOrderRecordVO.getPhone()) ? "" : appointmentOrderRecordVO.getPhone()))); - //订单地址 - String serviceAddress = StringUtils.isBlank(appointmentOrderRecordVO.getServiceAddress()) ? "" : appointmentOrderRecordVO.getServiceAddress(); - if (StringUtils.isNotBlank(serviceAddress) && appointmentOrderRecordVO.getServiceAddress().length() > 20) { - serviceAddress = appointmentOrderRecordVO.getServiceAddress().substring(0, 19); - } - amountParamMap.put("thing1", new MessageValueEntity(serviceAddress)); - paramsMap.put("data", amountParamMap); - //发送 - this.sendPosts(appletAccessToken, paramsMap); - } - } - } - - - /** - * 获取appletAccessToken - * - * @return com.xinyilu.common.entity.AppletAccessToken - **/ - private AppletAccessToken getAppletAccessToken() { - //获取AppletAccessToken的值 - AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(nurseAppletChatConfig.getAppletId(), nurseAppletChatConfig.getSecret()); - if (Objects.isNull(appletAccessToken)) { - log.error("获取微信小程序accessToken信息失败!"); - } - if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != AppletSubscriptionMessageEnum.SUCCESS_ERRCODE.getValue()) { - log.error("获取微信小程序accessToken信息失败,失败信息为:" + appletAccessToken.getErrmsg(), 201); - } - if (StringUtils.isBlank(appletAccessToken.getAccessToken())) { - log.error("accessToken信息为空!"); - } - return appletAccessToken; - } - - - /** - * 发送 - * - * @param appletAccessToken 令牌 - * @param paramsMap 模板 - **/ - @Override - public void sendPosts(AppletAccessToken appletAccessToken, Map paramsMap) { - //拼接请求地址并发送 - String messageUrl = MESSAGE_PUSH_URL + appletAccessToken.getAccessToken(); - String param = JSON.toJSONString(paramsMap); - String result = HttpUtils.sendPostJson(messageUrl, param); - //返回参数映射 - AppletAccessToken errCode = JSON.parseObject(result, AppletAccessToken.class); - if (Objects.nonNull(errCode) && Objects.nonNull(errCode.getErrcode())) { - switch (errCode.getErrcode()) { - case Constants.SUCCESS_ERRCODE: - log.info("发送消息成功!"); - break; - case Constants.INVALID_CREDENTIAL_ACCESS_TOKEN_ISINVALID_OR_NOT_LATEST: - log.error("取 access_token 时 AppSecret 错误,或者 access_token 无效!"); - break; - case Constants.INVALID_OPENID: - log.error("不合法的 OpenId!"); - break; - case Constants.INVALID_ACCESS_TOKEN: - log.error("合法的 access_token!"); - break; - case Constants.INVALID_TEMPLATE_ID: - log.error("不合法的 template_id!"); - break; - case Constants.ARGUMENT_INVALID: - log.error("参数无效!"); - break; - case Constants.DENY_SUBSCRIPTION: - log.error("用户拒接订阅!"); - break; - default: - break; - } - } - } -} diff --git a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/stationmessagepush/StationMessagePushService.java b/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/stationmessagepush/StationMessagePushService.java deleted file mode 100644 index eb3ce10..0000000 --- a/xinelu-nurse-manage/src/main/java/com/xinelu/manage/service/stationmessagepush/StationMessagePushService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.xinelu.manage.service.stationmessagepush; - - - -import com.xinelu.common.entity.AppletAccessToken; -import com.xinelu.manage.domain.appointmentorder.AppointmentOrder; -import com.xinelu.manage.domain.personsubscribemessage.PersonSubscribeMessage; -import com.xinelu.manage.vo.appointmentorder.AppointmentOrderInfoVO; -import com.xinelu.manage.vo.appointmentorder.AppointmentOrderRecordVO; -import com.xinelu.manage.vo.appointmentorder.AppointmentReceivingOrderVO; -import com.xinelu.manage.vo.stationmessagepush.WaitReceiveMessagePushVO; - -import java.util.Map; - -/** - * 派单消息推送Service接口 - * - * @author zh - * @date 2023-04-03 - */ -public interface StationMessagePushService { - /** - * 派单后提醒护理员接单提醒 - * - * @param appointmentOrder 订单信息 - */ - void waitReceiveMessagePush(AppointmentOrder appointmentOrder); - - /** - * 服务代派单通知运营人员 - * - * @param appointmentOrderInfo 订单信息表 - **/ - void serviceDispatchOperationsPush(AppointmentOrderInfoVO appointmentOrderInfo); - - /** - * 接单提醒通知运营人员 - * - * @param appointmentReceivingOrder 订单信息表 - **/ - void receivingOrdersOperationsPush(AppointmentReceivingOrderVO appointmentReceivingOrder); - - /** - * 拒单通知运营人员 - * - * @param appointmentReceivingOrder 订单信息表 - **/ - void refusalOrdersOperationsPush(AppointmentReceivingOrderVO appointmentReceivingOrder); - - /** - * 订单完成通知运营人员 - * - * @param appointmentOrderRecordVO 订单信息表 - **/ - void orderCompletionOperationsPush(AppointmentOrderRecordVO appointmentOrderRecordVO); - - /** - * 发送 - * - * @param appletAccessToken 令牌 - * @param paramsMap 模板 - **/ - void sendPosts(AppletAccessToken appletAccessToken, Map paramsMap); - - /** - * 待接单消息推送 - * - * @param appletAccessToken 令牌 - * @param dispatchOrderDetails 订单信息 - * @param personSubscribeMessage 订阅消息记录 - */ - void waitReceiveMessage(WaitReceiveMessagePushVO dispatchOrderDetails, PersonSubscribeMessage personSubscribeMessage, AppletAccessToken appletAccessToken); -} diff --git a/xinelu-nurse-manage/src/main/resources/mapper/manage/goodsOrder/GoodsOrderMapper.xml b/xinelu-nurse-manage/src/main/resources/mapper/manage/goodsOrder/GoodsOrderMapper.xml index 75cfa51..1e4821c 100644 --- a/xinelu-nurse-manage/src/main/resources/mapper/manage/goodsOrder/GoodsOrderMapper.xml +++ b/xinelu-nurse-manage/src/main/resources/mapper/manage/goodsOrder/GoodsOrderMapper.xml @@ -34,6 +34,7 @@ + @@ -117,7 +118,8 @@ original_total_price, health_consultation_content, health_appoint_date, - hospital_person_name + hospital_person_name, + consultation_info_id from goods_order @@ -273,6 +275,8 @@ hospital_person_name, + consultation_info_id, + #{nurseStationId}, @@ -331,6 +335,8 @@ #{hospitalPersonName}, + #{consultationInfoId}, + @@ -421,6 +427,9 @@ hospital_person_name = #{hospitalPersonName}, + consultation_info_id = + #{consultationInfoId}, + where id = #{id} diff --git a/xinelu-nurse-manage/src/main/resources/mapper/manage/hospitalpersoninfo/HospitalPersonInfoMapper.xml b/xinelu-nurse-manage/src/main/resources/mapper/manage/hospitalpersoninfo/HospitalPersonInfoMapper.xml index 1932e78..6ff9497 100644 --- a/xinelu-nurse-manage/src/main/resources/mapper/manage/hospitalpersoninfo/HospitalPersonInfoMapper.xml +++ b/xinelu-nurse-manage/src/main/resources/mapper/manage/hospitalpersoninfo/HospitalPersonInfoMapper.xml @@ -22,6 +22,8 @@ + + @@ -71,6 +73,8 @@ person_introduce, person_sort, person_picture_url, + person_account, + person_password, create_by, create_time, update_by, @@ -238,6 +242,10 @@ person_picture_url, + person_account, + + person_password, + create_by, create_time, @@ -270,6 +278,10 @@ #{personPictureUrl}, + #{personAccount}, + + #{personPassword}, + #{createBy}, #{createTime}, @@ -316,6 +328,12 @@ person_picture_url = #{personPictureUrl}, + person_account = + #{personAccount}, + + person_password = + #{personPassword}, + create_by = #{createBy}, @@ -367,6 +385,12 @@ person_picture_url = #{personPictureUrl}, + person_account = + #{personAccount}, + + person_password = + #{personPassword}, + create_by = #{createBy}, diff --git a/xinelu-nurse-manage/src/main/resources/mapper/manage/orderevaluateinfo/OrderEvaluateInfoMapper.xml b/xinelu-nurse-manage/src/main/resources/mapper/manage/orderevaluateinfo/OrderEvaluateInfoMapper.xml index 8a0b86c..0abd8a7 100644 --- a/xinelu-nurse-manage/src/main/resources/mapper/manage/orderevaluateinfo/OrderEvaluateInfoMapper.xml +++ b/xinelu-nurse-manage/src/main/resources/mapper/manage/orderevaluateinfo/OrderEvaluateInfoMapper.xml @@ -194,8 +194,8 @@ composite_score = #{compositeScore}, - - order_source = #{orderSource}, + order_source = + #{orderSource}, create_by = #{createBy}, diff --git a/xinelu-nurse-manage/src/main/resources/mapper/manage/patientinfo/PatientInfoMapper.xml b/xinelu-nurse-manage/src/main/resources/mapper/manage/patientinfo/PatientInfoMapper.xml index dbc2589..dc50793 100644 --- a/xinelu-nurse-manage/src/main/resources/mapper/manage/patientinfo/PatientInfoMapper.xml +++ b/xinelu-nurse-manage/src/main/resources/mapper/manage/patientinfo/PatientInfoMapper.xml @@ -42,6 +42,10 @@ + + + + @@ -77,7 +81,11 @@ del_flag, personal_wechat_code_url, disabling_condition, - disabling_reason + disabling_reason, + disease, + city_code, + binding_time, + is_checked from patient_info @@ -289,6 +297,14 @@ disabling_reason, + disease, + + city_code, + + binding_time, + + is_checked, + #{communityCode}, @@ -361,6 +377,14 @@ #{disablingReason}, + #{disease}, + + #{cityCode}, + + #{bindingTime}, + + #{isChecked}, + @@ -472,6 +496,18 @@ disabling_reason = #{disablingReason}, + disease = + #{disease}, + + city_code = + #{cityCode}, + + binding_time = + #{bindingTime}, + + is_checked = + #{isChecked}, + where id = #{id} diff --git a/xinelu-nurse-manage/src/main/resources/mapper/manage/paymentinfo/PaymentInfoMapper.xml b/xinelu-nurse-manage/src/main/resources/mapper/manage/paymentinfo/PaymentInfoMapper.xml new file mode 100644 index 0000000..0dd3544 --- /dev/null +++ b/xinelu-nurse-manage/src/main/resources/mapper/manage/paymentinfo/PaymentInfoMapper.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + select id, + patient_id, + nurse_station_person_id, + order_no, + payment_title, + transaction_no, + pay_price, + pay_type, + pay_channel, + wechat_trade_state, + alipay_trade_state, + pay_notify_content, + pay_time, + payment_merchant_type, + del_flag, + create_by, + create_time, + update_by, + update_time + from payment_info + + + + + + + + insert into payment_info + + patient_id, + + nurse_station_person_id, + + order_no, + + payment_title, + + transaction_no, + + pay_price, + + pay_type, + + pay_channel, + + wechat_trade_state, + + alipay_trade_state, + + pay_notify_content, + + pay_time, + + payment_merchant_type, + + del_flag, + + create_by, + + create_time, + + update_by, + + update_time, + + + + #{patientId}, + + #{nurseStationPersonId}, + + #{orderNo}, + + #{paymentTitle}, + + #{transactionNo}, + + #{payPrice}, + + #{payType}, + + #{payChannel}, + + #{wechatTradeState}, + + #{alipayTradeState}, + + #{payNotifyContent}, + + #{payTime}, + + #{paymentMerchantType}, + + #{delFlag}, + + #{createBy}, + + #{createTime}, + + #{updateBy}, + + #{updateTime}, + + + + + + update payment_info + + patient_id = + #{patientId}, + + nurse_station_person_id = + #{nurseStationPersonId}, + + order_no = + #{orderNo}, + + payment_title = + #{paymentTitle}, + + transaction_no = + #{transactionNo}, + + pay_price = + #{payPrice}, + + pay_type = + #{payType}, + + pay_channel = + #{payChannel}, + + wechat_trade_state = + #{wechatTradeState}, + + alipay_trade_state = + #{alipayTradeState}, + + pay_notify_content = + #{payNotifyContent}, + + pay_time = + #{payTime}, + + payment_merchant_type = + #{paymentMerchantType}, + + del_flag = + #{delFlag}, + + create_by = + #{createBy}, + + create_time = + #{createTime}, + + update_by = + #{updateBy}, + + update_time = + #{updateTime}, + + + where id = #{id} + + + + delete + from payment_info + where id = #{id} + + + + delete from payment_info where id in + + #{id} + + + + + diff --git a/xinelu-nurse-manage/src/main/resources/mapper/manage/refundinfo/RefundInfoMapper.xml b/xinelu-nurse-manage/src/main/resources/mapper/manage/refundinfo/RefundInfoMapper.xml new file mode 100644 index 0000000..2caaa99 --- /dev/null +++ b/xinelu-nurse-manage/src/main/resources/mapper/manage/refundinfo/RefundInfoMapper.xml @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select id, + patient_id, + nurse_station_person_id, + order_no, + refund_no, + out_refund_no, + transaction_no, + refund_reason, + refund_type, + wechat_refund_status, + alipay_refund_status, + order_total_price, + refund_price, + currency, + channel, + userReceivedAccount, + success_time, + refund_notify_content, + apply_refund_return_content, + refund_merchant_type, + del_flag, + create_by, + create_time, + update_by, + update_time + from refund_info + + + + + + + + insert into refund_info + + patient_id, + + nurse_station_person_id, + + order_no, + + refund_no, + + out_refund_no, + + transaction_no, + + refund_reason, + + refund_type, + + wechat_refund_status, + + alipay_refund_status, + + order_total_price, + + refund_price, + + currency, + + channel, + + userReceivedAccount, + + success_time, + + refund_notify_content, + + apply_refund_return_content, + + refund_merchant_type, + + del_flag, + + create_by, + + create_time, + + update_by, + + update_time, + + + + #{patientId}, + + #{nurseStationPersonId}, + + #{orderNo}, + + #{refundNo}, + + #{outRefundNo}, + + #{transactionNo}, + + #{refundReason}, + + #{refundType}, + + #{wechatRefundStatus}, + + #{alipayRefundStatus}, + + #{orderTotalPrice}, + + #{refundPrice}, + + #{currency}, + + #{channel}, + + #{userreceivedaccount}, + + #{successTime}, + + #{refundNotifyContent}, + + #{applyRefundReturnContent}, + + #{refundMerchantType}, + + #{delFlag}, + + #{createBy}, + + #{createTime}, + + #{updateBy}, + + #{updateTime}, + + + + + + update refund_info + + patient_id = + #{patientId}, + + nurse_station_person_id = + #{nurseStationPersonId}, + + order_no = + #{orderNo}, + + refund_no = + #{refundNo}, + + out_refund_no = + #{outRefundNo}, + + transaction_no = + #{transactionNo}, + + refund_reason = + #{refundReason}, + + refund_type = + #{refundType}, + + wechat_refund_status = + #{wechatRefundStatus}, + + alipay_refund_status = + #{alipayRefundStatus}, + + order_total_price = + #{orderTotalPrice}, + + refund_price = + #{refundPrice}, + + currency = + #{currency}, + + channel = + #{channel}, + + userReceivedAccount = + #{userreceivedaccount}, + + success_time = + #{successTime}, + + refund_notify_content = + #{refundNotifyContent}, + + apply_refund_return_content = + #{applyRefundReturnContent}, + + refund_merchant_type = + #{refundMerchantType}, + + del_flag = + #{delFlag}, + + create_by = + #{createBy}, + + create_time = + #{createTime}, + + update_by = + #{updateBy}, + + update_time = + #{updateTime}, + + + where id = #{id} + + + + delete + from refund_info + where id = #{id} + + + + delete from refund_info where id in + + #{id} + + + + + update refund_info + set wechat_refund_status = #{wechatRefundStatus}, + success_time = #{successTime}, + refund_notify_content = #{refundNotifyContent}, + update_time = now() + where order_no = #{orderNo} + and out_refund_no = #{outRefundNo} + and wechat_refund_status <> #{wechatRefundStatus} + + + + UPDATE refund_info + SET wechat_refund_status = #{weChatRefundStatus}, + success_time = #{successTime}, + update_time = now() + WHERE del_flag = 0 + and order_no = #{orderNo} + and wechat_refund_status <> #{weChatRefundStatus} + + + + diff --git a/xinelu-quartz/pom.xml b/xinelu-quartz/pom.xml index ecff609..13ea494 100644 --- a/xinelu-quartz/pom.xml +++ b/xinelu-quartz/pom.xml @@ -35,6 +35,15 @@ xinelu-common + + com.xinelu + xinelu-nurse-manage + + + + com.xinelu + xinelu-nurse-applet + - \ No newline at end of file + diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/CouponTaskController.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/CouponTaskController.java new file mode 100644 index 0000000..1bfb061 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/CouponTaskController.java @@ -0,0 +1,30 @@ +package com.xinelu.quartz.controller; + +import com.xinelu.quartz.task.CouponTask; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @Description 优惠券定时任务控制器 + * @Author 纪寒 + * @Date 2023-02-28 15:04:38 + * @Version 1.0 + */ +@RestController +@RequestMapping("/monitor/couponTask") +public class CouponTaskController { + + @Resource + private CouponTask couponTask; + + /** + * 手动执行更新会员领取已过期的优惠券状态定时任务 + */ + @GetMapping("/patientCouponStatus") + public void patientCouponStatus() { + couponTask.patientCouponReceiveStatusTask(); + } +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/PaymentInfoTaskController.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/PaymentInfoTaskController.java new file mode 100644 index 0000000..249db9f --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/PaymentInfoTaskController.java @@ -0,0 +1,42 @@ +package com.xinelu.quartz.controller; + +import com.xinelu.quartz.task.PaymentInfoTask; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @Description 手动处理支付定时任务控制器 + * @Author 纪寒 + * @Date 2022-10-21 15:11:38 + * @Version 1.0 + */ +@RestController +@RequestMapping("/monitor/payTask") +public class PaymentInfoTaskController { + + @Resource + private PaymentInfoTask paymentInfoTask; + + /** + * 手动执行关闭订单定时任务 + * + * @throws Exception 异常信息 + */ + @GetMapping("/handCloseOrder") + public void handCloseOrder() throws Exception { + paymentInfoTask.automaticOrderTask(); + } + + /** + * 手动执行更新订单状态定时任务 + * + * @throws Exception 异常信息 + */ + @GetMapping("/handOrderStatus") + public void handOrderStatus() throws Exception { + paymentInfoTask.automaticUpdateOrderStatusTask(); + } +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/RefundInfoTaskController.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/RefundInfoTaskController.java new file mode 100644 index 0000000..2ef9ba8 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/controller/RefundInfoTaskController.java @@ -0,0 +1,32 @@ +package com.xinelu.quartz.controller; + +import com.xinelu.quartz.task.RefundInfoTask; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @Description 手动处理退款定时任务控制器 + * @Author 纪寒 + * @Date 2022-10-25 14:39:10 + * @Version 1.0 + */ +@RestController +@RequestMapping("/monitor/refundTask") +public class RefundInfoTaskController { + + @Resource + private RefundInfoTask refundInfoTask; + + /** + * 手动执行修改退款单状态定时任务 + * + * @throws Exception 异常信息 + */ + @GetMapping("/handleRefundStatus") + public void handleRefundStatus() throws Exception { + refundInfoTask.automaticProcessRefundInfo(); + } +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/service/CouponTaskService.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/CouponTaskService.java new file mode 100644 index 0000000..a9606df --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/CouponTaskService.java @@ -0,0 +1,15 @@ +package com.xinelu.quartz.service; + +/** + * @Description 优惠券定时任务业务层 + * @Author 纪寒 + * @Date 2023-02-28 14:58:30 + * @Version 1.0 + */ +public interface CouponTaskService { + + /** + * 自动修改会员领取已过期的优惠券状态,第二天凌晨12点半执行一次 + */ + void patientCouponReceiveStatusTask(); +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/service/PaymentInfoTaskService.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/PaymentInfoTaskService.java new file mode 100644 index 0000000..43d2976 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/PaymentInfoTaskService.java @@ -0,0 +1,24 @@ +package com.xinelu.quartz.service; + +/** + * @Description 支付定时任务业务层 + * @Author 纪寒 + * @Date 2022-10-21 15:03:05 + * @Version 1.0 + */ +public interface PaymentInfoTaskService { + + /** + * 自动关闭商品订单24小时与预约订单2小时未支付的订单信息,每10分钟执行一次 + * + * @throws Exception 异常信息 + */ + void automaticOrderTask() throws Exception; + + /** + * 自动修改未支付的订单状态,每10分钟执行一次 + * + * @throws Exception 异常信息 + */ + void automaticUpdateOrderStatusTask() throws Exception; +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/service/RefundInfoTaskService.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/RefundInfoTaskService.java new file mode 100644 index 0000000..339a24f --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/RefundInfoTaskService.java @@ -0,0 +1,18 @@ +package com.xinelu.quartz.service; + +/** + * @Description 微信退款定时任务业务层 + * @Author 纪寒 + * @Date 2022-10-25 14:32:12 + * @Version 1.0 + */ +public interface RefundInfoTaskService { + + /** + * 自动处理退款状态定时任务, + * 防止由于网络等其它原因未接受到退款回调通知进而导致的退款单状态修改不及时 + * + * @throws Exception 异常信息 + */ + void automaticProcessRefundInfo() throws Exception; +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/CouponTaskServiceImpl.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/CouponTaskServiceImpl.java new file mode 100644 index 0000000..81fdb73 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/CouponTaskServiceImpl.java @@ -0,0 +1,64 @@ +package com.xinelu.quartz.service.impl; + +import com.xinelu.common.enums.CouponUseStatusEnum; +import com.xinelu.common.exception.ServiceException; +import com.xinelu.manage.domain.patientcouponreceive.PatientCouponReceive; +import com.xinelu.manage.mapper.patientcouponreceive.PatientCouponReceiveMapper; +import com.xinelu.quartz.service.CouponTaskService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @Description + * @Author 纪寒 + * @Date 2023-02-28 14:59:01 + * @Version 1.0 + */ +@Service +@Slf4j +public class CouponTaskServiceImpl implements CouponTaskService { + + @Resource(name = "transactionManager") + private DataSourceTransactionManager transactionManager; + @Resource + private PatientCouponReceiveMapper patientCouponReceiveMapper; + + /** + * 自动修改会员领取已过期的优惠券状态,第二天凌晨12点半执行一次 + */ + @Override + public void patientCouponReceiveStatusTask() { + log.info("开始执行修改会员领取已过期的优惠券状态定时任务......"); + LocalDateTime timePrevious = LocalDateTime.now(); + List patientCouponReceiveList = patientCouponReceiveMapper.getPatientCouponExpirationEndTime(timePrevious, CouponUseStatusEnum.EXPIRED.getInfo()); + if (CollectionUtils.isEmpty(patientCouponReceiveList)) { + return; + } + TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + List idList = patientCouponReceiveList.stream().filter(item -> Objects.nonNull(item.getId())).map(PatientCouponReceive::getId).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(idList)) { + int insertCount = patientCouponReceiveMapper.updateCouponReceiveStatus(CouponUseStatusEnum.EXPIRED.getInfo(), idList); + if (insertCount <= 0) { + throw new ServiceException("更新修改券状态失败!"); + } + } + transactionManager.commit(transactionStatus); + log.info("完成修改会员领取已过期的优惠券状态定时任务......"); + } catch (Exception e) { + log.error("修改会员领取已过期的优惠券状态定时任务失败,失败原因为 =====> {}", e.getMessage()); + transactionManager.rollback(transactionStatus); + throw e; + } + } +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/PaymentInfoTaskServiceImpl.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/PaymentInfoTaskServiceImpl.java new file mode 100644 index 0000000..57e9c87 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/PaymentInfoTaskServiceImpl.java @@ -0,0 +1,386 @@ +package com.xinelu.quartz.service.impl; + +import com.alibaba.fastjson2.JSON; +import com.xinelu.applet.service.goodstock.GoodsStockService; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatPaymentService; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.OrderStatusInfoVO; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatQueryOrderVO; +import com.xinelu.common.config.XylWeChatPaymentConfig; +import com.xinelu.common.config.YlypWeChatPaymentConfig; +import com.xinelu.common.constant.Constants; +import com.xinelu.common.enums.*; +import com.xinelu.manage.domain.appointmentorder.AppointmentOrder; +import com.xinelu.manage.domain.goodsOrder.GoodsOrder; +import com.xinelu.manage.domain.paymentinfo.PaymentInfo; +import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import com.xinelu.manage.mapper.patientcouponreceive.PatientCouponReceiveMapper; +import com.xinelu.manage.mapper.paymentinfo.PaymentInfoMapper; +import com.xinelu.manage.vo.AppointOrderAndDetailsInfo; +import com.xinelu.manage.vo.goods.GoodsOrderAndDetailsInfo; +import com.xinelu.quartz.service.PaymentInfoTaskService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.support.atomic.RedisAtomicLong; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import javax.annotation.Resource; +import javax.sql.rowset.serial.SerialException; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @Description 支付定时任务实现类 + * @Author 纪寒 + * @Date 2022-10-21 15:03:41 + * @Version 1.0 + */ +@Slf4j +@Service +public class PaymentInfoTaskServiceImpl implements PaymentInfoTaskService { + + @Resource + private AppointmentOrderMapper appointmentOrderMapper; + @Resource + private GoodsOrderMapper goodsOrderMapper; + @Resource + private WeChatPaymentService weChatPaymentService; + @Resource + private PaymentInfoMapper paymentInfoMapper; + @Resource + private XylWeChatPaymentConfig xylWeChatPaymentConfig; + @Resource + private YlypWeChatPaymentConfig ylypWeChatPaymentConfig; + @Resource(name = "transactionManager") + private DataSourceTransactionManager transactionManager; + @Resource + private GoodsStockService goodsStockService; + @Resource + private RedisTemplate redisTemplate; + @Resource + private PatientCouponReceiveMapper patientCouponReceiveMapper; + + /** + * 成功状态码 + */ + private static final int SUCCESS_CODE = 200; + + /** + * 成功状态码 + */ + private static final int SUCCESS_CODE_TWO = 204; + + /** + * 自动关闭商品订单2小时与预约订单2小时未支付的订单信息,每10分钟执行一次 + * + * @throws Exception 异常信息 + */ + @Override + public void automaticOrderTask() throws Exception { + LocalDateTime localDateTime = LocalDateTime.now().minusHours(2); + List appointmentOrderList = appointmentOrderMapper.getWaitPayAppointmentOrderList(localDateTime); + List goodsOrderList = goodsOrderMapper.getWaitPayGoodsOrderList(localDateTime); + if (CollectionUtils.isEmpty(appointmentOrderList) && CollectionUtils.isEmpty(goodsOrderList)) { + return; + } + TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + List successAppointOrderList = Lists.newArrayList(); + try { + if (CollectionUtils.isNotEmpty(appointmentOrderList)) { + successAppointOrderList = processAppointmentOrderInfo(appointmentOrderList); + } + if (CollectionUtils.isNotEmpty(goodsOrderList)) { + processGoodsOrderInfo(goodsOrderList); + } + transactionManager.commit(transactionStatus); + } catch (Exception e) { + transactionManager.rollback(transactionStatus); + log.error("自动关闭订单失败,失败原因为 =====> {}", e.getMessage()); + if (CollectionUtils.isNotEmpty(successAppointOrderList)) { + for (AppointOrderAndDetailsInfo orderAndDetailsInfo : successAppointOrderList) { + String appointLimitCountKey = Constants.PRE_APPOINTMENT_LIMIT_COUNT_KEY + orderAndDetailsInfo.getNurseStationItemId() + "_" + orderAndDetailsInfo.getServiceDate() + "_" + orderAndDetailsInfo.getServiceStartTime(); + RedisAtomicLong redisAtomicLong = new RedisAtomicLong(appointLimitCountKey, Objects.requireNonNull(redisTemplate.getConnectionFactory())); + if (redisAtomicLong.get() > 0) { + redisAtomicLong.decrementAndGet(); + } + } + } + throw e; + } + } + + /** + * 自动修改未支付的订单状态,每15分钟执行一次 + * + * @throws Exception 异常信息 + */ + @Override + public void automaticUpdateOrderStatusTask() throws Exception { + List appointmentOrderList = appointmentOrderMapper.getWaitPayStatusAppointmentOrderList(OrderStatusEnum.WAIT_PAY.getInfo()); + List goodsOrderList = goodsOrderMapper.getWaitPayStatusGoodsOrderList(GooodsOrderStatusEnum.WAIT_PAY.getInfo()); + if (CollectionUtils.isEmpty(appointmentOrderList) && CollectionUtils.isEmpty(goodsOrderList)) { + return; + } + TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + if (CollectionUtils.isNotEmpty(appointmentOrderList)) { + updateAppointmentPaymentInfo(appointmentOrderList); + } + if (CollectionUtils.isNotEmpty(goodsOrderList)) { + updateGoodsPaymentInfo(goodsOrderList); + } + transactionManager.commit(transactionStatus); + } catch (Exception e) { + log.error("修改订单状态定时任务失败,失败原因为 =====> {}", e.getMessage()); + transactionManager.rollback(transactionStatus); + throw e; + } + } + + /** + * 处理预约订单状态 + * + * @param appointmentOrderList 预约订单列表 + * @return List 处理成功的预约订单信息 + * @throws Exception 异常信息 + */ + private List processAppointmentOrderInfo(List appointmentOrderList) throws Exception { + List successList = Lists.newArrayList(); + List closedOrderList = Lists.newArrayList(); + for (AppointOrderAndDetailsInfo orderAndDetailsInfo : appointmentOrderList) { + if (StringUtils.isBlank(orderAndDetailsInfo.getOrderNo())) { + continue; + } + OrderStatusInfoVO vo = new OrderStatusInfoVO(); + OrderStatusInfoVO statusInfoVO = weChatPaymentService.queryAppointmentOrderStatus(orderAndDetailsInfo.getOrderNo(), vo); + if (BooleanUtils.isFalse(statusInfoVO.getPayFlag())) { + closedOrderList.add(orderAndDetailsInfo.getOrderNo()); + continue; + } + int statusCode = weChatPaymentService.closeWeChatOrderInfo(orderAndDetailsInfo.getOrderNo(), BuySourceEnum.NURSE_STATION.getInfo()); + if (statusCode == SUCCESS_CODE || statusCode == SUCCESS_CODE_TWO) { + updateAppointmentOrderStatus(orderAndDetailsInfo, successList); + } + } + if (CollectionUtils.isNotEmpty(closedOrderList)) { + List waitPayAppointList = appointmentOrderMapper.getWaitPayAppointList(closedOrderList); + if (CollectionUtils.isNotEmpty(waitPayAppointList)) { + for (AppointOrderAndDetailsInfo orderAndDetailsInfo : waitPayAppointList) { + updateAppointmentOrderStatus(orderAndDetailsInfo, successList); + } + } + } + return successList; + } + + /** + * 处理商品订单信息 + * + * @param goodsOrderList 商品订单列表 + * @throws Exception 异常信息 + */ + private void processGoodsOrderInfo(List goodsOrderList) throws Exception { + List orderList = Lists.newArrayList(); + List closedOrderList = Lists.newArrayList(); + for (GoodsOrderAndDetailsInfo goodOrder : goodsOrderList) { + if (StringUtils.isBlank(goodOrder.getOrderNo())) { + continue; + } + OrderStatusInfoVO vo = new OrderStatusInfoVO(); + OrderStatusInfoVO statusInfoVO = weChatPaymentService.queryGoodsOrderStatus(goodOrder.getOrderNo(), vo, goodOrder.getBuySource()); + if (BooleanUtils.isFalse(statusInfoVO.getPayFlag())) { + closedOrderList.add(goodOrder.getOrderNo()); + continue; + } + int statusCode = weChatPaymentService.closeWeChatOrderInfo(goodOrder.getOrderNo(), goodOrder.getBuySource()); + if (statusCode == SUCCESS_CODE || statusCode == SUCCESS_CODE_TWO) { + orderList.add(goodOrder.getOrderNo()); + } + if (StringUtils.isNotBlank(goodOrder.getOrderType()) && !OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(goodOrder.getOrderType())) { + goodsStockService.addGoodsStockInfo(goodOrder.getOrderNo(), goodOrder.getGoodsAttributeDetailsId(), Objects.isNull(goodOrder.getGoodsCount()) ? 0 : goodOrder.getGoodsCount()); + if (Objects.nonNull(goodOrder.getCouponId()) && Objects.nonNull(goodOrder.getPatientId())) { + patientCouponReceiveMapper.updatePatientCouponUseStatus(goodOrder.getPatientId(), goodOrder.getCouponId(), CouponUseStatusEnum.NOT_USED.getInfo()); + } + } + } + if (CollectionUtils.isNotEmpty(orderList)) { + log.info("自动修改商品订单信息状态 ======> [{}]", orderList); + goodsOrderMapper.updateBatchGoodsOrderStatus(orderList, GooodsOrderStatusEnum.CANCEL.getInfo()); + } + if (CollectionUtils.isNotEmpty(closedOrderList)) { + //说明当前订单在微信系统中已经关闭,需要重新确认本地订单状态是否同步更新,未更新则需要同步更新并且新增库存数量 + List goodsOrderInfoList = goodsOrderMapper.getWaitPayGoodsOrderCountList(closedOrderList); + if (CollectionUtils.isNotEmpty(goodsOrderInfoList)) { + //新增库存数量和修改优惠券状态,健康咨询类型的订单无需新增库存数量和退还优惠券 + for (GoodsOrderAndDetailsInfo detailsInfo : goodsOrderInfoList) { + if (StringUtils.isNotBlank(detailsInfo.getOrderType()) && OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(detailsInfo.getOrderType())) { + continue; + } + goodsStockService.addGoodsStockInfo(detailsInfo.getOrderNo(), detailsInfo.getGoodsAttributeDetailsId(), Objects.isNull(detailsInfo.getGoodsCount()) ? 0 : detailsInfo.getGoodsCount()); + if (Objects.nonNull(detailsInfo.getCouponId()) && Objects.nonNull(detailsInfo.getPatientId())) { + patientCouponReceiveMapper.updatePatientCouponUseStatus(detailsInfo.getPatientId(), detailsInfo.getCouponId(), CouponUseStatusEnum.NOT_USED.getInfo()); + } + } + //批量更新本地订单状态,将订单状态修改为已取消 + List orderNos = goodsOrderInfoList.stream().filter(item -> StringUtils.isNotBlank(item.getOrderNo())).map(GoodsOrderAndDetailsInfo::getOrderNo).distinct().collect(Collectors.toList()); + goodsOrderMapper.updateBatchGoodsOrderStatus(orderNos, GooodsOrderStatusEnum.CANCEL.getInfo()); + } + } + } + + /** + * 新增预约订单支付信息 + * + * @param appointmentOrderList 预约订单列表 + * @throws Exception 异常信息 + */ + private void updateAppointmentPaymentInfo(List appointmentOrderList) throws Exception { + for (AppointmentOrder appointmentOrder : appointmentOrderList) { + if (StringUtils.isBlank(appointmentOrder.getOrderNo())) { + continue; + } + OrderStatusInfoVO vo = new OrderStatusInfoVO(); + OrderStatusInfoVO statusInfoVO = weChatPaymentService.queryAppointmentOrderStatus(appointmentOrder.getOrderNo(), vo); + if (StringUtils.isNotBlank(statusInfoVO.getTradeStatus()) + && WeChatTradeStateEnum.SUCCESS.getInfo().equals(statusInfoVO.getTradeStatus())) { + insertAppointmentOrderPaymentInfo(appointmentOrder, statusInfoVO); + } + } + } + + /** + * 新增商品订单支付信息 + * + * @param goodsOrderList 商品订单列表 + * @throws Exception 异常信息 + */ + private void updateGoodsPaymentInfo(List goodsOrderList) throws Exception { + for (GoodsOrder goodsOrder : goodsOrderList) { + if (Objects.isNull(goodsOrder) || StringUtils.isBlank(goodsOrder.getOrderNo())) { + continue; + } + OrderStatusInfoVO vo = new OrderStatusInfoVO(); + OrderStatusInfoVO statusInfoVO = weChatPaymentService.queryGoodsOrderStatus(goodsOrder.getOrderNo(), vo, goodsOrder.getBuySource()); + if (StringUtils.isNotBlank(statusInfoVO.getTradeStatus()) + && WeChatTradeStateEnum.SUCCESS.getInfo().equals(statusInfoVO.getTradeStatus())) { + insertGoodsOrderPaymentInfo(goodsOrder, statusInfoVO); + } + } + } + + /** + * 修改预约订单状态和记录预约订单信息 + * + * @param appointmentOrder 预约订单信息 + * @param vo 微信查单信息 + * @throws Exception 异常信息 + */ + private void insertAppointmentOrderPaymentInfo(AppointmentOrder appointmentOrder, OrderStatusInfoVO vo) throws Exception { + appointmentOrderMapper.updateAppointmentOrderStatus(OrderStatusEnum.WAIT_DISPATCH.getInfo(), appointmentOrder.getOrderNo()); + int paymentInfoCount = paymentInfoMapper.getPaymentInfoByOrderNo(appointmentOrder.getOrderNo()); + if (paymentInfoCount <= 0) { + WeChatQueryOrderVO weChatQueryOrderVO = vo.getWeChatQueryOrderVO(); + PaymentInfo paymentInfo = buildPaymentInfo(weChatQueryOrderVO, null, appointmentOrder); + int insertCount = paymentInfoMapper.insertPaymentInfo(paymentInfo); + if (insertCount <= 0) { + log.error("记录预约订单支付日志出错,参数为 ====> [{}]", paymentInfo); + throw new SerialException("记录预约订单支付日志出错,请联系管理员!"); + } + } + } + + /** + * 修改商品订单状态和记录商品订单支付日志信息 + * + * @param goodsOrder 商品订单信息 + * @param vo 微信查单信息 + * @throws Exception 异常信息 + */ + private void insertGoodsOrderPaymentInfo(GoodsOrder goodsOrder, OrderStatusInfoVO vo) throws Exception { + int paymentInfoCount = 0; + if (Objects.nonNull(goodsOrder)) { + goodsOrderMapper.updateGoodsOrderStatus(GooodsOrderStatusEnum.WAIT_RECEIVED_GOODS.getInfo(), goodsOrder.getOrderNo()); + paymentInfoCount = paymentInfoMapper.getPaymentInfoByOrderNo(goodsOrder.getOrderNo()); + } + if (paymentInfoCount <= 0) { + WeChatQueryOrderVO weChatQueryOrderVO = vo.getWeChatQueryOrderVO(); + PaymentInfo paymentInfo = buildPaymentInfo(weChatQueryOrderVO, goodsOrder, null); + int insertCount = paymentInfoMapper.insertPaymentInfo(paymentInfo); + if (insertCount <= 0) { + log.error("记录商品或者学习培训支付订单支付日志出错,参数为 ====> [{}]", paymentInfo); + throw new SerialException("记录商品或者学习培训支付订单支付日志出错,请联系管理员!"); + } + } + } + + /** + * 构建支付信息参数 + * + * @param weChatQueryOrderVO 微信查单返回结果信息 + * @param goodsOrderInfo 商品订单信息 + * @param appointmentOrderInfo 预约订单信息 + */ + public PaymentInfo buildPaymentInfo(WeChatQueryOrderVO weChatQueryOrderVO, GoodsOrder goodsOrderInfo, + AppointmentOrder appointmentOrderInfo) { + PaymentInfo paymentInfo = new PaymentInfo(); + if (Objects.nonNull(goodsOrderInfo)) { + paymentInfo.setPatientId(Objects.isNull(goodsOrderInfo.getPatientId()) ? null : goodsOrderInfo.getPatientId()); + paymentInfo.setOrderNo(StringUtils.isBlank(goodsOrderInfo.getOrderNo()) ? "" : goodsOrderInfo.getOrderNo()); + paymentInfo.setPayChannel(StringUtils.isBlank(goodsOrderInfo.getOrderChannel()) ? "" : goodsOrderInfo.getOrderChannel()); + } else if (Objects.nonNull(appointmentOrderInfo)) { + paymentInfo.setPatientId(Objects.isNull(appointmentOrderInfo.getPatientId()) ? null : appointmentOrderInfo.getPatientId()); + paymentInfo.setOrderNo(StringUtils.isBlank(appointmentOrderInfo.getOrderNo()) ? "" : appointmentOrderInfo.getOrderNo()); + paymentInfo.setPayChannel(StringUtils.isBlank(appointmentOrderInfo.getOrderChannel()) ? "" : appointmentOrderInfo.getOrderChannel()); + } + paymentInfo.setTransactionNo(StringUtils.isBlank(weChatQueryOrderVO.getTransactionId()) ? "" : weChatQueryOrderVO.getTransactionId()); + paymentInfo.setPayPrice(BigDecimal.valueOf(Objects.isNull(weChatQueryOrderVO.getAmount().getPayerTotal()) ? 0 : weChatQueryOrderVO.getAmount().getPayerTotal()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN)); + paymentInfo.setPayType(PayTypeEnum.WECHAT_PAY.getInfo()); + paymentInfo.setWechatTradeState(StringUtils.isBlank(weChatQueryOrderVO.getTradeState()) ? "" : weChatQueryOrderVO.getTradeState()); + paymentInfo.setPayNotifyContent(JSON.toJSON(weChatQueryOrderVO).toString()); + paymentInfo.setPayTime(LocalDateTime.parse(StringUtils.isBlank(weChatQueryOrderVO.getSuccessTime()) ? "" : weChatQueryOrderVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME)); + if (weChatQueryOrderVO.getMchid().equals(xylWeChatPaymentConfig.getXylMchId())) { + paymentInfo.setPaymentMerchantType(PaymentMerchantTypeEnum.XINYILU.getInfo()); + } + if (weChatQueryOrderVO.getMchid().equals(ylypWeChatPaymentConfig.getYlypMchId())) { + paymentInfo.setPaymentMerchantType(PaymentMerchantTypeEnum.YILUYOUPIN.getInfo()); + } + paymentInfo.setDelFlag(0); + paymentInfo.setCreateTime(LocalDateTime.now()); + return paymentInfo; + } + + /** + * 修改预约订单状态和修改预约次数上限 + * + * @param orderAndDetailsInfo 输入参数 + * @param successList 处理成功的订单集合 + */ + private void updateAppointmentOrderStatus(AppointOrderAndDetailsInfo orderAndDetailsInfo, List successList) { + //关闭系统内部预约订单 + List orderList = Collections.singletonList(orderAndDetailsInfo.getOrderNo()); + appointmentOrderMapper.updateBatchAppointmentOrderStatus(orderList, OrderStatusEnum.CANCEL.getInfo()); + //新增Redis中的预约次数 + if (Objects.nonNull(orderAndDetailsInfo.getAppointmentLimitCount()) && StringUtils.equals(AppointmentOrderTypeEnum.OTHER.getInfo(), orderAndDetailsInfo.getOrderType())) { + String appointLimitCountKey = Constants.PRE_APPOINTMENT_LIMIT_COUNT_KEY + orderAndDetailsInfo.getNurseStationItemId() + "_" + orderAndDetailsInfo.getServiceDate() + "_" + orderAndDetailsInfo.getServiceStartTime(); + RedisAtomicLong redisAtomicLong = new RedisAtomicLong(appointLimitCountKey, Objects.requireNonNull(redisTemplate.getConnectionFactory())); + if (redisAtomicLong.get() >= 0 && redisAtomicLong.get() < orderAndDetailsInfo.getAppointmentLimitCount()) { + //预约次数加一 + redisAtomicLong.incrementAndGet(); + successList.add(orderAndDetailsInfo); + } + } + } + +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/RefundInfoTaskServiceImpl.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/RefundInfoTaskServiceImpl.java new file mode 100644 index 0000000..30436c3 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/service/impl/RefundInfoTaskServiceImpl.java @@ -0,0 +1,164 @@ +package com.xinelu.quartz.service.impl; + +import com.xinelu.applet.service.goodstock.GoodsStockService; +import com.xinelu.applet.service.wechatpaymentinfo.WeChatRefundService; +import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundInfoVO; +import com.xinelu.common.constant.Constants; +import com.xinelu.common.enums.*; +import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper; +import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper; +import com.xinelu.manage.mapper.patientcouponreceive.PatientCouponReceiveMapper; +import com.xinelu.manage.mapper.refundinfo.RefundInfoMapper; +import com.xinelu.manage.vo.RefundOrderInfoVO; +import com.xinelu.quartz.service.RefundInfoTaskService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.support.atomic.RedisAtomicLong; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * @Description 微信退款定时任务业务层实现类 + * @Author 纪寒 + * @Date 2022-10-25 14:32:40 + * @Version 1.0 + */ +@Slf4j +@Service +public class RefundInfoTaskServiceImpl implements RefundInfoTaskService { + + @Resource + private AppointmentOrderMapper appointmentOrderMapper; + @Resource + private GoodsOrderMapper goodsOrderMapper; + @Resource(name = "transactionManager") + private DataSourceTransactionManager transactionManager; + @Resource + private WeChatRefundService weChatRefundService; + @Resource + private RefundInfoMapper refundInfoMapper; + @Resource + private GoodsStockService goodsStockService; + @Resource + private RedisTemplate redisTemplate; + @Resource + private PatientCouponReceiveMapper patientCouponReceiveMapper; + + /** + * 自动处理退款状态定时任务,每15分钟执行一次 + * 防止由于网络等其它原因未接受到退款回调通知进而导致的退款单状态修改不及时 + * + * @throws Exception 异常信息 + */ + @Override + public void automaticProcessRefundInfo() throws Exception { + List appointmentOrderList = appointmentOrderMapper.getRefundAppointmentOrderInfo(OrderStatusEnum.WAIT_REFUND.getInfo(), RefundStatusEnum.PROCESSING.getInfo(), ConfirmRefundStatusEnum.CONFIRMED.getInfo()); + List refundGoodsOrderLit = goodsOrderMapper.getRefundGoodsOrderInfo(GooodsOrderStatusEnum.WAIT_REFUND.getInfo(), RefundStatusEnum.PROCESSING.getInfo(), ConfirmRefundStatusEnum.CONFIRMED.getInfo()); + if (CollectionUtils.isEmpty(appointmentOrderList) && CollectionUtils.isEmpty(refundGoodsOrderLit)) { + return; + } + TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + List successAppointOrderList = Lists.newArrayList(); + try { + if (CollectionUtils.isNotEmpty(appointmentOrderList)) { + successAppointOrderList = processAppointmentRefundInfo(appointmentOrderList); + } + if (CollectionUtils.isNotEmpty(refundGoodsOrderLit)) { + processGoodsRefundInfo(refundGoodsOrderLit); + } + transactionManager.commit(transactionStatus); + } catch (Exception e) { + transactionManager.rollback(transactionStatus); + log.error("处理微信退款定时任务异常,异常信息 =====> {}", e.getMessage()); + if (CollectionUtils.isNotEmpty(successAppointOrderList)) { + for (RefundOrderInfoVO refundOrderInfoVO : successAppointOrderList) { + String appointLimitCountKey = Constants.PRE_APPOINTMENT_LIMIT_COUNT_KEY + refundOrderInfoVO.getNurseStationItemId() + "_" + refundOrderInfoVO.getServiceDate() + "_" + refundOrderInfoVO.getServiceStartTime(); + RedisAtomicLong redisAtomicLong = new RedisAtomicLong(appointLimitCountKey, Objects.requireNonNull(redisTemplate.getConnectionFactory())); + if (redisAtomicLong.get() > 0) { + redisAtomicLong.decrementAndGet(); + } + } + } + throw e; + } + } + + /** + * 处理退款的预约订单信息 + * + * @param appointmentOrderList 预约订单列表信息 + * @return 处理成功的订单编号集合 + */ + private List processAppointmentRefundInfo(List appointmentOrderList) { + List successList = Lists.newArrayList(); + for (RefundOrderInfoVO refundOrderInfoVO : appointmentOrderList) { + if (StringUtils.isBlank(refundOrderInfoVO.getOrderNo()) || StringUtils.isBlank(refundOrderInfoVO.getOutRefundNo())) { + continue; + } + WeChatRefundInfoVO weChatRefundInfoVO = weChatRefundService.queryAppointmentOrderRefundStatus(refundOrderInfoVO.getOutRefundNo()); + if (StringUtils.isNotBlank(weChatRefundInfoVO.getStatus()) + && RefundStatusEnum.SUCCESS.getInfo().equals(weChatRefundInfoVO.getStatus())) { + List orderNoList = Collections.singletonList(refundOrderInfoVO.getOrderNo()); + LocalDateTime successTime = StringUtils.isBlank(weChatRefundInfoVO.getSuccessTime()) ? LocalDateTime.now() : LocalDateTime.parse(weChatRefundInfoVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME); + refundInfoMapper.updateBatchRefundStatus(refundOrderInfoVO.getOrderNo(), successTime, weChatRefundInfoVO.getStatus()); + appointmentOrderMapper.updateBatchAppointmentOrderStatus(orderNoList, OrderStatusEnum.REFUNDED.getInfo()); + if (Objects.nonNull(refundOrderInfoVO.getAppointmentLimitCount()) && StringUtils.equals(AppointmentOrderTypeEnum.OTHER.getInfo(), refundOrderInfoVO.getAppointmentOrderType())) { + String appointLimitCountKey = Constants.PRE_APPOINTMENT_LIMIT_COUNT_KEY + refundOrderInfoVO.getNurseStationItemId() + "_" + refundOrderInfoVO.getServiceDate() + "_" + refundOrderInfoVO.getServiceStartTime(); + RedisAtomicLong redisAtomicLong = new RedisAtomicLong(appointLimitCountKey, Objects.requireNonNull(redisTemplate.getConnectionFactory())); + if (redisAtomicLong.get() >= 0 && redisAtomicLong.get() < refundOrderInfoVO.getAppointmentLimitCount()) { + redisAtomicLong.incrementAndGet(); + successList.add(refundOrderInfoVO); + } + } + } + } + return successList; + } + + /** + * 处理退款成功的商品订单信息 + * + * @param refundGoodsOrderLit 商品退款订单信息 + * @throws Exception 异常信息 + */ + private void processGoodsRefundInfo(List refundGoodsOrderLit) throws Exception { + List orderNoList = Lists.newArrayList(); + for (RefundOrderInfoVO refundOrderInfoVO : refundGoodsOrderLit) { + if (StringUtils.isBlank(refundOrderInfoVO.getOrderNo()) + || StringUtils.isBlank(refundOrderInfoVO.getOutRefundNo()) || StringUtils.isBlank(refundOrderInfoVO.getBuySource())) { + continue; + } + WeChatRefundInfoVO weChatRefundInfoVO = weChatRefundService.queryGoodsOrderRefundStatus(refundOrderInfoVO.getOutRefundNo(), refundOrderInfoVO.getBuySource()); + if (StringUtils.isNotBlank(weChatRefundInfoVO.getStatus()) + && RefundStatusEnum.SUCCESS.getInfo().equals(weChatRefundInfoVO.getStatus())) { + orderNoList.add(refundOrderInfoVO.getOrderNo()); + } + log.info("修改商品订单表状态和增加库存数量,订单编号=====> {}, 商品属性明细表id======> {}", refundOrderInfoVO.getOrderNo(), refundOrderInfoVO.getGoodsAttributeDetailsId()); + LocalDateTime successTime = StringUtils.isBlank(weChatRefundInfoVO.getSuccessTime()) ? LocalDateTime.now() : LocalDateTime.parse(weChatRefundInfoVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME); + refundInfoMapper.updateBatchRefundStatus(refundOrderInfoVO.getOrderNo(), successTime, weChatRefundInfoVO.getStatus()); + if (StringUtils.isNotBlank(refundOrderInfoVO.getOrderType()) && !OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(refundOrderInfoVO.getOrderType())) { + String stockNum = StringUtils.isBlank(refundOrderInfoVO.getGoodsCount()) ? "0" : refundOrderInfoVO.getGoodsCount(); + goodsStockService.addGoodsStockInfo(refundOrderInfoVO.getOrderNo(), refundOrderInfoVO.getGoodsAttributeDetailsId(), Integer.parseInt(stockNum)); + if (Objects.nonNull(refundOrderInfoVO.getCouponId()) && Objects.nonNull(refundOrderInfoVO.getPatientId())) { + patientCouponReceiveMapper.updatePatientCouponUseStatus(refundOrderInfoVO.getPatientId(), refundOrderInfoVO.getCouponId(), CouponUseStatusEnum.NOT_USED.getInfo()); + } + } + } + if (CollectionUtils.isNotEmpty(orderNoList)) { + goodsOrderMapper.updateBatchGoodsOrderStatus(orderNoList, OrderStatusEnum.REFUNDED.getInfo()); + } + } + +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/task/CouponTask.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/task/CouponTask.java new file mode 100644 index 0000000..4fda424 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/task/CouponTask.java @@ -0,0 +1,28 @@ +package com.xinelu.quartz.task; + +import com.xinelu.quartz.service.CouponTaskService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * @Description 优惠券相关定时任务 + * @Author 纪寒 + * @Date 2023-02-28 14:57:33 + * @Version 1.0 + */ +@Slf4j +@Component("couponTask") +public class CouponTask { + + @Resource + private CouponTaskService couponTaskService; + + /** + * 自动修改会员领取已过期的优惠券状态,第二天凌晨12点半执行一次 + */ + public void patientCouponReceiveStatusTask() { + couponTaskService.patientCouponReceiveStatusTask(); + } +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/task/PaymentInfoTask.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/task/PaymentInfoTask.java new file mode 100644 index 0000000..5e569e8 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/task/PaymentInfoTask.java @@ -0,0 +1,45 @@ +package com.xinelu.quartz.task; + +import com.xinelu.quartz.service.PaymentInfoTaskService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * @Description 支付定时任务类 + * @Author 纪寒 + * @Date 2022-10-21 14:34:36 + * @Version 1.0 + */ +@Slf4j +@Component("paymentTask") +public class PaymentInfoTask { + + @Resource + private PaymentInfoTaskService paymentInfoTaskService; + + /** + * 自动关闭商品订单2小时与预约订单2小时未支付的订单信息,每15分钟执行一次 + * + * @throws Exception 异常信息 + */ + public void automaticOrderTask() throws Exception { + log.info("开始执行自动关闭订单定时任务......"); + paymentInfoTaskService.automaticOrderTask(); + log.info("完成自动关闭订单定时任务......"); + } + + /** + * 自动修改未支付的订单状态,每15分钟执行一次 + * 该定时任务用与接收微信支付回调通知失败或者网络原因导致微信支付系统支付成功,但是本地订单状态未同步更新的情况 + * + * @throws Exception 异常信息 + */ + public void automaticUpdateOrderStatusTask() throws Exception { + log.info("开始执行修改订单状态定时任务......"); + paymentInfoTaskService.automaticUpdateOrderStatusTask(); + log.info("完成修改订单状态定时任务......"); + } + +} diff --git a/xinelu-quartz/src/main/java/com/xinelu/quartz/task/RefundInfoTask.java b/xinelu-quartz/src/main/java/com/xinelu/quartz/task/RefundInfoTask.java new file mode 100644 index 0000000..de957c4 --- /dev/null +++ b/xinelu-quartz/src/main/java/com/xinelu/quartz/task/RefundInfoTask.java @@ -0,0 +1,33 @@ +package com.xinelu.quartz.task; + +import com.xinelu.quartz.service.RefundInfoTaskService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * @Description + * @Author 纪寒 + * @Date 2022-10-25 14:35:59 + * @Version 1.0 + */ +@Slf4j +@Component("refundTask") +public class RefundInfoTask { + + @Resource + private RefundInfoTaskService refundInfoTaskService; + + /** + * 自动处理退款状态定时任务, + * 防止由于网络等其它原因未接受到退款回调通知进而导致的退款单状态修改不及时 + * + * @throws Exception 异常信息 + */ + public void automaticProcessRefundInfo() throws Exception { + log.info("开始执行关闭退款状态定时任务........"); + refundInfoTaskService.automaticProcessRefundInfo(); + log.info("完成关闭退款状态定时任务........"); + } +}