diff --git a/pom.xml b/pom.xml index 7e952b7c4..05dc3e5ce 100644 --- a/pom.xml +++ b/pom.xml @@ -96,6 +96,15 @@ 123456 + + local + + local + warn + ruoyi + 123456 + + diff --git a/ruoyi-admin/src/main/java/org/dromara/app/customer/AppRedPacketController.java b/ruoyi-admin/src/main/java/org/dromara/app/customer/AppRedPacketController.java index f22add31b..bb1f83cc2 100644 --- a/ruoyi-admin/src/main/java/org/dromara/app/customer/AppRedPacketController.java +++ b/ruoyi-admin/src/main/java/org/dromara/app/customer/AppRedPacketController.java @@ -10,10 +10,7 @@ import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.satoken.utils.LoginHelper; import org.springframework.beans.factory.annotation.Autowired; -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 org.springframework.web.bind.annotation.*; import java.util.Map; @@ -30,6 +27,7 @@ public class AppRedPacketController { /** * 发红包接口 + * * @param request 发红包请求参数 * @return 红包创建结果 */ @@ -47,6 +45,7 @@ public class AppRedPacketController { /** * 抢红包接口 + * * @return 抢红包结果 */ @PostMapping("/grab") @@ -61,17 +60,17 @@ public class AppRedPacketController { return R.ok("红包领取成功", result); } -// /** -// * 查询红包详情接口 -// * @param packetId 红包ID -// * @return 红包详情 -// */ -// @GetMapping("/detail/{packetId}") -// @Operation(summary = "查询红包详情") -// public R getRedPacketDetail(@PathVariable Long packetId) { -// RedPacketDetailVO detail = redPacketService.getRedPacketDetail(packetId); -// return R.ok(detail); -// } + /** + * 查询红包详情接口 + * + * @return 红包详情 + */ + @GetMapping("/refund") + @Operation(summary = "退回红包") + public R getRedPacketDetail() { + redPacketService.checkAndRefundExpiredRedPackets(); + return R.ok(); + } // // /** // * 查询用户领取的红包记录 diff --git a/ruoyi-admin/src/main/resources/application-local.yml b/ruoyi-admin/src/main/resources/application-local.yml new file mode 100644 index 000000000..b802cf49e --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-local.yml @@ -0,0 +1,281 @@ +--- # 监控中心配置 +spring.boot.admin.client: + # 增加客户端开关 + enabled: false + url: http://43.143.227.203:9090/admin + instance: + service-host-type: IP + metadata: + username: ${spring.boot.admin.client.username} + userpassword: ${spring.boot.admin.client.password} + username: @monitor.username@ + password: @monitor.password@ + +--- # snail-job 配置 +snail-job: + enabled: false + # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 + group: "ruoyi_group" + # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表 + token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" + server: + host: 43.143.227.203 + port: 17888 + # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 + namespace: ${spring.profiles.active} + # 随主应用端口漂移 + port: 2${server.port} + # 客户端ip指定 + host: + # RPC类型: netty, grpc + rpc-type: grpc + +--- # 数据源配置 +spring: + datasource: + type: com.zaxxer.hikari.HikariDataSource + # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content + dynamic: + # 性能分析插件(有性能损耗 不建议生产环境使用) + p6spy: true + # 设置默认的数据源或者数据源组,默认值即为 master + primary: master + # 严格模式 匹配不到数据源则报错 + strict: true + datasource: + # 主库数据源 + master: + type: ${spring.datasource.type} + driverClassName: com.mysql.cj.jdbc.Driver + # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 + # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) + url: jdbc:mysql://43.143.227.203:13306/soopin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true + username: wzj + password: A085F27A43B0 + # # 从库数据源 + # slave: + # lazy: true + # type: ${spring.datasource.type} + # driverClassName: com.mysql.cj.jdbc.Driver + # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true + # username: + # password: + # oracle: + # type: ${spring.datasource.type} + # driverClassName: oracle.jdbc.OracleDriver + # url: jdbc:oracle:thin:@//localhost:1521/XE + # username: ROOT + # password: root + # postgres: + # type: ${spring.datasource.type} + # driverClassName: org.postgresql.Driver + # url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true + # username: root + # password: root + # sqlserver: + # type: ${spring.datasource.type} + # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver + # url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true + # username: SA + # password: root + hikari: + # 最大连接池数量 + maxPoolSize: 20 + # 最小空闲线程数量 + minIdle: 10 + # 配置获取连接等待超时的时间 + connectionTimeout: 30000 + # 校验超时时间 + validationTimeout: 5000 + # 空闲连接存活最大时间,默认10分钟 + idleTimeout: 600000 + # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟 + maxLifetime: 1800000 + # 多久检查一次连接的活性 + keepaliveTime: 300000 + +--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) +spring.data: + redis: + # 地址 + host: 43.143.227.203 + # 端口,默认为6379 + port: 16379 + # 数据库索引 + database: 2 + # 密码(如没有密码请注释掉) + password: e4ea0caebfd2 + # 连接超时时间 + timeout: 10s + # 是否开启ssl + ssl.enabled: false + +# redisson 配置 +redisson: + # redis key前缀 + keyPrefix: + # 线程池数量 + threads: 4 + # Netty线程池数量 + nettyThreads: 8 + # 单节点配置 + singleServerConfig: + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus + # 最小空闲连接数 + connectionMinimumIdleSize: 8 + # 连接池大小 + connectionPoolSize: 32 + # 连接空闲超时,单位:毫秒 + idleConnectionTimeout: 10000 + # 命令等待超时,单位:毫秒 + timeout: 3000 + # 发布和订阅连接池大小 + subscriptionConnectionPoolSize: 50 + +--- # RocketMQ 配置 +rocketmq: + # RocketMQ 服务器地址 + name-server: 43.143.227.203:9876 + # 生产者配置 + producer: + # 生产者组名 + group: wzj_prod + # 发送消息超时时间 + send-message-timeout: 30000 + # 消息最大长度 + max-message-size: 4194304 + # 消息发送失败重试次数 + retry-times-when-send-failed: 3 + # 异步消息发送失败重试次数 + retry-times-when-send-async-failed: 3 + # 消费者配置 + consumer: + # 拉取消息最大数量 + pull-batch-size: 10 + # 消费者组 (系统模块) + group: wzj_prod + # 是否启动消费者 + enabled: true +--- # mail 邮件发送 +mail: + enabled: false + host: smtp.163.com + port: 465 + # 是否需要用户名密码验证 + auth: true + # 发送方,遵循RFC-822标准 + from: xxx@163.com + # 用户名(注意:如果使用foxmail邮箱,此处user为qq号) + user: xxx@163.com + # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助) + pass: xxxxxxxxxx + # 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。 + starttlsEnable: true + # 使用SSL安全连接 + sslEnable: true + # SMTP超时时长,单位毫秒,缺省值不超时 + timeout: 0 + # Socket连接超时值,单位毫秒,缺省值不超时 + connectionTimeout: 0 + +--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商 +# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用 +sms: + # 配置源类型用于标定配置来源(interface,yaml) + config-type: yaml + # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制 + restricted: true + # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效 + minute-max: 1 + # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效 + account-max: 30 + # 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中 + blends: + # 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可 + # 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户 + config1: + # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 + supplier: alibaba + # 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。 + access-key-id: 您的accessKey + # 称为accessSecret有些称之为apiSecret + access-key-secret: 您的accessKeySecret + signature: 您的短信签名 + sdk-app-id: 您的sdkAppId + config2: + # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 + supplier: tencent + access-key-id: AKIDvhEVWHm0xe5JGxOZXGitnRovlKcfRzIN + access-key-secret: qPhiTxA7oENFrCH5dvxiCQN4UdWAYgYA + signature: 无终街天津科技 + sdk-app-id: 1400966042 + + +--- # 三方授权 +justauth: + # 前端外网访问地址 + address: http://82.156.121.2:8880/ + type: + alipay_wallet: # 支付宝钱包 + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet + alipay-public-key: MIIB**************DAQAB + wechat_open: # 微信开放平台 + client-id: wxebcdaea31881caab + client-secret: 71826d76bad096ec5407897c6ed1391f + redirect-uri: ${justauth.address}/social-callback?source=wechat_open + wechat_mp: # 微信小程序 + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_mp + wechat_enterprise: # 微信企业 + client-id: 10**********6 + client-secret: 1f7d08**********5b7**********29e + redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise + agent-id: 1000002 + + +# 腾讯云IM配置 +tencent: + im: + enabled: true # 启用腾讯云IM + sdk-app-id: 1600080789 # 你的腾讯云 SDKAppID + secret-key: "311b5309d714a20f7f5b54360ee21b1e24ec208ebcd25ce8f47d24753bccc091" # 你的密钥 + administrator: "administrator" # 管理员账号 + expire-time: 604800 # UserSig 过期时间(7天,单位:秒) + # mongodb + data: + mongodb: + uri: 82.156.121.2:37017 + database: wzj-shop + username: admin + password: A1969bf8 + authentication-database: admin + # replica-set-name: mongoreplset + +easypay: + api-path-prefix: https://phoenix.eycard.cn/yqt + req-id: D01X00000801861 + certificate-id: 20250917 + mcht-code: 531000022034161 + easypay-public-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLLVY70e67BcK4V08P+69dfBeMmMYDopf3HF9G6meqPTVxyGYlEb0XwT0UA6g8t2HzG8FaKgTFKgOvhr+EFbBcF+AYdrgFYZSjR4hWBkWiOyKC66wQ7kQhYzC4kwetcDp5TftJfSivbAC1Lm8/Gf2+ZpaDuHDPjLCFS2gQYI5dqwIDAQAB + merRsaPrivateKey: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDLgDEh0hsPTmHLdEYp6LCo3LMnXMLCV+wUxRn5lvcAa7gn8RZyLDGiT5WdR0SpJDbBhWL1WbnUd7dJulzjbb0N5NzrO3HntjzKIpzhfChw3BBtM3PR8xvS17Wt4vRN6JvY4w0sphKesxbHWiMHUTOzKrQBEdXasMujmxV0N9R2GzTLK0Pn4ROWCzeQQhiJ2oOc3Eqkus9/C+3LcxkU08nF/q0X/kzHGS+Gn+JL/Eo6vpQExg7rQs0mnrKvNuPPGKpyKNpRmKWtiA8GTBeFnwZlP8kYj9Z8NYxLsT6fJnqpZ8wZ++T2PS7CIIo6JSIKz0ElNrRRD2Ei7lyCZAjUBQLLAgMBAAECggEBAIRjGhOBhx8XA+IC+55KBZtlMJub6gvafPgqHbLUtk2sxjodylduTr/j/FY8RfuvVnvhFba9r3n8g93QApvmCUafq+TQYFK4qKVrjRnX1stNLtaL0X41JNWuhT/hVMPWXoTjeO+h/p0Frvzzs7QP7I1Ta5UCkFhcCa6etn9Lzskh0uXe4ylMmt5lAuvFAeIuE5icMxu4n75RXUVxaBSOKjQ0ujQWMh46ncrX0f9oGkDbWE37LF61sf2iuXpPwnIAwk/e/zOpnCi9EHOJtCJbVr+ncDRvlZsEf5hVnxYgT2bQrUrSD9An5e4zgJF6rigsDhmNfvp0W/bJnXPIIg1MYbECgYEA5MlizB9XmttiaAo9sMjAUE18cxgEq2pIU8l8WOj//XAsf64AlrlWJxpJdNYkfdRiinnRIxroo1cYx3RMWqdGbYVk+7DJBNut6R0bg0oGgJoeBFnCe/xNGsBk7MZwc4//5sfRC2rbtuYFPn8VkNB5HllhddD51L6lObAp4Uf14/MCgYEA47TX4AmgcAjhVCUvC4ZUuiqAku/suw0vkG6FNxuSYY5GezPvwWx0JviaohaIm5JkgjNNASFhx12XG+PZoPDNGi9vzotVkI69LnOdlf3imVaJR7u5H8730Thbdd5oKi66KYXJGv3hppwh7qAu8VkdMavvCT24jILNiGiA0OBOE8kCgYA5JoFSgiXNHi5X1O8SISPBK4oB6icIdtU4cOVqBFImCgZjoqCtBgEaZXuh/vhAonQ3KTTv8wHYA6LB+DA2mQCDzUWrhb7BQusPh2DfC/fR2i3TYmStuhm8rADKEMv4YilHifSTSI84Af+fW/mUIi+PQD6TQq+V0EXPwkzD5MjstwKBgQDZZ5SlBwvza8cXe9kK+9pxVJslr4UqolBDagIut1hvZFPO1auX1WCgxMN+9ly/jGoCFdDzv1eH7ceUjVr/2mk5EwmA/m9XcbEWZLSUvK5ZENJJduYthIH/c/t+8jYp8Cs18dIsvzFuzatoFfA75oWFI086V3+YSFrMXlp/E2n4YQKBgQCKiynvzcRA8GoK6ibGhwUc5lpVUOVqpIdmVG5bXbnKYoU7Jkf2pOUwzLQGKOj9KS1Z80jkZA9p22BLKD/VXF0PvGBhx1Ujpil1vd96I/KcGRsmCu3b3AxK7qzDt6Y0nVk5bN72RYq4F/iRU+ijoIAuLsyrn/e0eaJweiqzr/gK4g== + trade-backUrl: http://43.143.227.203:8880/trans/easypay/trade/callback +wechat: + pay: + v3: + mch-id: 1658665710 # 商户号 + mch-serial-no: 6BA681D9B219034D6F7851F57D61BE9317AB48FD # 商户证书序列号 + api-v3-key: T9iE71aHSmjtM35z4bDLuU3gFX8s2I2h # APIv3密钥 + private-key-path: "/java/cert/apiclient_key.pem" # 商户私钥文件路径 + transfer-notify-url: https://wuzhongjie.com.cn/prod-api/trans/withdraw/callback # 转账回调地址 + app-id: wxebcdaea31881caab # 应用ID + secret: 71826d76bad096ec5407897c6ed1391f # 应用密钥 + callback-url: https://wuzhongjie.com.cn/prod-api/app/payment/callback/WECHAT + mini-program: + # app-id: wx87a5db19138da60d + # secret: 856ca8bae38ccaecc1353c9abedf6b41 + app-id: wx2fb87f0f1f05d314 + secret: 86fbcab880e4066ac5c75af6f4f003c2 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index bb6dd58bd..99a6edf14 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -50,8 +50,8 @@ spring: # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) url: jdbc:mysql://mysql:3306/soopin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true - username: wzj - password: A085F27A43B0 + username: wzj_prod + password: Kp8$rT2*jQ6$sH4% # # 从库数据源 # slave: # lazy: true diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java index 953132838..2d2e222f1 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java @@ -311,21 +311,18 @@ public class MemberServiceImpl extends ServiceImpl implemen @Override public IPage getMemberPageList(MemberBO query, Page page) { IPage memeberPage= memberMapper.getMember(page, query); + List records = memeberPage.getRecords(); + + //检查是否是朋友 LoginUser tokenUser = LoginHelper.getLoginUser(); if (tokenUser != null) { - List records = memeberPage.getRecords(); + //去掉本人 + records=records.stream().filter(memberVO -> !memberVO.getId().equals(tokenUser.getUserId())).collect(Collectors.toList()); for (MemberVO memberVO : records) { -// -// boolean followFlag = fansService.queryDoIFollowVloger(tokenUser.getUserId(), memberVO.getId()); -// if(followFlag){ -// memberVO.setFollowFlag(YesOrNo.YES.type); -// }else{ -// memberVO.setFollowFlag(YesOrNo.NO.type); -// } memberVO.setDoIFollowVloger(fansService.queryDoIFollowVloger(tokenUser.getUserId(), memberVO.getId())); - } + } return memeberPage; } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WithdrawController.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WithdrawController.java index 0e4860c5c..19411dec5 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WithdrawController.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WithdrawController.java @@ -108,4 +108,11 @@ public class WithdrawController { return R.ok(service.removeById(id)); } + @Operation(summary = "检查超时") + @GetMapping("/check") + public R check() { + service.checkAndRefundExpiredWithdraws(); + return R.ok(); + } + } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/enums/RedPacketStatus.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/enums/RedPacketStatus.java new file mode 100644 index 000000000..626182688 --- /dev/null +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/enums/RedPacketStatus.java @@ -0,0 +1,21 @@ +package com.wzj.soopin.transaction.enums; + +/** + * 红包状态 + */ +public enum RedPacketStatus { + STATUS_UNRECEIVED(0), + STATUS_PART_RECEIVED(1), + STATUS_ALL_RECEIVED(2), + STATUS_EXPIRED(3), + STATUS_REFUNDED(4); + + private int code; + + RedPacketStatus(int code) { + } + + public int getCode() { + return code; + } +} diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/IWithdrawService.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/IWithdrawService.java index ea420c09f..96689d367 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/IWithdrawService.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/IWithdrawService.java @@ -12,4 +12,8 @@ public interface IWithdrawService extends IService { InitiateBatchTransferResponseNew withdraw (Withdraw withdraw); + void checkAndRefundExpiredWithdraws(); + + + boolean refund(Long id); } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/RedPacketService.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/RedPacketService.java index fc735f012..bd57db12b 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/RedPacketService.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/RedPacketService.java @@ -1,13 +1,20 @@ package com.wzj.soopin.transaction.service; +import com.baomidou.mybatisplus.extension.service.IService; +import com.wzj.soopin.order.domain.entity.RedPacket; import com.wzj.soopin.order.domain.query.GrabRedPacketRequest; import com.wzj.soopin.order.domain.query.SendRedPacketRequest; import java.util.Map; -public interface RedPacketService { +public interface RedPacketService extends IService { Map sendRedPacket(SendRedPacketRequest request); Map grabRedPacket(GrabRedPacketRequest request); + + + void checkAndRefundExpiredRedPackets(); + + void refundRemainingAmount(RedPacket redPacket); } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/RedPacketServiceImpl.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/RedPacketServiceImpl.java index 524ce08dd..3e798d838 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/RedPacketServiceImpl.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/RedPacketServiceImpl.java @@ -1,6 +1,7 @@ package com.wzj.soopin.transaction.service.impl; import cn.hutool.core.date.DateTime; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wzj.soopin.member.enums.AccountBillSourceEnum; import com.wzj.soopin.member.mapper.MemberAccountMapper; @@ -10,6 +11,9 @@ import com.wzj.soopin.order.domain.query.GrabRedPacketRequest; import com.wzj.soopin.order.domain.query.SendRedPacketRequest; import com.wzj.soopin.order.mapper.RedPacketMapper; import com.wzj.soopin.order.mapper.RedPacketReceiveMapper; +import com.wzj.soopin.transaction.domain.po.Withdraw; +import com.wzj.soopin.transaction.enums.RedPacketStatus; +import com.wzj.soopin.transaction.enums.WithdrawStatus; import com.wzj.soopin.transaction.service.IAccountBillService; import com.wzj.soopin.transaction.service.RedPacketService; import lombok.RequiredArgsConstructor; @@ -44,12 +48,7 @@ public class RedPacketServiceImpl extends ServiceImpl 0) { refundRemainingAmount(redPacket); } else { - redPacket.setStatus(STATUS_EXPIRED); + redPacket.setStatus(RedPacketStatus.STATUS_EXPIRED.getCode()); redPacketMapper.updateById(redPacket); throw new BaseException("红包已过期"); } } // 检查是否已领完 - if (redPacket.getStatus() == STATUS_ALL_RECEIVED) { + if (redPacket.getStatus() == RedPacketStatus.STATUS_ALL_RECEIVED.getCode()) { throw new BaseException("红包已被领完"); } @@ -243,7 +242,9 @@ public class RedPacketServiceImpl extends ServiceImpl expiredRedPackets = redPacketMapper.selectExpiredRedPackets(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(RedPacket::getStatus, RedPacketStatus.STATUS_UNRECEIVED.getCode(), RedPacketStatus.STATUS_PART_RECEIVED.getCode()); + queryWrapper.le(RedPacket::getCreateTime, LocalDateTime.now()); + List expiredRedPackets = redPacketMapper.selectList(queryWrapper); for (RedPacket redPacket : expiredRedPackets) { if (redPacket.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0) { refundRemainingAmount(redPacket); } else { - redPacket.setStatus(STATUS_EXPIRED); + redPacket.setStatus(RedPacketStatus.STATUS_EXPIRED.getCode()); redPacketMapper.updateById(redPacket); } } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java index 682020425..e3a7086f2 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java @@ -5,11 +5,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wzj.soopin.content.domain.po.Comment; import com.wzj.soopin.member.domain.po.Member; +import com.wzj.soopin.order.domain.entity.RedPacket; import com.wzj.soopin.transaction.domain.bo.WithdrawBO; import com.wzj.soopin.member.domain.po.MemberAccount; import com.wzj.soopin.member.domain.po.AccountBill; import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferRequestNew; import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferResponseNew; +import com.wzj.soopin.transaction.domain.entity.TransferDetailEntityNew; import com.wzj.soopin.transaction.domain.entity.TransferSceneReportInfoNew; import com.wzj.soopin.transaction.domain.po.Withdraw; import com.wzj.soopin.member.enums.AccountBillChangeTypeEnum; @@ -36,6 +38,8 @@ import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.translation.annotation.Translation; import org.dromara.system.domain.SysTenantAccount; import org.dromara.system.service.ISysTenantAccountService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -95,7 +99,7 @@ public class WithdrawServiceImpl extends ServiceImpl i InitiateBatchTransferRequestNew request = new InitiateBatchTransferRequestNew(); //商户AppID request.setAppid(wechatPayConfig.getAppId()); - //商户单号 + //商户单号 这里使用id request.setOutBillNo(withdraw.getId()+""); request.setTransferAmount(withdraw.getMoney().multiply(BigDecimal.valueOf(100)).intValue()); //转账场景ID @@ -153,6 +157,8 @@ public class WithdrawServiceImpl extends ServiceImpl i + + @Override @Transactional public InitiateBatchTransferResponseNew withdraw (Withdraw withdraw) { @@ -204,4 +210,50 @@ public class WithdrawServiceImpl extends ServiceImpl i MqUtil.sendIMMessage(buildMessage(withdraw, MessageActionEnum.ORDER_WITHDRAW_AUDIT)); return response; } + + @Override + public void checkAndRefundExpiredWithdraws() { + // 查询所有超过24小时的提现 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Withdraw::getStatus, WithdrawStatus.PENDING.getCode()); + queryWrapper.le(Withdraw::getCreateTime, LocalDateTime.now()); + List expiredWithdraws = baseMapper.selectList(queryWrapper); + + for (Withdraw withdraw : expiredWithdraws) { + //检查是否领取,如果没有领取则退回 + TransferDetailEntityNew response = null; + try { + response = wxPayService.getTransferDetailByOutNoNew(withdraw.getId()+""); + } catch (Exception e) { + log.error("查询转账单时发生异常: {}", e.getMessage()); + } + if(response.getState().equals("SUCCESS")) { + //已领取未回调 + //更新状态为已领取,处理回调业务 + withdrawCallback(withdraw.getId()); +// }else if(response.getState().equals("FAIL")){ +// refund(withdraw.getId()); +// } + }else{ + refund(withdraw.getId()); + } + } + } + + @Override + @Transactional + public boolean refund(Long id) { + //更新提现申请单的状态为转账失败 + Withdraw withdraw = getById(id); + if(!withdraw.getStatus().equals(WithdrawStatus.PENDING.getCode())){ + return false; + } + withdraw.setStatus(WithdrawStatus.FAIL.getCode()); + updateById(withdraw); + //生成变动记录 + accountBillService.addMoney(withdraw.getMoney(),withdraw.getMemberId(),AccountBillSourceEnum.WITHDRAW_REFUND,"提现退回"); + //发送消息 + MqUtil.sendIMMessage(buildMessage(withdraw, MessageActionEnum.ORDER_WITHDRAW_REFUSE)); + return true; + } } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/task/RedPacketRefundTask.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/task/RedPacketRefundTask.java new file mode 100644 index 000000000..282accd0d --- /dev/null +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/task/RedPacketRefundTask.java @@ -0,0 +1,52 @@ +package com.wzj.soopin.transaction.task; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.wzj.soopin.order.domain.entity.RedPacket; +import com.wzj.soopin.transaction.enums.RedPacketStatus; +import com.wzj.soopin.transaction.service.RedPacketService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Slf4j +@Component +@RequiredArgsConstructor +public class RedPacketRefundTask { + + private final RedPacketService redPacketService; + + /** + * 每小时执行一次 + */ + @Scheduled(cron = "0 0 * * * ?") + @Transactional(rollbackFor = Exception.class) + public void processScheduledMessages() { + log.info("开始处理红包超时"); + try { + // 查询所有未领取或部分领取且已过期的红包 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(RedPacket::getStatus, RedPacketStatus.STATUS_UNRECEIVED.getCode(), RedPacketStatus.STATUS_PART_RECEIVED.getCode()); + queryWrapper.le(RedPacket::getCreateTime, LocalDateTime.now().minusDays(1)); + List expiredRedPackets = redPacketService.list(queryWrapper); + + for (RedPacket redPacket : expiredRedPackets) { + if (redPacket.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0) { + redPacketService.refundRemainingAmount(redPacket); + } else { + redPacket.setStatus(RedPacketStatus.STATUS_EXPIRED.getCode()); + redPacketService.updateById(redPacket); + } + } + log.info("定时消息处理完成,共处理{}条消息"); + } catch (Exception e) { + log.error("处理定时消息时发生错误", e); + } + } + +} diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/task/WithdrawRefundTask.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/task/WithdrawRefundTask.java new file mode 100644 index 000000000..f6f07f426 --- /dev/null +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/task/WithdrawRefundTask.java @@ -0,0 +1,62 @@ +package com.wzj.soopin.transaction.task; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.wzj.soopin.transaction.domain.entity.TransferDetailEntityNew; +import com.wzj.soopin.transaction.domain.po.Withdraw; +import com.wzj.soopin.transaction.enums.WithdrawStatus; +import com.wzj.soopin.transaction.service.IWithdrawService; +import com.wzj.soopin.transaction.service.RedPacketService; +import com.wzj.soopin.transaction.service.impl.WxPayService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +@Slf4j +@Component +@RequiredArgsConstructor +public class WithdrawRefundTask { + private final IWithdrawService withdrawService; + private final WxPayService wxPayService; + + /** + * 每小时执行一次 + */ + @Scheduled(cron = "0 0 * * * ?") + @Transactional(rollbackFor = Exception.class) + public void processScheduledMessages() { + log.info("开始处理红包超时"); + try { + // 查询所有超过24小时的提现 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Withdraw::getStatus, WithdrawStatus.PENDING.getCode()); + queryWrapper.le(Withdraw::getCreateTime, LocalDateTime.now().minusDays(1)); + List expiredWithdraws = withdrawService.list(queryWrapper); + + for (Withdraw withdraw : expiredWithdraws) { + //检查是否领取,如果没有领取则退回 + TransferDetailEntityNew response = null; + try { + response = wxPayService.getTransferDetailByOutNoNew(withdraw.getId()+""); + } catch (Exception e) { + log.error("查询转账单时发生异常: {}", e.getMessage()); + } + if(response.getState().equals("SUCCESS")){ + //已领取未回调 + //更新状态为已领取,处理回调业务 + withdrawService.withdrawCallback(withdraw.getId()); + }else { + //失败 + withdrawService.refund(withdraw.getId()); + } + } + log.info("定时消息处理完成,共处理{}条消息", 0); + } catch (Exception e) { + log.error("处理定时消息时发生错误", e); + } + } +} diff --git a/script/docker/docker.txt b/script/docker/docker.txt index 3c34c03d3..9ade5160f 100644 --- a/script/docker/docker.txt +++ b/script/docker/docker.txt @@ -59,9 +59,9 @@ docker run -d \ --restart always \ -p 8880:8080 \ --network prod \ - -v /var/local/docker/java/data:/java \ - -v /var/local/docker/java/logs:/logs \ - -v /var/fs/cgroup:/sys/fs/cgroup:ro \ + -v /usr/local/docker/java/data:/java \ + -v /usr/local/docker/java/logs:/logs \ + -v /usr/fs/cgroup:/sys/fs/cgroup:ro \ -e TZ=Asia/Shanghai \ -e JAVA_OPTS="-Xms512m -Xmx800m \ -XX:+UseContainerSupport \