package com.gs.xky.service;
|
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.gs.xky.config.DataAcquisitionConfiguration;
|
import lombok.Data;
|
import lombok.RequiredArgsConstructor;
|
import okhttp3.*;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.stereotype.Service;
|
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.concurrent.TimeUnit;
|
|
@Service
|
@RequiredArgsConstructor
|
public class WorkWXService {
|
|
private static final Logger log = LoggerFactory.getLogger(WorkWXService.class);
|
|
private final OkHttpClient client = new OkHttpClient.Builder()
|
.connectTimeout(90, TimeUnit.SECONDS)
|
.readTimeout(90, TimeUnit.SECONDS)
|
.build();
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
public String getAccessToken() throws IOException {
|
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
|
DataAcquisitionConfiguration.CORPID,
|
DataAcquisitionConfiguration.CORPSECRET);
|
|
Request request = new Request.Builder()
|
.url(url)
|
.get()
|
.build();
|
|
try (Response response = client.newCall(request).execute()) {
|
if (!response.isSuccessful()) {
|
log.error("获取企业微信access_token失败,HTTP状态码: {}", response.code());
|
throw new IOException("获取access_token失败: " + response.message());
|
}
|
|
String responseBody = response.body().string();
|
WorkWXTokenResponse tokenResponse = objectMapper.readValue(responseBody, WorkWXTokenResponse.class);
|
|
if (tokenResponse.getErrcode() != 0) {
|
log.error("获取企业微信access_token失败,错误码: {}, 错误信息: {}",
|
tokenResponse.getErrcode(), tokenResponse.getErrmsg());
|
throw new IOException("获取access_token失败: " + tokenResponse.getErrmsg());
|
}
|
|
log.info("成功获取企业微信access_token,有效期: {}秒", tokenResponse.getExpiresIn());
|
log.info("access_token : {}", tokenResponse.getAccessToken());
|
return tokenResponse.getAccessToken();
|
}
|
}
|
|
public String getContactAccessToken() throws IOException {
|
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
|
DataAcquisitionConfiguration.CORPID,
|
DataAcquisitionConfiguration.TXL_CORPSECRET);
|
|
Request request = new Request.Builder()
|
.url(url)
|
.get()
|
.build();
|
|
try (Response response = client.newCall(request).execute()) {
|
if (!response.isSuccessful()) {
|
log.error("获取企业微信通讯录access_token失败,HTTP状态码: {}", response.code());
|
throw new IOException("获取通讯录access_token失败: " + response.message());
|
}
|
|
String responseBody = response.body().string();
|
WorkWXTokenResponse tokenResponse = objectMapper.readValue(responseBody, WorkWXTokenResponse.class);
|
|
if (tokenResponse.getErrcode() != 0) {
|
log.error("获取企业微信通讯录access_token失败,错误码: {}, 错误信息: {}",
|
tokenResponse.getErrcode(), tokenResponse.getErrmsg());
|
throw new IOException("获取通讯录access_token失败: " + tokenResponse.getErrmsg());
|
}
|
|
log.info("成功获取企业微信通讯录access_token,有效期: {}秒", tokenResponse.getExpiresIn());
|
return tokenResponse.getAccessToken();
|
}
|
}
|
|
public String getUserIdByMobile(String mobile) throws IOException {
|
String accessToken = getContactAccessToken();
|
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=%s", accessToken);
|
|
Map<String, Object> requestBody = new HashMap<>();
|
requestBody.put("mobile", mobile);
|
|
MediaType mediaType = MediaType.parse("application/json; charset=UTF-8");
|
String jsonBody = objectMapper.writeValueAsString(requestBody);
|
RequestBody body = RequestBody.create(mediaType, jsonBody);
|
|
Request request = new Request.Builder()
|
.url(url)
|
.post(body)
|
.addHeader("Content-Type", "application/json; charset=UTF-8")
|
.build();
|
|
try (Response response = client.newCall(request).execute()) {
|
if (!response.isSuccessful()) {
|
log.error("通过手机号获取userid失败,HTTP状态码: {}", response.code());
|
throw new IOException("获取userid失败: " + response.message());
|
}
|
|
String responseBody = response.body().string();
|
log.info("通过手机号获取userid响应: {}", responseBody);
|
|
WorkWXUserIdResponse userIdResponse = objectMapper.readValue(responseBody, WorkWXUserIdResponse.class);
|
|
if (userIdResponse.getErrcode() != 0) {
|
log.error("通过手机号获取userid失败,错误码: {}, 错误信息: {}",
|
userIdResponse.getErrcode(), userIdResponse.getErrmsg());
|
throw new IOException("获取userid失败: " + userIdResponse.getErrmsg());
|
}
|
|
log.info("成功通过手机号 {} 获取userid: {}", mobile, userIdResponse.getUserid());
|
return userIdResponse.getUserid();
|
}
|
}
|
|
public List<WorkWXUser> getUserList() throws IOException {
|
String accessToken = getContactAccessToken();
|
String url = String.format(
|
"https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=%s&department_id=1&fetch_child=1",
|
accessToken);
|
|
Request request = new Request.Builder()
|
.url(url)
|
.get()
|
.build();
|
|
try (Response response = client.newCall(request).execute()) {
|
if (!response.isSuccessful()) {
|
log.error("获取企业微信用户列表失败,HTTP状态码: {}", response.code());
|
throw new IOException("获取用户列表失败: " + response.message());
|
}
|
|
String responseBody = response.body().string();
|
log.info("获取用户列表响应: {}", responseBody);
|
|
WorkWXUserListResponse userListResponse = objectMapper.readValue(responseBody, WorkWXUserListResponse.class);
|
|
if (userListResponse.getErrcode() != 0) {
|
log.error("获取企业微信用户列表失败,错误码: {}, 错误信息: {}",
|
userListResponse.getErrcode(), userListResponse.getErrmsg());
|
throw new IOException("获取用户列表失败: " + userListResponse.getErrmsg());
|
}
|
|
log.info("成功获取企业微信用户列表,用户数量: {}",
|
userListResponse.getUserlist() != null ? userListResponse.getUserlist().size() : 0);
|
return userListResponse.getUserlist();
|
}
|
}
|
|
public List<CheckinData> getCheckinData(long startTime, long endTime, List<String> useridList) throws IOException {
|
String accessToken = getAccessToken();
|
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token=%s", accessToken);
|
|
List<CheckinData> allCheckinData = new ArrayList<>();
|
|
int batchSize = 100;
|
int totalUsers = useridList.size();
|
int batchCount = (totalUsers + batchSize - 1) / batchSize;
|
|
log.info("开始获取打卡数据,总用户数: {}, 分批数: {}, 时间范围: {} - {}", totalUsers, batchCount, startTime, endTime);
|
|
for (int i = 0; i < batchCount; i++) {
|
int fromIndex = i * batchSize;
|
int toIndex = Math.min((i + 1) * batchSize, totalUsers);
|
|
List<String> batchUserList = useridList.subList(fromIndex, toIndex);
|
log.info("正在获取第 {}/{} 批打卡数据,用户数: {}", i + 1, batchCount, batchUserList.size());
|
|
Map<String, Object> requestBody = new HashMap<>();
|
requestBody.put("opencheckindatatype", 3);
|
requestBody.put("starttime", startTime);
|
requestBody.put("endtime", endTime);
|
requestBody.put("useridlist", batchUserList);
|
|
MediaType mediaType = MediaType.parse("application/json; charset=UTF-8");
|
String jsonBody = objectMapper.writeValueAsString(requestBody);
|
RequestBody body = RequestBody.create(mediaType, jsonBody);
|
|
Request request = new Request.Builder()
|
.url(url)
|
.post(body)
|
.addHeader("Content-Type", "application/json; charset=UTF-8")
|
.build();
|
|
try (Response response = client.newCall(request).execute()) {
|
if (!response.isSuccessful()) {
|
log.error("获取打卡数据失败,HTTP状态码: {}", response.code());
|
throw new IOException("获取打卡数据失败: " + response.message());
|
}
|
|
String responseBody = response.body().string();
|
|
WorkWXCheckinResponse checkinResponse = objectMapper.readValue(responseBody, WorkWXCheckinResponse.class);
|
|
if (checkinResponse.getErrcode() != 0) {
|
log.error("获取打卡数据失败,错误码: {}, 错误信息: {}",
|
checkinResponse.getErrcode(), checkinResponse.getErrmsg());
|
throw new IOException("获取打卡数据失败: " + checkinResponse.getErrmsg());
|
}
|
|
if (checkinResponse.getCheckindata() != null) {
|
allCheckinData.addAll(checkinResponse.getCheckindata());
|
log.info("第 {}/{} 批获取到打卡记录数: {}", i + 1, batchCount, checkinResponse.getCheckindata().size());
|
}
|
}
|
|
if (i < batchCount - 1) {
|
try {
|
Thread.sleep(500);
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
log.warn("批次间等待被中断");
|
}
|
}
|
}
|
|
log.info("打卡数据获取完成,总记录数: {}", allCheckinData.size());
|
return allCheckinData;
|
}
|
|
@Data
|
private static class WorkWXTokenResponse {
|
private Integer errcode;
|
private String errmsg;
|
@JsonProperty("access_token")
|
private String accessToken;
|
@JsonProperty("expires_in")
|
private Integer expiresIn;
|
}
|
|
@Data
|
private static class WorkWXUserIdResponse {
|
private Integer errcode;
|
private String errmsg;
|
private String userid;
|
}
|
|
@Data
|
private static class WorkWXUserListResponse {
|
private Integer errcode;
|
private String errmsg;
|
private List<WorkWXUser> userlist;
|
}
|
|
@Data
|
public static class WorkWXUser {
|
private String userid;
|
private String name;
|
private List<Integer> department;
|
@JsonProperty("open_userid")
|
private String openUserid;
|
}
|
|
@Data
|
private static class WorkWXCheckinResponse {
|
private Integer errcode;
|
private String errmsg;
|
private List<CheckinData> checkindata;
|
}
|
|
@Data
|
public static class CheckinData {
|
private String userid;
|
private String groupname;
|
@JsonProperty("checkin_type")
|
private String checkinType;
|
@JsonProperty("exception_type")
|
private String exceptionType;
|
@JsonProperty("checkin_time")
|
private Long checkinTime;
|
@JsonProperty("location_title")
|
private String locationTitle;
|
@JsonProperty("location_detail")
|
private String locationDetail;
|
private String wifiname;
|
private String notes;
|
private String wifimac;
|
private String mediaids;
|
private Double lat;
|
private Double lng;
|
}
|
}
|