Commit 4146c7a9 authored by 李健华's avatar 李健华

Merge branch 'feature/oneId-2022-02-15' into 'master'

Feature/one id 2022 02 15

See merge request !48
parents bc4ccd9a bf6049eb
...@@ -411,6 +411,11 @@ ...@@ -411,6 +411,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies> </dependencies>
......
package cn.quantgroup.xyqb.controller.external;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
import cn.quantgroup.xyqb.aspect.captcha.CaptchaFiniteValidator;
import cn.quantgroup.xyqb.aspect.captcha.LoginInterceptor;
import cn.quantgroup.xyqb.aspect.limit.PasswordFreeAccessValidator;
import cn.quantgroup.xyqb.aspect.lock.PasswordErrorFiniteValidator;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.Merchant;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserAttached;
import cn.quantgroup.xyqb.entity.UserDetail;
import cn.quantgroup.xyqb.exception.UserNotExistException;
import cn.quantgroup.xyqb.exception.VerificationCodeErrorException;
import cn.quantgroup.xyqb.model.*;
import cn.quantgroup.xyqb.model.session.SessionStruct;
import cn.quantgroup.xyqb.model.session.SessionValue;
import cn.quantgroup.xyqb.model.webchat.AccessTokenResponse;
import cn.quantgroup.xyqb.service.http.IHttpService;
import cn.quantgroup.xyqb.service.merchant.IMerchantService;
import cn.quantgroup.xyqb.service.register.IUserRegisterService;
import cn.quantgroup.xyqb.service.session.ISessionService;
import cn.quantgroup.xyqb.service.sms.ISmsService;
import cn.quantgroup.xyqb.service.user.*;
import cn.quantgroup.xyqb.service.wechat.IWechatFollowService;
import cn.quantgroup.xyqb.service.wechat.IWechatService;
import cn.quantgroup.xyqb.session.XyqbSessionContextHolder;
import cn.quantgroup.xyqb.util.IpUtil;
import cn.quantgroup.xyqb.util.PasswordUtil;
import cn.quantgroup.xyqb.util.TenantUtil;
import cn.quantgroup.xyqb.util.ValidationUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.util.*;
import static cn.quantgroup.xyqb.Constants.VERIFICATION_CODE_FINITE_COUNT_NEW;
/**
* 微信公众号与企业微信关注情况
*
*/
@Slf4j
@RestController
@RequestMapping("/wechatFollow")
public class WechatFollowController implements IBaseController {
@Autowired
private IWechatFollowService wechatFollowService;
@Autowired
private DataSource dataSource;
@Autowired
private JdbcTemplate jdbcTemplate;
@RequestMapping("/wechatFollowTask")
public JsonResult wechatFollowTask() {
wechatFollowService.executeTask();
return null;
}
}
...@@ -64,12 +64,12 @@ public class AppletController { ...@@ -64,12 +64,12 @@ public class AppletController {
*/ */
@Validated @Validated
@PostMapping("/login") @PostMapping("/login")
public JsonResult login(@RequestParam String appName, @RequestParam String openId, @RequestParam(required = false) Integer tenantId, String utmSource, @RequestParam(required = false) Integer appNo) { public JsonResult login(@RequestParam String appName, @RequestParam String openId, @RequestParam(required = false) Integer tenantId, String utmSource, @RequestParam(required = false) Integer appNo, @RequestParam(required = false) String unionId) {
if (!containsAppName(appName)) { if (!containsAppName(appName)) {
throw new DataException("appName不合法"); throw new DataException("appName不合法");
} }
LoginVo login = iAppletService.login(appName, openId, tenantId, utmSource); LoginVo login = iAppletService.login(appName, openId, tenantId, utmSource, unionId);
return JsonResult.buildSuccessResultGeneric(login); return JsonResult.buildSuccessResultGeneric(login);
} }
......
package cn.quantgroup.xyqb.entity;
import cn.quantgroup.xyqb.util.EmojiUtil;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* 微信公众号和企业微信关注情况表
*/
@Entity
@Table(name = "wechat_info_relation")
@Data
public class WechatInfoRelation extends BaseEntity implements Serializable {
private static final long serialVersionUID = 8208660828881784475L;
@Column(name = "user_id")
private Long userId;
@Column(name = "open_id")
private String openId;
@Column(name = "union_id")
private String unionId;
@Column(name = "is_follow_wechat")
private Integer isFollowWechat;
@Column(name = "is_follow_enterprise_wechat")
private Integer isFollowEnterpriseWechat;
@Column(name = "is_followed_wechat")
private Integer isFollowedWechat;
@Column(name = "is_followed_enterprise_wechat")
private Integer isFollowedEnterpriseWechat;
}
package cn.quantgroup.xyqb.model.webchat;
import lombok.Data;
import java.io.Serializable;
@Data
public class ContactInfoResponse implements Serializable {
private static final long serialVersionUID = -1L;
private String externalUserid;
private String name;
private Integer type;
private String unionid;
}
package cn.quantgroup.xyqb.model.webchat;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
/**
*
* 获取部门下成员的客户信息
*/
@Data
public class ContactListResponse implements Serializable {
private static final long serialVersionUID = -1L;
private Object followInfo;
private ContactInfoResponse externalContact;
}
package cn.quantgroup.xyqb.model.webchat;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
* 获取部门下成员的客户列表
*/
@Data
public class CustomerListResponse implements Serializable {
private static final long serialVersionUID = -1L;
private Integer errcode;
private String errmsg;
private List<ContactListResponse> external_contact_list;
private String nextCursor;
}
package cn.quantgroup.xyqb.model.webchat;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
* 获取部门下成员信息
*/
@Data
public class DepartmentInfoResponse implements Serializable {
private static final long serialVersionUID = -1L;
private String userid;
private String name;
}
package cn.quantgroup.xyqb.model.webchat;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
* 获取部门下成员列表
*/
@Data
public class DepartmentListResponse implements Serializable {
private static final long serialVersionUID = -1L;
private Integer errcode;
private String errmsg;
private List<DepartmentInfoResponse> userlist;
}
package cn.quantgroup.xyqb.model.webchat;
import lombok.Data;
import javax.persistence.Column;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@Data
public class WechatUserListResponse implements Serializable {
private static final long serialVersionUID = -1L;
private Integer total;
private Integer count;
private Map<String, List<String>> data;
private String next_openid;
private Integer errcode;
private String errmsg;
}
package cn.quantgroup.xyqb.repository;
import cn.quantgroup.xyqb.entity.WechatInfoRelation;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import static org.springframework.transaction.annotation.Propagation.MANDATORY;
public interface IWeChatInfoRelationRepository extends JpaRepository<WechatInfoRelation, Long> {
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query(value = "update wechat_info_relation as wir set wir.is_follow_wechat = 1 where wir.open_id IN (?1)", nativeQuery = true)
void updateIsFollowWechatInOpenIdList(List<String> openIdList);
}
...@@ -72,4 +72,17 @@ public interface IWeChatUserRepository extends JpaRepository<WechatUserInfo, Lon ...@@ -72,4 +72,17 @@ public interface IWeChatUserRepository extends JpaRepository<WechatUserInfo, Lon
@Modifying @Modifying
@Query(value = "update wechat_userinfo set user_id=null,phone_no='*' where (open_id=?1 or user_id=?2) and app_name=?3", nativeQuery = true) @Query(value = "update wechat_userinfo set user_id=null,phone_no='*' where (open_id=?1 or user_id=?2) and app_name=?3", nativeQuery = true)
int dissociateUser(String openId, Long userId, String appName); int dissociateUser(String openId, Long userId, String appName);
/**
* 更新unionId
* @param userId
* @param appName
* @param unionId
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query(value = "update wechat_userinfo set union_id=?3 where user_id=?1 and app_name=?2", nativeQuery = true)
int updateUserUnionId(Long userId, String appName, String unionId);
} }
...@@ -12,5 +12,5 @@ import cn.quantgroup.xyqb.entity.middleoffice.AppletParamEntry; ...@@ -12,5 +12,5 @@ import cn.quantgroup.xyqb.entity.middleoffice.AppletParamEntry;
*/ */
public interface IAppletService { public interface IAppletService {
Long relevance(AppletParamEntry appletParamEntry); Long relevance(AppletParamEntry appletParamEntry);
LoginVo login(String appName, String openId, Integer tenantId, String utmSource); LoginVo login(String appName, String openId, Integer tenantId, String utmSource, String unionId);
} }
...@@ -104,7 +104,7 @@ public class AppletServiceImpl implements IAppletService { ...@@ -104,7 +104,7 @@ public class AppletServiceImpl implements IAppletService {
@Override @Override
public LoginVo login(String appName, String openId, Integer tenantId, String utmSource) { public LoginVo login(String appName, String openId, Integer tenantId, String utmSource, String unionId) {
if (TenantUtil.validationTenantIdIsNullOrZero(tenantId)) { if (TenantUtil.validationTenantIdIsNullOrZero(tenantId)) {
tenantId = TenantUtil.TENANT_DEFAULT; tenantId = TenantUtil.TENANT_DEFAULT;
} }
...@@ -128,6 +128,10 @@ public class AppletServiceImpl implements IAppletService { ...@@ -128,6 +128,10 @@ public class AppletServiceImpl implements IAppletService {
} }
iOauthLoginInfoService.addLoginInfo(user, tenantId); iOauthLoginInfoService.addLoginInfo(user, tenantId);
if (!unionId.equals(wechatUserInfo.getUnionId())) {
iWeChatUserRepository.updateUserUnionId(wechatUserInfo.getUserId(), appName, unionId);
}
} else { } else {
// 通过租户id和openId查询是否有关联 // 通过租户id和openId查询是否有关联
Long userId = tenantService.getTenantCustomerInfoByOpenId(openId, tenantId); Long userId = tenantService.getTenantCustomerInfoByOpenId(openId, tenantId);
...@@ -142,6 +146,7 @@ public class AppletServiceImpl implements IAppletService { ...@@ -142,6 +146,7 @@ public class AppletServiceImpl implements IAppletService {
} }
} }
LoginVo loginVo = loginModule.loginByUserId(user.getRegisteredFrom(), LoginVo loginVo = loginModule.loginByUserId(user.getRegisteredFrom(),
utmSource == null ? "" : utmSource, user.getId(), tenantId); utmSource == null ? "" : utmSource, user.getId(), tenantId);
return loginVo; return loginVo;
......
package cn.quantgroup.xyqb.service.wechat;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.webchat.AccessTokenResponse;
public interface IWechatFollowService {
AccessTokenResponse getToken();
JsonResult executeWechatFollowStatus(String nextOpenId, String period);
void executeTask();
}
package cn.quantgroup.xyqb.service.wechat.impl;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.event.WechatBindEvent;
import cn.quantgroup.xyqb.exception.WechatRelateUserException;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.webchat.*;
import cn.quantgroup.xyqb.repository.IWeChatInfoRelationRepository;
import cn.quantgroup.xyqb.repository.IWeChatUserRepository;
import cn.quantgroup.xyqb.service.http.IHttpService;
import cn.quantgroup.xyqb.service.wechat.IWechatFollowService;
import cn.quantgroup.xyqb.service.wechat.IWechatService;
import cn.quantgroup.xyqb.util.GcodeUtils;
import cn.quantgroup.xyqb.util.ValidationUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* Created by Miraculous on 2017/1/19.
*/
@Slf4j
@Service
public class WechatFollowServiceImpl implements IWechatFollowService {
private static final String WECHAT_FOLLOW_TOKEN_KEY_PREFIX = "wechatFollow:token:";
@Value("${wechat.appid}")
private String appId;
@Value("${wechat.secret}")
private String secret;
@Value("${qywechat.corpid}")
private String corpid;
@Value("${qywehcat.secret}")
private String qySecret;
// 部门
@Value("${qywehcat.departmentId}")
private Integer departmentId;
private String accessTokenUrl;
private String userListUrl;
private String qyAccessTokenUrl;
private String departmentUserListUrl;
private String customerInfoListBatchUrl;
@Resource
private IHttpService httpService;
@Resource
private IWeChatInfoRelationRepository weChatInfoRelationRepository;
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
@Resource
private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private JdbcTemplate jdbcTemplate;
// 公众号
private final Integer WECHAT_ACCOUNT = 1;
//企业微信
private final Integer ENTERPRISE_WECHAT = 2;
// 公众号类型
private final String WECHAT_XYQB = "xyqb";
// 游标值
private String cursorValue = "";
@PostConstruct
private void init() {
// 公众号
accessTokenUrl = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, secret);
userListUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s";
// 企业微信
qyAccessTokenUrl = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", corpid, qySecret);
// 成员列表
departmentUserListUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=%s&department_id=%s&fetch_child=1";
//批量获取客户详情
customerInfoListBatchUrl = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=%s";
}
@Override
public AccessTokenResponse getToken() {
try {
String response = httpService.get(accessTokenUrl);
if (StringUtils.isEmpty(response)) {
return null;
}
AccessTokenResponse accessTokenResponse = JSONObject.parseObject(response,
AccessTokenResponse.class);
if (accessTokenResponse == null) {
return null;
}
accessTokenResponse.setInitialTime(System.currentTimeMillis() - Constants.MILLIS_OF_TEN_SECOND);
redisTemplate.opsForValue().set(WECHAT_FOLLOW_TOKEN_KEY_PREFIX, JSONObject.toJSONString(accessTokenResponse), accessTokenResponse.getExpiresIn() + Constants.THOUSAND_SECOND, TimeUnit.SECONDS);
return accessTokenResponse;
} catch (Exception ex) {
return null;
}
}
@Override
public JsonResult executeWechatFollowStatus(String nextOpenId, String period) {
AccessTokenResponse token = getToken();
String userListUrlFormat = String.format(userListUrl, token.getAccessToken(), nextOpenId);
try {
String response = httpService.get(userListUrlFormat);
if (response != null) {
WechatUserListResponse wechatUserListResponse = JSONObject.parseObject(response, WechatUserListResponse.class);
if (wechatUserListResponse.getErrcode() == null && wechatUserListResponse.getCount() > 0) {
nextOpenId = wechatUserListResponse.getNext_openid();
List<String> opendIdList = wechatUserListResponse.getData().get("openid");
if (!opendIdList.isEmpty()) {
String[] openIds = opendIdList.toArray(new String[0]);
String openIdStrs = String.join("\',\'", openIds);
openIdStrs = "\'" + openIdStrs + "\'";
// 添加公众号数据
String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`) SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where app_name='%s' and user_id is not null and `open_id` IN (%s)", WECHAT_ACCOUNT, period, WECHAT_XYQB, openIdStrs);
jdbcTemplate.update(sql);
}
if (nextOpenId != "") {
executeWechatFollowStatus(nextOpenId, period);
}
return JsonResult.buildSuccessResult("", opendIdList);
} else {
return null;
}
}
} catch (Exception ex) {
log.error("同步微信公众号数据失败--{}", ex.getMessage());
return null;
}
return null;
}
@Override
public void executeTask() {
// 初始化任务数据
// initTask();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYYMMdd");
String period = simpleDateFormat.format(new Date());
// 微信公众号关注数据更新
executeWechatFollowStatus("", period);
// 企业微信关注数据更新
executeEnterpriseFollowStatus("", period);
}
private JsonResult executeEnterpriseFollowStatus(String s, String period) {
try {
String response = httpService.get(qyAccessTokenUrl);
if (StringUtils.isEmpty(response)) {
return null;
}
AccessTokenResponse accessTokenResponse = JSONObject.parseObject(response,
AccessTokenResponse.class);
if (accessTokenResponse.getAccessToken() != null) {
String deparmentList = String.format(departmentUserListUrl, accessTokenResponse.getAccessToken(), departmentId);
String departmentRep = httpService.get(deparmentList);
DepartmentListResponse departmentListResponse = JSONObject.parseObject(departmentRep, DepartmentListResponse.class);
if (!departmentListResponse.getUserlist().isEmpty()) {
List<String> userIdList = departmentListResponse.getUserlist().stream().map(DepartmentInfoResponse::getUserid).collect(Collectors.toList());
System.out.println(userIdList);
if (!userIdList.isEmpty()) {
// 批量查询客户详情
batchQueryCustomerDetailInfo2(accessTokenResponse.getAccessToken(), userIdList, "", period);
}
}
}
} catch (Exception e) {
log.error("同步企业微信数据失败--{}", e.getMessage());
return null;
}
return null;
}
private JsonResult batchQueryCustomerDetailInfo(String accessToken, List<String> userIdList, String cursor, String period) {
// 查询客户详情
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("userid_list", userIdList);
parameters.put("cursor", cursor);
parameters.put("limit", "100");
String customerInfoUrl = String.format(customerInfoListBatchUrl, accessToken);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.postForEntity(customerInfoUrl, parameters, String.class); //提交的body内容为user对象,请求的返回的body类型为String
log.info("batchQueryCustomerDetailInfo--customerInfoUrl:{}, parameters:{}", customerInfoUrl, parameters);
CustomerListResponse customerListResponse = JSONObject.parseObject(responseEntity.getBody(), CustomerListResponse.class);
if (customerListResponse.getErrcode() == 0) {
// 获取所有unionId
List<String> unionIdAll = customerListResponse.getExternal_contact_list().stream().map(a -> a.getExternalContact().getUnionid()).collect(Collectors.toList());
if (!unionIdAll.isEmpty()) {
String[] unionIds = unionIdAll.toArray(new String[0]);
String unionIdStrs = String.join("\',\'", unionIds);
unionIdStrs = "\'" + unionIdStrs + "\'";
// String sql = String.format("INSERT INTO wechat_enterprise(`unionid`) values ('%s')", String.join(",", unionIdAll));
String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`) SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where user_id is not null and `union_id` IN (%s)", ENTERPRISE_WECHAT, period, unionIdStrs);
jdbcTemplate.update(sql);
}
// 根据unionid 添加现有指定信息
// 判断nextCursor不为空,继续获取更多客户
log.info("customerListResponse--{}", JSONObject.toJSONString(customerListResponse));
if (!"".equals(customerListResponse.getNextCursor()) && !customerListResponse.getExternal_contact_list().isEmpty()) {
batchQueryCustomerDetailInfo(accessToken, userIdList, customerListResponse.getNextCursor(), period);
}
return JsonResult.buildSuccessResult();
} else {
batchQueryCustomerDetailInfo(accessToken, userIdList, customerListResponse.getNextCursor(), period);
}
return JsonResult.buildSuccessResult();
}
private JsonResult batchQueryCustomerDetailInfo2(String accessToken, List<String> userIdList, String cursor, String period) {
// 查询客户详情
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("userid_list", userIdList);
parameters.put("cursor", cursor);
parameters.put("limit", "100");
String customerInfoUrl = String.format(customerInfoListBatchUrl, accessToken);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.postForEntity(customerInfoUrl, parameters, String.class); //提交的body内容为user对象,请求的返回的body类型为String
log.info("batchQueryCustomerDetailInfo--customerInfoUrl:{}, parameters:{}", customerInfoUrl, parameters);
CustomerListResponse customerListResponse = JSONObject.parseObject(responseEntity.getBody(), CustomerListResponse.class);
if (customerListResponse.getErrcode() == 0) {
// 获取所有unionId
List<String> unionIdAll = customerListResponse.getExternal_contact_list().stream().map(a -> a.getExternalContact().getUnionid()).collect(Collectors.toList());
if (!unionIdAll.isEmpty()) {
String[] unionIds = unionIdAll.toArray(new String[0]);
String unionIdStrs = String.join("\',\'", unionIds);
unionIdStrs = "\'" + unionIdStrs + "\'";
// String sql = String.format("INSERT INTO wechat_enterprise(`unionid`) values ('%s')", String.join(",", unionIdAll));
String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`) SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where user_id is not null and `union_id` IN (%s)", ENTERPRISE_WECHAT, period, unionIdStrs);
jdbcTemplate.update(sql);
}
// 根据unionid 添加现有指定信息
// 判断nextCursor不为空,继续获取更多客户
log.info("customerListResponse--{}", JSONObject.toJSONString(customerListResponse));
cursorValue = customerListResponse.getNextCursor();
while (!"".equals(cursorValue)) {
batchQueryCustomerDetailFor(accessToken, userIdList, cursorValue, period);
}
// if (!"".equals(customerListResponse.getNextCursor()) && !customerListResponse.getExternal_contact_list().isEmpty()) {
// batchQueryCustomerDetailInfo(accessToken, userIdList, customerListResponse.getNextCursor(), period);
// }
return JsonResult.buildSuccessResult();
} else {
batchQueryCustomerDetailFor(accessToken, userIdList, customerListResponse.getNextCursor(), period);
}
return JsonResult.buildSuccessResult();
}
private void batchQueryCustomerDetailFor(String accessToken, List<String> userIdList, String cursor, String period) {
// 查询客户详情
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("userid_list", userIdList);
parameters.put("cursor", cursor);
parameters.put("limit", "100");
String customerInfoUrl = String.format(customerInfoListBatchUrl, accessToken);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.postForEntity(customerInfoUrl, parameters, String.class); //提交的body内容为user对象,请求的返回的body类型为String
log.info("batchQueryCustomerDetailInfo--customerInfoUrl:{}, parameters:{}", customerInfoUrl, parameters);
CustomerListResponse customerListResponse = JSONObject.parseObject(responseEntity.getBody(), CustomerListResponse.class);
if (customerListResponse.getErrcode() == 0) {
// 获取所有unionId
List<String> unionIdAll = customerListResponse.getExternal_contact_list().stream().map(a -> a.getExternalContact().getUnionid()).collect(Collectors.toList());
if (!unionIdAll.isEmpty()) {
String[] unionIds = unionIdAll.toArray(new String[0]);
String unionIdStrs = String.join("\',\'", unionIds);
unionIdStrs = "\'" + unionIdStrs + "\'";
// String sql = String.format("INSERT INTO wechat_enterprise(`unionid`) values ('%s')", String.join(",", unionIdAll));
String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`) SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where user_id is not null and `union_id` IN (%s)", ENTERPRISE_WECHAT, period, unionIdStrs);
jdbcTemplate.update(sql);
}
// 根据unionid 添加现有指定信息
// 判断nextCursor不为空,继续获取更多客户
log.info("customerListResponse--{}", JSONObject.toJSONString(customerListResponse));
cursorValue = customerListResponse.getNextCursor();
}
}
private void initTask() {
try {
// 获取最大微信微信息ID
log.info("微信同步公众号新增数据开始--");
String querySql = "SELECT MAX(`wechat_userinfo_id`) as maxid FROM wechat_info_relation";
Integer maxId = jdbcTemplate.queryForObject(querySql, Integer.class);
System.out.println(maxId);
if (maxId == null) {
maxId = 0;
}
// 同步新增微信公众号数据(app_name 为 xyqb 并且有open_id和union_id)
String sql = String.format("INSERT INTO wechat_info_relation(`wechat_userinfo_id`, `user_id`, `open_id`, `union_id`) SELECT id, user_id, open_id, open_id from wechat_userinfo where id>%s and `open_id` is not null", maxId);
jdbcTemplate.update(sql);
log.info("微信同步公众号新增数据完成--");
// 修改当前所有关注状态为 0 表示未关注
log.info("修改微信关注状态开始--");
String updateSql = "UPDATE wechat_info_relation set is_follow_wechat=0, is_follow_enterprise_wechat=0";
jdbcTemplate.update(updateSql);
log.info("修改微信关注状态完成--");
} catch (Exception e) {
log.error("微信公众号与企业微信关注情况任务失败---{}", e.getMessage());
}
}
}
package cn.quantgroup.xyqb.xxlJob;
import cn.quantgroup.xyqb.service.wechat.IWechatFollowService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@JobHandler(value = "WechatFollowStatusJobHandler")
public class WechatFollowStatusJobHandler extends IJobHandler {
@Autowired
private IWechatFollowService wechatFollowService;
@Override
public ReturnT<String> execute(String s) throws Exception {
wechatFollowService.executeTask();
return SUCCESS;
}
}
package cn.quantgroup.xyqb.xxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
@Configuration
@Slf4j
public class XxlJobConfig {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean(initMethod = "start", destroyMethod = "destroy")
public XxlJobSpringExecutor xxlJobExecutor() {
log.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
// 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
// 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxlJobSpringExecutor.setAppName(appName);
//xxlJobSpringExecutor.setAppName("xxl-job-executor-vcc-analysis");
// 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxlJobSpringExecutor.setIp(ip);
// 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxlJobSpringExecutor.setPort(port);
// 执行器通讯TOKEN [选填]:非空时启用;调度中心和执行器进行安全性校验,双方AccessToken匹配才允许通讯
xxlJobSpringExecutor.setAccessToken(accessToken);
// 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxlJobSpringExecutor.setLogPath(logPath);
// 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效;
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
}
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