Sfoglia il codice sorgente

feature: 教职工自助
1.自助查询、自助挂失和自助充值服务接口实现
2.对充值业务进行了完善,增加了校验第三方支付是否已入账

luo.yibo@datuai.com 1 anno fa
parent
commit
bea6498547
50 ha cambiato i file con 1281 aggiunte e 184 eliminazioni
  1. 1 0
      ruoyi-api/pom.xml
  2. 27 0
      ruoyi-api/ruoyi-api-consume/pom.xml
  3. 23 0
      ruoyi-api/ruoyi-api-consume/src/main/java/org/dromara/consume/api/RemoteConsumeService.java
  4. 148 0
      ruoyi-api/ruoyi-api-consume/src/main/java/org/dromara/consume/api/domain/bo/RemoteConsumptionBo.java
  5. 146 0
      ruoyi-api/ruoyi-api-consume/src/main/java/org/dromara/consume/api/domain/vo/RemoteUserAccountVo.java
  6. 1 4
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/api/ReturnResult.java
  7. 2 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/RuoYiBackstageApplication.java
  8. 10 8
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtCardtypeServiceImpl.java
  9. 41 3
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/accouunt/UserAccountBusiness.java
  10. 2 2
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/card/CardBusiness.java
  11. 1 2
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/consume/ConsumeBusiness.java
  12. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/consume/strategy/Impl/TermConsumeStrategyImpl.java
  13. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/errfill/ErrFillBusiness.java
  14. 103 51
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/payments/PayBaseBusiness.java
  15. 52 40
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/payments/PayOrderBusiness.java
  16. 113 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/self/SelfBusiness.java
  17. 24 3
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/controller/CardApiController.java
  18. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/controller/PtCardController.java
  19. 2 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/bo/PtCardBo.java
  20. 0 2
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/convert/RemoteCardBoConvert.java
  21. 1 3
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/convert/RemoteCardVoConvert.java
  22. 1 5
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/dubbo/RemoteCardServiceImpl.java
  23. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/mapper/PtCardMapper.java
  24. 8 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/service/IPtCardService.java
  25. 28 2
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/service/impl/PtCardServiceImpl.java
  26. 46 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/controller/self/SelfController.java
  27. 138 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/controller/self/TeacherController.java
  28. 34 15
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/convert/YcVoConvert.java
  29. 43 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/account/AccountInfoVo.java
  30. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/card/InitCardVo.java
  31. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/card/PtCardVo.java
  32. 11 3
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcBagVo.java
  33. 21 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcCardVo.java
  34. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcInitCardVo.java
  35. 25 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcUserAccount.java
  36. 14 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcUserVo.java
  37. 3 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/mq/KafkaNormalConsumer.java
  38. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/controller/PtUserAccountController.java
  39. 7 6
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/bo/PtBagBo.java
  40. 10 13
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/bo/PtUserAccountBo.java
  41. 0 2
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/convert/RemoteUserAccountVoConvert.java
  42. 5 4
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/vo/PtBagVo.java
  43. 1 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/vo/PtUserAccountInfoVo.java
  44. 14 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/service/impl/PtUserAccountServiceImpl.java
  45. 49 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/task/AsyncTaskService.java
  46. 7 1
      ruoyi-server/ruoyi-server-consume/pom.xml
  47. 31 0
      ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/dubbo/RemoteConsumeServiceImpl.java
  48. 6 1
      ruoyi-server/ruoyi-server-mqdata/pom.xml
  49. 26 0
      ruoyi-server/ruoyi-server-mqdata/src/main/java/org/dromara/server/mq/constant/kafka/YktEventContraints.java
  50. 48 0
      ruoyi-server/ruoyi-server-mqdata/src/main/java/org/dromara/server/mq/event/kafka/impl/card/ConsumeEventStrategyImpl.java

+ 1 - 0
ruoyi-api/pom.xml

@@ -14,6 +14,7 @@
         <module>ruoyi-api-resource</module>
         <module>ruoyi-api-workflow</module>
         <module>ruoyi-api-backstage</module>
+        <module>ruoyi-api-consume</module>
     </modules>
 
     <artifactId>ruoyi-api</artifactId>

+ 27 - 0
ruoyi-api/ruoyi-api-consume/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.dromara</groupId>
+        <artifactId>ruoyi-api</artifactId>
+        <version>${revision}</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-api-consume</artifactId>
+
+    <description>
+        ruoyi-api-consume 一卡通消费接口服务模块
+    </description>
+
+    <dependencies>
+
+        <!-- RuoYi Common Core-->
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 23 - 0
ruoyi-api/ruoyi-api-consume/src/main/java/org/dromara/consume/api/RemoteConsumeService.java

@@ -0,0 +1,23 @@
+package org.dromara.consume.api;
+
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.domain.model.ErrorInfo;
+import org.dromara.consume.api.domain.bo.RemoteConsumptionBo;
+
+/**
+ * @ClassName RemoteConsumeService
+ * @Description 消费远程服务接口
+ * @Author luoyibo
+ * @Date 2024-11-12 12:40
+ * @Version 1.0
+ * @since jdk17
+ */
+public interface RemoteConsumeService {
+
+    /**
+     * 处理kafka消费数据
+     * @param bo 消费数据
+     * @return 处理结果
+     */
+    R<ErrorInfo>  dealKafkaConsumeData(RemoteConsumptionBo bo);
+}

+ 148 - 0
ruoyi-api/ruoyi-api-consume/src/main/java/org/dromara/consume/api/domain/bo/RemoteConsumptionBo.java

@@ -0,0 +1,148 @@
+package org.dromara.consume.api.domain.bo;
+
+import lombok.Data;
+import org.dromara.common.core.enums.CreditTypeEnum;
+import org.dromara.common.core.enums.SystemUseTypeEnum;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * name: ConsumeBo
+ * package: org.dromara.backstage.consumption.domain.bo
+ * description: 消费业务对象,和消费相关的业务都使用此业务对象
+ *             属性可能会根据业务动态调整,最早的业务是错扣补款业务
+ * date: 2024-09-04 08:53:02 08:53
+ *
+ * @author luoyibo
+ * @version 0.1
+ * @since JDK 1.8
+ */
+@Data
+public class RemoteConsumptionBo {
+    //region 消费业务基础属性
+    /**
+     * 人员账户Id
+     */
+    private Long userId;
+    /**
+     * 账户流水号
+     */
+    private Long userNo;
+
+    /**
+     * 学/工号
+     */
+    private String userNumb;
+
+    /**
+     * 人员姓名
+     */
+    private String realName;
+
+    /**
+     * 卡流水号
+     */
+    private Long cardNo;
+
+    /**
+     * 物理卡号
+     */
+    private Long factoryId;
+    /**
+     * 钱包代码
+     */
+    private String bagType;
+
+    /**
+     * 消费金额
+     */
+    private BigDecimal consumeMoney;
+
+    /**
+     * 消费钱包余额
+     */
+    private BigDecimal balance;
+    /**
+     * 消费日期
+     */
+    private Date consumeDate;
+
+    /**
+     * 设备机号
+     */
+    private Long termNo;
+
+    /**
+     * 机器流水号
+     */
+    private Long termRecordId;
+    /**
+     * 餐类Id
+     */
+    private Long mealType;
+
+    /**
+     * 消费明细记录Id
+     */
+    private String consumeId;
+
+    /**
+     * 记录Id
+     */
+    private Long recordId;
+    /**
+     * 消费记录标志位?
+     */
+    private Long recordStatus;
+
+    /**
+     * 状态标识(记录消费类型?)
+     */
+    private Integer statusFlag;
+    /**
+     * 系统使用类型
+     */
+    private SystemUseTypeEnum useType;
+    /**
+     * 操作员Id
+     */
+    private Long operatorId;
+    /**
+     * 操作员姓名
+     */
+    private String operatorName;
+
+    /**
+     * 交易类型
+     */
+    private CreditTypeEnum creditType;
+
+    /**
+     * 租户编号
+     */
+    private String tenantId;
+
+    /**
+     * 防伪验证码(记录消费模式的中文信息)
+     */
+    private String digitalSign;
+
+    /**
+     * 原始消费记录Id
+     */
+    private String originalId;
+    //endregion
+
+    //region 错扣补款属性
+    /**
+     * 补款日期
+     */
+    private Date fillDate;
+
+    /**
+     * 操作金额
+     */
+    private BigDecimal operatorMoney;
+    //endregion
+}

+ 146 - 0
ruoyi-api/ruoyi-api-consume/src/main/java/org/dromara/consume/api/domain/vo/RemoteUserAccountVo.java

@@ -0,0 +1,146 @@
+package org.dromara.consume.api.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 一卡通账户视图对象 t_pt_userAccount
+ *
+ * @author LionLi
+ * @date 2024-08-05
+ */
+@Data
+public class RemoteUserAccountVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 账户Id,主键
+     */
+    private Long userId;
+
+    /**
+     * 岗位Id
+     */
+    private Long postId;
+
+    /**
+     * 部门Id
+     */
+    private Long deptId;
+
+    /**
+     * 账户名/登录账号
+     */
+    private String userName;
+
+    /**
+     * 账户编号/工号
+     */
+    private String userNumb;
+
+    /**
+     * 账户姓名
+     */
+    private String realName;
+
+    /**
+     * 账户性别,见sys_user_sex字典类型
+     */
+    private String sex;
+
+    /**
+     * 账户类型(0=内部账户 1=老师 2=学生 3=家长  4=其他人员)
+     */
+    private String category;
+
+    /**
+     * 手机号码
+     */
+    private String phone;
+
+    /**
+     * 身份证号
+     */
+    private String idNumber;
+
+    /**
+     * 一卡通账户状态(0-未开户  1-已开户  -1已销户)
+     */
+    private String accountStatus;
+
+    /**
+     * 账户是否被冻结,见sys_yes_no字典类型
+     */
+    private String freezeStatus;
+
+    /**
+     * 消费密码
+     */
+    private String consumePwd;
+
+    /**
+     * 账户流水号
+     */
+    private Long userNo;
+
+    /**
+     * 账户卡片类型
+     */
+    private Long cardType;
+
+    /**
+     * 账户有效期
+     */
+    private Date lifespan;
+
+     /**
+     * 人脸照片地址
+     */
+    private String photo;
+
+    /**
+     * 唯一身份标识,第三方统一身份认证ID
+     */
+    private String otherId;
+
+    /**
+     * 第三方人员状态
+     */
+    private String userState;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 账户状态,见sys_normal_disable字典类型
+     */
+    private String status;
+
+    /**
+     * 部门名
+     */
+    private String deptName;
+
+    /**
+     * 卡类名
+     */
+    private String cardTypeName;
+
+    /**
+     * 账户余额
+     */
+    private String accountBalance;
+
+    /**
+     * 账户发卡信息
+     */
+    private String accountCard;
+}

+ 1 - 4
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/api/ReturnResult.java

@@ -94,10 +94,7 @@ public class ReturnResult implements IResult{
         return result;
     }
     public static ReturnResult failure(Integer code,String message,Object data) {
-        ReturnResult result = new ReturnResult();
-        result.setCode(code);
-        result.setMessage(message);
-        result.setSuccess(false);
+        ReturnResult result = failure(code, message);
         result.setData(data);
         return result;
     }

+ 2 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/RuoYiBackstageApplication.java

@@ -4,8 +4,8 @@ import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
+import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
 
 /**
  * 系统模块
@@ -15,6 +15,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
 @EnableDubbo
 @SpringBootApplication
 @EnableScheduling
+@EnableAsync
 public class RuoYiBackstageApplication {
     public static void main(String[] args) {
         SpringApplication application = new SpringApplication(RuoYiBackstageApplication.class);

+ 10 - 8
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtCardtypeServiceImpl.java

@@ -46,7 +46,7 @@ public class PtCardtypeServiceImpl implements IPtCardtypeService {
      */
     @Cacheable(cacheNames = CacheNames.PT_CARD_TYPE, key = "#typeId")
     @Override
-    public PtCardtypeVo queryById(Long typeId){
+    public PtCardtypeVo queryById(Long typeId) {
         return baseMapper.selectVoById(typeId);
     }
 
@@ -82,6 +82,7 @@ public class PtCardtypeServiceImpl implements IPtCardtypeService {
         LambdaQueryWrapper<PtCardtype> lqw = Wrappers.lambdaQuery();
         lqw.like(StringUtils.isNotBlank(bo.getTypeName()), PtCardtype::getTypeName, bo.getTypeName());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), PtCardtype::getStatus, bo.getStatus());
+        lqw.eq(bo.getCode() != null, PtCardtype::getCode, bo.getCode());
         lqw.orderByAsc(PtCardtype::getTypeId);
         return lqw;
     }
@@ -119,11 +120,11 @@ public class PtCardtypeServiceImpl implements IPtCardtypeService {
     /**
      * 保存前的数据校验
      */
-    private void validEntityBeforeSave(PtCardtype entity){
+    private void validEntityBeforeSave(PtCardtype entity) {
         LambdaQueryWrapper<PtCardtype> queryWrapper = Wrappers.lambdaQuery();
-        queryWrapper.ne(entity.getTypeId()!=null, PtCardtype::getTypeId, entity.getTypeId())
+        queryWrapper.ne(entity.getTypeId() != null, PtCardtype::getTypeId, entity.getTypeId())
             .and(e -> e.eq(PtCardtype::getTypeName, entity.getTypeName()).or().eq(PtCardtype::getCode, entity.getCode()));
-        if(baseMapper.selectCount(queryWrapper) > 0){
+        if (baseMapper.selectCount(queryWrapper) > 0) {
             throw new ServiceException("卡片类别名称或编号已存在");
         }
     }
@@ -137,11 +138,12 @@ public class PtCardtypeServiceImpl implements IPtCardtypeService {
      */
     @Override
     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if(isValid){
-            //TODO 做一些业务上的校验,判断是否需要校验
+        if (isValid) {
+            // TODO 做一些业务上的校验,判断是否需要校验
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
     /*
      *
      * 通过卡片类别Id查询卡片名称
@@ -171,11 +173,11 @@ public class PtCardtypeServiceImpl implements IPtCardtypeService {
      */
     @Cacheable(cacheNames = CacheNames.PT_CARD_TYPE, key = "#code")
     @Override
-    public PtCardtypeVo queryByCode(Long code){
+    public PtCardtypeVo queryByCode(Long code) {
         PtCardtypeBo bo = new PtCardtypeBo();
         bo.setCode(code);
         List<PtCardtypeVo> list = baseMapper.selectVoList(buildQueryWrapper(bo));
-        return list==null?null:list.get(0);
+        return list == null ? null : list.get(0);
     }
 
 

+ 41 - 3
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/accouunt/UserAccountBusiness.java

@@ -12,17 +12,26 @@ package org.dromara.backstage.business.accouunt;
  */
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.backstage.business.card.CardBusiness;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
+import org.dromara.backstage.cardCenter.service.IPtCardService;
+import org.dromara.backstage.domain.vo.account.AccountInfoVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
+import org.dromara.backstage.payment.domain.bo.PtBagBo;
 import org.dromara.backstage.payment.domain.bo.PtUserAccountBo;
+import org.dromara.backstage.payment.domain.vo.PtBagVo;
+import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.backstage.payment.service.IPtBagService;
 import org.dromara.backstage.payment.service.IPtUserAccountService;
 import org.dromara.common.core.domain.R;
 import org.springframework.stereotype.Service;
 
 import java.text.MessageFormat;
+import java.util.List;
 
 @RequiredArgsConstructor
 @Service
@@ -30,20 +39,22 @@ import java.text.MessageFormat;
 public class UserAccountBusiness {
     private final IPtUserAccountService ptUserAccountService;
     private final IPtBagService bagService;
+    private final IPtCardService cardService;
     private final CardBusiness cardBusiness;
 
     /**
      * 开通一卡通账户
+     *
      * @param bo 一卡通账户业务
      * @return 开通结果
      */
     public R<String> openAccount(PtUserAccountBo bo) {
-        //写账户表
+        // 写账户表
         boolean flag = ptUserAccountService.insertByBo(bo);
         if (flag) {
-            //写账户表成功,初始化钱包表
+            // 写账户表成功,初始化钱包表
             bagService.initAccountBag(bo.getUserId());
-            //钱包表初始化成功,同时发虚拟卡
+            // 钱包表初始化成功,同时发虚拟卡
             PtCardBo cardBo = BeanUtil.copyProperties(bo, PtCardBo.class);
             R<String> rs = cardBusiness.openVirtualCard(cardBo);
             //--------- 设置 流水号和主键id set 到 cardBo
@@ -53,4 +64,31 @@ public class UserAccountBusiness {
         }
         return R.fail(MessageFormat.format("[一卡通开户]-[失败]-[写账户表失败,开户Id:{0}]", bo.getUserId()));
     }
+
+    /**
+     * 查询一卡通账户信息
+     *
+     * @param bo 一卡通账户业务
+     * @return 账户信息:基本信息、账户卡片、账户钱包
+     */
+    public R<AccountInfoVo> getAccountInfo(PtUserAccountBo bo) {
+        PtUserAccountVo ptUserAccountVo = ptUserAccountService.selectVoOneByBo(bo);
+        if (ObjectUtil.isEmpty(ptUserAccountVo)) {
+            return R.fail();
+        }
+        AccountInfoVo accountInfoVo = new AccountInfoVo();
+
+        // 卡片信息
+        List<PtCardVo> cardVos = cardService.queryList(new PtCardBo().setUserId(ptUserAccountVo.getUserId()));
+        if (CollectionUtil.isNotEmpty(cardVos)) {
+            accountInfoVo.setAccountCards(cardVos);
+            ptUserAccountVo.setAccountCard("已发卡");
+        }
+        // 钱包信息
+        List<PtBagVo> bagVos = bagService.queryList(new PtBagBo().setUserId(ptUserAccountVo.getUserId()));
+        accountInfoVo.setAccountBags(bagVos);
+        // 基本信息
+        accountInfoVo.setAccountBase(ptUserAccountVo);
+        return R.ok(accountInfoVo);
+    }
 }

+ 2 - 2
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/card/CardBusiness.java

@@ -10,8 +10,8 @@ import org.dromara.backstage.basics.domain.vo.PtWorkstationVo;
 import org.dromara.backstage.basics.service.IPtParameterService;
 import org.dromara.backstage.basics.service.IPtWorkstationService;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.vo.InitCardVo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.InitCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.payment.domain.bo.PtBagBo;
 import org.dromara.backstage.payment.domain.vo.PtBagVo;

+ 1 - 2
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/consume/ConsumeBusiness.java

@@ -6,13 +6,12 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.backstage.basics.domain.vo.PtMealTypeVo;
 import org.dromara.backstage.basics.service.IPtMealtypeService;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.consumption.domain.bo.*;
 import org.dromara.backstage.consumption.domain.vo.*;
 import org.dromara.backstage.consumption.service.*;
 import org.dromara.backstage.payment.domain.bo.PtBagBo;
-import org.dromara.backstage.payment.domain.bo.PtUserAccountBo;
 import org.dromara.backstage.payment.domain.vo.PtBagVo;
 import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.backstage.payment.service.IPtBagService;

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/consume/strategy/Impl/TermConsumeStrategyImpl.java

@@ -5,7 +5,7 @@ import lombok.RequiredArgsConstructor;
 import org.dromara.backstage.basics.domain.vo.PtMealTypeVo;
 import org.dromara.backstage.business.consume.ConsumeBusiness;
 import org.dromara.backstage.business.consume.strategy.IConsumeStrategy;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.consumption.domain.bo.ConsumptionBo;
 import org.dromara.backstage.consumption.domain.vo.XfConsumeDetailOriginalVo;
 import org.dromara.backstage.consumption.domain.vo.XfConsumeDetailVo;

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/errfill/ErrFillBusiness.java

@@ -6,7 +6,7 @@ import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import org.dromara.backstage.basics.domain.vo.PtMealTypeVo;
 import org.dromara.backstage.basics.service.IPtMealtypeService;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.consumption.domain.bo.ConsumptionBo;
 import org.dromara.backstage.consumption.domain.bo.XfConsumeDetailBo;

+ 103 - 51
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/payments/PayBaseBusiness.java

@@ -1,8 +1,10 @@
 package org.dromara.backstage.business.payments;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -10,7 +12,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.backstage.basics.domain.vo.PtWorkstationVo;
 import org.dromara.backstage.basics.service.IPtWorkstationService;
 import org.dromara.backstage.cardCenter.domain.bo.PtSubsidyitemBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
 import org.dromara.backstage.cardCenter.domain.vo.PtSubsidyitemVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.cardCenter.service.IPtSubsidyitemService;
@@ -25,6 +26,7 @@ import org.dromara.backstage.consumption.service.IXfCreditAccountBackService;
 import org.dromara.backstage.consumption.service.IXfCreditAccountService;
 import org.dromara.backstage.consumption.service.IXfTermService;
 import org.dromara.backstage.consumption.service.IXfUserTotalService;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.payment.domain.bo.PtBagBo;
 import org.dromara.backstage.payment.domain.bo.PurseInOutBo;
 import org.dromara.backstage.payment.domain.vo.PtBagVo;
@@ -32,6 +34,7 @@ import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.backstage.payment.service.IPtBagService;
 import org.dromara.backstage.payment.service.IPtUserAccountService;
 import org.dromara.common.core.constant.Constants;
+import org.dromara.common.core.constant.DefaultConstants;
 import org.dromara.common.core.enums.CreditStatusEnum;
 import org.dromara.common.core.enums.CreditTypeEnum;
 import org.dromara.common.core.exception.payments.PaymentsException;
@@ -69,31 +72,55 @@ public class PayBaseBusiness {
     private final IXfCreditAccountService creditAccountService;
     private final IXfUserTotalService userTotalService;
     private final IPtSubsidyitemService subsidyItemService;
+
+    /**
+     * 校验第三方支付是否已入账
+     *
+     * @param bo 收支对象
+     */
+    public void checkOriginalRecord(PurseInOutBo bo) {
+        if (ObjUtil.isNotEmpty(bo.getCustomerSn())) {
+            String customerSn = bo.getCustomerSn();
+            XfCreditAccountBackBo backBo = new XfCreditAccountBackBo();
+            backBo.setOriginalId(customerSn);
+            List<XfCreditAccountBackVo> list = creditAccountBackService.queryList(backBo);
+            if (CollectionUtil.isNotEmpty(list)) {
+                if (list.parallelStream().anyMatch(
+                    p -> ObjUtil.isNotEmpty(p.getCreditId()) && ObjectUtil.equals(p.getOriginalId(), customerSn))) {
+                    log.info("[{}订单信息验证失败-[该笔支付已入账]-[{}]", bo.getCreditType().message(), JSONUtil.toJsonStr(bo));
+                    throw new PaymentsException(MessageFormat.format("该笔支付已入账,支付流水号:{0}", customerSn));
+                }
+            }
+        }
+    }
+
     /**
      * 检查资金收支的账户信息,资金收支必须有对应的收支账户
+     *
      * @param orderBo 资金收支业务对象
      * @return 账户信息
      */
-    public PtUserAccountVo checkUserAccount(PurseInOutBo orderBo){
+    public PtUserAccountVo checkUserAccount(PurseInOutBo orderBo) {
         PtUserAccountVo userAccountVo = userAccountService.queryById(orderBo.getUserId());
-        if(ObjUtil.isEmpty(userAccountVo)){
-            throw new PaymentsException(MessageFormat.format("无此账户信息,账户Id:{0}",orderBo.getUserId()));
+        if (ObjUtil.isEmpty(userAccountVo)) {
+            throw new PaymentsException(MessageFormat.format("无此账户信息,账户Id:{0}", orderBo.getUserId()));
         }
         return userAccountVo;
     }
 
     /**
      * 检查资金收支对应的卡片信息,只要开通了一卡通账户就可以资金收支,因此卡片信息是可能为空的
+     *
      * @param orderBo 资金收支业务对象
      * @return 卡片信息
      */
-    public PtCardVo checkUserCard(PurseInOutBo orderBo){
+    public PtCardVo checkUserCard(PurseInOutBo orderBo) {
         PtCardVo ptCardVo;
         if (orderBo.getCardId() != null && orderBo.getCardId() > 0) {
-            //如果传入了cardId,根据cardId查询卡片信息
+            // 如果传入了cardId,根据cardId查询卡片信息
             ptCardVo = cardService.queryById(orderBo.getCardId());
         } else {
-            //查询当前人的正常主卡
+            // 查询当前人的正常主卡
             ptCardVo = cardService.queryMainCardByUserId(orderBo.getUserId());
         }
         return ptCardVo;
@@ -101,24 +128,26 @@ public class PayBaseBusiness {
 
     /**
      * 检查资金收支钱包信息,资金收支必须有对应的收支钱包
+     *
      * @param orderBo 资金收支业务对象
      * @return 钱包信息
      */
-    public PtBagVo checkUserBag(PurseInOutBo orderBo){
+    public PtBagVo checkUserBag(PurseInOutBo orderBo) {
         PtBagVo ptBagVo = bagService.queryByUserBagCode(orderBo.getUserId(), orderBo.getBagCode());
-        if(ObjUtil.isEmpty(ptBagVo)){
-            throw new PaymentsException(MessageFormat.format("无此账户钱包信息,账户Id:{0},钱包代码:{1}",orderBo.getUserId(),orderBo.getBagCode()));
+        if (ObjUtil.isEmpty(ptBagVo)) {
+            throw new PaymentsException(MessageFormat.format("无此账户钱包信息,账户Id:{0},钱包代码:{1}", orderBo.getUserId(), orderBo.getBagCode()));
         }
         return ptBagVo;
     }
 
     /**
      * 检查资金收支消费设备信息,有些收支操作是通过专用消费机操作的,设备信息有可能为空
+     *
      * @param orderBo 资金收支业务对象
      * @return 设备信息
      */
-    public XfTermVo checkTerm(PurseInOutBo orderBo){
-        if(orderBo.getTermNo()==null || orderBo.getTermNo()==0L){
+    public XfTermVo checkTerm(PurseInOutBo orderBo) {
+        if (orderBo.getTermNo() == null || orderBo.getTermNo() == 0L) {
             return null;
         }
         return termService.queryByNo(orderBo.getTermNo());
@@ -126,30 +155,33 @@ public class PayBaseBusiness {
 
     /**
      * 检查资金收支消费工作站信息,有些收支操作是通过工作站操作,工作站信息有可能为空
+     *
      * @param orderBo 资金收支业务对象
      * @return 工作站信息
      */
-    public PtWorkstationVo checkWorkStation(PurseInOutBo orderBo){
-        if(orderBo.getStationId()==null || orderBo.getStationId()==0L){
+    public PtWorkstationVo checkWorkStation(PurseInOutBo orderBo) {
+        if (orderBo.getStationId() == null || orderBo.getStationId() == 0L) {
             return null;
         }
-        //这里的工作站Id实际上对应的是工作站的编号
-        return workstationService.queryById(orderBo.getStationId());
+        // 这里的工作站Id实际上对应的是工作站的编号
+        return workstationService.queryVoByNumber(orderBo.getStationId(), DefaultConstants.TENANT_ID);
     }
 
     /**
      * 计算收支操作后的钱包余额
-     * @param bagVo 钱包信息
+     *
+     * @param bagVo   钱包信息
      * @param orderBo 收支订单业务对象
      */
-    public void calculateBalance(PtBagVo bagVo,PurseInOutBo orderBo){
+    public void calculateBalance(PtBagVo bagVo, PurseInOutBo orderBo) {
         if (Objects.requireNonNull(orderBo.getCreditType()) == CreditTypeEnum.COMMISSION_CHARGE) {
-            //管理费实际是不扣钱包余额的
+            // 管理费实际是不扣钱包余额的
             orderBo.setBalance(bagVo.getBalance());
         } else {
             orderBo.setBalance(bagVo.getBalance().add(orderBo.getReceiptMoney()));
         }
     }
+
     /**
      * 收支入账前校验收支原始记录
      *
@@ -171,10 +203,11 @@ public class PayBaseBusiness {
 
     /**
      * 资金收支时计算管理费
+     *
      * @param bo 资金收支业务对象
      * @return 管理费收支业务对象
      */
-     public PurseInOutBo computeCommission(PurseInOutBo bo) {
+    public PurseInOutBo computeCommission(PurseInOutBo bo) {
         if (bo.getTakeCommission().equals(Constants.TAKE_COMMISSION)) {
             Long cardType = bo.getCardTypeId();
             if (bo.getCardTypeId() == null) {
@@ -182,22 +215,23 @@ public class PayBaseBusiness {
                 cardType = accountVo.getCardType();
             }
             bo.setCardTypeId(cardType);
-            //如果要收管理费,则计算管理费
+            // 如果要收管理费,则计算管理费
             PtBagBo bagBo = BeanUtil.copyProperties(bo, PtBagBo.class);
             BigDecimal commission = cardService.computeCommission(bagBo);
             if (commission.compareTo(BigDecimal.ZERO) > 0) {
-                //如果管理费>0,是要入资金收支记录的
+                // 如果管理费>0,是要入资金收支记录的
                 PurseInOutBo commissionBo = new PurseInOutBo();
                 BeanUtil.copyProperties(bo, commissionBo);
                 commissionBo.setReceiptMoney(commission);
                 commissionBo.setCreditType(CreditTypeEnum.COMMISSION_CHARGE);
-                //个人收支入账的金额要减去收掉的管理费
+                // 个人收支入账的金额要减去收掉的管理费
                 bo.setReceiptMoney(bo.getReceiptMoney().subtract(commission));
                 return commissionBo;
             }
         }
         return null;
     }
+
     /**
      * 生成原始收支记录(收支流水备份表)
      *
@@ -208,42 +242,49 @@ public class PayBaseBusiness {
      * @param workstationVo 资金收支工作站信息
      * @return 原始收支记录
      */
-    public XfCreditAccountBackVo createOriginalRecord(PurseInOutBo bo, PtUserAccountVo accountVo, PtCardVo cardVo, PtBagVo bagVo, XfTermVo termVo, PtWorkstationVo workstationVo) {
+    public XfCreditAccountBackVo createOriginalRecord(PurseInOutBo bo, PtUserAccountVo accountVo, PtCardVo cardVo, PtBagVo bagVo, XfTermVo termVo,
+                                                      PtWorkstationVo workstationVo) {
         XfCreditAccountBackBo xfCreditaccountbackBo = new XfCreditAccountBackBo();
         String backId = getRecordKeyId(bo, accountVo, bagVo);
         xfCreditaccountbackBo.setBackId(backId);
 
-        //设置交易数据
+        // 设置交易数据
         xfCreditaccountbackBo.setCreditTime(new Date());
         xfCreditaccountbackBo.setCreditType(bo.getCreditType().code().toString());
         xfCreditaccountbackBo.setReceiptMoney(bo.getReceiptMoney());
         xfCreditaccountbackBo.setPayStyle(bo.getPayStyle());
         xfCreditaccountbackBo.setCreditStatus(CreditStatusEnum.CREATE.code());
         xfCreditaccountbackBo.setUseType(bo.getUseType().code());
-        xfCreditaccountbackBo.setOperatorId(bo.getOperatorId());
+        xfCreditaccountbackBo.setOperatorId(ObjectUtil.isEmpty(bo.getOperatorId()) ? bo.getUserId() : bo.getOperatorId());
+        xfCreditaccountbackBo.setCreateBy(ObjectUtil.isEmpty(bo.getOperatorId()) ? bo.getUserId() : bo.getOperatorId());
+        xfCreditaccountbackBo.setUpdateBy(ObjectUtil.isEmpty(bo.getOperatorId()) ? bo.getUserId() : bo.getOperatorId());
 
-        //设置交易人数据
+        // 设置交易人数据
         xfCreditaccountbackBo.setUserId(bo.getUserId());
 
-        //设置交易卡片数据mq
+        // 设置交易卡片数据mq
         if (ObjUtil.isNotEmpty(cardVo)) {
             xfCreditaccountbackBo.setCardNo(cardVo.getCardNo());
         }
-        //设置账户钱包信息
+        // 设置账户钱包信息
         xfCreditaccountbackBo.setBagType(bagVo.getBagCode());
         xfCreditaccountbackBo.setCardValue(bo.getBalance());
 
-        //设置交易设备信息
+        // 设置交易设备信息
         if (ObjUtil.isNotEmpty(termVo)) {
             xfCreditaccountbackBo.setTermNo(termVo.getTermNo());
             xfCreditaccountbackBo.setTermRecordId(bo.getTermRecordId());
         }
 
-        //设置交易工作站信息
+        // 设置交易工作站信息
         if (ObjUtil.isNotEmpty(workstationVo)) {
-            xfCreditaccountbackBo.setStationId(workstationVo.getStationId());
+            xfCreditaccountbackBo.setStationId(workstationVo.getStationNumb());
+        }
+        // 如果有第三方支付的流水号,需要记入
+        if (ObjUtil.isNotEmpty(bo.getCustomerSn())) {
+            xfCreditaccountbackBo.setOriginalId(bo.getCustomerSn());
         }
-        //原始订单入库
+        // 原始订单入库
         XfCreditAccountBackVo creditAccountBackVo = creditAccountBackService.createOriginalRecord(xfCreditaccountbackBo);
         if (ObjUtil.isEmpty(creditAccountBackVo)) {
             String message = MessageUtils.message("payments.OriginalRecord.create", JSONUtil.parse(bo));
@@ -263,47 +304,51 @@ public class PayBaseBusiness {
      * @param originalId    原始收支记录Id(收支备份表主键)
      * @return 正式收支记录
      */
-    public XfCreditAccountVo keepAccounts(PurseInOutBo bo, PtUserAccountVo accountVo, PtCardVo cardVo, PtBagVo bagVo, XfTermVo termVo, PtWorkstationVo workstationVo, String originalId) {
+    public XfCreditAccountVo keepAccounts(PurseInOutBo bo, PtUserAccountVo accountVo, PtCardVo cardVo, PtBagVo bagVo, XfTermVo termVo,
+                                          PtWorkstationVo workstationVo, String originalId) {
         XfCreditAccountBo xfCreditaccountbo = new XfCreditAccountBo();
         String accountId = getRecordKeyId(bo, accountVo, bagVo);
         xfCreditaccountbo.setCreditId(accountId);
 
-        //设置交易数据
+        // 设置交易数据
         xfCreditaccountbo.setCreditTime(DateUtil.date());
         xfCreditaccountbo.setCreditType(bo.getCreditType().code().toString());
         xfCreditaccountbo.setReceiptMoney(bo.getReceiptMoney());
         xfCreditaccountbo.setPayStyle(bo.getPayStyle());
         xfCreditaccountbo.setUseType(bo.getUseType().code());
 
-        //设置交易账户信息
+        // 设置交易账户信息
         xfCreditaccountbo.setUserId(accountVo.getUserId());
         xfCreditaccountbo.setUserNumb(accountVo.getUserNumb());
         xfCreditaccountbo.setRealName(accountVo.getRealName());
         xfCreditaccountbo.setDeptId(accountVo.getDeptId());
         xfCreditaccountbo.setDeptName(accountVo.getDeptName());
-        //设置设备信息
-        if(ObjUtil.isNotEmpty(termVo)) {
+        // 设置设备信息
+        if (ObjUtil.isNotEmpty(termVo)) {
             xfCreditaccountbo.setTermNo(termVo.getTermNo());
             xfCreditaccountbo.setTermName(termVo.getTermName());
             xfCreditaccountbo.setTermRecordId(bo.getTermRecordId());
         }
-        if(ObjUtil.isNotEmpty(workstationVo)) {
-            //设置工作站信息
+        if (ObjUtil.isNotEmpty(workstationVo)) {
+            // 设置工作站信息
             xfCreditaccountbo.setStationNumb(workstationVo.getStationNumb());
             xfCreditaccountbo.setStationName(workstationVo.getStationName());
         }
-        //设置卡片信息
+        // 设置卡片信息
         xfCreditaccountbo.setCardNo(cardVo.getCardNo());
         xfCreditaccountbo.setCardType(cardVo.getCardType());
         xfCreditaccountbo.setCardCount(bagVo.getRechargeCount() + 1);
         xfCreditaccountbo.setCardTypeName(cardVo.getCardTypeName());
         xfCreditaccountbo.setMainCard(cardVo.getMainCard());
-        //设置钱包信息
+        // 设置钱包信息
         xfCreditaccountbo.setBagType(bagVo.getBagCode());
         xfCreditaccountbo.setCardValue(bo.getBalance());
         // 设置操作员信息
-        xfCreditaccountbo.setOperatorName(bo.getOperatorName());
-        xfCreditaccountbo.setOperatorId(bo.getOperatorId());
+        xfCreditaccountbo.setOperatorName(ObjectUtil.isEmpty(bo.getOperatorName()) ? accountVo.getRealName() : bo.getOperatorName());
+        xfCreditaccountbo.setOperatorId(ObjectUtil.isEmpty(bo.getOperatorId()) ? bo.getUserId() : bo.getOperatorId());
+
+        xfCreditaccountbo.setCreateBy(ObjectUtil.isEmpty(bo.getOperatorId()) ? bo.getUserId() : bo.getOperatorId());
+        xfCreditaccountbo.setUpdateBy(ObjectUtil.isEmpty(bo.getOperatorId()) ? bo.getUserId() : bo.getOperatorId());
 
         xfCreditaccountbo.setOriginalId(originalId);
 
@@ -317,9 +362,10 @@ public class PayBaseBusiness {
 
     /**
      * 处理个人日统计表
-     * @param bo 收支信息
+     *
+     * @param bo        收支信息
      * @param accountVo 账户信息
-     * @param cardVo 账户卡片信息
+     * @param cardVo    账户卡片信息
      */
     public void createOrUpdateUserTotal(PurseInOutBo bo, PtUserAccountVo accountVo, PtCardVo cardVo) {
         XfUserTotalBo xfUserTotalBo = new XfUserTotalBo();
@@ -341,6 +387,7 @@ public class PayBaseBusiness {
 
     /**
      * 更新钱包余额
+     *
      * @param bo 收支业务对象
      * @return 更新后钱包余额
      */
@@ -351,8 +398,9 @@ public class PayBaseBusiness {
 
     /**
      * 更新原始订单的入账状态
-     * @param bo 收支信息
-     * @param status 入账状态
+     *
+     * @param bo        收支信息
+     * @param status    入账状态
      * @param cardValue 入账后账户余额
      */
     public void updateOriginalOrderStatus(PurseInOutBo bo, Integer status, BigDecimal cardValue) {
@@ -361,20 +409,23 @@ public class PayBaseBusiness {
 
     /**
      * 获取待入账的补助明细
+     *
      * @return 补助明细
      */
-    public List<PtSubsidyitemVo> selectPostSubsidyItem(){
+    public List<PtSubsidyitemVo> selectPostSubsidyItem() {
         return subsidyItemService.selectPostSubsidyItem();
     }
 
     /**
      * 更新补助明细的到账状态
+     *
      * @param bo 补助明细
      * @return 更新状态
      */
-    public boolean updatePostSubsidyItemStatus(PtSubsidyitemBo bo){
+    public boolean updatePostSubsidyItemStatus(PtSubsidyitemBo bo) {
         return subsidyItemService.updateByBo(bo);
     }
+
     /**
      * 生成资金收支备份表和收支表的32位主键Id
      *
@@ -392,6 +443,7 @@ public class PayBaseBusiness {
         } else {
             key3 = bo.getReceiptMoney().negate().multiply(a).intValue();
         }
-        return RecordIdUtils.getRecordId(new Date(), Short.parseShort(bo.getCreditType().code().toString()), Integer.parseInt(accountVo.getUserNo().toString()), key3, Integer.parseInt(bagVo.getBagCode()));
+        return RecordIdUtils.getRecordId(new Date(), Short.parseShort(bo.getCreditType().code().toString()),
+                                         Integer.parseInt(accountVo.getUserNo().toString()), key3, Integer.parseInt(bagVo.getBagCode()));
     }
 }

+ 52 - 40
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/payments/PayOrderBusiness.java

@@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.backstage.basics.domain.vo.PtWorkstationVo;
 import org.dromara.backstage.cardCenter.domain.bo.PtSubsidyitemBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.domain.vo.PtSubsidyitemVo;
 import org.dromara.backstage.consumption.domain.vo.XfCreditAccountBackVo;
 import org.dromara.backstage.consumption.domain.vo.XfCreditAccountVo;
@@ -47,11 +47,14 @@ public class PayOrderBusiness {
 
     /**
      * 生成收支原始订单信息,写t_xf_creditAccountBack表
+     *
      * @param orderBo 收支订单业务对象
      * @return 原始订单信息
      */
     public XfCreditAccountBackVo createOrder(PurseInOutBo orderBo) {
-        log.info("[{}订单信息验证-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+        log.info("[{}订单信息验证-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+        // 校验第三方支付入账情况
+        payBaseBusiness.checkOriginalRecord(orderBo);
         // 获取创建订单的辅助信息
         PtUserAccountVo userAccountVo = payBaseBusiness.checkUserAccount(orderBo);
         PtCardVo userCardVo = payBaseBusiness.checkUserCard(orderBo);
@@ -60,22 +63,23 @@ public class PayOrderBusiness {
         PtWorkstationVo workstationVo = payBaseBusiness.checkWorkStation(orderBo);
 
         // 生成原始订单记录
-        log.info("[{}订单验证通过,创建订单]-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+        log.info("[{}订单验证通过,创建订单]-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
         // 生成原始订单记录前先计算收支后的钱包余额,这里只是记录下收支完成后的钱包应有余额,但还没有实际更新钱包余额
-        payBaseBusiness.calculateBalance(userBagVo,orderBo);
+        payBaseBusiness.calculateBalance(userBagVo, orderBo);
         return payBaseBusiness.createOriginalRecord(orderBo, userAccountVo,
-            userCardVo, userBagVo, termVo, workstationVo);
+                                                    userCardVo, userBagVo, termVo, workstationVo);
     }
 
     /**
      * 收支订单入库
      * 写/更新表:收支明细表:t_xf_creditAccount 个人日统计表:t_xf_userTotal 账户钱包表:t_pt_bag
+     *
      * @param orderBo 收支订单业务对象
      * @return 入库后的收支订单业务对象
      */
     @Transactional(rollbackFor = ConsumeException.class)
     public PurseInOutBo postOrder(PurseInOutBo orderBo) {
-        //校验待入库的原始订单
+        // 校验待入库的原始订单
         payBaseBusiness.ValidOriginalRecord(orderBo.getOriginalId());
         // 获取入库订单的辅助信息
         PtUserAccountVo userAccountVo = payBaseBusiness.checkUserAccount(orderBo);
@@ -84,22 +88,23 @@ public class PayOrderBusiness {
         XfTermVo termVo = payBaseBusiness.checkTerm(orderBo);
         PtWorkstationVo workstationVo = payBaseBusiness.checkWorkStation(orderBo);
         // 生成收支明细表
-        log.info("[{}订单处理收支明细]-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
-        XfCreditAccountVo orderDetailVo = payBaseBusiness.keepAccounts(orderBo, userAccountVo, userCardVo, userBagVo, termVo, workstationVo, orderBo.getOriginalId());
+        log.info("[{}订单处理收支明细]-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+        XfCreditAccountVo orderDetailVo = payBaseBusiness.keepAccounts(orderBo, userAccountVo, userCardVo, userBagVo, termVo, workstationVo,
+                                                                       orderBo.getOriginalId());
         orderBo.setCreditId(orderDetailVo.getCreditId());
         orderBo.setBalance(userBagVo.getBalance());
-        //如果交易类型不为收管理费,则继续下面的操作以完成订单入库
-        if(!orderBo.getCreditType().equals(CreditTypeEnum.COMMISSION_CHARGE)){
+        // 如果交易类型不为收管理费,则继续下面的操作以完成订单入库
+        if (!orderBo.getCreditType().equals(CreditTypeEnum.COMMISSION_CHARGE)) {
             // 处理个人日统计表
-            log.info("[{}订单处理人日统计表]-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+            log.info("[{}订单处理人日统计表]-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
             payBaseBusiness.createOrUpdateUserTotal(orderBo, userAccountVo, userCardVo);
 
             // 更新个人钱包余额
-            log.info("[{}订单处理钱包余额]-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+            log.info("[{}订单处理钱包余额]-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
             PtBagVo afterBagVo = payBaseBusiness.updateBalance(orderBo);
             orderBo.setBalance(afterBagVo.getBalance());
             // 入账成功,更新原始订单的入账状态
-            log.info("[{}订单更新入账状态]-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+            log.info("[{}订单更新入账状态]-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
             payBaseBusiness.updateOriginalOrderStatus(orderBo, CreditStatusEnum.SUCCESS.code(), afterBagVo.getBalance());
         }
         return orderBo;
@@ -107,18 +112,19 @@ public class PayOrderBusiness {
 
     /**
      * 普通收支业务处理:充值/批量充值 退款/批量退款
+     *
      * @param orderBo 收支业务对象
      * @return 处理结果
      */
     @Transactional(rollbackFor = ConsumeException.class)
     public R<PurseInOutBo> createNormalOrder(PurseInOutBo orderBo) {
-        //将收支请求写入原始收支记录表
-        log.info("[准备创建{}订单-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+        // 将收支请求写入原始收支记录表
+        log.info("[准备创建{}订单-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
         XfCreditAccountBackVo OriginalOrder = createOrder(orderBo);
         orderBo.setOriginalId(OriginalOrder.getBackId());
 
-        //原始收支记录成功,收支入账
-        log.info("准备[{}订单入账]-[{}]",orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
+        // 原始收支记录成功,收支入账
+        log.info("准备[{}订单入账]-[{}]", orderBo.getCreditType().message(), JSONUtil.toJsonStr(orderBo));
         PurseInOutBo result = postOrder(orderBo);
 
         return R.ok(result);
@@ -126,20 +132,21 @@ public class PayOrderBusiness {
 
     /**
      * 补助收支入账
+     *
      * @return 入账结果
      */
     @Transactional(rollbackFor = ConsumeException.class)
-    public R<Object> createSubsidyOrder(){
+    public R<Object> createSubsidyOrder() {
         List<String> infoList = new ArrayList<>();
         Map<String, Integer> mapCount = new HashMap<>();
-        mapCount.put("successCount",0);
-        mapCount.put("errorCount",0);
-        //获取需要入账的补助明细
+        mapCount.put("successCount", 0);
+        mapCount.put("errorCount", 0);
+        // 获取需要入账的补助明细
         List<PtSubsidyitemVo> list = payBaseBusiness.selectPostSubsidyItem();
-        if(ObjUtil.isEmpty(list)|| list.isEmpty()){
+        if (ObjUtil.isEmpty(list) || list.isEmpty()) {
             return R.fail("[补助到账]-[没有需要入账的补助明细]");
         }
-        list.parallelStream().forEach(item->{
+        list.parallelStream().forEach(item -> {
             PurseInOutBo orderBo = createSubsidyPostBo(item);
             int successCount;
             int errorCount;
@@ -147,21 +154,22 @@ public class PayOrderBusiness {
             try {
                 R<PurseInOutBo> result = createNormalOrder(orderBo);
                 if (result.getCode() == R.SUCCESS) {
-                    //到账成功,更新补助明细的到账状态
+                    // 到账成功,更新补助明细的到账状态
                     item.setGetDate(DateUtil.date());
                     item.setFillStatus("Y");
                     PtSubsidyitemBo bo = BeanUtil.copyProperties(item, PtSubsidyitemBo.class);
                     boolean bl = payBaseBusiness.updatePostSubsidyItemStatus(bo);
-                    if(bl){
+                    if (bl) {
                         successCount = mapCount.get("successCount");
-                        successCount ++;
-                        mapCount.put("successCount",successCount);
+                        successCount++;
+                        mapCount.put("successCount", successCount);
                     }
                 } else {
                     errorCount = mapCount.get("errorCount");
-                    errorCount ++;
-                    mapCount.put("errorCount",errorCount);
-                    infoList.add(MessageFormat.format("[补助到账失败]-[补助信息:{0}]-[错误信息:{1}]", JSONUtil.toJsonStr(orderBo), result.getData().toString()));
+                    errorCount++;
+                    mapCount.put("errorCount", errorCount);
+                    infoList.add(MessageFormat.format("[补助到账失败]-[补助信息:{0}]-[错误信息:{1}]", JSONUtil.toJsonStr(orderBo),
+                                                      result.getData().toString()));
                 }
             } catch (Exception e) {
                 infoList.add(MessageFormat.format("[补助到账失败]-[补助信息:{0}]-[错误信息:{1}]", JSONUtil.toJsonStr(orderBo), e.getMessage()));
@@ -172,22 +180,25 @@ public class PayOrderBusiness {
         log.info(message);
         return R.ok(message);
     }
+
     /**
      * 资金收支时计算管理费
+     *
      * @param bo 资金收支业务对象
      * @return 管理费收支业务对象
      */
-    public PurseInOutBo computeCommission(PurseInOutBo bo){
+    public PurseInOutBo computeCommission(PurseInOutBo bo) {
         return payBaseBusiness.computeCommission(bo);
     }
 
     /**
      * 充值入账
+     *
      * @param bo 充值业务对象
      * @return 入账结果
      */
     @Transactional(rollbackFor = ConsumeException.class)
-    public R<PurseInOutBo> recharge(PurseInOutBo bo){
+    public R<PurseInOutBo> recharge(PurseInOutBo bo) {
         bo.setUseType(SystemUseTypeEnum.CONSUME);
         PurseInOutBo commissionBo = computeCommission(bo);
         try {
@@ -204,7 +215,7 @@ public class PayOrderBusiness {
                 return R.fail(result.getMsg());
             }
         } catch (Exception e) {
-            log.error("充值失败",e);
+            log.error("充值失败", e);
             return R.fail(e.getMessage());
         }
     }
@@ -214,31 +225,32 @@ public class PayOrderBusiness {
      * @return 退款结果
      */
     @Transactional(rollbackFor = ConsumeException.class)
-    public R<PurseInOutBo>refund(PurseInOutBo bo){
-        //校验钱包余额是否充足
+    public R<PurseInOutBo> refund(PurseInOutBo bo) {
+        // 校验钱包余额是否充足
         PurseInOutBo boCopy = BeanUtil.copyProperties(bo, PurseInOutBo.class);
         PtBagVo bagVo = payBaseBusiness.checkUserBag(boCopy);
         if (bagVo.getBalance().compareTo(boCopy.getReceiptMoney()) < 0) {
-            return R.fail(MessageFormat.format("钱包余额不足,当前余额为:{0}", bagVo.getBalance()),boCopy);
+            return R.fail(MessageFormat.format("钱包余额不足,当前余额为:{0}", bagVo.getBalance()), boCopy);
         }
         boCopy.setUseType(SystemUseTypeEnum.CONSUME);
-        //退款是记支出,所以金额设置为负数
+        // 退款是记支出,所以金额设置为负数
         boCopy.setReceiptMoney(boCopy.getReceiptMoney().negate());
         try {
             R<PurseInOutBo> result = createNormalOrder(boCopy);
             if (result.getCode() == R.SUCCESS) {
                 return R.ok(result.getData());
             } else {
-                return R.fail(result.getMsg(),boCopy);
+                return R.fail(result.getMsg(), boCopy);
             }
         } catch (Exception e) {
-            log.error("退款失败",e);
-            return R.fail(e.getMessage(),boCopy);
+            log.error("退款失败", e);
+            return R.fail(e.getMessage(), boCopy);
         }
     }
 
     /**
      * 将要入账的补助信息转成收支订单业务对象
+     *
      * @param item 补助信息
      * @return 收支订单
      */

+ 113 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/self/SelfBusiness.java

@@ -0,0 +1,113 @@
+package org.dromara.backstage.business.self;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.backstage.task.AsyncTaskService;
+import org.dromara.common.core.api.ReturnResult;
+import org.dromara.common.core.enums.CreditTypeEnum;
+import org.dromara.common.core.enums.ResultCodeEnum;
+import org.dromara.common.core.exception.ApiException;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @ClassName SelfBusiness
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-12 21:07
+ * @Version 1.0
+ * @since jdk17
+ */
+@RequiredArgsConstructor
+@Service
+@Slf4j
+public class SelfBusiness {
+    @Value("${third-api.sms-api}")
+    String smsApi;
+    @Value("${third-api.accountName}")
+    String accountName;
+    @Value("${third-api.accountPwd}")
+    String accountPwd;
+    @Value("${third-api.recharge-back-url}")
+    String rechargeBackUrl;
+    @Value("${third-api.pay-api}")
+    String payApi;
+    private final AsyncTaskService asyncTaskService;
+
+    /**
+     * 获取短信平台token
+     */
+    public void loginSms() {
+        Map<String, String> mapAccount = new HashMap<>(2);
+        mapAccount.put("name", accountName);
+        mapAccount.put("pwd", accountPwd);
+
+        String loginUrl = smsApi + "sms/api/v1/login";
+        // String loginUrl = "https://ykt.hnswdx.gov.cn/sms/api/v1/login";
+        HttpRequest req = HttpUtil.createPost(loginUrl);
+        ReturnResult result = JSONUtil.toBean(req.body(JSONUtil.toJsonStr(mapAccount)).execute().body(), ReturnResult.class);
+        log.info("[短信平台登录]-{}", JSONUtil.toJsonStr(result));
+        if(result.isSuccess()){
+            RedisUtils.deleteObject("yktSmsToken");
+            RedisUtils.setCacheObject("yktSmsToken", result.getData().toString());
+        }
+    }
+
+    /**
+     * 发送短信
+      * @param phone 电话号码
+     * @param message 发送内容
+     */
+    public void sendSms(String phone, String message) {
+        if(!RedisUtils.hasKey("yktSmsToken")){
+            loginSms();
+        }
+        asyncTaskService.asyncSendSms(phone, message);
+    }
+
+    public ReturnResult getWechatRechargeQrCode(Map<String, String> mapParams){
+        long cardNo = Long.parseLong(mapParams.get("cardNo"));
+        int termNo = Integer.parseInt(mapParams.get("termNo"));
+        int bagCode = Integer.parseInt(mapParams.get("bagCode"));
+        int workStationNumb = Integer.parseInt(mapParams.get("workStationNumb"));
+        String userId = mapParams.get("userId");
+        String userXm = mapParams.get("userXm");
+        String deptName = mapParams.get("deptName");
+        String deptId = mapParams.get("deptId");
+        String mobile = mapParams.get("mobile");
+        BigDecimal dealValue = new BigDecimal(mapParams.get("dealValue"));
+        String dealDate = mapParams.get("dealDate");
+        String operatorId = mapParams.get("operatorId");
+
+        CreditTypeEnum creditType = CreditTypeEnum.WECHAT_RECHARGE;
+        String callBackUrl = rechargeBackUrl + "/teacher/api/v1/recharge/" + userId + "/" + bagCode + "/" + dealValue + "/" + workStationNumb + "/";
+        return createQrCode(creditType, userId, userXm, deptId, deptName, mobile, dealValue, callBackUrl);
+    }
+
+    private ReturnResult createQrCode(CreditTypeEnum creditType, String userId, String userXm, String deptId, String deptName, String mobile, BigDecimal dealValue, String callBackUrl){
+        String sendUrl = payApi + "?title=" + CreditTypeEnum.WECHAT_RECHARGE.message() + "&userId=" + userId
+                             + "&name=" + userXm
+                             + "&deptName=" + deptName
+                             + "&deptId=" + deptId
+                             + "&mobile=" + Base64.encode(mobile)
+                             + "&amount=" + dealValue
+                             + "&dealType=" + CreditTypeEnum.WECHAT_RECHARGE.code()
+                             + "&callBackUrl=" + callBackUrl;
+        HttpRequest req = HttpUtil.createGet(sendUrl);
+        try(HttpResponse res = req.execute()){
+            return JSONUtil.toBean(res.body(), ReturnResult.class);
+        }catch (Exception e){
+            throw new ApiException("生成微信收款码错误", ResultCodeEnum.INTERFACE_OUTER_INVOKE_ERROR.code());
+        }
+    }
+}

+ 24 - 3
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/controller/CardApiController.java

@@ -6,9 +6,10 @@ import cn.hutool.core.util.ObjectUtil;
 import lombok.RequiredArgsConstructor;
 import org.dromara.backstage.business.card.CardBusiness;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.convert.YcVoConvert;
-import org.dromara.backstage.cardCenter.domain.vo.InitCardVo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.cardCenter.service.IPtCardService;
+import org.dromara.backstage.domain.convert.YcVoConvert;
+import org.dromara.backstage.domain.vo.card.InitCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.common.core.api.ResponseResult;
 import org.dromara.common.core.api.ReturnResult;
 import org.dromara.common.core.constant.DefaultConstants;
@@ -23,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.text.MessageFormat;
 import java.util.Map;
 
 /**
@@ -41,6 +43,7 @@ import java.util.Map;
 @RequestMapping("/card")
 public class CardApiController extends BaseController {
     private final CardBusiness cardBusiness;
+    private final IPtCardService cardService;
 
     @PostMapping("/api/v1/new")
     public ReturnResult initNewCard(@RequestBody Map<String, Object> initParam) {
@@ -86,6 +89,24 @@ public class CardApiController extends BaseController {
         return ReturnResult.success();
     }
 
+    /**
+     * 挂失卡片
+     * @param mapParams 参数
+     * @return 返回结果
+     */
+    @PostMapping("/api/v1/lock")
+    public ReturnResult lockCard(@RequestBody Map<String, String> mapParams){
+        Long cardNo = Long.parseLong(mapParams.get("cardNo"));
+        Long FactorId = Long.parseLong(mapParams.get("factoryFixId"));
+        PtCardBo bo = new PtCardBo().setCardNo(cardNo).setFactoryId(FactorId);
+        PtCardVo vo = cardService.lockCardByBo(bo);
+        if(ObjUtil.isNotEmpty(vo)) {
+            return ReturnResult.success(YcVoConvert.cardVoConvert(vo));
+        }
+        String message = MessageFormat.format("没有对应的卡片信息,卡流水号:{0},物理卡号:{1}", cardNo, FactorId);
+        return ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND.code(), message);
+    }
+
     private PtCardBo getInitInfo(Map<String, Object> initParam) {
         PtCardBo bo = new PtCardBo();
         bo.setUserId(ObjUtil.isNotEmpty(initParam.get("userId")) ? Long.parseLong(initParam.get("userId").toString()) : 0);

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/controller/PtCardController.java

@@ -7,7 +7,7 @@ import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
 import org.dromara.backstage.business.payments.PayOrderBusiness;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.payment.domain.bo.PurseInOutBo;
 import org.dromara.common.core.domain.R;

+ 2 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/bo/PtCardBo.java

@@ -3,6 +3,7 @@ package org.dromara.backstage.cardCenter.domain.bo;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
 import org.dromara.backstage.cardCenter.domain.PtCard;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 
@@ -15,6 +16,7 @@ import java.util.Date;
  * @date 2024-08-06
  */
 @Data
+@Accessors(chain = true)
 @EqualsAndHashCode(callSuper = true)
 @AutoMapper(target = PtCard.class, reverseConvertGenerate = false)
 public class PtCardBo extends BaseEntity {

+ 0 - 2
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/convert/RemoteCardBoConvert.java

@@ -2,9 +2,7 @@ package org.dromara.backstage.cardCenter.domain.convert;
 
 import io.github.linpeilie.BaseMapper;
 import org.dromara.backstage.api.domain.bo.RemoteCardBo;
-import org.dromara.backstage.api.domain.vo.RemoteCardVo;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
 import org.mapstruct.Mapper;
 import org.mapstruct.MappingConstants;
 import org.mapstruct.ReportingPolicy;

+ 1 - 3
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/convert/RemoteCardVoConvert.java

@@ -1,10 +1,8 @@
 package org.dromara.backstage.cardCenter.domain.convert;
 
 import io.github.linpeilie.BaseMapper;
-import org.dromara.backstage.api.domain.bo.RemotePtAreaBo;
 import org.dromara.backstage.api.domain.vo.RemoteCardVo;
-import org.dromara.backstage.basics.domain.bo.PtAreaBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.mapstruct.Mapper;
 import org.mapstruct.MappingConstants;
 import org.mapstruct.ReportingPolicy;

+ 1 - 5
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/dubbo/RemoteCardServiceImpl.java

@@ -2,14 +2,10 @@ package org.dromara.backstage.cardCenter.dubbo;
 
 import lombok.RequiredArgsConstructor;
 import org.apache.dubbo.config.annotation.DubboService;
-import org.dromara.backstage.api.RemoteBagService;
 import org.dromara.backstage.api.RemoteCardService;
-import org.dromara.backstage.api.domain.bo.RemoteCardBo;
 import org.dromara.backstage.api.domain.vo.RemoteCardVo;
-import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
-import org.dromara.backstage.payment.service.IPtBagService;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.springframework.stereotype.Service;
 

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/mapper/PtCardMapper.java

@@ -1,7 +1,7 @@
 package org.dromara.backstage.cardCenter.mapper;
 
 import org.dromara.backstage.cardCenter.domain.PtCard;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 
 /**

+ 8 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/service/IPtCardService.java

@@ -1,6 +1,6 @@
 package org.dromara.backstage.cardCenter.service;
 
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
 import org.dromara.backstage.payment.domain.bo.PtBagBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -159,4 +159,11 @@ public interface IPtCardService {
     PtCardVo selectOneByBo(PtCardBo bo);
 
     PtCardVo saveOrUpdate(PtCardBo bo);
+
+    /**
+     * 根据卡片业务对象挂失卡片并返回挂失后的卡片信息
+     * @param bo 卡片业务对象
+     * @return 挂失后的卡片信息
+     */
+    PtCardVo lockCardByBo(PtCardBo bo);
 }

+ 28 - 2
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/service/impl/PtCardServiceImpl.java

@@ -1,5 +1,6 @@
 package org.dromara.backstage.cardCenter.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjUtil;
@@ -14,9 +15,9 @@ import org.dromara.backstage.basics.service.IPtCardtypeService;
 import org.dromara.backstage.basics.service.IPtParameterService;
 import org.dromara.backstage.cardCenter.domain.PtCard;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
 import org.dromara.backstage.cardCenter.mapper.PtCardMapper;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.payment.domain.bo.PtBagBo;
 import org.dromara.common.core.constant.CacheNames;
 import org.dromara.common.core.constant.Constants;
@@ -83,7 +84,14 @@ public class PtCardServiceImpl implements IPtCardService {
     @Override
     public List<PtCardVo> queryList(PtCardBo bo) {
         LambdaQueryWrapper<PtCard> lqw = buildQueryWrapper(bo);
-        return baseMapper.selectVoList(lqw);
+        List<PtCardVo> list =  baseMapper.selectVoList(lqw);
+        if (ObjUtil.isNotNull(list) && !list.isEmpty()) {
+            list.parallelStream().forEach(p-> {
+                PtCardtypeVo cardTypeVo = cardTypeService.queryByCode(p.getCardType());
+                p.setCardTypeName(cardTypeVo.getTypeName());
+            });
+        }
+        return list;
     }
 
     private LambdaQueryWrapper<PtCard> buildQueryWrapper(PtCardBo bo) {
@@ -397,4 +405,22 @@ public class PtCardServiceImpl implements IPtCardService {
         }
         return null;
     }
+
+    @Override
+    public PtCardVo lockCardByBo(PtCardBo bo) {
+        LambdaUpdateWrapper<PtCard> lpw = new LambdaUpdateWrapper<>();
+        lpw.set(PtCard::getStatus, '2');
+        lpw.set(PtCard::getChangeTime, DateUtil.date());
+        lpw.eq(PtCard::getStatus, '1');
+        lpw.eq(bo.getCardId() != null, PtCard::getCardId, bo.getCardId());
+        lpw.eq(bo.getFactoryId() != null, PtCard::getFactoryId, bo.getFactoryId());
+        lpw.eq(bo.getCardNo() != null, PtCard::getCardNo, bo.getCardNo());
+        if(baseMapper.update(null,lpw)>0){
+            List<PtCardVo> list = this.queryList(bo);
+            if(CollectionUtil.isNotEmpty(list)){
+                return list.get(0);
+            }
+        }
+        return null;
+    }
 }

+ 46 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/controller/self/SelfController.java

@@ -0,0 +1,46 @@
+package org.dromara.backstage.controller.self;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.backstage.business.self.SelfBusiness;
+import org.dromara.common.core.api.ResponseResult;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+/**
+ * @ClassName SelfController
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-12 21:15
+ * @Version 1.0
+ * @since jdk17
+ */
+@RestController("SelfController")
+@ResponseResult
+@RequestMapping("/self")
+@Slf4j
+@RequiredArgsConstructor
+public class SelfController {
+    private final SelfBusiness selfBusiness;
+
+    /**
+     * 发送手机短信
+     * @param mapSendInfo 发送信息
+     */
+    @PostMapping(value = "/api/v1/sendSms")
+    public void sendSms(@RequestBody Map<String, String> mapSendInfo) {
+        String mobile = mapSendInfo.get("mobile");
+        String message = mapSendInfo.get("content");
+
+        selfBusiness.sendSms(mobile, message);
+    }
+
+    @GetMapping("api/v1/wechat/result/{deptId}/{userId}")
+    public boolean queryWxPayResult(@PathVariable("deptId") String deptId,@PathVariable("userId") String userId) {
+        // WxPayDetail getData = selfBusiness.getIsPayByDeptIdAndUserId(deptId,userId);
+        // return getData.isPayStatus();
+
+        return true;
+    }
+}

+ 138 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/controller/self/TeacherController.java

@@ -0,0 +1,138 @@
+package org.dromara.backstage.controller.self;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.backstage.business.accouunt.UserAccountBusiness;
+import org.dromara.backstage.business.payments.PayOrderBusiness;
+import org.dromara.backstage.business.self.SelfBusiness;
+import org.dromara.backstage.domain.convert.YcVoConvert;
+import org.dromara.backstage.domain.vo.account.AccountInfoVo;
+import org.dromara.backstage.payment.domain.bo.PtUserAccountBo;
+import org.dromara.backstage.payment.domain.bo.PurseInOutBo;
+import org.dromara.common.core.api.ResponseResult;
+import org.dromara.common.core.api.ReturnResult;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.enums.*;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @ClassName TeacherController
+ * @Description 教职工自助控制器
+ * @Author luoyibo
+ * @Date 2024-11-08 21:05
+ * @Version 1.0
+ * @since jdk17
+ */
+@RestController("TeacherController")
+@ResponseResult
+@RequestMapping("/teacher")
+@Slf4j
+@RequiredArgsConstructor
+public class TeacherController {
+    private final UserAccountBusiness userAccountBusiness;
+    private final SelfBusiness selfBusiness;
+    private final PayOrderBusiness payOrderBusiness;
+
+    /**
+     * 根据手机号获取教职工信息
+     *
+     * @param mobile 手机号
+     * @return 教职工信息
+     */
+    @GetMapping("/api/v1/account/mobile/{mobile}")
+    public ReturnResult getUserByMobile(@PathVariable("mobile") String mobile) {
+        if (ObjectUtil.isEmpty(mobile)) {
+            return ReturnResult.failure(ResultCodeEnum.PARAM_IS_BLANK, "手机号不能为空");
+        }
+        String dePhone = Base64.decodeStr(mobile);
+        PtUserAccountBo bo = new PtUserAccountBo().setPhone(dePhone).setCategory("1,3,4");
+        R<AccountInfoVo> result = userAccountBusiness.getAccountInfo(bo);
+        if (R.isError(result)) {
+            return ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND, MessageFormat.format("没有手机号[{0}]对应的人员信息", dePhone));
+        }
+        return ReturnResult.success(YcVoConvert.ycUserAccountConvert(result.getData()));
+    }
+
+    /**
+     * 根据身份证号获取教职工信息
+     *
+     * @param identity 身份证号
+     * @return 教职工信息
+     */
+    @GetMapping("/api/v1/account/identity/{identity}")
+    public ReturnResult getUserByIdentity(@PathVariable("identity") String identity) {
+        if (ObjectUtil.isEmpty(identity)) {
+            return ReturnResult.failure(ResultCodeEnum.PARAM_IS_BLANK, "身份证号不能为空");
+        }
+        String deIdentity = Base64.decodeStr(identity);
+        PtUserAccountBo bo = new PtUserAccountBo().setIdNumber(deIdentity).setCategory("1,3,4");
+        R<AccountInfoVo> result = userAccountBusiness.getAccountInfo(bo);
+        if (R.isError(result)) {
+            return ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND, MessageFormat.format("没有身份号[{0}]对应的人员信息", deIdentity));
+        }
+        return ReturnResult.success(YcVoConvert.ycUserAccountConvert(result.getData()));
+    }
+
+    /**
+     * 获取教职工微信充值二维码
+     *
+     * @param mapParams 充值参数
+     * @return 二维码
+     */
+    @PostMapping("/api/v1/wechat/recharge/qrcode")
+    public ReturnResult getWeChatRechargeCode(@RequestBody Map<String, String> mapParams) {
+        ReturnResult result = selfBusiness.getWechatRechargeQrCode(mapParams);
+        Map<String, String> mapReturn = new HashMap<>(2);
+        mapReturn.put("qrCode", result.getData().toString());
+        mapReturn.put("orderSn", result.getMessage());
+
+        return ReturnResult.success(mapReturn);
+    }
+
+    @GetMapping("/api/v1/recharge/{userId}/{bagCode}/{dealValue}/{workStationNumb}/{orderSn}")
+    public boolean wechatRecharge(@PathVariable("userId") String userId
+        , @PathVariable("bagCode") int bagCode, @PathVariable("dealValue") BigDecimal dealValue
+        , @PathVariable("workStationNumb") int workStationNumb, @PathVariable("orderSn") String orderSn) {
+//        String callBackUrl = rechargeBackUrl + "/teacher/api/v1/recharge/" + cardNo + "/" + userId + "/" + bagCode + "/" + dealValue + "/" + workStationNumb + "/";
+        Date transDateTime = new Date();
+        // 收支类型
+        CreditTypeEnum creditType = CreditTypeEnum.RECHARGE;
+        // 支付方式
+        PayStyleEnum payStyle = PayStyleEnum.WECHAT;
+        // 钱包更新类型
+        BalanceUpdateEnum updateType = BalanceUpdateEnum.RECHARGE;
+        PurseInOutBo bo = new PurseInOutBo();
+        bo.setUserId(Long.valueOf(userId));
+        bo.setBagCode(String.valueOf(bagCode));
+        // bo.setBalance();
+        bo.setPayStyle(payStyle.code().toString());
+        bo.setTakeCommission("N");
+        bo.setReceiptMoney(dealValue);
+        bo.setOperationMode(updateType);
+        bo.setCreditType(creditType);
+        // bo.setCardId();
+        // bo.setCardTypeId();
+        // bo.setTermNo();
+        // bo.setTermRecordId();
+        bo.setStationId((long) workStationNumb);
+        // bo.setOperatorId();
+        // bo.setOperatorName();
+        bo.setUseType(SystemUseTypeEnum.CONSUME);
+        // bo.setOriginalId();
+        // bo.setCreditId();
+        bo.setCustomerSn(orderSn);
+        // bo.setPayeeSn();
+
+        R<PurseInOutBo> result = payOrderBusiness.recharge(bo);
+
+        return R.isSuccess(result);
+    }
+}

+ 34 - 15
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/convert/YcVoConvert.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/convert/YcVoConvert.java

@@ -1,13 +1,11 @@
-package org.dromara.backstage.cardCenter.domain.convert;
+package org.dromara.backstage.domain.convert;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
-import org.dromara.backstage.cardCenter.domain.vo.InitCardVo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
-import org.dromara.backstage.cardCenter.domain.vo.yc.YcBagVo;
-import org.dromara.backstage.cardCenter.domain.vo.yc.YcCardVo;
-import org.dromara.backstage.cardCenter.domain.vo.yc.YcInitCardVo;
-import org.dromara.backstage.cardCenter.domain.vo.yc.YcUserVo;
+import org.dromara.backstage.domain.vo.account.AccountInfoVo;
+import org.dromara.backstage.domain.vo.card.InitCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
+import org.dromara.backstage.domain.vo.yc.*;
 import org.dromara.backstage.payment.domain.vo.PtBagVo;
 import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.common.core.constant.DefaultConstants;
@@ -15,6 +13,7 @@ import org.dromara.common.core.enums.CardStatusEnum;
 import org.dromara.common.core.enums.UserAccountStatusEnum;
 import org.dromara.common.core.enums.UserCategoryEnum;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -42,15 +41,15 @@ public class YcVoConvert {
         cardVo.setMainDeputyTypeName(ObjectUtil.equals(vo.getMainCard(), "Y") ? "主卡" : "副卡");
         cardVo.setVersion(0);
         cardVo.setCardTypeName(vo.getCardTypeName());
-        cardVo.setDeposit(vo.getDeposit());
-        cardVo.setIssueFee(vo.getProductCost());
-        cardVo.setCommissionCharge(vo.getCommissionCharge());
-        cardVo.setZheJiuFee(vo.getDepreciation());
+        cardVo.setDeposit(ObjectUtil.equals(vo.getDeposit(),null) ? BigDecimal.ZERO : vo.getDeposit());
+        cardVo.setIssueFee(ObjectUtil.equals(vo.getProductCost(),null) ? BigDecimal.ZERO : vo.getProductCost());
+        cardVo.setCommissionCharge(ObjectUtil.equals(vo.getCommissionCharge(),null) ? BigDecimal.ZERO : vo.getCommissionCharge());
+        cardVo.setZheJiuFee(ObjectUtil.equals(vo.getDepreciation(),null) ? BigDecimal.ZERO : vo.getDepreciation());
 
         return cardVo;
     }
 
-    public static YcUserVo YcUserAccountConvert(PtUserAccountVo vo) {
+    public static YcUserVo YcUserConvert(PtUserAccountVo vo) {
         YcUserVo userVo = new YcUserVo();
         userVo.setUserId(vo.getUserId().toString());
         userVo.setUserXm(vo.getRealName());
@@ -68,14 +67,15 @@ public class YcVoConvert {
         userVo.setUserExpiryDate(DateUtil.format(vo.getLifespan(), DefaultConstants.DATE_TIME_FORMAT));
         userVo.setUserNo(vo.getUserNo().intValue());
         userVo.setPhotoUrl(vo.getPhoto());
-        userVo.setHasCard(null);
+        userVo.setHasCard(vo.getAccountCard());
         userVo.setCollegeName(null);
-
+        userVo.setMobilePhone(vo.getPhone());
         return userVo;
     }
 
     public static YcBagVo ycBagVoConvert(PtBagVo vo) {
         YcBagVo bagVo = new YcBagVo();
+        bagVo.setCardBagId(vo.getBagId());
         bagVo.setBagCode(vo.getBagCode());
         bagVo.setBagName(vo.getBagName());
         bagVo.setBagStatus(1);
@@ -91,7 +91,7 @@ public class YcVoConvert {
 
         ycInitCardVo.setCard(cardVoConvert(vo.getCard()));
 
-        ycInitCardVo.setUser(YcUserAccountConvert(vo.getUser()));
+        ycInitCardVo.setUser(YcUserConvert(vo.getUser()));
 
         List<YcBagVo> ycBagVos = new ArrayList<>();
         vo.getBags().parallelStream().forEach(p -> ycBagVos.add(ycBagVoConvert(p)));
@@ -99,4 +99,23 @@ public class YcVoConvert {
 
         return ycInitCardVo;
     }
+
+    public static YcUserAccount ycUserAccountConvert(AccountInfoVo vo) {
+        YcUserAccount ycUserAccount = new YcUserAccount();
+        ycUserAccount.setUserBase(YcUserConvert(vo.getAccountBase()));
+
+        List<YcBagVo> ycBagVos = new ArrayList<>();
+        vo.getAccountBags().parallelStream().forEach(p -> {
+            ycBagVos.add(ycBagVoConvert(p));
+        });
+        ycUserAccount.setUserBags(ycBagVos);
+
+        List<YcCardVo> ycCardVos = new ArrayList<>();
+        vo.getAccountCards().parallelStream().forEach(p -> {
+            ycCardVos.add(cardVoConvert(p));
+        });
+        ycUserAccount.setUserCards(ycCardVos);
+
+        return ycUserAccount;
+    }
 }

+ 43 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/account/AccountInfoVo.java

@@ -0,0 +1,43 @@
+package org.dromara.backstage.domain.vo.account;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
+import org.dromara.backstage.payment.domain.vo.PtBagVo;
+import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName AccountInfoVo
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-08 21:27
+ * @Version 1.0
+ * @since jdk17
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+public class AccountInfoVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 账户基本信息
+     */
+    private PtUserAccountVo accountBase;
+
+    /**
+     * 账户钱包信息
+     */
+    private List<PtBagVo> accountBags = new ArrayList<>();
+
+    /**
+     * 账户卡片信息
+     */
+    private List<PtCardVo> accountCards = new ArrayList<>();
+}

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/vo/InitCardVo.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/card/InitCardVo.java

@@ -1,4 +1,4 @@
-package org.dromara.backstage.cardCenter.domain.vo;
+package org.dromara.backstage.domain.vo.card;
 
 import lombok.Data;
 import org.dromara.backstage.payment.domain.vo.PtBagVo;

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/vo/PtCardVo.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/card/PtCardVo.java

@@ -1,4 +1,4 @@
-package org.dromara.backstage.cardCenter.domain.vo;
+package org.dromara.backstage.domain.vo.card;
 
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;

+ 11 - 3
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/vo/yc/YcBagVo.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcBagVo.java

@@ -1,4 +1,4 @@
-package org.dromara.backstage.cardCenter.domain.vo.yc;
+package org.dromara.backstage.domain.vo.yc;
 
 import lombok.Data;
 
@@ -18,11 +18,18 @@ import java.math.BigDecimal;
 public class YcBagVo implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
+
+    /**
+     * 钱包Id
+     */
+    private Long cardBagId;
+
     /**
      * 钱包代码
      * 1-消费现金钱包 2-水控钱包 3-消费补助钱包 4-脱机信用钱包 5-就餐钱包 6-配餐钱包
      */
     private String bagCode;
+
     /**
      * 钱包名称
      */
@@ -45,14 +52,15 @@ public class YcBagVo implements Serializable {
     private BigDecimal cardValue;
 
     /**
-     * 用户Id
+     * 人员Id
      */
     private String userId;
 
     /**
-     * 用户编号
+     * 人员编号
      */
     private String userNumb;
+
     /**
      * 充值次数
      */

+ 21 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/vo/yc/YcCardVo.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcCardVo.java

@@ -1,4 +1,4 @@
-package org.dromara.backstage.cardCenter.domain.vo.yc;
+package org.dromara.backstage.domain.vo.yc;
 
 import lombok.Data;
 
@@ -80,6 +80,15 @@ public class YcCardVo implements Serializable {
      * 卡片记录版本号
      */
     private int version;
+
+    /**
+     * 卡片功能类型
+     */
+    private int cardFuncType;
+    /**
+     * 卡片功能类型名称
+     */
+    private String cardFuncTypeName="用户卡";
     //endregion
 
     //region 根据卡片类型关联到的卡片押金、工本费等信息
@@ -108,4 +117,15 @@ public class YcCardVo implements Serializable {
      */
     private  BigDecimal zheJiuFee;
     //endregion
+
+    //region 卡上余额信息
+    /**
+     * 卡上水控余额
+     */
+    private BigDecimal waterBalance=BigDecimal.ZERO;
+    /**
+     * 卡上脱机信用钱包余额
+     */
+    private BigDecimal creditBalance=BigDecimal.ZERO;
+    //endregion
 }

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/vo/yc/YcInitCardVo.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcInitCardVo.java

@@ -1,4 +1,4 @@
-package org.dromara.backstage.cardCenter.domain.vo.yc;
+package org.dromara.backstage.domain.vo.yc;
 
 import lombok.Data;
 

+ 25 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcUserAccount.java

@@ -0,0 +1,25 @@
+package org.dromara.backstage.domain.vo.yc;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @ClassName YcUserAccount
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-08 20:59
+ * @Version 1.0
+ * @since jdk17
+ */
+@Data
+public class YcUserAccount implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    YcUserVo userBase;
+    List<YcBagVo> userBags;
+    List<YcCardVo> userCards;
+}

+ 14 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/domain/vo/yc/YcUserVo.java → ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/domain/vo/yc/YcUserVo.java

@@ -1,4 +1,4 @@
-package org.dromara.backstage.cardCenter.domain.vo.yc;
+package org.dromara.backstage.domain.vo.yc;
 
 import lombok.Data;
 
@@ -63,18 +63,22 @@ public class YcUserVo implements Serializable {
      * 人员性别
      */
     private String userSex;
+
     /**
      * 人员性别名称
      */
     private String userSexName;
+
     /**
      * 人员卡类Id
      */
     private Integer userCardTypeId;
+
     /**
      * 人员卡类名称
      */
     private String userCardTypeName;
+
     /**
      * 人员有效期
      */
@@ -95,6 +99,15 @@ public class YcUserVo implements Serializable {
      */
     private String hasCard;
 
+    /**
+     * 人员手机号
+     */
+    private String mobilePhone;
+
+    /**
+     * 人员身份证号
+     */
+    private String idNumber;
     /**
      * 人员学院名称
      */

+ 3 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/mq/KafkaNormalConsumer.java

@@ -69,6 +69,9 @@ public class KafkaNormalConsumer {
         recordBo.setRecordStatus(Long.valueOf(data.get("posRecordState").toString()));
         recordBo.setCreditType(CreditTypeEnum.TERM_CONSUME);
         recordBo.setTenantId("20200813044411");
+
+
+
         R<Object> result = consumeStrategyContent.createOrder(recordBo);
         XfConsumeDetailOriginalVo vo = (XfConsumeDetailOriginalVo)result.getData();
 

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/controller/PtUserAccountController.java

@@ -10,7 +10,7 @@ import lombok.RequiredArgsConstructor;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.message.kafka.aop.annotation.SyncDataToLocal;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.payment.domain.bo.PtBagBo;
 import org.dromara.backstage.payment.domain.bo.PtUserAccountBo;

+ 7 - 6
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/bo/PtBagBo.java

@@ -1,17 +1,17 @@
 package org.dromara.backstage.payment.domain.bo;
 
-import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
 import org.dromara.backstage.payment.domain.PtBag;
 import org.dromara.common.core.enums.BalanceUpdateEnum;
 import org.dromara.common.core.enums.CreditTypeEnum;
 import org.dromara.common.core.enums.SystemUseTypeEnum;
-import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.common.core.validate.AddGroup;
 import org.dromara.common.core.validate.EditGroup;
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import jakarta.validation.constraints.*;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
 
 import java.math.BigDecimal;
 
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
  * @date 2024-08-06
  */
 @Data
+@Accessors(chain = true)
 @EqualsAndHashCode(callSuper = true)
 @AutoMapper(target = PtBag.class, reverseConvertGenerate = false)
 public class PtBagBo extends BaseEntity {

+ 10 - 13
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/bo/PtUserAccountBo.java

@@ -1,26 +1,22 @@
 package org.dromara.backstage.payment.domain.bo;
 
-import cn.hutool.core.util.DesensitizedUtil;
-import org.dromara.backstage.payment.domain.PtUserAccount;
-import org.dromara.common.encrypt.annotation.EncryptField;
-import org.dromara.common.encrypt.enumd.AlgorithmType;
-import org.dromara.common.mybatis.core.domain.BaseEntity;
-import org.dromara.common.core.validate.AddGroup;
-import org.dromara.common.core.validate.EditGroup;
 import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
-import jakarta.validation.constraints.*;
+import lombok.experimental.Accessors;
+import org.dromara.backstage.payment.domain.PtUserAccount;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.encrypt.annotation.EncryptField;
+import org.dromara.common.encrypt.enumd.AlgorithmType;
+import org.dromara.common.tenant.core.TenantEntity;
 
 import java.io.Serial;
 import java.util.Date;
 import java.util.List;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
-import org.dromara.common.sensitive.annotation.Sensitive;
-import org.dromara.common.sensitive.core.SensitiveStrategy;
-import org.dromara.common.tenant.core.TenantEntity;
-
 /**
  * 一卡通账户业务对象 t_pt_userAccount
  *
@@ -28,6 +24,7 @@ import org.dromara.common.tenant.core.TenantEntity;
  * @date 2024-08-05
  */
 @Data
+@Accessors(chain = true)
 @EqualsAndHashCode(callSuper = true)
 @AutoMapper(target = PtUserAccount.class, reverseConvertGenerate = false)
 public class PtUserAccountBo extends TenantEntity {

+ 0 - 2
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/convert/RemoteUserAccountVoConvert.java

@@ -1,9 +1,7 @@
 package org.dromara.backstage.payment.domain.convert;
 
 import io.github.linpeilie.BaseMapper;
-import org.dromara.backstage.api.domain.vo.RemoteCardVo;
 import org.dromara.backstage.api.domain.vo.RemoteUserAccountVo;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
 import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.mapstruct.Mapper;
 import org.mapstruct.MappingConstants;

+ 5 - 4
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/vo/PtBagVo.java

@@ -1,17 +1,17 @@
 package org.dromara.backstage.payment.domain.vo;
 
-import org.dromara.backstage.payment.domain.PtBag;
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;
-import org.dromara.common.excel.annotation.ExcelDictFormat;
-import org.dromara.common.excel.convert.ExcelDictConvert;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
+import lombok.experimental.Accessors;
+import org.dromara.backstage.payment.domain.PtBag;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
-import java.util.Date;
 
 
 
@@ -22,6 +22,7 @@ import java.util.Date;
  * @date 2024-08-06
  */
 @Data
+@Accessors(chain = true)
 @ExcelIgnoreUnannotated
 @AutoMapper(target = PtBag.class)
 public class PtBagVo implements Serializable {

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/vo/PtUserAccountInfoVo.java

@@ -1,7 +1,7 @@
 package org.dromara.backstage.payment.domain.vo;
 
 import lombok.Data;
-import org.dromara.backstage.cardCenter.domain.vo.PtCardVo;
+import org.dromara.backstage.domain.vo.card.PtCardVo;
 
 import java.io.Serial;
 import java.io.Serializable;

+ 14 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/service/impl/PtUserAccountServiceImpl.java

@@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.backstage.basics.service.IPtCardtypeService;
 import org.dromara.backstage.cardCenter.domain.bo.PtCardBo;
 import org.dromara.backstage.cardCenter.service.IPtCardService;
 import org.dromara.backstage.payment.domain.PtUserAccount;
@@ -62,6 +63,7 @@ public class PtUserAccountServiceImpl implements IPtUserAccountService {
     private final PtUserAccountMapper baseMapper;
     private final IPtCardService ptCardService;
     private final IPtBagService bagService;
+    private final IPtCardtypeService cardTypeService;
     //private final CardBusiness cardBusiness;
 
     @DubboReference
@@ -147,7 +149,15 @@ public class PtUserAccountServiceImpl implements IPtUserAccountService {
         lqw.like(StringUtils.isNotBlank(bo.getNickName()), PtUserAccount::getNickName, bo.getNickName());
         lqw.like(StringUtils.isNotBlank(bo.getRealName()), PtUserAccount::getRealName, bo.getRealName());
         lqw.eq(StringUtils.isNotBlank(bo.getSex()), PtUserAccount::getSex, bo.getSex());
-        lqw.eq(StringUtils.isNotBlank(bo.getCategory()), PtUserAccount::getCategory, bo.getCategory());
+        if(StringUtils.isNotBlank(bo.getCategory())){
+            List<String> list = Arrays.asList(bo.getCategory().split(","));
+            if(list.size()>1){
+                lqw.in(StringUtils.isNotBlank(bo.getCategory()), PtUserAccount::getCategory, list);
+            } else{
+                lqw.eq(PtUserAccount::getCategory, bo.getCategory());
+            }
+        }
+
         lqw.eq(StringUtils.isNotBlank(bo.getEmail()), PtUserAccount::getEmail, bo.getEmail());
         lqw.eq(StringUtils.isNotBlank(bo.getAddress()), PtUserAccount::getAddress, bo.getAddress());
         lqw.eq(StringUtils.isNotBlank(bo.getPhone()), PtUserAccount::getPhone, bo.getPhone());
@@ -518,6 +528,9 @@ public class PtUserAccountServiceImpl implements IPtUserAccountService {
                 String deptName = remoteDeptService.selectDeptNameByIds(vo.getDeptId().toString());
                 vo.setDeptName(deptName);
 
+                String cardTypeName = cardTypeService.queryByCode(vo.getCardType()).getTypeName();
+                vo.setCardTypeName(cardTypeName);
+
                 RedisUtils.addCacheList(CacheNames.PT_USER_ACCOUNT, vo);
                 return vo;
             }

+ 49 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/task/AsyncTaskService.java

@@ -0,0 +1,49 @@
+package org.dromara.backstage.task;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.api.ReturnResult;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @ClassName AsyncTaskService
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-12 21:00
+ * @Version 1.0
+ * @since jdk17
+ */
+@Slf4j
+@Service
+public class AsyncTaskService {
+    @Value("${third-api.sms-api}")
+    String smsApi;
+
+    public void asyncSendSms(String mobile, String message) {
+        String keyToken = "yktSmsToken";
+        String sendUrl = smsApi + "sms/api/v1/send";
+        String tokens = RedisUtils.getCacheObject(keyToken);
+        Map<String, String> mapHeaders = new HashMap<>(2);
+        mapHeaders.put("businessName","ykt");
+        mapHeaders.put("token", tokens);
+
+        Map<String, String> mapMessages = new HashMap<>(2);
+        mapMessages.put("mobile", mobile);
+        mapMessages.put("message", message);
+        try {
+            HttpRequest req = HttpUtil.createPost(sendUrl);
+            req.headerMap(mapHeaders,false);
+            ReturnResult sendResult = JSONUtil.toBean(req.body(JSONUtil.toJsonStr(mapMessages)).execute().body(), ReturnResult.class);
+            log.info("[短信发送]-{\"内容\":\"{}\",\"结果\":\"{}\"", message, sendResult.getMessage());
+        } catch (Exception ex) {
+            log.info("[短信发送]-{\"内容\":\"{}\",\"发送异常\":\"{}\"", message, ex.getMessage());
+        }
+    }
+}

+ 7 - 1
ruoyi-server/ruoyi-server-consume/pom.xml

@@ -98,7 +98,7 @@
             <groupId>org.dromara</groupId>
             <artifactId>ruoyi-api-system</artifactId>
         </dependency>
-        <dependency>
+         <dependency>
             <groupId>cn.com.kingbase</groupId>
             <artifactId>kingbase8</artifactId>
         </dependency>
@@ -108,6 +108,12 @@
             <version>2.2.0</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-api-consume</artifactId>
+            <version>2.2.0</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 31 - 0
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/dubbo/RemoteConsumeServiceImpl.java

@@ -0,0 +1,31 @@
+package org.dromara.server.consume.dubbo;
+
+import cn.hutool.core.bean.BeanUtil;
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.domain.model.ErrorInfo;
+import org.dromara.consume.api.RemoteConsumeService;
+import org.dromara.consume.api.domain.bo.RemoteConsumptionBo;
+import org.dromara.server.common.domain.consume.bo.ConsumptionBo;
+import org.dromara.server.consume.business.ConsumeBusiness;
+import org.springframework.stereotype.Service;
+
+/**
+ * @ClassName RemoteConsumeServiceImpl
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-12 13:17
+ * @Version 1.0
+ * @since jdk17
+ */
+@RequiredArgsConstructor
+@Service
+@DubboService
+public class RemoteConsumeServiceImpl implements RemoteConsumeService {
+    private final ConsumeBusiness consumeBusiness;
+    @Override
+    public R<ErrorInfo> dealKafkaConsumeData(RemoteConsumptionBo bo) {
+        return consumeBusiness.fullOrder(BeanUtil.copyProperties(bo, ConsumptionBo.class));
+    }
+}

+ 6 - 1
ruoyi-server/ruoyi-server-mqdata/pom.xml

@@ -98,7 +98,6 @@
             <groupId>org.dromara</groupId>
             <artifactId>ruoyi-api-system</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.dromara</groupId>
             <artifactId>ruoyi-api-resource</artifactId>
@@ -123,6 +122,12 @@
             <version>2.2.0</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-api-consume</artifactId>
+            <version>2.2.0</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 26 - 0
ruoyi-server/ruoyi-server-mqdata/src/main/java/org/dromara/server/mq/constant/kafka/YktEventContraints.java

@@ -0,0 +1,26 @@
+package org.dromara.server.mq.constant.kafka;
+
+/**
+ * @ClassName YktEventContraints
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-12 11:46
+ * @Version 1.0
+ * @since jdk17
+ */
+public class YktEventContraints {
+    /**
+     * 一卡通业务系统编号
+     */
+    public static final String SENDER = "005";
+
+    // 消费记录
+    public static final String CONSUME_DETAIL = SENDER + "00001";
+    // 报道状态
+    public static final String CHECKIN_STATE = SENDER + "00002";
+    // 缴费状态
+    public static final String PayStatus = SENDER + "00003";
+
+    // 卡片信息
+    public static final String CARD_INFO = SENDER + "00004";
+}

+ 48 - 0
ruoyi-server/ruoyi-server-mqdata/src/main/java/org/dromara/server/mq/event/kafka/impl/card/ConsumeEventStrategyImpl.java

@@ -0,0 +1,48 @@
+package org.dromara.server.mq.event.kafka.impl.card;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONObject;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.constant.DefaultConstants;
+import org.dromara.common.core.enums.CreditTypeEnum;
+import org.dromara.consume.api.RemoteConsumeService;
+import org.dromara.consume.api.domain.bo.RemoteConsumptionBo;
+import org.dromara.server.mq.constant.kafka.YktEventContraints;
+import org.dromara.server.mq.event.kafka.IEventStrategy;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+/**
+ * @ClassName ConsumeEventStrategyImpl
+ * @Description TODO
+ * @Author luoyibo
+ * @Date 2024-11-12 11:52
+ * @Version 1.0
+ * @since jdk17
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service(YktEventContraints.CONSUME_DETAIL)
+public class ConsumeEventStrategyImpl implements IEventStrategy {
+    private final RemoteConsumeService remoteConsumeService;
+    @Override
+    public void doMsgHandle(JSONObject data) {
+        RemoteConsumptionBo recordBo = new RemoteConsumptionBo();
+        String time = data.get("consumeDate").toString();
+        recordBo.setConsumeMoney(new BigDecimal(data.get("consumeValue").toString()));
+        recordBo.setConsumeDate(DateUtil.parse(time));
+        recordBo.setCardNo(Long.valueOf(data.get("cardNo").toString()));
+        recordBo.setFactoryId(Long.valueOf(data.get("factoryFixId").toString()));
+        recordBo.setTermNo(Long.valueOf( data.get("termNo").toString()));
+        recordBo.setTermRecordId(Long.valueOf(data.get("termRecordID").toString()));
+        recordBo.setRealName(data.get("xm").toString());
+        recordBo.setUserNumb(data.get("userNumb").toString());
+        recordBo.setRecordStatus(Long.valueOf(data.get("posRecordState").toString()));
+        recordBo.setCreditType(CreditTypeEnum.TERM_CONSUME);
+        recordBo.setTenantId(DefaultConstants.TENANT_ID);
+
+        remoteConsumeService.dealKafkaConsumeData(recordBo);
+    }
+}