Merge remote-tracking branch 'origin/feature-20240104' into feature-20240104

master
elliott 2 years ago
commit 9a8fe80c6a

@ -27,6 +27,11 @@ public class WxConfig {
private String accessTokenUrl;
private String obtainWxOfficialAccountUserUrl;
private String ObtainUserInfoByOpenidUrl;
public String getLoginUrl() {
return loginUrl;
@ -51,4 +56,20 @@ public class WxConfig {
public void setAccessTokenUrl(String accessTokenUrl) {
this.accessTokenUrl = accessTokenUrl;
}
public String getObtainWxOfficialAccountUserUrl() {
return obtainWxOfficialAccountUserUrl;
}
public void setObtainWxOfficialAccountUserUrl(String obtainWxOfficialAccountUserUrl) {
this.obtainWxOfficialAccountUserUrl = obtainWxOfficialAccountUserUrl;
}
public String getObtainUserInfoByOpenidUrl() {
return ObtainUserInfoByOpenidUrl;
}
public void setObtainUserInfoByOpenidUrl(String obtainUserInfoByOpenidUrl) {
ObtainUserInfoByOpenidUrl = obtainUserInfoByOpenidUrl;
}
}

@ -1,12 +1,17 @@
package com.flossom.miniProgram.controller;
import com.flossom.common.core.utils.StringUtils;
import com.flossom.common.core.web.controller.BaseController;
import com.flossom.common.core.web.domain.AjaxResult;
import com.flossom.miniProgram.domain.vo.UserMemberUpdateVo;
import com.flossom.miniProgram.service.IWxUserMemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@RestController
@RequestMapping("/user")
public class UserMemberController extends BaseController {
@ -23,6 +28,10 @@ public class UserMemberController extends BaseController {
*/
@PostMapping("/login")
public AjaxResult login(@RequestParam(value = "code") String code) throws Exception {
if (StringUtils.isBlank(code)) {
logger.error("登录code不能为空");
return AjaxResult.error("登录失败");
}
return AjaxResult.success(wxUserMemberService.login(code));
}
@ -36,6 +45,10 @@ public class UserMemberController extends BaseController {
*/
@PostMapping("/upgradeMember")
public AjaxResult upgradeMember(@RequestParam(value = "code") String code) throws Exception {
if (StringUtils.isBlank(code)) {
logger.error("获取手机号code不能为空");
return AjaxResult.error("获取手机号失败");
}
return AjaxResult.success("获取成功", wxUserMemberService.upgradeMember(code));
}
@ -45,7 +58,7 @@ public class UserMemberController extends BaseController {
* @return
*/
@PostMapping("/updateUser")
public AjaxResult updateUser(@RequestBody UserMemberUpdateVo userMemberUpdateVo) {
public AjaxResult updateUser(@RequestBody @Validated UserMemberUpdateVo userMemberUpdateVo) {
wxUserMemberService.updateUser(userMemberUpdateVo);
return AjaxResult.success();
}

@ -40,4 +40,14 @@ public class WxNoRemindController extends BaseController {
return AjaxResult.success();
}
/**
*
*
* @return
*/
@GetMapping("/isAttentionOfficialAccount")
public R isAttentionOfficialAccount() throws Exception {
return R.ok(wxNoRemindService.isAttentionOfficialAccount());
}
}

@ -0,0 +1,167 @@
package com.flossom.miniProgram.domain.vo;
import java.util.List;
/**
*
*/
public class OfficialAccountUserDetailRet {
private List<userInfoList> user_info_list;
private Integer errcode;
private String errmsg;
public OfficialAccountUserDetailRet() {
}
public OfficialAccountUserDetailRet(List<userInfoList> user_info_list, Integer errcode, String errmsg) {
this.user_info_list = user_info_list;
this.errcode = errcode;
this.errmsg = errmsg;
}
public List<userInfoList> getUser_info_list() {
return user_info_list;
}
public void setUser_info_list(List<userInfoList> user_info_list) {
this.user_info_list = user_info_list;
}
public Integer getErrcode() {
return errcode;
}
public void setErrcode(Integer errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
class userInfoList {
private Integer subscribe;
private String openid;
private String language;
private String subscribe_time;
private String unionid;
private String remark;
private Integer groupid;
private List<Integer> tagid_list;
private String subscribe_scene;
private String qr_scene;
private String qr_scene_str;
public userInfoList() {
}
public userInfoList(Integer subscribe, String openid, String language, String subscribe_time, String unionid, String remark, Integer groupid, List<Integer> tagid_list, String subscribe_scene, String qr_scene, String qr_scene_str) {
this.subscribe = subscribe;
this.openid = openid;
this.language = language;
this.subscribe_time = subscribe_time;
this.unionid = unionid;
this.remark = remark;
this.groupid = groupid;
this.tagid_list = tagid_list;
this.subscribe_scene = subscribe_scene;
this.qr_scene = qr_scene;
this.qr_scene_str = qr_scene_str;
}
public Integer getSubscribe() {
return subscribe;
}
public void setSubscribe(Integer subscribe) {
this.subscribe = subscribe;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getSubscribe_time() {
return subscribe_time;
}
public void setSubscribe_time(String subscribe_time) {
this.subscribe_time = subscribe_time;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Integer getGroupid() {
return groupid;
}
public void setGroupid(Integer groupid) {
this.groupid = groupid;
}
public List<Integer> getTagid_list() {
return tagid_list;
}
public void setTagid_list(List<Integer> tagid_list) {
this.tagid_list = tagid_list;
}
public String getSubscribe_scene() {
return subscribe_scene;
}
public void setSubscribe_scene(String subscribe_scene) {
this.subscribe_scene = subscribe_scene;
}
public String getQr_scene() {
return qr_scene;
}
public void setQr_scene(String qr_scene) {
this.qr_scene = qr_scene;
}
public String getQr_scene_str() {
return qr_scene_str;
}
public void setQr_scene_str(String qr_scene_str) {
this.qr_scene_str = qr_scene_str;
}
}
}

@ -0,0 +1,32 @@
package com.flossom.miniProgram.domain.vo;
/**
*
*/
public class OfficialAccountUserReq {
private String openid;
private String lang = "zh_CN";
public OfficialAccountUserReq() {
}
public OfficialAccountUserReq(String openid) {
this.openid = openid;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}

@ -0,0 +1,100 @@
package com.flossom.miniProgram.domain.vo;
import java.util.List;
/**
*
*/
public class OfficialAccountUserRet {
private Integer total;
private Integer count;
private data data;
private String next_openid;
private Integer errcode;
private String errmsg;
public OfficialAccountUserRet() {
}
public OfficialAccountUserRet(Integer total, Integer count, OfficialAccountUserRet.data data, String next_openid, Integer errcode, String errmsg) {
this.total = total;
this.count = count;
this.data = data;
this.next_openid = next_openid;
this.errcode = errcode;
this.errmsg = errmsg;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public OfficialAccountUserRet.data getData() {
return data;
}
public void setData(OfficialAccountUserRet.data data) {
this.data = data;
}
public String getNext_openid() {
return next_openid;
}
public void setNext_openid(String next_openid) {
this.next_openid = next_openid;
}
public Integer getErrcode() {
return errcode;
}
public void setErrcode(Integer errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public List<String> getOpenidList() {
return getData().getOpenid();
}
class data {
private List<String> openid;
public data() {
}
public data(List<String> openid) {
this.openid = openid;
}
public List<String> getOpenid() {
return openid;
}
public void setOpenid(List<String> openid) {
this.openid = openid;
}
}
}

@ -1,8 +1,10 @@
package com.flossom.miniProgram.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.flossom.common.core.annotation.Excel;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
public class UserMemberUpdateVo {
@ -10,6 +12,8 @@ public class UserMemberUpdateVo {
/**
*
*/
@NotNull(message = "昵称不能为空")
@Size(min = 1, max = 20, message = "昵称长度需要控制在20位以内")
private String nickname;
/**
@ -20,22 +24,85 @@ public class UserMemberUpdateVo {
/**
*
*/
private Integer province;
@NotNull(message = "请选择省")
private Integer provinceId;
/**
*
*/
private Integer city;
@NotNull(message = "请选择市")
private Integer cityId;
/**
*
*/
private Integer area;
@NotNull(message = "请选择区")
private Integer areaId;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@NotNull(message = "请选择生日日期")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
public UserMemberUpdateVo() {
}
public UserMemberUpdateVo(String nickname, String headimg, Integer provinceId, Integer cityId, Integer areaId, Date birthday) {
this.nickname = nickname;
this.headimg = headimg;
this.provinceId = provinceId;
this.cityId = cityId;
this.areaId = areaId;
this.birthday = birthday;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getHeadimg() {
return headimg;
}
public void setHeadimg(String headimg) {
this.headimg = headimg;
}
public Integer getProvinceId() {
return provinceId;
}
public void setProvinceId(Integer provinceId) {
this.provinceId = provinceId;
}
public Integer getCityId() {
return cityId;
}
public void setCityId(Integer cityId) {
this.cityId = cityId;
}
public Integer getAreaId() {
return areaId;
}
public void setAreaId(Integer areaId) {
this.areaId = areaId;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}

@ -1,6 +1,7 @@
package com.flossom.miniProgram.service;
import com.flossom.common.core.domain.entity.WxNoRemindRecord;
import com.sun.org.apache.xpath.internal.operations.Bool;
public interface IWxNoRemindService {
@ -8,4 +9,6 @@ public interface IWxNoRemindService {
void closeOfficialAccount();
Boolean isAttentionOfficialAccount() throws Exception;
}

@ -7,6 +7,7 @@ import com.flossom.common.core.utils.DateUtils;
import com.flossom.common.core.web.domain.AjaxResult;
import com.flossom.common.security.utils.SecurityUtils;
import com.flossom.miniProgram.service.IWxNoRemindService;
import com.flossom.miniProgram.utils.MiniProgramUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -28,4 +29,9 @@ public class WxNoRemindServiceImpl implements IWxNoRemindService {
wxNoRemindRecord.setCreateTime(DateUtils.getNowDate());
wxNoRemindRecordMapper.insertWxNoRemindRecord(wxNoRemindRecord);
}
@Override
public Boolean isAttentionOfficialAccount() throws Exception {
return MiniProgramUtils.isAttentionOfficialAccount(SecurityUtils.getLoginUser().getWxUserMember().getUnionid());
}
}

@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -100,27 +101,31 @@ public class WxUserMemberServiceImpl implements IWxUserMemberService {
@Override
public String upgradeMember(String code) throws Exception {
String accessToken = MiniProgramUtils.getAccessToken(SecurityUtils.getLoginUser().getWxUserMember().getOpenid());
if (StringUtils.isBlank(accessToken)) {
throw new ServiceException("获取用户手机号码失败");
}
// 获取手机号
String result = MiniProgramUtils.getPhone(code, accessToken);
String result = MiniProgramUtils.getPhone(code);
logger.info("请求微信服务器获取手机号码返回结果:{}", result);
WxCode2PhoneRet wxCode2PhoneRet = JSON.parseObject(result, WxCode2PhoneRet.class);
if (wxCode2PhoneRet.getErrcode() != 0) {
logger.error("获取用户手机号码失败: {}", wxCode2PhoneRet.getErrmsg());
throw new ServiceException("获取用户手机号码失败");
}
wxUserMemberMapper.upgradeMember(wxCode2PhoneRet.getPhoneInfo().getPhoneNumber(), SecurityUtils.getWxUserId().intValue());
wxUserMemberMapper.upgradeMember(wxCode2PhoneRet.getPhoneInfo().getPhoneNumber(), SecurityUtils.getLoginUser().getWxUserMember().getId().intValue());
return wxCode2PhoneRet.getPhoneInfo().getPhoneNumber();
}
@Override
public void updateUser(UserMemberUpdateVo userMemberUpdateVo) {
WxUserMember wxUserMember = new WxUserMember();
// 完善用户信息, 判断是否标记完善信息
WxUserMember wxUserMember = SecurityUtils.getLoginUser().getWxUserMember();
if (wxUserMember.getIsCompleteInformation() == null ||
wxUserMember.getIsCompleteInformation() == 0) {
// 修改完善
wxUserMember.setIsCompleteInformation(1);
// TODO 首次完善,增加加分
}
BeanUtils.copyProperties(userMemberUpdateVo, wxUserMember);
wxUserMember.setUpdateTime(DateUtils.getNowDate());
wxUserMemberMapper.updateWxUserMember(wxUserMember);
}

@ -3,19 +3,26 @@ package com.flossom.miniProgram.utils;
import com.alibaba.fastjson.JSON;
import com.flossom.common.core.constant.CacheConstants;
import com.flossom.common.core.domain.entity.WxParameterSetting;
import com.flossom.common.core.exception.ServiceException;
import com.flossom.common.core.mapper.WxParameterSettingMapper;
import com.flossom.common.core.utils.StringUtils;
import com.flossom.common.redis.service.RedisService;
import com.flossom.miniProgram.config.properties.WxConfig;
import com.flossom.miniProgram.domain.vo.OfficialAccountUserDetailRet;
import com.flossom.miniProgram.domain.vo.OfficialAccountUserReq;
import com.flossom.miniProgram.domain.vo.OfficialAccountUserRet;
import com.flossom.miniProgram.domain.vo.WxAccessTokenRet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
*
@ -94,29 +101,18 @@ public class MiniProgramUtils {
}
/**
* @param code
* @return <p></p>
* errcode number
* errmsg string
* phone_info object
*
* phoneNumber string
* purePhoneNumber string
* countryCode string
* acceess_token
*
* @return
* @throws Exception
*/
public static String getPhone(String code, String accessToken) throws Exception {
Map<String, String> params = new HashMap();
params.put("code", code);
return HttpClientUtils.postParameters(wxConfig.getObtainPhoneUrl() + "?access_token=" + accessToken, JSON.toJSONString(params));
}
public static String getAccessToken(String openid) throws Exception {
public static String getAccessToken() throws Exception {
/**
* TODO: access_token redis access_token 2使
* 1 redis access_token access_token
*/
String accessToken = redisService.getCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE + openid);
String accessToken = redisService.getCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE);
if (StringUtils.isBlank(accessToken)) {
// 获取 access_token
Map<String, String> params = new HashMap();
@ -132,10 +128,138 @@ public class MiniProgramUtils {
return null;
}
// 保存缓存
redisService.setCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE + openid,
redisService.setCacheObject(CacheConstants.WX_ACCESS_TOKEN_CACHE,
wxAccessTokenRet.getAccess_token(), CacheConstants.WX_ACCESS_TOKEN_EXPIRATION, TimeUnit.MINUTES);
return wxAccessTokenRet.getAccess_token();
}
return accessToken;
}
/**
* @param code
* @return <p></p>
* errcode number
* errmsg string
* phone_info object
*
* phoneNumber string
* purePhoneNumber string
* countryCode string
*/
public static String getPhone(String code) throws Exception {
String accessToken = getAccessToken();
if (StringUtils.isBlank(accessToken)) {
throw new ServiceException("获取用户手机号码失败");
}
Map<String, String> params = new HashMap();
params.put("code", code);
return HttpClientUtils.postParameters(wxConfig.getObtainPhoneUrl() + "?access_token=" + accessToken, JSON.toJSONString(params));
}
/**
*
* TODO: 10000OpenID
*
* @param nextOpenid openid
* @return
* @throws Exception
*/
public static OfficialAccountUserRet obtainWxOfficialAccountUser(String nextOpenid) throws Exception {
String accessToken = getAccessToken();
if (StringUtils.isBlank(accessToken)) {
logger.error("获取关注微信公众号用户列表失败获取accessToken失败");
throw new ServiceException("操作失败");
}
Map<String, String> params = new HashMap();
params.put("access_token", accessToken);
if (StringUtils.isNotBlank(nextOpenid)) {
params.put("next_openid", nextOpenid);
}
String result = HttpClientUtils.getParameters(wxConfig.getObtainWxOfficialAccountUserUrl(), params);
logger.info("请求微信服务器获取关注微信公众号的用户列表:{}", result);
OfficialAccountUserRet officialAccountUserRet = JSON.parseObject(result, OfficialAccountUserRet.class);
if (officialAccountUserRet.getErrcode() != 0) {
logger.error("获取 关注微信公众号的用户列表 失败: {}", officialAccountUserRet.getErrmsg());
throw new ServiceException("操作失败");
}
return officialAccountUserRet;
}
/**
* unionid
* TODO: officialAccountUserReqList 100
*/
public static OfficialAccountUserDetailRet ObtainUserInfoByOpenid(List<OfficialAccountUserReq> officialAccountUserReqList) throws Exception {
String accessToken = getAccessToken();
if (StringUtils.isBlank(accessToken)) {
logger.error("获取关注微信公众号用户的unionid获取accessToken失败");
throw new ServiceException("操作失败");
}
Map<String, String> params = new HashMap();
params.put("user_list", JSON.toJSONString(officialAccountUserReqList));
String result = HttpClientUtils.postParameters(wxConfig.getObtainUserInfoByOpenidUrl() + "access_token=" + accessToken, params);
logger.info("请求微信服务器获获取 关注微信公众号用户的 unionid列表{}", result);
OfficialAccountUserDetailRet officialAccountUserDetailRet = JSON.parseObject(result, OfficialAccountUserDetailRet.class);
if (officialAccountUserDetailRet.getErrcode() != 0) {
logger.error("获取 关注微信公众号的用户列表 失败: {}", officialAccountUserDetailRet.getErrmsg());
throw new ServiceException("操作失败");
}
return officialAccountUserDetailRet;
}
/**
*
*
* @return
*/
public static Boolean isAttentionOfficialAccount(String unionId) throws Exception {
String nextOpenid = null;
Integer currentTotal = 0;
while (true) {
// 1、获取关注微信公众号的用户列表
OfficialAccountUserRet officialAccountUserRet = obtainWxOfficialAccountUser(null);
if (officialAccountUserRet.getErrcode() != 0) {
logger.error("获取微信用户列表失败: {}", officialAccountUserRet.getErrmsg());
throw new ServiceException("获取微信用户列表失败");
}
if (officialAccountUserRet.getCount() == null || officialAccountUserRet.getCount() == 0) {
return false;
}
currentTotal += officialAccountUserRet.getCount();
nextOpenid = officialAccountUserRet.getNext_openid();
List<String> openidList = officialAccountUserRet.getOpenidList();
logger.info("微信公众号关注列表:{}", openidList);
// 2、获取关注微信公众号的unionid
int pageSize = 100;
int page = (int) Math.ceil(officialAccountUserRet.getCount() / pageSize);
if (page > 0) {
List<String> pageOpenidList = officialAccountUserRet.getOpenidList();
for (int pageNo = 1; pageNo <= page; pageNo++) {
// 构建分页集合
List<String> pageList = pageOpenidList.stream().skip((pageNo - 1) * 100).limit(pageSize).collect(Collectors.toList());
// 获取 unionid 集合
List<OfficialAccountUserReq> officialAccountUserReqList = new ArrayList<>();
for (String openid : pageList) {
OfficialAccountUserReq officialAccountUserReq = new OfficialAccountUserReq(openid);
officialAccountUserReqList.add(officialAccountUserReq);
}
OfficialAccountUserDetailRet officialAccountUserDetailRet = ObtainUserInfoByOpenid(officialAccountUserReqList);
// 3、判断当前unionid是否在关注者列表
return officialAccountUserDetailRet.getUser_info_list().contains(unionId);
}
}
// 4、 查完全部,未找到退出
if (StringUtils.isBlank(nextOpenid) || officialAccountUserRet.getTotal() == currentTotal) {
break;
}
}
return false;
}
}

Loading…
Cancel
Save