Skip to content

Commit 0dfd7a0

Browse files
authored
🆕 #2676 【企业微信】增加家校应用-复学码接口支持
1 parent 6ce418a commit 0dfd7a0

File tree

18 files changed

+592
-38
lines changed

18 files changed

+592
-38
lines changed

spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpProperties.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public class WxCpProperties {
3838
* 微信企业号应用 EncodingAESKey
3939
*/
4040
private String aesKey;
41+
/**
42+
* 微信企业号应用 会话存档私钥
43+
*/
44+
private String msgAuditPriKey;
4145
/**
4246
* 微信企业号应用 会话存档类库路径
4347
*/

spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/AbstractWxCpConfigStorageConfiguration.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ protected WxCpDefaultConfigImpl config(WxCpDefaultConfigImpl config, WxCpPropert
1818
String token = properties.getToken();
1919
Integer agentId = properties.getAgentId();
2020
String aesKey = properties.getAesKey();
21-
// 企业微信,会话存档路径
21+
// 企业微信,私钥,会话存档路径
22+
String msgAuditPriKey = properties.getMsgAuditPriKey();
2223
String msgAuditLibPath = properties.getMsgAuditLibPath();
2324

2425
config.setCorpId(corpId);
@@ -32,6 +33,9 @@ protected WxCpDefaultConfigImpl config(WxCpDefaultConfigImpl config, WxCpPropert
3233
if (StringUtils.isNotBlank(aesKey)) {
3334
config.setAesKey(aesKey);
3435
}
36+
if (StringUtils.isNotBlank(msgAuditPriKey)) {
37+
config.setMsgAuditPriKey(msgAuditPriKey);
38+
}
3539
if (StringUtils.isNotBlank(msgAuditLibPath)) {
3640
config.setMsgAuditLibPath(msgAuditLibPath);
3741
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,26 @@ public interface WxCpMsgAuditService {
3434
* 获取解密的聊天数据Model
3535
*
3636
* @param chatData getChatDatas()获取到的聊天数据
37+
* @param pkcs1 使用什么方式进行解密,1代表使用PKCS1进行解密,2代表PKCS8进行解密 ...
3738
* @return 解密后的聊天数据
3839
* @throws Exception
3940
*/
40-
WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception;
41+
WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception;
4142

4243
/**
4344
* 获取解密的聊天数据明文
4445
*
4546
* @param chatData getChatDatas()获取到的聊天数据
47+
* @param pkcs1 使用什么方式进行解密,1代表使用PKCS1进行解密,2代表PKCS8进行解密 ...
4648
* @return 解密后的明文
4749
* @throws Exception
4850
*/
49-
String getChatPlainText(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception;
51+
String getChatPlainText(@NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception;
5052

5153
/**
5254
* 获取媒体文件
5355
* 针对图片、文件等媒体数据,提供sdk接口拉取数据内容。
54-
*
56+
* <p>
5557
* 注意:
5658
* 根据上面返回的文件类型,拼接好存放文件的绝对路径即可。此时绝对路径写入文件流,来达到获取媒体文件的目的。
5759
* 详情可以看官方文档,亦可阅读此接口源码。
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package me.chanjar.weixin.cp.api;
2+
3+
import me.chanjar.weixin.common.error.WxErrorException;
4+
import me.chanjar.weixin.cp.bean.school.WxCpCustomizeHealthInfo;
5+
import me.chanjar.weixin.cp.bean.school.WxCpResultList;
6+
7+
import javax.validation.constraints.NotNull;
8+
import java.util.List;
9+
10+
/**
11+
* 企业微信家校应用 复学码相关接口.
12+
* https://developer.work.weixin.qq.com/document/path/93744
13+
* <p>
14+
* 权限说明:
15+
* 仅复学码应用可以调用
16+
*
17+
* @author <a href="https://github.com/0katekate0">Wang_Wong</a>
18+
* @date: 2022/5/31 9:10
19+
*/
20+
public interface WxCpSchoolService {
21+
22+
/**
23+
* 获取老师健康信息
24+
* 请求方式: POST(HTTPS)
25+
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/user/get_teacher_customize_health_info?access_token=ACCESS_TOKEN
26+
*
27+
* @param date
28+
* @param nextKey
29+
* @param limit
30+
* @return
31+
* @throws WxErrorException
32+
*/
33+
WxCpCustomizeHealthInfo getTeacherCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException;
34+
35+
/**
36+
* 获取学生健康信息
37+
* 请求方式: POST(HTTPS)
38+
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/user/get_student_customize_health_info?access_token=ACCESS_TOKEN
39+
*
40+
* @param date
41+
* @param nextKey
42+
* @param limit
43+
* @return
44+
* @throws WxErrorException
45+
*/
46+
WxCpCustomizeHealthInfo getStudentCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException;
47+
48+
/**
49+
* 获取师生健康码
50+
* 请求方式:POST(HTTPS)
51+
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/get_health_qrcode?access_token=ACCESS_TOKEN
52+
*
53+
* @param userIds
54+
* @param type
55+
* @return
56+
* @throws WxErrorException
57+
*/
58+
WxCpResultList getHealthQrCode(@NotNull List<String> userIds, @NotNull Integer type) throws WxErrorException;
59+
60+
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,13 @@ public interface WxCpService extends WxService {
400400
*/
401401
WxCpOaService getOaService();
402402

403+
/**
404+
* 获取家校应用复学码相关接口的服务类对象
405+
*
406+
* @return
407+
*/
408+
WxCpSchoolService getSchoolService();
409+
403410
/**
404411
* 获取家校应用健康上报的服务类对象
405412
*

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH
4949
private WxCpTagService tagService = new WxCpTagServiceImpl(this);
5050
private WxCpAgentService agentService = new WxCpAgentServiceImpl(this);
5151
private WxCpOaService oaService = new WxCpOaServiceImpl(this);
52+
private WxCpSchoolService schoolService = new WxCpSchoolServiceImpl(this);
5253
private WxCpSchoolHealthService schoolHealthService = new WxCpSchoolHealthServiceImpl(this);
5354
private WxCpLivingService livingService = new WxCpLivingServiceImpl(this);
5455
private WxCpOaAgentService oaAgentService = new WxCpOaAgentServiceImpl(this);
@@ -494,6 +495,11 @@ public WxCpOaService getOaService() {
494495
return oaService;
495496
}
496497

498+
@Override
499+
public WxCpSchoolService getSchoolService() {
500+
return schoolService;
501+
}
502+
497503
@Override
498504
public WxCpSchoolHealthService getSchoolHealthService() {
499505
return schoolHealthService;

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,46 +97,59 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S
9797
Finance.FreeSlice(slice);
9898
WxCpChatDatas chatDatas = WxCpChatDatas.fromJson(content);
9999
if (chatDatas.getErrCode().intValue() != 0) {
100+
Finance.DestroySingletonSDK(sdk);
100101
throw new WxErrorException(chatDatas.toJson());
101102
}
102103

103104
return chatDatas;
104105
}
105106

106107
@Override
107-
public WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception {
108-
String plainText = this.decryptChatData(chatData);
108+
public WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception {
109+
String plainText = this.decryptChatData(chatData, pkcs1);
109110
return WxCpChatModel.fromJson(plainText);
110111
}
111112

112-
public String decryptChatData(WxCpChatDatas.WxCpChatData chatData) throws Exception {
113-
// 企业获取的会话内容将用公钥加密,企业可用自行保存的私钥解开会话内容数据,aeskey不能为空
114-
String priKey = cpService.getWxCpConfigStorage().getAesKey();
113+
public String decryptChatData(WxCpChatDatas.WxCpChatData chatData, Integer pkcs1) throws Exception {
114+
/**
115+
* 企业获取的会话内容,使用企业自行配置的消息加密公钥进行加密,企业可用自行保存的私钥解开会话内容数据。
116+
* msgAuditPriKey 会话存档私钥不能为空
117+
*/
118+
String priKey = cpService.getWxCpConfigStorage().getMsgAuditPriKey();
115119
if (StringUtils.isEmpty(priKey)) {
116-
throw new WxErrorException("请配置会话存档私钥【aesKey】");
120+
throw new WxErrorException("请配置会话存档私钥【msgAuditPriKey】");
117121
}
118122

119-
String decryptByPriKey = WxCpCryptUtil.decryptByPriKey(chatData.getEncryptRandomKey(), priKey);
120-
// 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
123+
String decryptByPriKey = WxCpCryptUtil.decryptPriKey(chatData.getEncryptRandomKey(), priKey, pkcs1);
124+
/**
125+
* 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
126+
*/
121127
long sdk = Finance.SingletonSDK();
122128
long msg = Finance.NewSlice();
123129

130+
/**
131+
* 解密会话存档内容
132+
* sdk不会要求用户传入rsa私钥,保证用户会话存档数据只有自己能够解密。
133+
* 此处需要用户先用rsa私钥解密encrypt_random_key后,作为encrypt_key参数传入sdk来解密encrypt_chat_msg获取会话存档明文。
134+
*/
124135
int ret = Finance.DecryptData(sdk, decryptByPriKey, chatData.getEncryptChatMsg(), msg);
125136
if (ret != 0) {
126137
Finance.FreeSlice(msg);
127138
Finance.DestroySingletonSDK(sdk);
128139
throw new WxErrorException("msg err ret " + ret);
129140
}
130141

131-
// 明文
142+
/**
143+
* 明文
144+
*/
132145
String plainText = Finance.GetContentFromSlice(msg);
133146
Finance.FreeSlice(msg);
134147
return plainText;
135148
}
136149

137150
@Override
138-
public String getChatPlainText(WxCpChatDatas.@NonNull WxCpChatData chatData) throws Exception {
139-
return this.decryptChatData(chatData);
151+
public String getChatPlainText(WxCpChatDatas.@NonNull WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception {
152+
return this.decryptChatData(chatData, pkcs1);
140153
}
141154

142155
@Override
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package me.chanjar.weixin.cp.api.impl;
2+
3+
import com.google.gson.JsonObject;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import me.chanjar.weixin.common.error.WxErrorException;
7+
import me.chanjar.weixin.cp.api.WxCpSchoolService;
8+
import me.chanjar.weixin.cp.api.WxCpService;
9+
import me.chanjar.weixin.cp.bean.school.WxCpCustomizeHealthInfo;
10+
import me.chanjar.weixin.cp.bean.school.WxCpResultList;
11+
12+
import javax.validation.constraints.NotNull;
13+
import java.util.List;
14+
import java.util.Optional;
15+
16+
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.*;
17+
18+
/**
19+
* 企业微信家校应用 复学码相关接口实现类.
20+
* https://developer.work.weixin.qq.com/document/path/93744
21+
*
22+
* @author <a href="https://github.com/0katekate0">Wang_Wong</a>
23+
* @date: 2022/6/1 14:05
24+
*/
25+
@Slf4j
26+
@RequiredArgsConstructor
27+
public class WxCpSchoolServiceImpl implements WxCpSchoolService {
28+
29+
private final WxCpService cpService;
30+
31+
@Override
32+
public WxCpCustomizeHealthInfo getTeacherCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException {
33+
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_TEACHER_CUSTOMIZE_HEALTH_INFO);
34+
JsonObject jsonObject = new JsonObject();
35+
jsonObject.addProperty("date", date);
36+
jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100));
37+
if (nextKey != null) {
38+
jsonObject.addProperty("next_key", nextKey);
39+
}
40+
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
41+
return WxCpCustomizeHealthInfo.fromJson(responseContent);
42+
}
43+
44+
@Override
45+
public WxCpCustomizeHealthInfo getStudentCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException {
46+
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_STUDENT_CUSTOMIZE_HEALTH_INFO);
47+
JsonObject jsonObject = new JsonObject();
48+
jsonObject.addProperty("date", date);
49+
jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100));
50+
if (nextKey != null) {
51+
jsonObject.addProperty("next_key", nextKey);
52+
}
53+
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
54+
return WxCpCustomizeHealthInfo.fromJson(responseContent);
55+
}
56+
57+
@Override
58+
public WxCpResultList getHealthQrCode(@NotNull List<String> userIds, @NotNull Integer type) throws WxErrorException {
59+
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_HEALTH_QRCODE);
60+
JsonObject jsonObject = new JsonObject();
61+
jsonObject.addProperty("type", type);
62+
jsonObject.addProperty("userids", userIds.toString());
63+
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
64+
return WxCpResultList.fromJson(responseContent);
65+
}
66+
67+
}

0 commit comments

Comments
 (0)