🆕 #2676 【企业微信】增加家校应用-复学码接口支持

This commit is contained in:
0katekate0
2022-06-05 22:38:00 +08:00
committed by GitHub
parent 6ce418a719
commit 0dfd7a091c
18 changed files with 592 additions and 38 deletions

View File

@@ -34,24 +34,26 @@ public interface WxCpMsgAuditService {
* 获取解密的聊天数据Model
*
* @param chatData getChatDatas()获取到的聊天数据
* @param pkcs1 使用什么方式进行解密1代表使用PKCS1进行解密2代表PKCS8进行解密 ...
* @return 解密后的聊天数据
* @throws Exception
*/
WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception;
WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception;
/**
* 获取解密的聊天数据明文
*
* @param chatData getChatDatas()获取到的聊天数据
* @param pkcs1 使用什么方式进行解密1代表使用PKCS1进行解密2代表PKCS8进行解密 ...
* @return 解密后的明文
* @throws Exception
*/
String getChatPlainText(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception;
String getChatPlainText(@NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception;
/**
* 获取媒体文件
* 针对图片、文件等媒体数据提供sdk接口拉取数据内容。
*
* <p>
* 注意:
* 根据上面返回的文件类型,拼接好存放文件的绝对路径即可。此时绝对路径写入文件流,来达到获取媒体文件的目的。
* 详情可以看官方文档,亦可阅读此接口源码。

View File

@@ -0,0 +1,60 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.school.WxCpCustomizeHealthInfo;
import me.chanjar.weixin.cp.bean.school.WxCpResultList;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 企业微信家校应用 复学码相关接口.
* https://developer.work.weixin.qq.com/document/path/93744
* <p>
* 权限说明:
* 仅复学码应用可以调用
*
* @author <a href="https://github.com/0katekate0">Wang_Wong</a>
* @date: 2022/5/31 9:10
*/
public interface WxCpSchoolService {
/**
* 获取老师健康信息
* 请求方式: POSTHTTPS
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/user/get_teacher_customize_health_info?access_token=ACCESS_TOKEN
*
* @param date
* @param nextKey
* @param limit
* @return
* @throws WxErrorException
*/
WxCpCustomizeHealthInfo getTeacherCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException;
/**
* 获取学生健康信息
* 请求方式: POSTHTTPS
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/user/get_student_customize_health_info?access_token=ACCESS_TOKEN
*
* @param date
* @param nextKey
* @param limit
* @return
* @throws WxErrorException
*/
WxCpCustomizeHealthInfo getStudentCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException;
/**
* 获取师生健康码
* 请求方式POSTHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/user/get_health_qrcode?access_token=ACCESS_TOKEN
*
* @param userIds
* @param type
* @return
* @throws WxErrorException
*/
WxCpResultList getHealthQrCode(@NotNull List<String> userIds, @NotNull Integer type) throws WxErrorException;
}

View File

@@ -400,6 +400,13 @@ public interface WxCpService extends WxService {
*/
WxCpOaService getOaService();
/**
* 获取家校应用复学码相关接口的服务类对象
*
* @return
*/
WxCpSchoolService getSchoolService();
/**
* 获取家校应用健康上报的服务类对象
*

View File

@@ -49,6 +49,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
private WxCpTagService tagService = new WxCpTagServiceImpl(this);
private WxCpAgentService agentService = new WxCpAgentServiceImpl(this);
private WxCpOaService oaService = new WxCpOaServiceImpl(this);
private WxCpSchoolService schoolService = new WxCpSchoolServiceImpl(this);
private WxCpSchoolHealthService schoolHealthService = new WxCpSchoolHealthServiceImpl(this);
private WxCpLivingService livingService = new WxCpLivingServiceImpl(this);
private WxCpOaAgentService oaAgentService = new WxCpOaAgentServiceImpl(this);
@@ -494,6 +495,11 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
return oaService;
}
@Override
public WxCpSchoolService getSchoolService() {
return schoolService;
}
@Override
public WxCpSchoolHealthService getSchoolHealthService() {
return schoolHealthService;

View File

@@ -97,6 +97,7 @@ public class WxCpMsgAuditServiceImpl implements WxCpMsgAuditService {
Finance.FreeSlice(slice);
WxCpChatDatas chatDatas = WxCpChatDatas.fromJson(content);
if (chatDatas.getErrCode().intValue() != 0) {
Finance.DestroySingletonSDK(sdk);
throw new WxErrorException(chatDatas.toJson());
}
@@ -104,23 +105,33 @@ public class WxCpMsgAuditServiceImpl implements WxCpMsgAuditService {
}
@Override
public WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception {
String plainText = this.decryptChatData(chatData);
public WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception {
String plainText = this.decryptChatData(chatData, pkcs1);
return WxCpChatModel.fromJson(plainText);
}
public String decryptChatData(WxCpChatDatas.WxCpChatData chatData) throws Exception {
// 企业获取的会话内容将用公钥加密企业可用自行保存的私钥解开会话内容数据aeskey不能为空
String priKey = cpService.getWxCpConfigStorage().getAesKey();
public String decryptChatData(WxCpChatDatas.WxCpChatData chatData, Integer pkcs1) throws Exception {
/**
* 企业获取的会话内容,使用企业自行配置的消息加密公钥进行加密,企业可用自行保存的私钥解开会话内容数据。
* msgAuditPriKey 会话存档私钥不能为空
*/
String priKey = cpService.getWxCpConfigStorage().getMsgAuditPriKey();
if (StringUtils.isEmpty(priKey)) {
throw new WxErrorException("请配置会话存档私钥【aesKey】");
throw new WxErrorException("请配置会话存档私钥【msgAuditPriKey】");
}
String decryptByPriKey = WxCpCryptUtil.decryptByPriKey(chatData.getEncryptRandomKey(), priKey);
// 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice在使用完slice中数据后还需要调用FreeSlice释放。
String decryptByPriKey = WxCpCryptUtil.decryptPriKey(chatData.getEncryptRandomKey(), priKey, pkcs1);
/**
* 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice在使用完slice中数据后还需要调用FreeSlice释放。
*/
long sdk = Finance.SingletonSDK();
long msg = Finance.NewSlice();
/**
* 解密会话存档内容
* sdk不会要求用户传入rsa私钥保证用户会话存档数据只有自己能够解密。
* 此处需要用户先用rsa私钥解密encrypt_random_key后作为encrypt_key参数传入sdk来解密encrypt_chat_msg获取会话存档明文。
*/
int ret = Finance.DecryptData(sdk, decryptByPriKey, chatData.getEncryptChatMsg(), msg);
if (ret != 0) {
Finance.FreeSlice(msg);
@@ -128,15 +139,17 @@ public class WxCpMsgAuditServiceImpl implements WxCpMsgAuditService {
throw new WxErrorException("msg err ret " + ret);
}
// 明文
/**
* 明文
*/
String plainText = Finance.GetContentFromSlice(msg);
Finance.FreeSlice(msg);
return plainText;
}
@Override
public String getChatPlainText(WxCpChatDatas.@NonNull WxCpChatData chatData) throws Exception {
return this.decryptChatData(chatData);
public String getChatPlainText(WxCpChatDatas.@NonNull WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception {
return this.decryptChatData(chatData, pkcs1);
}
@Override

View File

@@ -0,0 +1,67 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpSchoolService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.school.WxCpCustomizeHealthInfo;
import me.chanjar.weixin.cp.bean.school.WxCpResultList;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.*;
/**
* 企业微信家校应用 复学码相关接口实现类.
* https://developer.work.weixin.qq.com/document/path/93744
*
* @author <a href="https://github.com/0katekate0">Wang_Wong</a>
* @date: 2022/6/1 14:05
*/
@Slf4j
@RequiredArgsConstructor
public class WxCpSchoolServiceImpl implements WxCpSchoolService {
private final WxCpService cpService;
@Override
public WxCpCustomizeHealthInfo getTeacherCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_TEACHER_CUSTOMIZE_HEALTH_INFO);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("date", date);
jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100));
if (nextKey != null) {
jsonObject.addProperty("next_key", nextKey);
}
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
return WxCpCustomizeHealthInfo.fromJson(responseContent);
}
@Override
public WxCpCustomizeHealthInfo getStudentCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_STUDENT_CUSTOMIZE_HEALTH_INFO);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("date", date);
jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100));
if (nextKey != null) {
jsonObject.addProperty("next_key", nextKey);
}
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
return WxCpCustomizeHealthInfo.fromJson(responseContent);
}
@Override
public WxCpResultList getHealthQrCode(@NotNull List<String> userIds, @NotNull Integer type) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_HEALTH_QRCODE);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("type", type);
jsonObject.addProperty("userids", userIds.toString());
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
return WxCpResultList.fromJson(responseContent);
}
}