Commit 731c5ae6 by zhangxingmin

小程序相关接口

parent e94b0a53
......@@ -5,4 +5,7 @@
<list />
</option>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -75,6 +75,11 @@
<groupId>com.yd</groupId>
<artifactId>yd-csf-wx-feign</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
</dependencies>
<build>
......
package com.yd.csf.wx.api.config;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 微信小程序配置类
*/
@Configuration
public class WxMaConfiguration {
@Value("${wx.miniapp.appid}")
private String appid;
@Value("${wx.miniapp.secret}")
private String secret;
@Bean
public WxMaService wxMaService() {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(appid);
config.setSecret(secret);
WxMaService service = new WxMaServiceImpl();
service.setWxMaConfig(config);
return service;
}
}
\ No newline at end of file
......@@ -4,7 +4,9 @@ import com.yd.common.result.Result;
import com.yd.csf.wx.api.service.ApiLoginService;
import com.yd.csf.wx.feign.client.login.ApiLoginFeignClient;
import com.yd.csf.wx.feign.request.login.ApiPhoneCodeLoginRequest;
import com.yd.csf.wx.feign.request.login.ApiWxLoginRequest;
import com.yd.csf.wx.feign.response.login.ApiPhoneCodeLoginResponse;
import com.yd.csf.wx.feign.response.login.ApiWxLoginResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -33,4 +35,14 @@ public class ApiLoginController implements ApiLoginFeignClient {
public Result<ApiPhoneCodeLoginResponse> phoneCodeLogin(ApiPhoneCodeLoginRequest request) {
return apiLoginService.phoneCodeLogin(request);
}
/**
* 微信小程序手机号快捷验证登录
* @param request
* @return
*/
@Override
public Result<ApiWxLoginResponse> wxLogin(ApiWxLoginRequest request) {
return apiLoginService.wxLogin(request);
}
}
......@@ -46,7 +46,7 @@ public class ApiUserController implements ApiUserFeignClient {
*/
@Override
public Result<IPage<ApiApprovalAccountPageResponse>> approvalAccountPage(ApiApprovalAccountPageRequest request) {
return null;
return apiUserService.approvalAccountPage(request);
}
/**
......
package com.yd.csf.wx.api.dto;
import lombok.Data;
/**
* 微信小程序用户信息实体类
*/
@Data
public class WxMaUserInfoDto {
/**
* 用户唯一标识
*/
private String openId;
/**
* 用户昵称
*/
private String nickName;
/**
* 用户头像图片的URL
*/
private String avatarUrl;
/**
* 用户的性别
*/
private Integer gender;
/**
* 用户所在国家
*/
private String country;
/**
* 用户所在省份
*/
private String province;
/**
* 用户所在城市
*/
private String city;
/**
* 显示所用的语言
*/
private String language;
}
\ No newline at end of file
......@@ -2,8 +2,12 @@ package com.yd.csf.wx.api.service;
import com.yd.common.result.Result;
import com.yd.csf.wx.feign.request.login.ApiPhoneCodeLoginRequest;
import com.yd.csf.wx.feign.request.login.ApiWxLoginRequest;
import com.yd.csf.wx.feign.response.login.ApiPhoneCodeLoginResponse;
import com.yd.csf.wx.feign.response.login.ApiWxLoginResponse;
public interface ApiLoginService {
Result<ApiPhoneCodeLoginResponse> phoneCodeLogin(ApiPhoneCodeLoginRequest request);
Result<ApiWxLoginResponse> wxLogin(ApiWxLoginRequest request);
}
package com.yd.csf.wx.api.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yd.common.result.Result;
import com.yd.csf.wx.feign.request.user.ApiApprovalAccountPageRequest;
import com.yd.csf.wx.feign.request.user.ApiApprovalAccountRequest;
import com.yd.csf.wx.feign.request.user.ApiUserImproveRequest;
import com.yd.csf.wx.feign.response.user.ApiApprovalAccountPageResponse;
import com.yd.csf.wx.feign.response.user.ApiUserDetailResponse;
import com.yd.csf.wx.feign.response.user.ApiUserImproveResponse;
import com.yd.user.feign.response.clientuser.ApiClientUserPageResponse;
......@@ -10,6 +13,8 @@ import com.yd.user.feign.response.clientuser.ApiClientUserPageResponse;
public interface ApiUserService {
Result<ApiUserImproveResponse> userImprove(ApiUserImproveRequest request);
Result<IPage<ApiApprovalAccountPageResponse>> approvalAccountPage(ApiApprovalAccountPageRequest request);
Result approvalAccount(ApiApprovalAccountRequest request);
Result<ApiUserDetailResponse> detail();
......
package com.yd.csf.wx.api.service;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.yd.csf.wx.api.dto.WxMaUserInfoDto;
public interface ApiWechatAuthService {
WxMaJscode2SessionResult getSessionInfo(String code);
String decryptPhoneNumber(String sessionKey, String encryptedData, String iv);
WxMaUserInfoDto getWxUserInfo(String openid);
}
package com.yd.csf.wx.api.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.yd.auth.core.config.LoginConfig;
import com.yd.auth.core.dto.AuthUserDto;
import com.yd.auth.core.security.JwtTokenProvider;
import com.yd.common.constant.RedisConstants;
import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ProjectEnum;
import com.yd.common.enums.TenantEnum;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.common.utils.RedisUtil;
import com.yd.csf.wx.api.dto.WxMaUserInfoDto;
import com.yd.csf.wx.api.service.ApiLoginService;
import com.yd.csf.wx.api.service.ApiUserService;
import com.yd.csf.wx.api.service.ApiWechatAuthService;
import com.yd.csf.wx.feign.dto.TokenDto;
import com.yd.csf.wx.feign.enums.RedirectPageEnum;
import com.yd.csf.wx.feign.request.login.ApiPhoneCodeLoginRequest;
import com.yd.csf.wx.feign.request.login.ApiWxLoginRequest;
import com.yd.csf.wx.feign.response.login.ApiPhoneCodeLoginResponse;
import com.yd.csf.wx.feign.response.login.ApiWxLoginResponse;
import com.yd.user.feign.client.clientuser.ApiClientUserFeignClient;
import com.yd.user.feign.request.clientuser.ApiClientUserPageRequest;
import com.yd.user.feign.response.clientuser.ApiClientUserPageResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
......@@ -26,8 +27,6 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
......@@ -50,6 +49,9 @@ public class ApiLoginServiceImpl implements ApiLoginService {
@Autowired
private ApiUserService apiUserService;
@Autowired
private ApiWechatAuthService wechatAuthService;
/**
* 手机验证码登录
* @param request
......@@ -120,5 +122,52 @@ public class ApiLoginServiceImpl implements ApiLoginService {
return authUserDto;
}
/**
* 微信小程序手机号快捷验证登录
* @param request
* @return
*/
@Override
public Result<ApiWxLoginResponse> wxLogin(ApiWxLoginRequest request) {
ApiWxLoginResponse loginResponse = new ApiWxLoginResponse();
//通过code获取session_key和openid
WxMaJscode2SessionResult session = wechatAuthService.getSessionInfo(request.getCode());
String sessionKey = session.getSessionKey();
String openId = session.getOpenid();
log.info("微信登录成功, openId: {}", openId);
//解密手机号
String phoneNumber = wechatAuthService.decryptPhoneNumber(
sessionKey, request.getEncryptedData(), request.getIv());
log.info("手机号解密成功: {}", phoneNumber);
//获取微信用户信息
WxMaUserInfoDto wxUserInfo = wechatAuthService.getWxUserInfo(openId);
//调用yd-user-api服务,查询客户端用户表信息,查询当前租户项目下是否有客户端手机号用户
ApiClientUserPageResponse response = apiUserService.getApiClientUserPageResponse(phoneNumber,"");
if (!Objects.isNull(response)) {
//有客户端手机号用户数据:判断审批状态是否审批成功,审批成功直接到首页,其他状态到审批进度页面
if (CommonEnum.APPROVAL_STATUS_CG.getCode().equals(response.getApprovalStatus())) {
//审批成功 - 跳转到首页
loginResponse.setRedirectPage(RedirectPageEnum.HOME_PAGE.getItemValue());
}else {
//其他状态 - 审批进度页
loginResponse.setRedirectPage(RedirectPageEnum.PROGRESS.getItemValue());
}
//生成客户端用户登录token
TokenDto tokenDto = generateToken(response);
loginResponse.setTokenDto(tokenDto);
//更新用户信息的openId
apiClientUserFeignClient.editOpenId(response.getClientUserBizId(),openId);
}else {
//无客户端手机号用户数据:判断入参有无推荐人邀请码,无推荐人邀请码则提示无权限登录。有推荐人邀请码到完善信息注册登录
if (StringUtils.isBlank(request.getInvitationCode())) {
throw new BusinessException("无权限登录!");
}
//有推荐人邀请码到完善信息页
loginResponse.setRedirectPage(RedirectPageEnum.IMPROVE.getItemValue());
}
loginResponse.setOpenId(openId);
return Result.success(loginResponse);
}
}
package com.yd.csf.wx.api.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.auth.core.dto.AuthUserDto;
import com.yd.auth.core.utils.SecurityUtil;
import com.yd.common.enums.CommonEnum;
......@@ -9,9 +10,14 @@ import com.yd.common.enums.TenantEnum;
import com.yd.common.result.Result;
import com.yd.csf.feign.client.agentreferralrelation.ApiAgentReferralRelationFeignClient;
import com.yd.csf.feign.request.agentreferralrelation.ApiAgentReferralRelationSaveRequest;
import com.yd.csf.service.dto.AgentReferralRelationDto;
import com.yd.csf.service.model.AgentReferralRelation;
import com.yd.csf.service.service.IAgentReferralRelationService;
import com.yd.csf.wx.api.service.ApiUserService;
import com.yd.csf.wx.feign.request.user.ApiApprovalAccountPageRequest;
import com.yd.csf.wx.feign.request.user.ApiApprovalAccountRequest;
import com.yd.csf.wx.feign.request.user.ApiUserImproveRequest;
import com.yd.csf.wx.feign.response.user.ApiApprovalAccountPageResponse;
import com.yd.csf.wx.feign.response.user.ApiUserDetailResponse;
import com.yd.csf.wx.feign.response.user.ApiUserImproveResponse;
import com.yd.user.feign.client.clientuser.ApiClientUserFeignClient;
......@@ -29,6 +35,7 @@ import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@Service
......@@ -40,6 +47,9 @@ public class ApiUserServiceImpl implements ApiUserService {
@Autowired
private ApiAgentReferralRelationFeignClient apiAgentReferralRelationFeignClient;
@Autowired
private IAgentReferralRelationService iAgentReferralRelationService;
/**
* 完善信息
* @param request
......@@ -79,11 +89,42 @@ public class ApiUserServiceImpl implements ApiUserService {
referrerId = pageResponse1.getClientUserBizId();
referrerAccount = pageResponse1.getPhone();
}
//保存推荐关系
saveAgentReferralRelation(agentIdList,referrerId,referrerAccount);
return Result.success();
}
/**
* 审批账号列表查询
* @param request
* @return
*/
@Override
public Result<IPage<ApiApprovalAccountPageResponse>> approvalAccountPage(ApiApprovalAccountPageRequest request) {
IPage<ApiApprovalAccountPageResponse> iPage = new Page<ApiApprovalAccountPageResponse>();
//查询被推荐人的用户业务ID列表 - 根据当前登录人作为推荐人查询
AuthUserDto authUserDto = SecurityUtil.getCurrentLoginUser();
//查询被推荐人列表
List<AgentReferralRelation> relations = iAgentReferralRelationService.queryList(AgentReferralRelationDto.builder().referrerId(authUserDto.getClientUserBizId()).build());
if (!CollectionUtils.isEmpty(relations)) {
List<String> agentIdList = relations.stream().map(AgentReferralRelation::getAgentId).collect(Collectors.toList());
ApiClientUserPageRequest pageRequest = new ApiClientUserPageRequest();
pageRequest.setClientUserBizIdList(agentIdList);
pageRequest.setApprovalStatus(request.getApprovalStatus());
Result<IPage<ApiClientUserPageResponse>> result = apiClientUserFeignClient.page(pageRequest);
if (!Objects.isNull(result.getData()) && !CollectionUtils.isEmpty(result.getData().getRecords())) {
BeanUtils.copyProperties(result.getData(),iPage);
iPage.setRecords(result.getData().getRecords().stream().map(dto -> {
ApiApprovalAccountPageResponse pageResponse = new ApiApprovalAccountPageResponse();
BeanUtils.copyProperties(dto,pageResponse);
return pageResponse;
}).collect(Collectors.toList()));
}
}
return Result.success(iPage);
}
/**
* 推荐人审批账号
* @param request
* @return
......
package com.yd.csf.wx.api.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yd.common.exception.BusinessException;
import com.yd.common.utils.HttpUtil;
import com.yd.csf.wx.api.dto.WxMaUserInfoDto;
import com.yd.csf.wx.api.service.ApiWechatAuthService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* 微信小程序服务类
*/
@Service
@Slf4j
public class ApiWechatAuthServiceImpl implements ApiWechatAuthService {
@Autowired
private WxMaService wxMaService;
@Value("${wx.miniapp.appid}")
private String appid;
/**
* 获取微信会话信息
* @param code
* @return
* @throws WxErrorException
*/
@Override
public WxMaJscode2SessionResult getSessionInfo(String code) {
try {
return wxMaService.getUserService().getSessionInfo(code);
} catch (WxErrorException e) {
e.printStackTrace();
throw new BusinessException("获取微信会话信息异常");
}
}
/**
* 解密手机号
* @param sessionKey
* @param encryptedData
* @param iv
* @return
*/
@Override
public String decryptPhoneNumber(String sessionKey, String encryptedData, String iv) {
try {
WxMaPhoneNumberInfo phoneNumberInfo = wxMaService.getUserService()
.getPhoneNoInfo(sessionKey, encryptedData, iv);
return phoneNumberInfo.getPhoneNumber();
} catch (Exception e) {
log.error("手机号解密失败", e);
throw new RuntimeException("手机号解密失败");
}
}
/**
* 通过openid获取微信用户信息
* @param openid
* @return
*/
@Override
public WxMaUserInfoDto getWxUserInfo(String openid) {
try {
String accessToken = wxMaService.getAccessToken();
String url = String.format("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN",
accessToken, openid);
String response = HttpUtil.get(url);
JSONObject jsonObject = JSON.parseObject(response);
if (jsonObject.containsKey("errcode")) {
log.warn("获取用户信息失败: {}", jsonObject.getString("errmsg"));
return null;
}
WxMaUserInfoDto userInfo = new WxMaUserInfoDto();
userInfo.setOpenId(openid);
userInfo.setNickName(jsonObject.getString("nickname"));
userInfo.setAvatarUrl(jsonObject.getString("headimgurl"));
userInfo.setGender(jsonObject.getInteger("sex"));
userInfo.setCountry(jsonObject.getString("country"));
userInfo.setProvince(jsonObject.getString("province"));
userInfo.setCity(jsonObject.getString("city"));
return userInfo;
} catch (Exception e) {
log.warn("获取微信用户信息失败: {}", e.getMessage());
return null;
}
}
}
\ No newline at end of file
......@@ -3,7 +3,9 @@ package com.yd.csf.wx.feign.client.login;
import com.yd.common.result.Result;
import com.yd.csf.wx.feign.fallback.login.ApiLoginFeignFallbackFactory;
import com.yd.csf.wx.feign.request.login.ApiPhoneCodeLoginRequest;
import com.yd.csf.wx.feign.request.login.ApiWxLoginRequest;
import com.yd.csf.wx.feign.response.login.ApiPhoneCodeLoginResponse;
import com.yd.csf.wx.feign.response.login.ApiWxLoginResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -23,4 +25,12 @@ public interface ApiLoginFeignClient {
@PostMapping("/phone/code")
Result<ApiPhoneCodeLoginResponse> phoneCodeLogin(@Validated @RequestBody ApiPhoneCodeLoginRequest request);
/**
* 微信小程序手机号快捷验证登录
* @param request
* @return
*/
@PostMapping("/wx")
Result<ApiWxLoginResponse> wxLogin(@Validated @RequestBody ApiWxLoginRequest request);
}
......@@ -3,7 +3,9 @@ package com.yd.csf.wx.feign.fallback.login;
import com.yd.common.result.Result;
import com.yd.csf.wx.feign.client.login.ApiLoginFeignClient;
import com.yd.csf.wx.feign.request.login.ApiPhoneCodeLoginRequest;
import com.yd.csf.wx.feign.request.login.ApiWxLoginRequest;
import com.yd.csf.wx.feign.response.login.ApiPhoneCodeLoginResponse;
import com.yd.csf.wx.feign.response.login.ApiWxLoginResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
......@@ -21,6 +23,11 @@ public class ApiLoginFeignFallbackFactory implements FallbackFactory<ApiLoginFei
public Result<ApiPhoneCodeLoginResponse> phoneCodeLogin(ApiPhoneCodeLoginRequest request) {
return null;
}
@Override
public Result<ApiWxLoginResponse> wxLogin(ApiWxLoginRequest request) {
return null;
}
};
}
}
package com.yd.csf.wx.feign.request.login;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ApiWxLoginRequest {
/**
* 前端调用wx.login获取code,用于后端交换openid和session_key
*/
@NotBlank(message = "code不能为空")
private String code;
/**
* 用户手机号的加密数据(微信小程序自动生成)
*/
@NotBlank(message = "encryptedData不能为空")
private String encryptedData;
/**
* AES加密算法的初始向量,用于解密 encryptedData
*/
@NotBlank(message = "iv不能为空")
private String iv;
/**
* 推荐人的邀请码,推荐链接带入进来,有值表示通过邀请加入,无值表示直接打开小程序
*/
private String invitationCode;
}
......@@ -5,4 +5,14 @@ import lombok.Data;
@Data
public class ApiApprovalAccountPageRequest extends PageDto {
/**
* 查询的内容(姓名/手机号/邮箱)
*/
private String queryContent;
/**
* 审批状态(待同意、待审批)
*/
private String approvalStatus;
}
......@@ -69,4 +69,9 @@ public class ApiUserImproveRequest {
*/
@NotBlank(message = "推荐人的邀请码不能为空")
private String invitationCode;
/**
* 小程序的openId
*/
private String openId;
}
package com.yd.csf.wx.feign.response.login;
import com.yd.csf.wx.feign.dto.TokenDto;
import lombok.Data;
@Data
public class ApiWxLoginResponse {
/**
* 跳转页:首页-HOME_PAGE,审批进度页-PROGRESS,完善信息页-IMPROVE
*/
private String redirectPage;
/**
* 小程序的openId
*/
private String openId;
/**
* 封装的TokenDto
*/
private TokenDto tokenDto;
}
......@@ -4,4 +4,94 @@ import lombok.Data;
@Data
public class ApiApprovalAccountPageResponse {
/**
* 主键ID
*/
private Long id;
/**
* 客户端用户表唯一业务ID
*/
private String clientUserBizId;
/**
* 头像
*/
private String avatar;
/**
* 姓名
*/
private String name;
/**
* 手机号
*/
private String phone;
/**
* 邮箱
*/
private String email;
/**
* 证件类型
*/
private String idCardType;
/**
* 证件号码
*/
private String idCardNumber;
// /**
// * 证件文件url列表
// */
// private List<String> idCardFileUrlList;
/**
* 银行卡号
*/
private String bankNumber;
/**
* 开户行
*/
private String openBank;
// /**
// * 银行卡文件url列表
// */
// private List<String> bankFileUrlList;
/**
* 邀请码
*/
private String invitationCode;
/**
* 状态(0:停用 1:启用)
*/
private Integer status;
/**
* 审批状态
*/
private String approvalStatus;
/**
* 注册来源(PC、小程序等)默认小程序 - MINI_PROGRAM
*/
private String registerSource;
/**
* 所属租户唯一业务ID(冗余)
*/
private String tenantBizId;
/**
* 所属项目唯一业务ID(冗余)
*/
private String projectBizId;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment