🆕 #2742【企业微信】 家校沟通-增加批量更新家长接口支持

This commit is contained in:
0katekate0 2022-07-12 16:34:23 +08:00 committed by GitHub
parent c68f2d2f36
commit d166c27fad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 480 additions and 1 deletions

View File

@ -9,6 +9,8 @@ import me.chanjar.weixin.cp.bean.WxCpUserDetail;
* OAuth2相关管理接口.
* Created by BinaryWang on 2017/6/24.
* </pre>
* <p>
* 文档1https://developer.work.weixin.qq.com/document/path/91856
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@ -84,6 +86,19 @@ public interface WxCpOAuth2Service {
*/
WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErrorException;
/**
* 获取家校访问用户身份
* 该接口用于根据code获取家长或者学生信息
* <p>
* 请求方式GETHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
*
* @param code
* @return
* @throws WxErrorException
*/
WxCpOauth2UserInfo getSchoolUserInfo(String code) throws WxErrorException;
/**
* <pre>
* 使用user_ticket获取成员详情.

View File

@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.api;
import lombok.NonNull;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import me.chanjar.weixin.cp.bean.school.user.*;
import java.util.List;
@ -16,6 +17,32 @@ import java.util.List;
*/
public interface WxCpSchoolUserService {
/**
* 获取访问用户身份
* 该接口用于根据code获取成员信息
* <p>
* 请求方式GETHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
*
* @param code
* @return
* @throws WxErrorException
*/
WxCpOauth2UserInfo getUserInfo(@NonNull String code) throws WxErrorException;
/**
* 获取家校访问用户身份
* 该接口用于根据code获取家长或者学生信息
* <p>
* 请求方式GETHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
*
* @param code
* @return
* @throws WxErrorException
*/
WxCpOauth2UserInfo getSchoolUserInfo(@NonNull String code) throws WxErrorException;
/**
* 创建学生
* 请求方式POSTHTTPS
@ -98,6 +125,39 @@ public interface WxCpSchoolUserService {
*/
WxCpBaseResp createParent(@NonNull WxCpCreateParentRequest request) throws WxErrorException;
/**
* 批量创建家长
* 请求方式POSTHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_create_parent?access_token=ACCESS_TOKEN
*
* @param request
* @return
* @throws WxErrorException
*/
WxCpBatchResultList batchCreateParent(@NonNull WxCpBatchCreateParentRequest request) throws WxErrorException;
/**
* 批量删除家长
* 请求方式POSTHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_delete_parent?access_token=ACCESS_TOKEN
*
* @param userIdList
* @return
* @throws WxErrorException
*/
WxCpBatchResultList batchDeleteParent(@NonNull String... userIdList) throws WxErrorException;
/**
* 批量更新家长
* 请求方式POSTHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_update_parent?access_token=ACCESS_TOKEN
*
* @param request
* @return
* @throws WxErrorException
*/
WxCpBatchResultList batchUpdateParent(@NonNull WxCpBatchUpdateParentRequest request) throws WxErrorException;
/**
* 更新家长
* 请求方式POSTHTTPS

View File

@ -77,6 +77,20 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service {
.userTicket(GsonHelper.getString(jo, "user_ticket"))
.expiresIn(GsonHelper.getString(jo, "expires_in"))
.externalUserId(GsonHelper.getString(jo, "external_userid"))
.parentUserId(GsonHelper.getString(jo, "parent_userid"))
.studentUserId(GsonHelper.getString(jo, "student_userid"))
.build();
}
@Override
public WxCpOauth2UserInfo getSchoolUserInfo(String code) throws WxErrorException {
String responseText = this.mainService.get(String.format(this.mainService.getWxCpConfigStorage().getApiUrl(GET_SCHOOL_USER_INFO), code), null);
JsonObject jo = GsonParser.parse(responseText);
return WxCpOauth2UserInfo.builder()
.deviceId(GsonHelper.getString(jo, "DeviceId"))
.parentUserId(GsonHelper.getString(jo, "parent_userid"))
.studentUserId(GsonHelper.getString(jo, "student_userid"))
.build();
}

View File

@ -11,6 +11,7 @@ import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpSchoolUserService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import me.chanjar.weixin.cp.bean.school.user.*;
import org.apache.commons.lang3.StringUtils;
@ -32,6 +33,16 @@ public class WxCpSchoolUserServiceImpl implements WxCpSchoolUserService {
private final WxCpService cpService;
@Override
public WxCpOauth2UserInfo getUserInfo(@NonNull String code) throws WxErrorException {
return cpService.getOauth2Service().getUserInfo(code);
}
@Override
public WxCpOauth2UserInfo getSchoolUserInfo(@NonNull String code) throws WxErrorException {
return cpService.getOauth2Service().getSchoolUserInfo(code);
}
@Override
public WxCpBaseResp createStudent(@NonNull String studentUserId, @NonNull String name, @NonNull List<Integer> departments) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(CREATE_STUDENT);
@ -104,6 +115,33 @@ public class WxCpSchoolUserServiceImpl implements WxCpSchoolUserService {
return WxCpBaseResp.fromJson(responseContent);
}
@Override
public WxCpBatchResultList batchCreateParent(@NonNull WxCpBatchCreateParentRequest request) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_CREATE_PARENT);
String responseContent = this.cpService.post(apiUrl, request.toJson());
return WxCpBatchResultList.fromJson(responseContent);
}
@Override
public WxCpBatchResultList batchDeleteParent(@NonNull String... userIdList) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_DELETE_PARENT);
JsonObject jsonObject = new JsonObject();
JsonArray jsonArray = new JsonArray();
for (String userId : userIdList) {
jsonArray.add(new JsonPrimitive(userId));
}
jsonObject.add("useridlist", jsonArray);
String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
return WxCpBatchResultList.fromJson(responseContent);
}
@Override
public WxCpBatchResultList batchUpdateParent(@NonNull WxCpBatchUpdateParentRequest request) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_UPDATE_PARENT);
String responseContent = this.cpService.post(apiUrl, request.toJson());
return WxCpBatchResultList.fromJson(responseContent);
}
@Override
public WxCpBaseResp updateParent(@NonNull WxCpUpdateParentRequest request) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(UPDATE_PARENT);

View File

@ -14,6 +14,8 @@ import java.io.Serializable;
* Created by BinaryWang on 2019/5/26.
* </pre>
*
* 文档1https://developer.work.weixin.qq.com/document/path/91707
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
@ -30,4 +32,7 @@ public class WxCpOauth2UserInfo implements Serializable {
private String userTicket;
private String expiresIn;
private String externalUserId;
private String parentUserId;
private String studentUserId;
}

View File

@ -0,0 +1,88 @@
package me.chanjar.weixin.cp.bean.school.user;
import com.google.gson.annotations.SerializedName;
import lombok.*;
import lombok.experimental.Accessors;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 批量创建家长.
*
* @author Wang_Wong
* @date 2022-07-11
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WxCpBatchCreateParentRequest implements Serializable {
private static final long serialVersionUID = -4960239393895754138L;
@SerializedName("parents")
private List<Parent> parents;
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Parent implements Serializable {
@SerializedName("parent_userid")
private String parentUserId;
@SerializedName("mobile")
private String mobile;
@SerializedName("to_invite")
private Boolean toInvite;
@SerializedName("children")
private List<Children> children;
public static Parent fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, Parent.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Children implements Serializable {
@SerializedName("student_userid")
private String studentUserId;
@SerializedName("relation")
private String relation;
public static Children fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, Children.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
public static WxCpBatchCreateParentRequest fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpBatchCreateParentRequest.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,88 @@
package me.chanjar.weixin.cp.bean.school.user;
import com.google.gson.annotations.SerializedName;
import lombok.*;
import lombok.experimental.Accessors;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 批量更新家长.
*
* @author Wang_Wong
* @date 2022-07-11
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WxCpBatchUpdateParentRequest implements Serializable {
private static final long serialVersionUID = -4960239393895754138L;
@SerializedName("parents")
private List<Parent> parents;
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Parent implements Serializable {
@SerializedName("parent_userid")
private String parentUserId;
@SerializedName("new_parent_userid")
private String newParentUserId;
@SerializedName("mobile")
private String mobile;
@SerializedName("children")
private List<Children> children;
public static Parent fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, Parent.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Children implements Serializable {
@SerializedName("student_userid")
private String studentUserId;
@SerializedName("relation")
private String relation;
public static Children fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, Children.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
public static WxCpBatchUpdateParentRequest fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpBatchUpdateParentRequest.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@ -36,6 +36,9 @@ public class WxCpCreateParentRequest implements Serializable {
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Children implements Serializable {
@SerializedName("student_userid")

View File

@ -67,6 +67,7 @@ public interface WxCpApiPathConsts {
interface OAuth2 {
String GET_USER_INFO = "/cgi-bin/user/getuserinfo?code=%s&agentid=%d";
String GET_SCHOOL_USER_INFO = "/cgi-bin/school/getuserinfo?code=%s";
String GET_USER_DETAIL = "/cgi-bin/user/getuserdetail";
String URL_OAUTH2_AUTHORIZE = "https://open.weixin.qq.com/connect/oauth2/authorize";
}
@ -195,6 +196,9 @@ public interface WxCpApiPathConsts {
String BATCH_CREATE_STUDENT = "/cgi-bin/school/user/batch_create_student";
String BATCH_DELETE_STUDENT = "/cgi-bin/school/user/batch_delete_student";
String BATCH_UPDATE_STUDENT = "/cgi-bin/school/user/batch_update_student";
String BATCH_CREATE_PARENT = "/cgi-bin/school/user/batch_create_parent";
String BATCH_DELETE_PARENT = "/cgi-bin/school/user/batch_delete_parent";
String BATCH_UPDATE_PARENT = "/cgi-bin/school/user/batch_update_parent";
String CREATE_STUDENT = "/cgi-bin/school/user/create_student";
String DELETE_STUDENT = "/cgi-bin/school/user/delete_student?userid=";

View File

@ -5,8 +5,10 @@ import lombok.extern.slf4j.Slf4j;
import lombok.var;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.XmlUtils;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.school.user.*;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@ -19,6 +21,8 @@ import java.io.InputStream;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
/**
* 企业微信家校沟通相关接口.
* https://developer.work.weixin.qq.com/document/path/91638
@ -52,6 +56,165 @@ public class WxCpSchoolUserTest {
final String exUserId = "wmOQpTDwAAJFHrryZ8I8ALLEZuLHIUKA";
/**
* 批量更新家长
*
* https://developer.work.weixin.qq.com/document/path/92336
*/
String batchUpdateParentRequestParam = "{\n" +
" \"parents\":[\n" +
" { \n" +
" \"parent_userid\": \"zhangsan_baba\",\n" +
"\t\t\t\"new_parent_userid\":\"zhangsan_baba_new\",\n" +
" \"mobile\": \"10000000000\",\n" +
" \"children\":[\n" +
" { \n" +
" \"student_userid\": \"zhangsan\",\n" +
" \"relation\": \"爸爸\"\n" +
" } \n" +
" ] \n" +
" }, \n" +
" { \n" +
" \"parent_userid\": \"lisi_mama\",\n" +
" \"mobile\": \"10000000001\",\n" +
" \"children\":[\n" +
" {\n" +
" \"student_userid\": \"lisi\",\n" +
" \"relation\": \"妈妈\"\n" +
" } \n" +
" ] \n" +
" } \n" +
" ] \n" +
"}";
WxCpBatchUpdateParentRequest batchUpdateParentRequest = WxCpBatchUpdateParentRequest.fromJson(batchUpdateParentRequestParam);
WxCpBatchResultList batchUpdateParentResult = cpService.getSchoolUserService().batchUpdateParent(batchUpdateParentRequest);
/**
* 批量删除家长
*
* https://developer.work.weixin.qq.com/document/path/92335
*/
WxCpBatchResultList batchDeleteParentResult = cpService.getSchoolUserService().batchDeleteParent(new String[]{"abc", userId});
/**
* 批量创建家长 封装请求参数
*
* https://developer.work.weixin.qq.com/document/path/92334
*/
var child1 = WxCpBatchCreateParentRequest.Children.builder()
.relation("爸爸")
.studentUserId("zhangsan")
.build();
var child2 = WxCpBatchCreateParentRequest.Children.builder()
.relation("伯父")
.studentUserId("lisi")
.build();
var child3 = WxCpBatchCreateParentRequest.Children.builder()
.relation("爸爸")
.studentUserId("lisi")
.build();
var child4 = WxCpBatchCreateParentRequest.Children.builder()
.relation("伯父")
.studentUserId("zhangsan")
.build();
List<WxCpBatchCreateParentRequest.Children> childrenList1 = Lists.newArrayList();
childrenList1.add(child1);
childrenList1.add(child2);
List<WxCpBatchCreateParentRequest.Children> childrenList2 = Lists.newArrayList();
childrenList2.add(child3);
childrenList2.add(child4);
var zhangsanParent = WxCpBatchCreateParentRequest.Parent.builder()
.parentUserId("zhangsan_parent_userid")
.mobile("18000000000")
.toInvite(false)
.children(childrenList1)
.build();
var lisiParent = WxCpBatchCreateParentRequest.Parent.builder()
.parentUserId("lisi_parent_userid")
.mobile("18000000001")
.children(childrenList2)
.build();
List<WxCpBatchCreateParentRequest.Parent> batchCreateParent = Lists.newArrayList();
batchCreateParent.add(zhangsanParent);
batchCreateParent.add(lisiParent);
WxCpBatchCreateParentRequest wxCpBatchCreateParentRequest = WxCpBatchCreateParentRequest.builder()
.parents(batchCreateParent)
.build();
// 请求参数json
String batchCreateParentRequestParam = "{\n" +
"\t\"parents\":[\n" +
"\t\t{\n" +
"\t\t\t\"parent_userid\": \"zhangsan_parent_userid\",\n" +
" \t\t\"mobile\": \"18000000000\",\n" +
"\t\t\t\"to_invite\": false,\n" +
"\t\t\t\"children\":[\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\t\"student_userid\": \"zhangsan\",\n" +
" \t\t \"relation\": \"爸爸\"\n" +
" \t\t },\n" +
" \t\t {\n" +
"\t\t\t\t\t\"student_userid\": \"lisi\",\n" +
" \t\t \"relation\": \"伯父\"\n" +
" \t\t }\n" +
" \t\t]\n" +
"\t\t},\n" +
"\t\t{\n" +
"\t\t\t\"parent_userid\": \"lisi_parent_userid\",\n" +
" \t\t\"mobile\": \"18000000001\",\n" +
"\t\t\t\"children\":[\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\t\"student_userid\": \"lisi\",\n" +
" \t\t \"relation\": \"爸爸\"\n" +
" \t\t },\n" +
" \t\t {\n" +
"\t\t\t\t\t\"student_userid\": \"zhangsan\",\n" +
" \t\t \"relation\": \"伯父\"\n" +
" \t\t }\n" +
" \t\t]\n" +
"\t\t}\n" +
"\t]\n" +
"}";
assertThat(wxCpBatchCreateParentRequest.toJson()).isEqualTo(GsonParser.parse(batchCreateParentRequestParam).toString());
WxCpBatchResultList batchCreateParentResult = cpService.getSchoolUserService().batchCreateParent(wxCpBatchCreateParentRequest);
// 返回结果
String batchResultStr = "{\n" +
"\t\"errcode\": 1,\n" +
"\t\"errmsg\": \"invalid parent_userid: lisi_parent_userid\",\n" +
"\t\"result_list\": [\n" +
"\t\t{\n" +
"\t\t\t\"parent_userid\": \"lisi_parent_userid\",\n" +
"\t\t\t\"errcode\": 1,\n" +
"\t\t\t\"errmsg\": \"invalid parent_userid: lisi_parent_userid\",\n" +
"\t\t}\n" +
"\t]\n" +
"}";
assertThat(batchCreateParentResult.toJson()).isEqualTo(GsonParser.parse(batchResultStr).toString());
/**
* 获取家校访问用户身份
*
* https://developer.work.weixin.qq.com/document/path/95791
*/
WxCpOauth2UserInfo schoolUserInfo = cpService.getSchoolUserService().getSchoolUserInfo("abc");
assertThat(schoolUserInfo).isNotNull();
WxCpOauth2UserInfo oauth2UserInfo = cpService.getSchoolUserService().getUserInfo("abc");
assertThat(oauth2UserInfo).isNotNull();
WxCpOauth2UserInfo userInfo = cpService.getOauth2Service().getUserInfo("abc");
assertThat(userInfo).isNotNull();
// 返回值
String batchResult = "{\n" +
"\t\"errcode\": 1,\n" +

View File

@ -10,7 +10,8 @@ import java.io.Serializable;
/**
* <pre>
* code换取session_key接口的响应
* 文档地址https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject
* 文档地址https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
*
* 微信返回报文{"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"}
* </pre>
* @author <a href="https://github.com/binarywang">Binary Wang</a>