微信自动登录

This commit is contained in:
Vinjor 2024-09-24 18:35:51 +08:00
parent 1097aba239
commit dd0630ad45
30 changed files with 705 additions and 38 deletions

View File

@ -15,6 +15,11 @@
点亮业务基础库
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-biz</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId>

View File

@ -9,6 +9,10 @@ public class BaseConstants {
public static final String CUS_TYPE_CORP_ATTN = "04";
/**政企客户*/
public static final String CUS_TYPE_CORP = "03";
/**私人客户*/
public static final String CUS_TYPE_PRIVATE = "01";
/**代办客户*/
public static final String CUS_TYPE_AGENT = "02";
/**客户标识*/
public static final String CUS_SIGN_CUSTOMER = "customer";
/**车辆标识*/
@ -23,8 +27,12 @@ public class BaseConstants {
public static final String SIGN_UPDATE = "update";
/**默认密码*/
public static final String PASSWORD_DEFAULT = "123456";
/**租户下部门名称*/
/**租户下部门名称--政企客户*/
public static final String DEPT_NAME_CORP_NAME = "政企客户";
/**租户下部门名称--私人客户*/
public static final String DEPT_NAME_PRIVATE_NAME = "私人客户";
/**租户下部门名称--代办客户*/
public static final String DEPT_NAME_AGENT_NAME = "代办客户";
/**私家车*/
public static final String CAR_CATEGORY_PRIVATE = "01";
/**货车*/

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.common;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class WechatCommon {
/**
* 微信公众号APPID
*/
@Value(value = "${wx.mp.app-id}")
public String APP_ID;
/**
* 微信公众号秘钥
*/
@Value(value = "${wx.mp.secret}")
public String APP_SECRET;
/**
* 获取网页的token,后续还有+"&code=&grant_type=authorization_code"
**/
public String getTokeUrl(){
String appId = APP_ID;
String appSecret = APP_SECRET;
return "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret;
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.app.customer;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.custom.service.CustomerMainService;
import cn.iocoder.yudao.module.custom.vo.CustomerMainSaveReqVO;
import cn.iocoder.yudao.module.system.api.user.dto.UserDTO;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import static cn.iocoder.yudao.common.BaseConstants.SIGN_CREATE;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* 客户管理
*
* @author : http://www.chiner.pro
* @date : 2024-7-31
*/
@RestController
@RequestMapping("/base/custom-app")
@Tag(name = "客户管理-小程序端接口")
@Validated
public class CustomerAPI {
@Resource
private CustomerMainService customerMainService;
@Resource
private AdminAuthService loginService;
/**
* 新增客户
*
* @param saveReqVO 保存客户信息扩展实体
* @return cn.iocoder.yudao.framework.common.pojo.CommonResult<java.lang.Boolean>
* @author PQZ
* @date 15:42 2024/8/1
**/
@PostMapping("/register")
@Operation(summary = "客户自行注册")
public CommonResult<?> createCustomerMain(@Valid @RequestBody CustomerMainSaveReqVO saveReqVO, HttpServletRequest request) {
//客户类型统一为私人客户
saveReqVO.setTypeCode("01");
//客户来源统一为04-维修
saveReqVO.setDataFrom("04");
//注册方式统一为自主创建
saveReqVO.setInviterType("01");
try {
UserDTO userDTO = customerMainService.saveCustomer(saveReqVO,SIGN_CREATE);
//注册并登录
return success(loginService.wxLoginByUserId(userDTO.getId(),userDTO.getUsername()));
}catch (ServiceException e){
return error(e);
}
}
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.app.wechat.controller;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.app.wechat.service.WechatService;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 微信登录控制层
*
*/
@RestController
@RequestMapping("/userClient/weChat")
@Tag(name = "微信登录")
@Validated
public class WechatLoginController {
@Autowired
private WechatService wechatService;
/**
* 微信获取openId
* @author vinjor-M
* @date 9:53 2024/8/2
* @param code 请求参数
**/
@GetMapping("/wechatLogin")
@Operation(summary = "微信获取openId")
public CommonResult<?> createCompany(String code) {
return wechatService.loginByOpenId(code);
}
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.app.wechat.service;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
/**
* @author vinjor-m
* @description 微信模块服务层
**/
public interface WechatService {
/**
* 微信自动登录
* @author vinjor-M
* @date 23:53 2024/9/23
* @param map 参数
**/
CommonResult<?> loginByOpenId(String code);
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.module.app.wechat.service.impl;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.app.wechat.service.WechatService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.util.WeChatLoginUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.LOCKED;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* @Author vinjor-m
* @Description 微信模块服务层
**/
@Service
public class WechatServiceImpl implements WechatService {
@Autowired
private WeChatLoginUtil weChatLoginUtil;
@Autowired
private AdminUserApi adminUserApi;
@Resource
private AdminAuthService loginService;
/**
* 微信自动登录
*
* @param code 参数
* @return java.lang.String
* @author vinjor-M
* @date 23:53 2024/9/23
**/
@Override
public CommonResult<?> loginByOpenId(String code) {
try {
//当前登录用户的openId
Map<String,String> authMap = getWeChatOpenId(code);
String openId = authMap.getOrDefault("openId",null);
//默认租户180查是否有user表数据
AdminUserRespDTO userRespDTO = adminUserApi.getUserByOpenId(openId,null);
if(null==userRespDTO){
//未找到用户去注册
return CommonResult.success(openId);
}else{
//找到用户登录并返回
return success(loginService.wxLoginByUserId(userRespDTO.getId(),userRespDTO.getUsername()));
}
}catch (Exception e){
e.printStackTrace();
return CommonResult.error(LOCKED.getCode(),e.getMessage());
}
}
/**
* 获取openId
* @author vinjor-M
* @date 23:56 2024/9/23
* @param code 静默/非静默授权拿到的code
* @return java.util.Map<java.lang.String,java.lang.String>
**/
private Map<String,String> getWeChatOpenId(String code) throws Exception {
Map<String,String> rtnMap = new HashMap<>(2);
try {
//code为空为没有获取到code
if (StringUtils.isNotBlank(code)) {
JSONObject tokenJson = weChatLoginUtil.getTokenJson(code);
//获取到tokenJson后解析tokenJson获取其openId
if (null != tokenJson && tokenJson.containsKey("openid")) {
rtnMap.put("openId",tokenJson.getStr("openid"));
rtnMap.put("token",tokenJson.getStr("access_token"));
}else{
throw new Exception("code过期");
}
}else{
throw new Exception("没有code");
}
return rtnMap;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
}

View File

@ -180,26 +180,5 @@ public class CustomerMainController {
return success(true);
}
/**
* 小程序客户注册
* cusName,phoneNumber,birthday,sex,inviter
*/
@PostMapping("/addUniUser")
public CommonResult<Boolean> addUniUser(@Valid @RequestBody CustomerMainSaveReqVO saveReqVO) {
if(!saveReqVO.getCode().isEmpty()){
String code = saveReqVO.getCode();
JSONObject jsonObj = new JSONObject();
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code="
+code+"&grant_type=authorization_code";
String response = HttpRequest.get(url).execute().body();
JSONObject json = JSONUtil.parseObj(response);
if (json.containsKey("access_token") && json.containsKey("openid")) {
String accessToken = json.getStr("access_token");
String openid = json.getStr("openid");
}
}
return null;
}
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.custom.entity.CustomerMain;
import cn.iocoder.yudao.module.custom.vo.CustomerMainPageReqVO;
import cn.iocoder.yudao.module.custom.vo.CustomerMainRespVO;
import cn.iocoder.yudao.module.custom.vo.CustomerMainSaveReqVO;
import cn.iocoder.yudao.module.system.api.user.dto.UserDTO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
@ -38,7 +39,7 @@ public interface CustomerMainService extends IService<CustomerMain> {
* @author PQZ
* @date 15:46 2024/8/1
**/
void saveCustomer(CustomerMainSaveReqVO saveReqVO, String sign);
UserDTO saveCustomer(CustomerMainSaveReqVO saveReqVO, String sign);
/**
* 根据客户id查询客户信息

View File

@ -31,6 +31,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -98,12 +99,12 @@ public class CustomerMainServiceImpl extends ServiceImpl<CustomerMainMapper, Cus
**/
@Override
@DSTransactional
public void saveCustomer(CustomerMainSaveReqVO saveReqVO, String sign) {
public UserDTO saveCustomer(CustomerMainSaveReqVO saveReqVO, String sign) {
Long userId;
UserDTO user = null;
try {
/*1、入参及基础参数值设置*/
CustomerMain main = JSONUtil.toBean(JSONUtil.parseObj(saveReqVO).toJSONString(0), CustomerMain.class);
Long userId;
UserDTO user;
/*2、新增客户时绑定绑定客户信息*/
if (SIGN_CREATE.equals(sign)){
//查询数据字典根据客户类型匹配出预设角色code
@ -135,11 +136,28 @@ public class CustomerMainServiceImpl extends ServiceImpl<CustomerMainMapper, Cus
user.setDeptId(deptId);
//客户信息表绑定deptCode
main.setDeptCode(deptId);
}else{
//私人客户和代办客户归属到默认的部门中
String deptName = "";
if(CUS_TYPE_PRIVATE.equals(main.getTypeCode())){
deptName =DEPT_NAME_PRIVATE_NAME;
}else if(CUS_TYPE_AGENT.equals(main.getTypeCode())){
deptName = DEPT_NAME_AGENT_NAME;
}
DeptRespDTO parentDept = deptApi.getDeptByName(deptName);
user.setDeptId(parentDept.getId());
}
//创建客户
userId = adminUserApi.createUser(user);
user.setId(userId);
} else {
userId = user.getId();
if(StringUtils.isNotEmpty(saveReqVO.getOpenId())){
//穿了openId更新openId
user.setOpenId(saveReqVO.getOpenId());
//更新用户表
adminUserApi.setOpenId(user.getId(),saveReqVO.getOpenId());
}
}
//客户表绑定用户id
main.setUserId(userId);
@ -149,16 +167,18 @@ public class CustomerMainServiceImpl extends ServiceImpl<CustomerMainMapper, Cus
permissionApi.assignUserRole(userId, roleCodes);
}
/*3、保存客户主表信息*/
//暂时写死会员id TODO
main.setMemberLevelId("9d4567b7e68803933f4917a4aab6b745");
this.saveOrUpdate(main);
/*4、保存扩展表信息*/
if (!saveReqVO.getItemList().isEmpty()) {
if ( null!=saveReqVO.getItemList() && !saveReqVO.getItemList().isEmpty()) {
customerItemService.saveCutomItem(main.getId(), saveReqVO.getItemList());
}
} catch (ServiceException e) {
log.error(e.getMessage());
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
}
return user;
}
/**

View File

@ -20,7 +20,7 @@ public class CustomerMainSaveReqVO extends CustomerMain {
List<BusiLabel> labelList;
/**
* Code
* 微信openId
*/
private String Code;
private String openId;
}

View File

@ -0,0 +1,222 @@
package cn.iocoder.yudao.util;
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class NetWorkHelper {
public String getHttpsResponse(String hsUrl, String requestMethod) {
URL url;
InputStream is = null;
String resultData = "";
try {
url = new URL(hsUrl);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
TrustManager[] tm = {xtm};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tm, null);
con.setSSLSocketFactory(ctx.getSocketFactory());
con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
con.setDoInput(true); //允许输入流即允许下载
//在android中必须将此项设置为false
con.setDoOutput(false); //允许输出流即允许上传
con.setUseCaches(false); //不使用缓冲
if(null!=requestMethod && !requestMethod.equals("")) {
con.setRequestMethod(requestMethod); //使用指定的方式
}
else{
con.setRequestMethod("GET"); //使用get请求
}
is = con.getInputStream(); //获取输入流此时才真正建立链接
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bufferReader = new BufferedReader(isr);
String inputLine = "";
while ((inputLine = bufferReader.readLine()) != null) {
resultData += inputLine + "\n";
}
Certificate[] certs = con.getServerCertificates();
int certNum = 1;
for (Certificate cert : certs) {
X509Certificate xcert = (X509Certificate) cert;
}
} catch (Exception e) {
e.printStackTrace();
}
return resultData;
}
/**
* 下载文件
* @param hsUrl
* @return
*/
public String DownLoadHttpsFile(String hsUrl, String fileName, String path) {
URL url;
InputStream is = null;
String filePath = path+fileName;
try {
url = new URL(hsUrl);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
TrustManager[] tm = {xtm};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tm, null);
con.setSSLSocketFactory(ctx.getSocketFactory());
con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
con.setDoInput(true); //允许输入流即允许下载
//在android中必须将此项设置为false
con.setDoOutput(false); //允许输出流即允许上传
con.setUseCaches(false); //不使用缓冲
con.setRequestMethod("GET"); //使用get请求
is = con.getInputStream(); //获取输入流此时才真正建立链接
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len=is.read(buffer)) != -1 ){
outStream.write(buffer, 0, len);
}
is.close();
byte[] fileBytes = outStream.toByteArray();
File file = new File(filePath);
FileOutputStream fops = new FileOutputStream(file);
fops.write(fileBytes);
fops.flush();
fops.close();
/* Certificate[] certs = con.getServerCertificates();
for (Certificate cert : certs) {
X509Certificate xcert = (X509Certificate) cert;
}*/
} catch (Exception e) {
e.printStackTrace();
}
return filePath;
}
/**
* HTTPS协议的POST请求
* @param hsUrl 请求地址
* @param json 请求数据
* @return
*/
public String PostHttpsResponse(String hsUrl, String json) {
URL url;
InputStream is = null;
String resultData = "";
try {
url = new URL(hsUrl);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
TrustManager[] tm = {xtm};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tm, null);
con.setSSLSocketFactory(ctx.getSocketFactory());
con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
con.setDoInput(true); //允许输入流即允许下载
//在android中必须将此项设置为false
con.setDoOutput(true); //允许输出流即允许上传
con.setUseCaches(false); //不使用缓冲
con.setRequestMethod("POST"); //使用get请求
//表单数据
if (null != json) {
OutputStream outputStream = con.getOutputStream();
outputStream.write(json.getBytes("UTF-8"));
outputStream.close();
}
is = con.getInputStream(); //获取输入流此时才真正建立链接
InputStreamReader isr = new InputStreamReader(is);
BufferedReader bufferReader = new BufferedReader(isr);
String inputLine = "";
while ((inputLine = bufferReader.readLine()) != null) {
resultData += inputLine + "\n";
}
/* log(con.getResponseCode());
log(con.getCipherSuite());
log("");*/
Certificate[] certs = con.getServerCertificates();
int certNum = 1;
for (Certificate cert : certs) {
X509Certificate xcert = (X509Certificate) cert;
/*log("Cert No. " + certNum++);
log(xcert.getType());
log(xcert.getPublicKey().getAlgorithm());
log(xcert.getIssuerDN());
log(xcert.getIssuerDN());
log(xcert.getNotAfter());
log(xcert.getNotBefore());
log("");*/
}
} catch (Exception e) {
e.printStackTrace();
}
return resultData;
}
X509TrustManager xtm = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
};
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.util;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.common.WechatCommon;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @Author vinjor-m
* @Description 微信模块工具类
**/
@Component
public class WeChatLoginUtil {
@Autowired
private WechatCommon wechatCommon;
/**
* @param code 授权后拿到的code
* @return net.sf.json.JSONObject
* ---modify history---
* Modify By Date Description
* @Author PQZ
* @Description 获取网页的token
* @Date 17:12 2021/1/26
**/
public JSONObject getTokenJson(String code) {
//请求获取网页的token
String url = wechatCommon.getTokeUrl() + "&code=" + code + "&grant_type=authorization_code";
NetWorkHelper helper = new NetWorkHelper();
String response = helper.getHttpsResponse(url, "");
return JSONUtil.parseObj(response);
}
}

View File

@ -146,6 +146,7 @@ public class YudaoWebSecurityConfigurerAdapter {
// 微信支付接口
.antMatchers("/admin-api/notify/**").permitAll()
.antMatchers("/userClient/pay/**").permitAll()
.antMatchers("/userClient/weChat/**").permitAll()
.antMatchers("/admin-api/websocket/**").permitAll()
// 小程序首页
.antMatchers("/admin-api/system/notice/listWx","/admin-api/system/swiper/listWx","/admin-api/system/shopconfig/listWx").permitAll()

View File

@ -41,6 +41,16 @@ public interface AdminUserApi {
*/
AdminUserRespDTO getUser(Long id);
/**
* 根据openid和租户id查询用户
* @author vinjor-M
* @date 11:29 2024/9/24
* @param openId 微信id
* @param tenantId 租户id可能为null
* @return cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO
**/
AdminUserRespDTO getUserByOpenId(String openId,String tenantId);
/**
* 通过用户 登录账户 查询用户
*
@ -137,5 +147,13 @@ public interface AdminUserApi {
*/
AdminUserRespDTO getUserByMobile(String mobile);
/**
* 设置用户openId
* @author vinjor-M
* @date 15:45 2024/9/24
* @param userId 用户id
* @param openId 微信id
**/
void setOpenId(Long userId,String openId);
}

View File

@ -18,6 +18,10 @@ public class AdminUserRespDTO {
* 用户ID
*/
private Long id;
/**
* 用户登录账号
*/
private String username;
/**
* 用户昵称
*/

View File

@ -47,5 +47,9 @@ public class UserDTO {
* 用户性别
**/
private String sex;
/**
* 用户openId
**/
private String openId;
}

View File

@ -64,6 +64,21 @@ public class AdminUserApiImpl implements AdminUserApi {
return BeanUtils.toBean(user, AdminUserRespDTO.class);
}
/**
* 根据openid和租户id查询用户
*
* @param openId 微信id
* @param tenantId 租户id可能为null
* @return cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO
* @author vinjor-M
* @date 11:29 2024/9/24
**/
@Override
public AdminUserRespDTO getUserByOpenId(String openId, String tenantId) {
AdminUserDO user = userService.selectUserByOpenId(openId,tenantId);
return BeanUtils.toBean(user, AdminUserRespDTO.class);
}
/**
* 通过用户 登录账户 查询用户
*
@ -153,4 +168,17 @@ public class AdminUserApiImpl implements AdminUserApi {
return BeanUtils.toBean(user, AdminUserRespDTO.class);
}
/**
* 设置用户openId
*
* @param userId 用户id
* @param openId 微信id
* @author vinjor-M
* @date 15:45 2024/9/24
**/
@Override
public void setOpenId(Long userId, String openId) {
userService.setOpenId(userId, openId);
}
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
@ -41,4 +42,6 @@ public interface DeptMapper extends BaseMapperX<DeptDO> {
default DeptDO selectTenantDeptTop(Long parentId, Long tenantId) {
return selectOne(DeptDO::getParentId, parentId, DeptDO::getTenantId, tenantId);
}
List<DeptDO> selectDeptByName(@Param("name")String name);
}

View File

@ -57,4 +57,6 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
AdminUserDO selectUserByPhone(String phone);
AdminUserDO getUserByMobileWithoutTenant(String phoneNumber);
int updateSetOpenId(@Param("userId")Long userId,@Param("openId")String openId);
}

View File

@ -75,4 +75,14 @@ public interface AdminAuthService {
AuthLoginRespVO wxLoginRescue(String decryptResult, String openId, Long inviteId);
AuthLoginRespVO wxLoginJc(String decryptResult, String openId, Long inviteId);
/**
* 根据用户id自动登录
* @author vinjor-M
* @date 12:17 2024/9/24
* @param userId 用户id
* @param userName 用户名称
* @return cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO
**/
AuthLoginRespVO wxLoginByUserId(Long userId,String userName);
}

View File

@ -439,4 +439,19 @@ public class AdminAuthServiceImpl implements AdminAuthService {
// 生成token
return createTokenAfterLoginSuccess(wxUser.getId(), wxUser.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
}
/**
* 根据用户id自动登录
*
* @param userId 用户id
* @param userName 用户名称
* @return cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO
* @author vinjor-M
* @date 12:17 2024/9/24
**/
@Override
public AuthLoginRespVO wxLoginByUserId(Long userId, String userName) {
// 生成token
return createTokenAfterLoginSuccess(userId, userName, LoginLogTypeEnum.LOGIN_USERNAME);
}
}

View File

@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqV
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -244,7 +245,8 @@ public class DeptServiceImpl implements DeptService {
**/
@Override
public DeptDO selectDeptByName(String name) {
return deptMapper.selectByDeptName(name);
List<DeptDO> list = deptMapper.selectDeptByName(name);
return list.size()>0?list.get(0):new DeptDO();
}

View File

@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2AccessTokenMapper;
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2RefreshTokenMapper;
import cn.iocoder.yudao.module.system.dal.redis.oauth2.OAuth2AccessTokenRedisDAO;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

View File

@ -219,4 +219,22 @@ public interface AdminUserService {
AdminUserDO selectUserByPhone(String phone);
AdminUserDO getUserByMobileWithoutTenant(String phoneNumber);
/**
* 根据openid和租户id查询用户
* @author vinjor-M
* @date 11:29 2024/9/24
* @param openId 微信id
* @param tenantId 租户id可能为null
**/
AdminUserDO selectUserByOpenId(String openId,String tenantId);
/**
* 设置用户openId
*
* @param userId 用户id
* @param openId 微信id
* @author vinjor-M
* @date 15:45 2024/9/24
**/
void setOpenId(Long userId,String openId);
}

View File

@ -28,6 +28,7 @@ import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
@ -530,6 +531,37 @@ public class AdminUserServiceImpl implements AdminUserService {
return userMapper.getUserByMobileWithoutTenant(phoneNumber);
}
/**
* 根据openid和租户id查询用户
*
* @param openId 微信id
* @param tenantId 租户id可能为null
* @author vinjor-M
* @date 11:29 2024/9/24
**/
@Override
public AdminUserDO selectUserByOpenId(String openId, String tenantId) {
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<AdminUserDO>()
.eq(AdminUserDO::getOpenId,openId);
if(StringUtils.isNotEmpty(tenantId)){
queryWrapper.eq(AdminUserDO::getTenantId,tenantId);
}
return userMapper.selectOne(queryWrapper);
}
/**
* 设置用户openId
*
* @param userId 用户id
* @param openId 微信id
* @author vinjor-M
* @date 15:45 2024/9/24
**/
@Override
public void setOpenId(Long userId, String openId) {
userMapper.updateSetOpenId(userId,openId);
}
/**
* 对密码进行加密
*

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper">
<select id="selectDeptByName" resultType="cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO">
select * from system_dept where name = #{name}
</select>
</mapper>

View File

@ -3,8 +3,11 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper">
<update id="updateSetOpenId">
UPDATE system_users SET open_id = #{openId} WHERE id = #{userId}
</update>
<select id="getUsersByRoleRescue" resultType="cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO">
<select id="getUsersByRoleRescue" resultType="cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO">
SELECT
distinct su.*
FROM

View File

@ -185,12 +185,10 @@ debug: false
--- #################### 微信公众号、小程序相关配置 ####################
wx:
mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档
# app-id: wx041349c6f39b268b # 测试号(牛希尧提供的)
# secret: 5abee519483bc9f8cb37ce280e814bd0
app-id: wx5b23ba7a5589ecbb # 测试号(自己的)
secret: 2a7b3b20c537e52e74afd395eb85f61f
# app-id: wxa69ab825b163be19 # 测试号Kongdy 提供的)
# secret: bd4f9fab889591b62aeac0d7b8d8b4a0
# app-id: wx8653afe16dffec37 # 蓝安
# secret: ab94673dd0cca78abd0a453d0aac9f98
app-id: wxb1f71e5e0c5f9ee7 # 点亮
secret: 2e9864a6b224feb6fba4ab73b70212cd
# 存储配置,解决 AccessToken 的跨节点的共享
config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis会自动从 Spring 中获取

View File

@ -223,6 +223,7 @@ yudao:
- /admin-api/system/config/configKey/**
- /websocket/**
- /userClient/pay/**
- /userClient/weChat/**
- /admin-api/websocket/**
- /admin-api/rescue/wxLoginRescue
- /admin-api/rescue/wxLoginJc
@ -281,6 +282,7 @@ yudao:
- /admin-api/system/tenant/getListByWebsite
- /admin-api/websocket/**
- /userClient/pay/**
- /userClient/weChat/**
ignore-tables:
- system_tenant
- system_tenant_package