Browse Source

Merge branch 'dev/2024/0822/update-app-Y' of feifan/mall-backend-app into master

登录后获取用户信息的时候返回用户是否关注公众号
Yangzw 2 months ago
parent
commit
7f01d07581

+ 4 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/duser/vo/DuserInfoVO.java

@@ -48,4 +48,8 @@ public class DuserInfoVO {
     @Schema(description = "是否是商户用户")
     private Boolean isShSystemUser;
 
+    @Schema(description = "安卓app注册id")
+    private String androidRegisterId;
+
+
 }

+ 1 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/duser/DuserServiceImpl.java

@@ -184,6 +184,7 @@ public class DuserServiceImpl implements DuserService {
                 .isSign(isSign)
                 .isPtSystemUser(isPtSystemUser)
                 .isShSystemUser(isShSystemUser)
+                .androidRegisterId(memberUserService.getUser(userId).getAndroidRegisterId())
                 .build();
 
     }

+ 1 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/api/user/MemberUserApiImpl.java

@@ -46,7 +46,7 @@ public class MemberUserApiImpl implements MemberUserApi {
 
     @Override
     public List<MemberUserRespDTO> getUsersByMobile(String mobile) {
-        return MemberUserConvert.INSTANCE.convertList2(userService.selectListByMobile(mobile));
+        return MemberUserConvert.INSTANCE.convertList2(userService. selectListByMobile(mobile));
     }
 
 }

+ 11 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/user/AppMemberUserController.java

@@ -47,7 +47,9 @@ public class AppMemberUserController {
     public CommonResult<AppMemberUserInfoRespVO> getUserInfo() {
         MemberUserDO user = userService.getUser(getLoginUserId());
         MemberLevelDO level = levelService.getLevel(user.getLevelId());
-        return success(MemberUserConvert.INSTANCE.convert(user, level));
+        AppMemberUserInfoRespVO convert = MemberUserConvert.INSTANCE.convert(user, level);
+        convert.setSubscribe(userService.getUserIsSubscribe(user.getId()));
+        return success(convert);
     }
 
     @PutMapping("/update")
@@ -58,6 +60,14 @@ public class AppMemberUserController {
         return success(true);
     }
 
+    @PutMapping("/addRegisterId")
+    @Operation(summary = "添加安卓的极光注册id")
+    @PreAuthenticated
+    public CommonResult<Boolean> addRegisterId(@NotEmpty String registerId) {
+        userService.addRegisterId(registerId);
+        return success(true);
+    }
+
     @PutMapping("/updateByAlipayAccount")
     @Operation(summary = "修改用户支付宝账号")
     public CommonResult<Boolean> updateUserByAlipayAccount(@RequestBody @Valid AppMemberUserUpdateAlipayAccountReqVO reqVO) {

+ 3 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java

@@ -71,4 +71,7 @@ public class AppMemberUserInfoRespVO {
     @Schema(description = "银行账号", example = "31488")
     private String bankAccount;
 
+    @Schema(description = "是否关注公众号")
+    private Boolean subscribe;
+
 }

+ 5 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/user/MemberUserDO.java

@@ -170,4 +170,9 @@ public class MemberUserDO extends TenantBaseDO {
      * 银行账号
      */
     private String bankAccount;
+
+    /**
+     * 安卓app注册id
+     */
+    private String androidRegisterId;
 }

+ 13 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserService.java

@@ -252,4 +252,17 @@ public interface MemberUserService {
      * @return 用户
      */
     MemberUserDO getUserByUserNameWithMobile(String username,String mobile);
+
+    /**
+     * 添加用户注册ID
+     * @param registerId 注册ID
+     */
+    void addRegisterId(String registerId);
+
+    /**
+     * 获取用户是否关注公众号
+     * @param userId 用户ID
+     * @return 是否关注
+     */
+    Boolean getUserIsSubscribe(Long userId);
 }

+ 108 - 8
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserServiceImpl.java

@@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.*;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
 import cn.newfeifan.mall.framework.common.enums.CommonStatusEnum;
 import cn.newfeifan.mall.framework.common.enums.UserTypeEnum;
 import cn.newfeifan.mall.framework.common.exception.ErrorCode;
@@ -23,10 +25,16 @@ import cn.newfeifan.mall.module.system.api.sms.SmsCodeApi;
 import cn.newfeifan.mall.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
 import cn.newfeifan.mall.module.system.api.social.SocialClientApi;
 import cn.newfeifan.mall.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
+import cn.newfeifan.mall.module.system.dal.dataobject.social.SocialUserBindDO;
+import cn.newfeifan.mall.module.system.dal.dataobject.social.SocialUserDO;
+import cn.newfeifan.mall.module.system.dal.mysql.social.SocialUserBindMapper;
+import cn.newfeifan.mall.module.system.dal.mysql.social.SocialUserMapper;
 import cn.newfeifan.mall.module.system.enums.sms.SmsSceneEnum;
 import cn.newfeifan.mall.module.system.service.user.AdminUserService;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -41,8 +49,10 @@ import java.util.List;
 
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.newfeifan.mall.framework.common.util.servlet.ServletUtils.getClientIP;
+import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.newfeifan.mall.module.member.enums.DictTypeConstants.*;
 import static cn.newfeifan.mall.module.member.enums.ErrorCodeConstants.*;
+import static cn.newfeifan.mall.module.system.constant.SystemConstants.WX_TICK_KEY_APPID;
 
 /**
  * 会员 User Service 实现类
@@ -75,6 +85,16 @@ public class MemberUserServiceImpl implements MemberUserService {
     private ShareLinkRegisterProducer shareLinkRegisterProducer;
     @Resource
     private AdminUserService adminUserService;
+    @Resource
+    private SocialUserMapper socialUserMapper;
+    @Resource
+    private SocialUserBindMapper socialUserBindMapper;
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+    @Value("${wx.mp.app-id}")
+    private String appid;
+    @Value("${wx.mp.secret}")
+    private String Wxgsecret;
 
     @Override
     public MemberUserDO getUserByMobile(String mobile) {
@@ -182,9 +202,9 @@ public class MemberUserServiceImpl implements MemberUserService {
         MemberUserDO user = memberUserMapper.selectById(userId);
 
         // 如果用户名被修改,则校验是否被有同名
-        if(reqVO.getUsername() != null && !reqVO.getUsername().equals(user.getUsername())){
+        if (reqVO.getUsername() != null && !reqVO.getUsername().equals(user.getUsername())) {
             Long count = selectCountByUsername(reqVO.getUsername());
-            if(count > 0){
+            if (count > 0) {
                 throw exception(AUTH_USERNAME_EXISTS);
             }
         }
@@ -401,16 +421,16 @@ public class MemberUserServiceImpl implements MemberUserService {
 
     @Override
     public MemberUserDO getUserByMobile(String mobile, Long userId) {
-        return memberUserMapper.selectOne(MemberUserDO::getMobile, mobile, MemberUserDO::getId,userId);
+        return memberUserMapper.selectOne(MemberUserDO::getMobile, mobile, MemberUserDO::getId, userId);
     }
 
     @Override
     public void updateUserByAlipayAccount(Long loginUserId, AppMemberUserUpdateAlipayAccountReqVO reqVO) {
-        if(isValidPhoneNumber(reqVO.getAlipayAccount()) || validateEmail(reqVO.getAlipayAccount())){
+        if (isValidPhoneNumber(reqVO.getAlipayAccount()) || validateEmail(reqVO.getAlipayAccount())) {
             MemberUserDO user = BeanUtils.toBean(reqVO, MemberUserDO.class);
             user.setId(loginUserId);
             memberUserMapper.updateById(user);
-        }else{
+        } else {
             ErrorCode ALIPAY_ACCOUNT_ERROR = new ErrorCode(1_004_001_000, "支付宝账号格式错误");
             throw exception(ALIPAY_ACCOUNT_ERROR);
         }
@@ -418,7 +438,7 @@ public class MemberUserServiceImpl implements MemberUserService {
 
     @Override
     public void updateUserByBankAccount(Long loginUserId, AppMemberUserUpdateBankAccountReqVO reqVO) {
-        if(!isAccountFormatValid(reqVO.getBankAccount())){
+        if (!isAccountFormatValid(reqVO.getBankAccount())) {
             ErrorCode BANK_COUNT_ERROR = new ErrorCode(1_004_001_000, "银行账号格式错误");
             throw exception(BANK_COUNT_ERROR);
         }
@@ -430,12 +450,92 @@ public class MemberUserServiceImpl implements MemberUserService {
 
     @Override
     public List<MemberUserDO> selectListByMobile(String mobile) {
-        return memberUserMapper.selectList(MemberUserDO::getMobile,mobile);
+        return memberUserMapper.selectList(MemberUserDO::getMobile, mobile);
     }
 
     @Override
     public MemberUserDO getUserByUserNameWithMobile(String username, String mobile) {
-        return memberUserMapper.selectOne(MemberUserDO::getUsername,username,MemberUserDO::getMobile,mobile);
+        return memberUserMapper.selectOne(MemberUserDO::getUsername, username, MemberUserDO::getMobile, mobile);
+    }
+
+    @Override
+    public void addRegisterId(String registerId) {
+        MemberUserDO memberUserDO = memberUserMapper.selectById(getLoginUserId());
+        if (registerId != null && !registerId.equals(memberUserDO.getAndroidRegisterId())) {
+            // 防止一台设备登录多个账号会导致异常发送的可能,所以如果有同样的registerId就先删除后加入
+            List<MemberUserDO> users = memberUserMapper.selectList(MemberUserDO::getAndroidRegisterId, registerId);
+            if(users != null){
+                for (MemberUserDO user : users) {
+                    user.setAndroidRegisterId(null);
+                    memberUserMapper.updateById(user);
+                }
+            }
+
+            memberUserDO.setAndroidRegisterId(registerId);
+            memberUserMapper.updateById(memberUserDO);
+        }
+    }
+
+    @Override
+    public Boolean getUserIsSubscribe(Long userId) {
+        SocialUserBindDO socialUserBindDO = socialUserBindMapper.selectOne(SocialUserBindDO::getUserId, getLoginUserId());
+        // 如果没有存储用户的openid就直接返回false
+        if(socialUserBindDO == null){
+            return false;
+        }
+        SocialUserDO socialUserDO = socialUserMapper.selectOne(SocialUserDO::getId, socialUserBindDO.getSocialUserId());
+        // 如果没有存储用户的openid就直接返回false
+        if(socialUserDO == null){
+            return false;
+        }
+
+        return isSubscribe(socialUserDO.getOpenid());
+    }
+
+    private Boolean isSubscribe(String openid) {
+        String requestUrl = StrUtil.format("https://api.weixin.qq.com/cgi-bin/user/info?access_token={}&openid={}&lang=zh_CN", getAccessToken(), openid);
+        String returnMsg = HttpUtil.get(requestUrl);
+        cn.hutool.json.JSONObject responseJsonObject = JSONUtil.parseObj(returnMsg);
+        if (ObjectUtil.isNull(responseJsonObject)) try {
+            throw new Exception("响应异常:获取信息为空!");
+        }catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        Integer subscribe = (Integer) responseJsonObject.get("subscribe");
+        log.info("用户信息:{}", responseJsonObject);
+        // 微信返回的数据中1为关注,0为未关注
+        return subscribe == 1;
+    }
+
+    /**
+     * 获取accessToken
+     *
+     * @return accessToken
+     */
+    private String getAccessToken() {
+
+        String accessToken = stringRedisTemplate.opsForValue().get(WX_TICK_KEY_APPID);
+
+        if (StrUtil.isEmpty(accessToken)) {
+            // 服务号的appid以及秘钥
+            String requestUrl = StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appid, Wxgsecret);
+            String returnMsg = HttpUtil.get(requestUrl);
+            cn.hutool.json.JSONObject responseJsonObject = JSONUtil.parseObj(returnMsg);
+            if (ObjectUtil.isNull(responseJsonObject)) try {
+                throw new Exception("响应异常:获取信息为空!");
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            accessToken = responseJsonObject.getStr("access_token");
+
+            //微信的accessToken的失效时间是两个小时,这里改为一小时五十五分钟,怕双方的时间误差导致accessToken失效
+            long expireTime = 60 * 60 + 55 * 60; // 1小时55分钟转换为秒
+            stringRedisTemplate.opsForValue().set(WX_TICK_KEY_APPID, accessToken, expireTime, java.util.concurrent.TimeUnit.SECONDS);
+        }
+
+        log.info("===========Access_token:{}", accessToken);
+
+        return accessToken;
     }
 
     /**

+ 3 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserServiceImpl.java

@@ -69,15 +69,18 @@ public class SocialUserServiceImpl implements SocialUserService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
+        log.info("开始获取社交用户:{}", reqDTO);
         // 获得社交用户
         SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
                 reqDTO.getCode(), reqDTO.getState());
+        log.info("拿到用户信息:{}", socialUser);
         Assert.notNull(socialUser, "社交用户不能为空");
 
         // 社交用户可能之前绑定过别的用户,需要进行解绑
 //        socialUserBindMapper.deleteByUserTypeAndSocialUserId(reqDTO.getUserType(), socialUser.getId());
 
         // 用户可能之前已经绑定过该社交类型,需要进行解绑
+        log.info("解绑用户信息");
         socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(reqDTO.getUserType(), reqDTO.getUserId(),
                 socialUser.getType());