系统用户关联企业微信用户

This commit is contained in:
dzq 2025-04-02 09:32:48 +08:00
parent 6f0e0587ab
commit 05f72a9a44
24 changed files with 301 additions and 37 deletions

View File

@ -107,14 +107,18 @@ public class QyDepartmentController extends BaseController {
@GetMapping("/depts")
public ResponseDTO<List<DeptDTO>> depts(@RequestParam String corpid) {
List<QyDepartmentEntity> qyDepartmentEntityList = departmentApplicationService.getDepartmentList();
if (StringUtils.isNoneBlank(corpid)) {
qyDepartmentEntityList = qyDepartmentEntityList.stream()
.filter(item -> StringUtils.equals(item.getCorpid(), corpid))
.collect(Collectors.toList());
if (StringUtils.isBlank(corpid)) {
corpid = "wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw";
}
// 根据corpid过滤部门列表
String finalCorpid = corpid;
qyDepartmentEntityList = qyDepartmentEntityList.stream()
.filter(item -> StringUtils.equals(item.getCorpid(), finalCorpid))
.collect(Collectors.toList());
List<DeptDTO> deptList = qyDepartmentEntityList.stream().map(entity -> {
DeptDTO dto = new DeptDTO(null); // 使用null初始化后续手动设置字段
dto.setId(entity.getId().longValue());
dto.setId(Long.parseLong(entity.getDepartmentId()));
dto.setParentId(Long.parseLong(entity.getParentid()));
dto.setDeptName(entity.getName());
dto.setOrderNum(0);

View File

@ -1,5 +1,6 @@
package com.agileboot.admin.controller.qywx;
import cn.hutool.json.JSONUtil;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.admin.customize.service.QywxScheduleJob;
import com.agileboot.common.core.base.BaseController;
@ -7,6 +8,11 @@ import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.api.QywxApiUtil;
import com.agileboot.domain.qywx.api.response.OpenidResponse;
import com.agileboot.domain.qywx.api.response.UserIdResponse;
import com.agileboot.domain.qywx.user.QyUserApplicationService;
import com.agileboot.domain.qywx.user.command.AddQyUserCommand;
import com.agileboot.domain.qywx.user.command.UpdateQyUserCommand;
@ -35,6 +41,7 @@ public class QyUserController extends BaseController {
private final QyUserApplicationService qyUserApplicationService;
private final QywxScheduleJob qywxScheduleJob;
private final AccessTokenApplicationService accessTokenApplicationService;
@Operation(summary = "用户列表")
@GetMapping
@ -81,4 +88,17 @@ public class QyUserController extends BaseController {
qywxScheduleJob.syncUserBindings();
return ResponseDTO.ok();
}
@GetMapping("/convertToOpenid")
public ResponseDTO<String> convertToOpenid(String corpid, String userid) {
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
OpenidResponse response = QywxApiUtil.convertToOpenid(accessToken.getAccessToken(), userid);
return ResponseDTO.ok(JSONUtil.toJsonStr(response));
}
@GetMapping("/convertToUserid")
public ResponseDTO<String> convertToUserid(String corpid, String openid) {
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
UserIdResponse response = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), openid);
return ResponseDTO.ok(JSONUtil.toJsonStr(response));
}
}

View File

@ -14,7 +14,6 @@ import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants.Captcha;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.exception.error.ErrorCode.Business;
@ -94,41 +93,52 @@ public class LoginService {
if (isCaptchaOn()) {
validateCaptcha(loginCommand.getUsername(), loginCommand.getCaptchaCode(), loginCommand.getCaptchaCodeKey());
}
// 用户验证
Authentication authentication;
// 企业微信扫码登录分支
if (StrUtil.isNotEmpty(loginCommand.getCode())) {
String userid = getQyUserinfo(loginCommand.getCorpid(), loginCommand.getCode());
String username = sysUserQyUserApplicationService.getUsernameByQyUserid(userid);
// 通过企业微信code获取用户ID
String userid = getQyUserid(loginCommand.getCorpid(), loginCommand.getCode());
// 根据企业微信用户ID查询系统用户名
SysUserEntity sysUserEntity = sysUserQyUserApplicationService.getSysUserByQyUserid(userid);
UserDetails user = fakeUserDetailsService.loadUserByUsername(username);
// 加载用户信息并创建认证对象跳过密码验证
UserDetails user = fakeUserDetailsService.loadUserByUsername(sysUserEntity.getUsername());
authentication = new UsernamePasswordAuthenticationToken(
user, null, user.getAuthorities());
} else {
// 普通账号密码登录分支
String decryptPassword = decryptPassword(loginCommand.getPassword());
try {
// 该方法会去调用UserDetailsServiceImpl#loadUserByUsername 校验用户名和密码 认证鉴权
// 调用认证管理器进行标准用户名密码认证
// 内部会调用UserDetailsServiceImpl#loadUserByUsername
authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
loginCommand.getUsername(), decryptPassword));
} catch (BadCredentialsException e) {
// 密码错误异常处理
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(loginCommand.getUsername(), LoginStatusEnum.LOGIN_FAIL,
MessageUtils.message("Business.LOGIN_WRONG_USER_PASSWORD")));
throw new ApiException(e, ErrorCode.Business.LOGIN_WRONG_USER_PASSWORD);
} catch (AuthenticationException e) {
// 认证通用异常处理
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(loginCommand.getUsername(), LoginStatusEnum.LOGIN_FAIL, e.getMessage()));
throw new ApiException(e, ErrorCode.Business.LOGIN_ERROR, e.getMessage());
} catch (Exception e) {
// 其他未知异常处理
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(loginCommand.getUsername(), LoginStatusEnum.LOGIN_FAIL, e.getMessage()));
throw new ApiException(e, Business.LOGIN_ERROR, e.getMessage());
}
}
// 把当前登录用户 放入上下文中
// 将认证信息存入安全上下文
SecurityContextHolder.getContext().setAuthentication(authentication);
// 这里获取的loginUser是UserDetailsServiceImpl#loadUserByUsername方法返回的LoginUser
// 从认证信息中获取系统登录用户对象
SystemLoginUser loginUser = (SystemLoginUser) authentication.getPrincipal();
// 记录登录成功信息
recordLoginInfo(loginUser);
// 生成token
// 生成JWT令牌并缓存用户信息
return tokenService.createTokenAndPutUserInCache(loginUser);
}
@ -246,7 +256,7 @@ public class LoginService {
return Convert.toBool(guavaCache.configCache.get(ConfigKeyEnum.CAPTCHA.getValue()));
}
private String getQyUserinfo(String corpid, String code) {
private String getQyUserid(String corpid, String code) {
try {
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
String url = String.format(

View File

@ -3,17 +3,25 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.api.response.GetBalanceResponse;
import com.agileboot.common.constant.WeixinConstants;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.exception.error.ErrorCode.Client;
import com.agileboot.common.utils.OpenSignUtil;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.api.QywxApiUtil;
import com.agileboot.domain.qywx.api.response.UserIdResponse;
import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService;
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity;
import com.agileboot.domain.qywx.user.QyUserApplicationService;
import com.agileboot.domain.qywx.user.db.QyUserEntity;
import com.agileboot.domain.shop.order.OrderApplicationService;
import com.agileboot.domain.shop.payment.dto.PaymentCallbackRequest;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -37,6 +45,9 @@ import org.springframework.web.client.RestTemplate;
@RequestMapping("/api/payment")
public class PaymentController {
private final OrderApplicationService orderApplicationService;
private final AccessTokenApplicationService accessTokenApplicationService;
private final QyUserApplicationService qyUserApplicationService;
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
// 新增回调接口
@PostMapping("/callback")
@ -98,6 +109,48 @@ public class PaymentController {
}
}
@GetMapping("/getBalance")
public ResponseDTO<GetBalanceResponse> getBalance(@RequestParam String openid) {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> qyAuthCorpInfoEntityList = authCorpInfoApplicationService.getByAppid(appid);
List<QyUserEntity> qyUserEntityList = new ArrayList<>();
for (QyAuthCorpInfoEntity qyAuthCorpInfoEntity : qyAuthCorpInfoEntityList) {
String corpid = qyAuthCorpInfoEntity.getCorpid();
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, corpid);
UserIdResponse userIdResponse = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), openid);
QyUserEntity qyUser = qyUserApplicationService.getUserByUserId(userIdResponse.getUserid(), corpid);
if (qyUser == null) {
continue;
}
qyUserEntityList.add(qyUser);
}
if (qyUserEntityList.isEmpty()) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的openid参数"));
}
// 找出余额最大的用户
QyUserEntity maxBalanceUser = qyUserEntityList.stream()
.filter(user -> user.getBalance() != null)
.max(Comparator.comparing(QyUserEntity::getBalance))
.orElse(null);
if (maxBalanceUser == null) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "未找到有效余额信息"));
}
// 创建响应对象假设GetBalanceResponse包含balance字段
GetBalanceResponse response = new GetBalanceResponse(maxBalanceUser.getUserid(), maxBalanceUser.getCorpid(), maxBalanceUser.getBalance());
return ResponseDTO.ok(response);
}
@GetMapping("/getBalanceByQyUserid")
public ResponseDTO<GetBalanceResponse> getBalanceByQyUserid(@RequestParam String corpid, @RequestParam String userid) {
QyUserEntity qyUser = qyUserApplicationService.getUserByUserId(userid, corpid);
// 创建响应对象假设GetBalanceResponse包含balance字段
GetBalanceResponse response = new GetBalanceResponse(qyUser.getUserid(), qyUser.getCorpid(), qyUser.getBalance());
return ResponseDTO.ok(response);
}
private PaymentCallbackRequest parseCallbackRequest(String requestBody) {
// 实现将URL参数解析为PaymentCallbackRequest
// 示例实现需要根据实际参数格式调整

View File

@ -1,27 +1,48 @@
package com.agileboot.api.controller.common;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.api.customize.service.JwtTokenService;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import java.util.Map;
import java.util.List;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.common.dto.QyLoginDTO;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.api.QywxApiUtil;
import com.agileboot.domain.qywx.api.response.OpenidResponse;
import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService;
import com.agileboot.domain.system.menu.MenuApplicationService;
import com.agileboot.domain.system.menu.dto.RouterDTO;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.AllArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
/**
* 调度日志操作处理
*
* @author ruoyi
*/
@Slf4j
@RestController
@RequestMapping("/common")
@AllArgsConstructor
public class LoginController extends BaseController {
private final JwtTokenService jwtTokenService;
private final AccessTokenApplicationService accessTokenApplicationService;
private final SysUserQyUserApplicationService sysUserQyUserApplicationService;
private final MenuApplicationService menuApplicationService;
/**
* 访问首页提示语
@ -32,7 +53,34 @@ public class LoginController extends BaseController {
return ResponseDTO.ok(token);
}
@GetMapping("/login/qy")
public ResponseDTO<QyLoginDTO> qyLogin(String corpid, String code, String state) {
try {
QyAccessTokenEntity qyAccessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", corpid);
// 通过企业微信code获取用户ID
String userid = QywxApiUtil.getQyUserid(qyAccessToken.getAccessToken(), code);
// 根据企业微信用户ID查询系统用户名
SysUserEntity sysUserEntity = sysUserQyUserApplicationService.getSysUserByQyUserid(userid);
SystemLoginUser loginUser = new SystemLoginUser();
loginUser.setAdmin(false);
loginUser.setUserId(sysUserEntity.getUserId());
List<RouterDTO> routerTree = menuApplicationService.getRouterTree(loginUser);
log.info("getRouterTreeuserid: {}, routerTree: {}", userid, JSONUtil.toJsonStr(routerTree));
int isCabinetAdmin = 0;
if (routerTree != null && !routerTree.isEmpty()) {
isCabinetAdmin = routerTree.stream().anyMatch(router -> router.getName().equals("CabinetCell"))
? 1 : 0;
}
OpenidResponse openidResponse = QywxApiUtil.convertToOpenid(qyAccessToken.getAccessToken(), userid);
return ResponseDTO.ok(new QyLoginDTO(userid, openidResponse.getOpenid(), isCabinetAdmin));
} catch (RestClientException e) {
log.error("qyLogin失败", e);
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "微信服务调用失败"));
}
}
}

View File

@ -0,0 +1,14 @@
package com.agileboot.api.response;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.math.BigDecimal;
@Data
@AllArgsConstructor
public class GetBalanceResponse {
private String userid;
private String corpid;
private BigDecimal balance;
}

View File

@ -0,0 +1,13 @@
package com.agileboot.domain.common.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class QyLoginDTO {
private String userid;
private String openid;
private Integer isCabinetAdmin;
}

View File

@ -2,10 +2,17 @@ package com.agileboot.domain.qywx.api;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.api.response.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.client.RestClientException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class QywxApiUtil {
@ -96,5 +103,27 @@ public class QywxApiUtil {
return JSONUtil.toBean(response, OpenidResponse.class);
}
public static String getQyUserid(String accessToken, String code) {
try {
String url = String.format(
"https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=%s&code=%s",
accessToken, code);
String response = HttpUtil.get(url);
log.info("微信getuserinfo接口返回: {}", response);
Map<String, Object> result = JSONUtil.toBean(response, HashMap.class);
if (result.containsKey("errcode") && !result.get("errcode").equals(0)) {
log.error("微信接口返回错误: {}", result);
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的code参数");
}
return String.valueOf(result.get("userid"));
} catch (RestClientException e) {
log.error("获取openid失败", e);
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "微信服务调用失败");
}
}
}

View File

@ -52,4 +52,8 @@ public class QyUserApplicationService {
model.deleteById();
}
}
public QyUserEntity getUserByUserId(String userid, String corpid) {
return userService.getUserByUserId(userid, corpid);
}
}

View File

@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
@ -142,6 +144,9 @@ public class QyUserEntity extends BaseEntity<QyUserEntity> {
@TableField("cid")
private Integer cid;
@ApiModelProperty("用户余额")
@TableField("balance")
private BigDecimal balance;
@Override
public Serializable pkVal() {

View File

@ -9,7 +9,7 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
public interface QyUserMapper extends BaseMapper<QyUserEntity> {
@Select("SELECT id, oper_id, open_userid, userid, name, mobile, department, user_order, position, gender, email, biz_mail, is_leader_in_dept, direct_leader, avatar, thumb_avatar, telephone, alias, extattr, status, qr_code, external_profile, external_position, address, main_department, enable, corpid, appid, cid " +
@Select("SELECT * " +
"FROM qy_user " +
"${ew.customSqlSegment}")
Page<QyUserEntity> getUserList(
@ -22,4 +22,13 @@ public interface QyUserMapper extends BaseMapper<QyUserEntity> {
"WHERE enable = '1' " +
"ORDER BY oper_id DESC")
List<QyUserEntity> selectAll();
@Select("SELECT * " +
"FROM qy_user " +
"WHERE userid = #{userid} " +
"AND corpid = #{corpid}" +
"AND enable = '1'" +
"AND deleted = 0")
QyUserEntity selectByUserid(@Param("userid") String userid, @Param("corpid") String corpid);
}

View File

@ -19,4 +19,5 @@ public interface QyUserService extends IService<QyUserEntity> {
List<QyUserEntity> selectAll();
QyUserEntity getUserByUserId(String userid, String corpid);
}

View File

@ -33,4 +33,9 @@ public class QyUserServiceImpl extends ServiceImpl<QyUserMapper, QyUserEntity> i
return this.list(wrapper);
}
@Override
public QyUserEntity getUserByUserId(String userid, String corpid) {
return baseMapper.selectByUserid(userid, corpid);
}
}

View File

@ -7,7 +7,12 @@ import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.qywx.user.db.QyUserEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import java.math.BigDecimal;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ExcelSheet(name = "企微用户信息列表")
@ -96,4 +101,7 @@ public class QyUserDTO {
@ExcelColumn(name = "应用ID")
private String appid;
@ExcelColumn(name = "用户余额")
private BigDecimal balance;
}

View File

@ -11,10 +11,12 @@ import lombok.EqualsAndHashCode;
@Data
public class SearchQyUserQuery<T> extends AbstractPageQuery<T> {
private String corpid;
private String userid;
private String name;
private String mobile;
private String department;
private String mainDepartment;
private String enable;
private Date startTime;
private Date endTime;
@ -24,11 +26,13 @@ public class SearchQyUserQuery<T> extends AbstractPageQuery<T> {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper
.eq(StrUtil.isNotEmpty(userid), "userid", userid)
.like(StrUtil.isNotEmpty(name), "name", name)
.like(StrUtil.isNotEmpty(mobile), "mobile", mobile)
.eq(StrUtil.isNotEmpty(department), "department", department)
.eq(StrUtil.isNotEmpty(enable), "enable", enable)
.eq(StrUtil.isNotBlank(corpid), "corpid", corpid)
.eq(StrUtil.isNotBlank(userid), "userid", userid)
.like(StrUtil.isNotBlank(name), "name", name)
.like(StrUtil.isNotBlank(mobile), "mobile", mobile)
.eq(StrUtil.isNotBlank(department), "department", department)
.eq(StrUtil.isNotBlank(mainDepartment), "main_department", mainDepartment)
.eq(StrUtil.isNotBlank(enable), "enable", enable)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
this.timeRangeColumn = "create_time";

View File

@ -10,6 +10,7 @@ import com.agileboot.domain.qywx.userQySys.dto.SysUserQyUserDTO;
import com.agileboot.domain.qywx.userQySys.model.SysUserQyUserModel;
import com.agileboot.domain.qywx.userQySys.model.SysUserQyUserModelFactory;
import com.agileboot.domain.qywx.userQySys.query.SearchSysUserQyUserQuery;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
@ -63,7 +64,7 @@ public class SysUserQyUserApplicationService {
return sysUserQyUserService.selectAll();
}
public String getUsernameByQyUserid(String userid) {
return sysUserQyUserService.getUsernameByQyUserid(userid);
public SysUserEntity getSysUserByQyUserid(String userid) {
return sysUserQyUserService.getSysUserByQyUserid(userid);
}
}

View File

@ -1,5 +1,6 @@
package com.agileboot.domain.qywx.userQySys.db;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
@ -39,11 +40,11 @@ public interface SysUserQyUserMapper extends BaseMapper<SysUserQyUserEntity> {
@Select("SELECT * FROM sys_user_qy_user WHERE sys_user_id = #{sysUserId} AND qy_user_id = #{qyUserId} LIMIT 1")
SysUserQyUserEntity selectBySysUserIdAndQyUserId(@Param("sysUserId") Long sysUserId, @Param("qyUserId") Integer qyUserId);
@Select("SELECT su.username " +
@Select("SELECT su.* " +
"FROM sys_user_qy_user suqy " +
"JOIN qy_user qu ON suqy.qy_user_id = qu.id " +
"JOIN sys_user su ON suqy.sys_user_id = su.user_id " +
"WHERE qu.userid = #{userid}")
String selectUsernameByQyUserid(@Param("userid") String userid);
SysUserEntity selectSysUserByQyUserid(@Param("userid") String userid);
}

View File

@ -1,6 +1,7 @@
package com.agileboot.domain.qywx.userQySys.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
@ -25,5 +26,5 @@ public interface SysUserQyUserService extends IService<SysUserQyUserEntity> {
SysUserQyUserEntity getBySysUserIdAndQyUserId(Long sysUserId, Integer qyUserId);
String getUsernameByQyUserid(String userid);
SysUserEntity getSysUserByQyUserid(String userid);
}

View File

@ -1,6 +1,7 @@
package com.agileboot.domain.qywx.userQySys.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -46,7 +47,7 @@ public class SysUserQyUserServiceImpl extends ServiceImpl<SysUserQyUserMapper, S
}
@Override
public String getUsernameByQyUserid(String userid) {
return baseMapper.selectUsernameByQyUserid(userid);
public SysUserEntity getSysUserByQyUserid(String userid) {
return baseMapper.selectSysUserByQyUserid(userid);
}
}

View File

@ -9,6 +9,9 @@ import com.agileboot.domain.cabinet.smartCabinet.db.SmartCabinetEntity;
import com.agileboot.domain.cabinet.smartCabinet.db.SmartCabinetService;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.mqtt.MqttService;
import com.agileboot.domain.qywx.user.db.QyUserEntity;
import com.agileboot.domain.qywx.user.db.QyUserService;
import com.agileboot.domain.qywx.user.model.QyUserModelFactory;
import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
import com.agileboot.domain.shop.goods.db.ShopGoodsService;
import com.agileboot.domain.shop.order.command.SubmitOrderCommand;
@ -30,6 +33,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -50,6 +54,8 @@ public class OrderApplicationService {
private final CabinetCellService cabinetCellService;
private final SmartCabinetService smartCabinetService;
private final MqttService mqttService;
private final QyUserService userService;
private final QyUserModelFactory qyUserModelFactory;
/*public PageDTO<ShopOrderDTO> getOrderList(SearchShopOrderQuery<> query) {
Page<ShopOrderEntity> page = orderService.page(query.toPage(), query.toQueryWrapper());
@ -122,12 +128,30 @@ public class OrderApplicationService {
processOrderGoods(orderModel, goodsList);
// 新增支付接口调用
WxJsApiPreCreateRequest paymentRequest = buildPaymentRequest(orderModel);
WxJsApiPreCreateResponse paymentResponse = paymentApplicationService.callJsApiPreCreate(paymentRequest);
return new CreateOrderResult(orderModel.getOrderId(), orderModel.getTotalAmount(), paymentResponse);
if (Objects.equals(command.getPaymentType(), "wechat")) {
// 新增支付接口调用
WxJsApiPreCreateRequest paymentRequest = buildPaymentRequest(orderModel);
WxJsApiPreCreateResponse paymentResponse = paymentApplicationService.callJsApiPreCreate(paymentRequest);
return new CreateOrderResult(orderModel.getOrderId(), orderModel.getTotalAmount(), paymentResponse, BigDecimal.valueOf(0));
} else if (Objects.equals(command.getPaymentType(), "balance")) {
QyUserEntity qyUser = userService.getUserByUserId(command.getUserid(), command.getCorpid());
// 余额不足
if (qyUser.getBalance().compareTo(orderModel.getTotalAmount()) < 0) {
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "余额不足");
} else {
qyUser.setBalance(qyUser.getBalance().subtract(orderModel.getTotalAmount()));
userService.updateById(qyUser);
}
// 金额转换元转分并四舍五入
BigDecimal amountInFen = orderModel.getTotalAmount()
.multiply(new BigDecimal("100"))
.setScale(0, RoundingMode.HALF_UP);
handlePaymentSuccess(orderModel.getOrderId(), Integer.valueOf(amountInFen.toPlainString()),
"balance-" + orderModel.getOrderId(), DateUtil.formatDateTime(new Date()));
return new CreateOrderResult(orderModel.getOrderId(), orderModel.getTotalAmount(), null, qyUser.getBalance());
}
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的支付类型");
}
private WxJsApiPreCreateRequest buildPaymentRequest(OrderModel orderModel) {

View File

@ -8,6 +8,10 @@ import lombok.Data;
@Data
public class SubmitOrderCommand {
private String openid;
private String userid;
private String corpid;
private ShopOrderEntity order;
// 支付类型'wechat' | 'balance'
private String paymentType;
private List<ShopOrderGoodsEntity> goodsList;
}

View File

@ -11,4 +11,5 @@ public class CreateOrderResult {
private Long orderId;
private BigDecimal totalAmount;
private WxJsApiPreCreateResponse paymentInfo;
private BigDecimal newBalance;
}

View File

@ -1,5 +1,6 @@
package com.agileboot.domain.system.dept.dto;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.domain.system.dept.db.SysDeptEntity;

View File

@ -14,4 +14,7 @@ CREATE TABLE `sys_user_qy_user` (
KEY `idx_qy_user_id` (`qy_user_id`),
CONSTRAINT `fk_sys_user_qy_user_sys` FOREIGN KEY (`sys_user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
CONSTRAINT `fk_sys_user_qy_user_qy` FOREIGN KEY (`qy_user_id`) REFERENCES `qy_user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统用户与企业微信用户关联表';
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统用户与企业微信用户关联表';
ALTER TABLE qy_user
ADD COLUMN `balance` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '用户余额(精度与商品价格对齐)';