From c79a494a58c633deb607f2e880f2ea1f6d9eea64 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期一, 15 十二月 2025 09:39:07 +0800
Subject: [PATCH] Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/jiashida

---
 ruoyi-system/src/main/java/com/ruoyi/system/model/TPhysicalGoods.java                   |   13 
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                         |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUser.java                         |   16 
 ruoyi-applet/src/main/resources/icbcpay/icbc-config-dev.yml                             |   55 ++++
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java      |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TPhysicalGoodsServiceImpl.java |   15 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java      |   22 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/TPhysicalGoodsService.java          |   11 
 ruoyi-system/lib/icbc-api-sdk-cop-io.jar                                                |    0 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java                |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/enums/ICBCRespOrderErrorEnum.java           |   52 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java                   |    7 
 ruoyi-system/lib/hsm-software-share-1.0.5.jar                                           |    0 
 ruoyi-system/lib/icbc-api-sdk-cop.jar                                                   |    0 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java                          |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserService.java                |    9 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java                        |    5 
 ruoyi-system/pom.xml                                                                    |   14 +
 ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java                 |   22 -
 ruoyi-applet/pom.xml                                                                    |    1 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java            |   86 ++++++
 ruoyi-system/src/main/java/com/ruoyi/system/vo/SupervisorUserVO.java                    |   22 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java       |   34 ++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java        |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TBigGiftPackage.java                  |   13 
 ruoyi-applet/src/main/resources/icbcpay/icbc-config-test.yml                            |   56 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/query/AppletPhysicalGoodsQuery.java         |   17 +
 ruoyi-applet/src/main/resources/icbcpay/icbc-config-prod.yml                            |   56 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/config/IcbcConfig.java                      |  136 ++++++++++
 ruoyi-system/src/main/java/com/ruoyi/system/utils/ICBCPayUtil.java                      |   80 ++++++
 ruoyi-system/lib/icbc-ca.jar                                                            |    0 
 31 files changed, 709 insertions(+), 52 deletions(-)

diff --git a/ruoyi-applet/pom.xml b/ruoyi-applet/pom.xml
index 2e585f6..4828583 100644
--- a/ruoyi-applet/pom.xml
+++ b/ruoyi-applet/pom.xml
@@ -186,6 +186,7 @@
                 <version>2.5.15</version>
                 <configuration>
                     <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                    <includeSystemScope>true</includeSystemScope> <!-- 本地jar包打包-->
                 </configuration>
                 <executions>
                     <execution>
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
index 1c0ddd3..a00f7d9 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
@@ -1,29 +1,84 @@
 package com.ruoyi.web.controller.api;
 
+import cn.hutool.core.util.PhoneUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUserApplet;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.model.TAppUser;
 import com.ruoyi.system.model.TBanner;
-import com.ruoyi.system.service.TBannerService;
+import com.ruoyi.system.model.TBigGiftPackage;
+import com.ruoyi.system.model.TPhysicalGoods;
+import com.ruoyi.system.query.AppletPhysicalGoodsQuery;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.vo.SupervisorUserVO;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 
+import javax.validation.constraints.NotNull;
 import java.util.List;
+import java.util.Objects;
 
 @Slf4j
 @RestController
 @RequestMapping("/index")
 @Api(tags = "首页模块")
+@Validated
 @RequiredArgsConstructor(onConstructor_ = {@Lazy})
 public class IndexController {
 
     private final TBannerService tBannerService;
+    private final TAppUserService tAppUserService;
+    private final TokenService tokenService;
+    private final ISysUserService sysUserService;
+    private final TBigGiftPackageService bigGiftPackageService;
+    private final TPhysicalGoodsService physicalGoodsService;
 
+    @ApiOperation("根据推广码获取上级用户信息")
+    @GetMapping("/getSuperiorInfo")
+    public R<SupervisorUserVO> getSuperiorInfo(@ApiParam(name = "superiorType", value = "上级类型 1:股东;2:营销员")
+                                               @NotNull(message = "上级类型不能为空") @RequestParam Integer superiorType,
+                                               @ApiParam(name = "spreadCode", value = "推广码")
+                                               @NotNull(message = "推广码不能为空") @RequestParam String spreadCode) {
+        SupervisorUserVO supervisorUserVO = new SupervisorUserVO();
+        //根据上级类型获取上级用户信息
+        if (superiorType.equals(1)) {
+            SysUser sysUser = sysUserService.selectByCode(spreadCode);
+            if (Objects.nonNull(sysUser)) {
+                supervisorUserVO.setId(sysUser.getUserId().intValue());
+                supervisorUserVO.setPhone((String) PhoneUtil.hideBetween(sysUser.getPhonenumber()));
+                supervisorUserVO.setNickName(sysUser.getNickName());
+                supervisorUserVO.setAvatar(""); //todo 设置默认头像
+            }
+        } else {
+            tAppUserService.lambdaQuery().eq(TAppUser::getCode, spreadCode).ne(TAppUser::getStatus, 3).last("LIMIT 1").oneOpt()
+                    .ifPresent(appUser -> {
+                        supervisorUserVO.setId(appUser.getId());
+                        supervisorUserVO.setPhone((String) PhoneUtil.hideBetween(appUser.getPhone()));
+                        supervisorUserVO.setAvatar(appUser.getProfilePhoto());
+                        supervisorUserVO.setNickName(appUser.getName());
+                    });
+        }
+        return R.ok(supervisorUserVO);
+    }
+
+    @ApiOperation("确认上级用户-接受邀请")
+    @GetMapping("/confirmSuperior")
+    public R<?> confirmSuperior(@ApiParam(name = "superiorType", value = "上级类型 1:股东;2:营销员")
+                                @NotNull(message = "上级类型不能为空") @RequestParam Integer superiorType,
+                                @ApiParam(name = "superiorId", value = "上级用户ID")
+                                @NotNull(message = "上级ID不能为空") @RequestParam Integer superiorId) {
+        LoginUserApplet loginUserApplet = tokenService.getLoginUserApplet();
+        tAppUserService.confirmSuperior(superiorType, superiorId, loginUserApplet);
+        return R.ok();
+    }
 
     @ApiOperation(value = "首页模块--轮播图",response = TBanner.class)
     @GetMapping(value = "/getBannerList")
@@ -38,5 +93,26 @@
         TBanner tBanner = tBannerService.getById(id);
         return R.ok(tBanner);
     }
+    @ApiOperation("获取大礼包列表")
+    @GetMapping("/big-gift/list")
+    public R<List<TBigGiftPackage>> getBigGiftList() {
+        return R.ok(bigGiftPackageService.list());
+    }
 
+    @ApiOperation("大礼包商品详情")
+    @GetMapping("/big-gift/detail/{id}")
+    public R<TBigGiftPackage> getBigGiftDetail(@ApiParam(name = "id", value = "大礼包ID") @PathVariable Integer id) {
+        return R.ok(bigGiftPackageService.getById(id));
+    }
+
+    @ApiOperation("实物商品分页列表")
+    @PostMapping("/physical-goods/page")
+    public R<IPage<TPhysicalGoods>> getPhysicalGoodsPageList(@RequestBody AppletPhysicalGoodsQuery query) {
+        return R.ok(physicalGoodsService.getPageList(query));
+    }
+    @ApiOperation("实物商品详情")
+    @GetMapping("/physical-goods/detail/{id}")
+    public R<TPhysicalGoods> getPhysicalGoodsDetail(@ApiParam(name = "id", value = "实物商品ID")@PathVariable Integer id) {
+        return  R.ok(physicalGoodsService.getById(id));
+    }
 }
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index 3bde689..e6a7770 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -140,7 +140,7 @@
         return ajax;
     }
 
-    @ApiOperation(value = "通过code获得openid,获取用户信息",tags = {"微信小程序登录"})
+    @ApiOperation(value = "通过code获得openid,获取用户信息")
     @PostMapping("/openIdByJsCode")
     public R<Map<String, Object>> openIdByJsCode(@RequestBody AppletUserEncrypteData data) {
         log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", data.getCode());
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
index db25016..9d2d175 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
@@ -1,26 +1,22 @@
 package com.ruoyi.web.core.config;
 
-import java.util.ArrayList;
-import java.util.List;
+import com.ruoyi.common.config.RuoYiConfig;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.models.auth.In;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import com.ruoyi.common.config.RuoYiConfig;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.models.auth.In;
 import springfox.documentation.builders.ApiInfoBuilder;
 import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.service.ApiKey;
-import springfox.documentation.service.AuthorizationScope;
-import springfox.documentation.service.Contact;
-import springfox.documentation.service.SecurityReference;
-import springfox.documentation.service.SecurityScheme;
+import springfox.documentation.service.*;
 import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spi.service.contexts.SecurityContext;
 import springfox.documentation.spring.web.plugins.Docket;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Swagger2的接口配置
@@ -113,9 +109,9 @@
         // 用ApiInfoBuilder进行定制
         return new ApiInfoBuilder()
                 // 设置标题
-                .title("标题:移动社区管理系统_接口文档")
+                .title("嘉视达小程序接口文档")
                 // 描述
-                .description("移动社区接口文档")
+                .description("嘉视达小程序接口文档")
                 // 作者信息
                 .contact(new Contact(ruoyiConfig.getName(), null, null))
                 // 版本
diff --git a/ruoyi-applet/src/main/resources/icbcpay/icbc-config-dev.yml b/ruoyi-applet/src/main/resources/icbcpay/icbc-config-dev.yml
new file mode 100644
index 0000000..4fa3ef7
--- /dev/null
+++ b/ruoyi-applet/src/main/resources/icbcpay/icbc-config-dev.yml
@@ -0,0 +1,55 @@
+icbc:
+  api:
+    # 聚合支付B2C线上消费下单接口url (无界面)
+    pay-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1"
+
+    # 订单拆分请求url
+    suborder-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/sersuborder/V1"
+
+    # 订单拆分前退款url
+    refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/merrefund/V1"
+
+    # 订单拆分后退款url
+    sub-order-refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/sersuborder/V1"
+
+    # 订单支付查询url
+    order-pay-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/orderqry/V1"
+
+    # 订单退款查询url
+    order-refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/refundqry/V1"
+
+    # 完整的回调通知地址,支付完成后通知商户的URL
+    notify-url: ""
+
+    # 回调方法的路径
+    notify-url-method: "/icbc/icbcNotify"
+
+
+
+  keys:
+    # 我方私钥,用于签名请求
+    my-private-key: ""
+    # 对方(即工行)网关公钥,用于验证返回的签名
+    api-gw-public-key: ""
+
+  # APP的编号,应用在API开放平台注册时生成
+  app-id: ""
+
+  # 商户编号,用于标识商户账户
+  mer-id: ""
+
+  # 收单产品协议编号,商户与银行的协议编号
+  mer-prtcl-no: ""
+
+  # 设备号,设备的唯一标识符
+  decive-info: ""
+
+  # 微信APP的编号,便于与微信支付接口对接
+  wx-app-id: ""
+
+  # 微信公众号的APP编号,供公众号支付使用
+  wx-gzh-app-id: ""
+
+  # 订单超时时间,单位为分钟
+  expire-time: "300"
+
diff --git a/ruoyi-applet/src/main/resources/icbcpay/icbc-config-prod.yml b/ruoyi-applet/src/main/resources/icbcpay/icbc-config-prod.yml
new file mode 100644
index 0000000..232ff6a
--- /dev/null
+++ b/ruoyi-applet/src/main/resources/icbcpay/icbc-config-prod.yml
@@ -0,0 +1,56 @@
+icbc:
+  api:
+    # 聚合支付B2C线上消费下单接口url (无界面)
+    pay-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1"
+
+    # 订单拆分请求url
+    suborder-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/sersuborder/V1"
+
+    # 订单拆分前退款url
+    refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/merrefund/V1"
+
+    # 订单拆分后退款url
+    sub-order-refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/sersuborder/V1"
+
+    # 订单支付查询url
+    order-pay-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/orderqry/V1"
+
+    # 订单退款查询url
+    order-refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/refundqry/V1"
+
+    # 完整的回调通知地址,支付完成后通知商户的URL
+    notify-url: ""
+
+    # 回调方法的路径
+    notify-url-method: "/icbc/icbcNotify"
+
+
+
+  keys:
+    # 我方私钥,用于签名请求
+    my-private-key: ""
+
+    # 对方(即工行)网关公钥,用于验证返回的签名
+    api-gw-public-key: ""
+
+  # APP的编号,应用在API开放平台注册时生成
+  app-id: ""
+
+  # 商户编号,用于标识商户账户
+  mer-id: ""
+
+  # 收单产品协议编号,商户与银行的协议编号
+  mer-prtcl-no: ""
+
+  # 设备号,设备的唯一标识符
+  decive-info: ""
+
+  # 微信APP的编号,便于与微信支付接口对接
+  wx-app-id: ""
+
+  # 微信公众号的APP编号,供公众号支付使用
+  wx-gzh-app-id: ""
+
+  # 订单超时时间,单位为分钟
+  expire-time: "300"
+
diff --git a/ruoyi-applet/src/main/resources/icbcpay/icbc-config-test.yml b/ruoyi-applet/src/main/resources/icbcpay/icbc-config-test.yml
new file mode 100644
index 0000000..232ff6a
--- /dev/null
+++ b/ruoyi-applet/src/main/resources/icbcpay/icbc-config-test.yml
@@ -0,0 +1,56 @@
+icbc:
+  api:
+    # 聚合支付B2C线上消费下单接口url (无界面)
+    pay-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1"
+
+    # 订单拆分请求url
+    suborder-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/sersuborder/V1"
+
+    # 订单拆分前退款url
+    refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/merrefund/V1"
+
+    # 订单拆分后退款url
+    sub-order-refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/sersuborder/V1"
+
+    # 订单支付查询url
+    order-pay-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/orderqry/V1"
+
+    # 订单退款查询url
+    order-refund-url: "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/refundqry/V1"
+
+    # 完整的回调通知地址,支付完成后通知商户的URL
+    notify-url: ""
+
+    # 回调方法的路径
+    notify-url-method: "/icbc/icbcNotify"
+
+
+
+  keys:
+    # 我方私钥,用于签名请求
+    my-private-key: ""
+
+    # 对方(即工行)网关公钥,用于验证返回的签名
+    api-gw-public-key: ""
+
+  # APP的编号,应用在API开放平台注册时生成
+  app-id: ""
+
+  # 商户编号,用于标识商户账户
+  mer-id: ""
+
+  # 收单产品协议编号,商户与银行的协议编号
+  mer-prtcl-no: ""
+
+  # 设备号,设备的唯一标识符
+  decive-info: ""
+
+  # 微信APP的编号,便于与微信支付接口对接
+  wx-app-id: ""
+
+  # 微信公众号的APP编号,供公众号支付使用
+  wx-gzh-app-id: ""
+
+  # 订单超时时间,单位为分钟
+  expire-time: "300"
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
index cee9882..456349a 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -38,6 +38,7 @@
             "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
             "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
             "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+    private static final DateTimeFormatter FORMATTER_WITH_T = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
 
     /**
      * 获取当前Date型日期
@@ -408,4 +409,8 @@
         return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
     }
 
+    public static String getCurrentDateTimeWithT() {
+        LocalDateTime now = LocalDateTime.now();
+        return now.format(FORMATTER_WITH_T);
+    }
 }
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
index d217081..638e95d 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -24,6 +24,7 @@
 import com.ruoyi.system.service.TAppUserService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -59,6 +60,9 @@
     private SysPermissionService permissionService;
     @Autowired
     private TAppUserService tAppUserService;
+
+    @Value("${spring.profiles.active}")
+    private String env;
 
     /**
      * 登录验证
@@ -203,12 +207,20 @@
             log.info("登录用户:{} 已被删除.", username);
             throw new ServiceException(MessageUtils.message("user.password.delete"));
         }
-        // 校验验证码
-        Object cacheObject = redisCache.getCacheObject(user.getPhone());
-        if(!code.equals(String.valueOf(cacheObject))){
-            log.info("登录用户:{} 短信验证码错误{}", username,code);
-            throw new ServiceException("短信验证码错误");
+        if ("test".equals(env) || "dev".equals(env)) {
+            if (!code.equals("111111")) {
+                log.info("登录用户:{} 短信验证码错误{}", username,code);
+                throw new ServiceException("短信验证码错误");
+            }
+        } else {
+            // 校验验证码
+            Object cacheObject = redisCache.getCacheObject(user.getPhone());
+            if(!code.equals(String.valueOf(cacheObject))){
+                log.info("登录用户:{} 短信验证码错误{}", username,code);
+                throw new ServiceException("短信验证码错误");
+            }
         }
+
         AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
         LoginUserApplet loginUser = new LoginUserApplet(user.getId(), null, null, null);
         recordAppLoginInfo(loginUser.getUserId().toString());
diff --git a/ruoyi-system/lib/hsm-software-share-1.0.5.jar b/ruoyi-system/lib/hsm-software-share-1.0.5.jar
new file mode 100644
index 0000000..486426b
--- /dev/null
+++ b/ruoyi-system/lib/hsm-software-share-1.0.5.jar
Binary files differ
diff --git a/ruoyi-system/lib/icbc-api-sdk-cop-io.jar b/ruoyi-system/lib/icbc-api-sdk-cop-io.jar
new file mode 100644
index 0000000..0d07f05
--- /dev/null
+++ b/ruoyi-system/lib/icbc-api-sdk-cop-io.jar
Binary files differ
diff --git a/ruoyi-system/lib/icbc-api-sdk-cop.jar b/ruoyi-system/lib/icbc-api-sdk-cop.jar
new file mode 100644
index 0000000..1c902ed
--- /dev/null
+++ b/ruoyi-system/lib/icbc-api-sdk-cop.jar
Binary files differ
diff --git a/ruoyi-system/lib/icbc-ca.jar b/ruoyi-system/lib/icbc-ca.jar
new file mode 100644
index 0000000..870b73b
--- /dev/null
+++ b/ruoyi-system/lib/icbc-ca.jar
Binary files differ
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
index a19e805..3718ac8 100644
--- a/ruoyi-system/pom.xml
+++ b/ruoyi-system/pom.xml
@@ -99,6 +99,20 @@
             <artifactId>wechatpay-apache-httpclient</artifactId>
             <version>0.4.9</version>
         </dependency>
+        <dependency>
+            <groupId>icbc-api-sdk-cop</groupId>
+            <artifactId>com.icbc</artifactId>
+            <version>1.0.0</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/lib/icbc-api-sdk-cop.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>icbc-api-sdk-cop-io</groupId>
+            <artifactId>com.icbc</artifactId>
+            <version>1.0.0</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/lib/icbc-api-sdk-cop-io.jar</systemPath>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/config/IcbcConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/config/IcbcConfig.java
new file mode 100644
index 0000000..774274e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/config/IcbcConfig.java
@@ -0,0 +1,136 @@
+package com.ruoyi.system.config;
+
+import com.icbc.api.DefaultIcbcClient;
+import com.icbc.api.IcbcConstants;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description:
+ * @author: yangchuan
+ * @create: 2024-11-18 17:10
+ */
+@Component
+@Data
+public class IcbcConfig {
+
+    /**
+     * 聚合支付B2C线上消费下单接口url (无界面)
+     */
+    @Value("${icbc.api.pay-url}")
+    private String apiPayUrl;
+
+    /**
+     * 订单拆分请求url
+     */
+    @Value("${icbc.api.suborder-url}")
+    private String apiSubOrderUrl;
+
+    /**
+     * 订单拆分前退款url
+     */
+    @Value("${icbc.api.refund-url}")
+    private String refundUrl;
+
+    /**
+     * 订单拆分后退款url
+     */
+    @Value("${icbc.api.sub-order-refund-url}")
+    private String subOrderRefundUrl;
+
+    /**
+     * 订单支付查询url
+     */
+    @Value("${icbc.api.order-pay-url}")
+    private String selectOrderPayUrl;
+
+    /**
+     * 订单退款查询url
+     */
+    @Value("${icbc.api.order-refund-url}")
+    private String selectOrderRefundUrl;
+
+
+    /**
+     * 我方私钥,用于签名请求
+     */
+    @Value("${icbc.keys.my-private-key}")
+    private String myPrivateKey;
+
+    /**
+     * 对方(即工行)网关公钥,用于验证返回的签名
+     */
+    @Value("${icbc.keys.api-gw-public-key}")
+    private String apiGwPublicKey;
+
+    /**
+     * APP编号
+     */
+    @Value("${icbc.app-id}")
+    private String appId;
+
+    /**
+     * 商户编号
+     */
+    @Value("${icbc.mer-id}")
+    private String merId;
+
+    /**
+     * 收单产品协议编号
+     */
+    @Value("${icbc.mer-prtcl-no}")
+    private String merPrtclNo;
+
+    /**
+     * 设备号
+     */
+    @Value("${icbc.decive-info}")
+    private String deciveInfo;
+
+    /**
+     * 完整回调通知地址
+     */
+    @Value("${icbc.api.notify-url}")
+    private String notifyUrl;
+
+    /**
+     * 完整回调通知地址
+     */
+    @Value("${icbc.api.notify-url-method}")
+    private String notifyUrlMethod;
+
+    /**
+     * 微信APP编号
+     */
+    @Value("${icbc.wx-app-id}")
+    private String wxAppId;
+
+    /**
+     * 微信公众号APP编号
+     */
+    @Value("${icbc.wx-gzh-app-id}")
+    private String wxGzhAppId;
+
+    /**
+     * 订单超时时间,单位为分钟
+     */
+    @Value("${icbc.expire-time}")
+    private String expireTime;
+
+    private volatile static DefaultIcbcClient instance = null;
+
+    public static DefaultIcbcClient getInstance(IcbcConfig icbcConfig) {
+        if (instance == null) {
+            synchronized (IcbcConfig.class) {
+                if (instance == null) {
+                    instance = new DefaultIcbcClient(icbcConfig.appId, IcbcConstants.SIGN_TYPE_RSA2, icbcConfig.myPrivateKey, icbcConfig.apiGwPublicKey);
+                }
+            }
+        }
+        return instance;
+    }
+
+}
+
+
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/enums/ICBCRespOrderErrorEnum.java b/ruoyi-system/src/main/java/com/ruoyi/system/enums/ICBCRespOrderErrorEnum.java
new file mode 100644
index 0000000..7e0654f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/enums/ICBCRespOrderErrorEnum.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum ICBCRespOrderErrorEnum {
+
+    SUCCESS("0", "成功"),
+    INVALID_PARAMETER("400011", "参数非法,原因可能为app id为空、app id非法、签名为空、应用系统时间与API平台系统时间不在限定差值以内、时间戳非法"),
+    API_NOT_FOUND("500018", "访问的API不存在"),
+    ILLEGAL_CALL("500020", "非法调用"),
+    MISSING_APP_PUBLIC_KEY("400016", "app公钥未维护"),
+    SIGNATURE_VERIFICATION_FAILED("400017", "签名验证失败"),
+    AUTHORIZATION_FAILED("400019", "授权验证失败"),
+    RATE_LIMIT_EXCEEDED("500031", "速率超限"),
+    CONCURRENCY_LIMIT_EXCEEDED("500032", "并发超限"),
+    PROXY_EXCEPTION("-500041", "代理异常"),
+    PROXY_TIMEOUT("-500042", "代理超时"),
+    GATEWAY_SIGNATURE_FAILED("-500044", "网关签名失败"),
+    GATEWAY_CONFIG_ERROR("500043", "网关配置文件错误,无法从配置文件中读取配置"),
+    GATEWAY_INTERNAL_ERROR("-500099", "网关内部异常"),
+    PARAMS_ERROR("20000000", "输入参数检查失败"),
+    SERVICE_UNKNOWN_ERROR("20000001", "Service层未知的服务异常"),
+    UNKNOWN_ERROR("-100000", "未知异常");
+
+    // 异常码
+    private String errorCode;
+    // 错误信息
+    private String errorMsg;
+
+    // 根据错误码查找错误信息
+    public static String getMessageByCode(String errorCode) {
+        for (ICBCRespOrderErrorEnum error : values()) {
+            if (error.getErrorCode().equals(errorCode)) {
+                return error.getErrorMsg();
+            }
+        }
+        return "未知错误";
+    }
+
+    // 根据错误码获取对应的枚举
+    public static ICBCRespOrderErrorEnum fromCode(String errorCode) {
+        for (ICBCRespOrderErrorEnum error : values()) {
+            if (error.getErrorCode().equals(errorCode)) {
+                return error;
+            }
+        }
+        return UNKNOWN_ERROR;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
index 38fd3bd..2810457 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -189,4 +189,11 @@
     int deleteUserByOldUserId(@Param("oldUserId")Long oldUserId);
 
     void updateUserInherit(SysUser user);
+
+    /**
+     * 根据推广码获取股东用户信息
+     * @param spreadCode
+     * @return
+     */
+    SysUser selectByCode(@Param("spreadCode") String spreadCode);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUser.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUser.java
index 79eff6b..07eb0e2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUser.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUser.java
@@ -1,17 +1,18 @@
 package com.ruoyi.system.model;
 
-import java.math.BigDecimal;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.IdType;
-import java.time.LocalDate;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 
 /**
  * <p>
@@ -105,5 +106,8 @@
     @TableField("status")
     private Integer status;
 
+    @ApiModelProperty(value = "股东ID")
+    @TableField("referrer_sys_user_id")
+    private Integer referrerSysUserId;
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TBigGiftPackage.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TBigGiftPackage.java
index 7614b53..2698527 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TBigGiftPackage.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TBigGiftPackage.java
@@ -1,16 +1,14 @@
 package com.ruoyi.system.model;
 
-import java.math.BigDecimal;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
 
 /**
  * <p>
@@ -90,6 +88,7 @@
 
     @ApiModelProperty(value = "状态 1=使用中 0=删除")
     @TableField("status")
+    @TableLogic
     private Integer status;
 
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TPhysicalGoods.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TPhysicalGoods.java
index d4029f5..aa2ce45 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TPhysicalGoods.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TPhysicalGoods.java
@@ -1,16 +1,14 @@
 package com.ruoyi.system.model;
 
-import java.math.BigDecimal;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
 
 /**
  * <p>
@@ -74,6 +72,7 @@
 
     @ApiModelProperty(value = "删除状态:1-未删除,0-已删除")
     @TableField("status")
+    @TableLogic
     private Integer status;
 
     @ApiModelProperty(value = "销量")
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/AppletPhysicalGoodsQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/AppletPhysicalGoodsQuery.java
new file mode 100644
index 0000000..6f3fb83
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/AppletPhysicalGoodsQuery.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.query;
+
+import com.ruoyi.common.core.domain.BasePage;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("实物商品查询对象")
+public class AppletPhysicalGoodsQuery extends BasePage {
+
+    @ApiModelProperty(value = "商品名称")
+    private String name;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
index f346b98..903e9d5 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -5,6 +5,7 @@
 import com.ruoyi.system.query.SysUserQuery;
 import com.ruoyi.system.vo.SysUserVO;
 
+import javax.validation.constraints.NotNull;
 import java.util.List;
 
 /**
@@ -289,4 +290,6 @@
     int deleteUserByOldUserId(Long oldUserId);
 
     void updateUserInherit(SysUser user);
+
+    SysUser selectByCode(@NotNull(message = "推广码不能为空") String spreadCode);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserService.java
index 9bbd030..6c6b5ff 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserService.java
@@ -2,6 +2,7 @@
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.core.domain.model.LoginUserApplet;
 import com.ruoyi.system.model.TAppUser;
 import com.ruoyi.system.query.AppUserListQuery;
 
@@ -17,4 +18,12 @@
 
     PageInfo<TAppUser> pageList(AppUserListQuery query);
 
+    /**
+     * 确认上级用户
+     *
+     * @param superiorType
+     * @param superiorId
+     * @param loginUserApplet
+     */
+    void confirmSuperior(Integer superiorType, Integer superiorId, LoginUserApplet loginUserApplet);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TPhysicalGoodsService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TPhysicalGoodsService.java
index c893f92..55a09e7 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TPhysicalGoodsService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TPhysicalGoodsService.java
@@ -1,7 +1,9 @@
 package com.ruoyi.system.service;
 
-import com.ruoyi.system.model.TPhysicalGoods;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.system.model.TPhysicalGoods;
+import com.ruoyi.system.query.AppletPhysicalGoodsQuery;
 
 /**
  * <p>
@@ -12,5 +14,10 @@
  * @since 2025-12-08
  */
 public interface TPhysicalGoodsService extends IService<TPhysicalGoods> {
-
+    /**
+     * 分页查询实物商品
+     * @param query
+     * @return
+     */
+    IPage<TPhysicalGoods> getPageList(AppletPhysicalGoodsQuery query);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index 66328f8..0e187b3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -722,4 +722,9 @@
     public SysUser selectByPhone(String phonenumber) {
         return userMapper.selectByPhone(phonenumber);
     }
+
+    @Override
+    public SysUser selectByCode(String spreadCode) {
+        return userMapper.selectByCode(spreadCode);
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java
index 2a6b7ca..10ded02 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java
@@ -2,13 +2,21 @@
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUserApplet;
 import com.ruoyi.system.mapper.TAppUserMapper;
 import com.ruoyi.system.model.TAppUser;
 import com.ruoyi.system.query.AppUserListQuery;
+import com.ruoyi.system.service.ISysUserService;
 import com.ruoyi.system.service.TAppUserService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * <p>
@@ -18,8 +26,11 @@
  * @author xiaochen
  * @since 2025-11-06
  */
+@Slf4j
 @Service
+@RequiredArgsConstructor(onConstructor_ = {@Lazy})
 public class TAppUserServiceImpl extends ServiceImpl<TAppUserMapper, TAppUser> implements TAppUserService {
+    private final ISysUserService sysUserService;
 
     @Override
     public PageInfo<TAppUser> pageList(AppUserListQuery query) {
@@ -28,4 +39,27 @@
         pageInfo.setRecords( list);
         return pageInfo;
     }
+
+    @Override
+    public void confirmSuperior(Integer superiorType, Integer superiorId, LoginUserApplet loginUserApplet) {
+        TAppUser appUser = this.lambdaQuery().eq(TAppUser::getId, loginUserApplet.getUserId()).ne(TAppUser::getStatus,3)
+                .last("LIMIT 1").one();
+        if (Objects.nonNull(appUser)) {
+            if (superiorType.equals(1)) {
+                //查询上级用户所属公司ID
+                SysUser sysUser = sysUserService.selectUserById(superiorId.longValue());
+                if (Objects.nonNull(sysUser)) {
+                    appUser.setReferrerSysUserId(superiorId);
+                } else {
+                    log.info("推广员不存在,绑定superiorId={}", superiorId);
+                }
+            } else {
+                if (appUser.getReferrerStatus().equals(1)) {
+                    appUser.setReferrerUserId(superiorId);
+                    appUser.setReferrerTime(LocalDateTime.now());
+                }
+            }
+            this.updateById(appUser);
+        }
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TPhysicalGoodsServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TPhysicalGoodsServiceImpl.java
index cace487..1bc0fd1 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TPhysicalGoodsServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TPhysicalGoodsServiceImpl.java
@@ -1,9 +1,12 @@
 package com.ruoyi.system.service.impl;
 
-import com.ruoyi.system.model.TPhysicalGoods;
-import com.ruoyi.system.mapper.TPhysicalGoodsMapper;
-import com.ruoyi.system.service.TPhysicalGoodsService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.system.mapper.TPhysicalGoodsMapper;
+import com.ruoyi.system.model.TPhysicalGoods;
+import com.ruoyi.system.query.AppletPhysicalGoodsQuery;
+import com.ruoyi.system.service.TPhysicalGoodsService;
 import org.springframework.stereotype.Service;
 
 /**
@@ -16,5 +19,9 @@
  */
 @Service
 public class TPhysicalGoodsServiceImpl extends ServiceImpl<TPhysicalGoodsMapper, TPhysicalGoods> implements TPhysicalGoodsService {
-
+    @Override
+    public IPage<TPhysicalGoods> getPageList(AppletPhysicalGoodsQuery query) {
+        return this.lambdaQuery().like(TPhysicalGoods::getName, query.getName())
+                .page(new Page<>(query.getPageNum(), query.getPageSize()));
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/ICBCPayUtil.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/ICBCPayUtil.java
new file mode 100644
index 0000000..d1692a2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/ICBCPayUtil.java
@@ -0,0 +1,80 @@
+package com.ruoyi.system.utils;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.icbc.api.DefaultIcbcClient;
+import com.icbc.api.IcbcApiException;
+import com.icbc.api.request.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1;
+import com.icbc.api.response.CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.WebUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.system.config.IcbcConfig;
+import com.ruoyi.system.enums.ICBCRespOrderErrorEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+
+@Slf4j
+@Component
+public class ICBCPayUtil {
+
+    @Autowired
+    private IcbcConfig icbcConfig;
+
+    public JSONObject wechatPay(String outTradeNo, BigDecimal totalPrice, String goodsName,String openid){
+        CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz bizContent = new
+                CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz();
+        bizContent.setMer_id(icbcConfig.getMerId());
+        bizContent.setMer_prtcl_no(icbcConfig.getMerPrtclNo());
+        bizContent.setDecive_info(icbcConfig.getDeciveInfo());
+        bizContent.setOut_trade_no(outTradeNo);
+        bizContent.setOrig_date_time(DateUtils.getCurrentDateTimeWithT());
+        //交易币种,目前工行只支持使用人民币(001)支付
+        bizContent.setFee_type("001");
+        bizContent.setSpbill_create_ip(IpUtils.getIpAddr(WebUtils.request()));
+        //金额,单位分
+        bizContent.setTotal_fee(String.valueOf(totalPrice.multiply(new BigDecimal(100)).intValue()));
+        //支付成功后回调url
+        bizContent.setMer_url(icbcConfig.getNotifyUrl());
+        bizContent.setBody(goodsName);
+        //收单接入方式,5-APP,7-微信公众号,8-支付宝生活号,9-微信小程序
+        bizContent.setAccess_type("9");
+        //支付方式,9-微信;10-支付宝;
+        bizContent.setPay_mode("9");
+        //商户在微信开放平台注册的APPID,支付方式为微信时不能为空
+        bizContent.setShop_appid(icbcConfig.getWxAppId());
+        //第三方用户标识,商户在微信公众号内或微信小程序内接入时必送,即access_type为7或9时,上送用户在商户APPID下的唯一标识;商户通过支付宝生活号接入时不送
+        bizContent.setOpen_id(openid);
+        bizContent.setIcbc_appid(icbcConfig.getAppId());
+        bizContent.setExpire_time(icbcConfig.getExpireTime());
+        //通知类型,表示在交易处理完成后把交易结果通知商户的处理模式。取值“HS”:在交易完成后将通知信息,主动发送给商户,发送地址为notify_url指定地址; 取值“AG”:在交易完成后不通知商户。不送或送空,默认为"HS"
+        bizContent.setNotify_type("HS");
+        //结果发送类型,通知方式为HS时有效。取值“0”:无论支付成功或者失败,银行都向商户发送交易通知信息;取值“1”,银行只向商户发送交易成功的通知信息。默认是"0"
+        bizContent.setResult_type("0");
+        CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1 request = new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1();
+        request.setServiceUrl(icbcConfig.getApiPayUrl());
+        request.setBizContent(bizContent);
+        DefaultIcbcClient client = IcbcConfig.getInstance(icbcConfig);
+        CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1 response;
+        JSONObject responsePackage = new JSONObject();
+        try {
+            log.info("准备调用工行支付成功,请求参数:{}", JSON.toJSONString(request));
+            response = client.execute(request);
+            if (response.isSuccess()) {
+                log.info("调用工行支付成功,返回信息:{}", JSON.toJSONString(response));
+                responsePackage = JSONObject.parseObject(response.getWx_data_package());
+            } else {
+                log.info("调用工行支付失败,返回信息:{}", JSON.toJSONString(response));
+                throw new ServiceException(ICBCRespOrderErrorEnum.fromCode(String.valueOf(response.getReturnCode())).getErrorMsg());
+            }
+        } catch (IcbcApiException e) {
+            log.error(e.toString(), e);
+        }
+        return responsePackage;
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SupervisorUserVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SupervisorUserVO.java
new file mode 100644
index 0000000..438efb1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SupervisorUserVO.java
@@ -0,0 +1,22 @@
+package com.ruoyi.system.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel("上级用户详情视图对象")
+public class SupervisorUserVO {
+
+    @ApiModelProperty("ID")
+    private Integer id;
+
+    @ApiModelProperty("昵称")
+    private String nickName;
+
+    @ApiModelProperty("头像")
+    private String avatar;
+
+    @ApiModelProperty("手机号码")
+    private String phone;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java
index a0113a1..70fa414 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java
@@ -6,7 +6,6 @@
 import lombok.Data;
 
 import java.util.Date;
-import java.util.List;
 
 /**
  * 用户对象 sys_user
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 6d9ccd6..72afa6b 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -287,8 +287,14 @@
 			   u.login_date AS loginDate, u.create_by AS createBy, u.create_time AS createTime, u.remark AS remark
 		from sys_user u where user_id &lt; 0 and u.status = 0 and u.del_flag = 0 order by user_id desc
 	</select>
+    <select id="selectByCode" resultType="com.ruoyi.common.core.domain.entity.SysUser">
+        select * from sys_user
+        <where>
+            role_type = 3 and del_flag = 0 and code = #{spreadCode}
+        </where>
+    </select>
 
-	<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
+    <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
  		insert into sys_user(
  			<if test="userId != null and userId != 0">user_id,</if>
  			<if test="deptId != null and deptId != 0">dept_id,</if>

--
Gitblit v1.7.1