diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java
index 3d97cb928..4109c0a03 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java
@@ -8,6 +8,7 @@ import java.util.List;
*
* 任务卡片管理接口.
* Created by Jeff on 2019-05-16.
+ * Updted by HeXiao on 2022-03-09.
*
*
* @author Jeff
@@ -23,9 +24,26 @@ public interface WxCpTaskCardService {
* 注意: 这个方法使用WxCpConfigStorage里的agentId
*
*
- * @param userIds 企业的成员ID列表
- * @param taskId 任务卡片ID
+ * @param userIds 企业的成员ID列表
+ * @param taskId 任务卡片ID
* @param replaceName 替换文案
*/
void update(List userIds, String taskId, String replaceName) throws WxErrorException;
+
+
+ /**
+ * 更新按钮为不可点击状态
+ * 详情请见https://developer.work.weixin.qq.com/document/path/94888#%E6%9B%B4%E6%96%B0%E6%8C%89%E9%92%AE%E4%B8%BA%E4%B8%8D%E5%8F%AF%E7%82%B9%E5%87%BB%E7%8A%B6%E6%80%81
+ * @param userIds 企业的成员ID列表
+ * @param partyIds 企业的部门ID列表
+ * @param tagIds 企业的标签ID列表
+ * @param atAll 更新整个任务接收人员
+ * @param responseCode 更新卡片所需要消费的code,可通过发消息接口和回调接口返回值获取,一个code只能调用一次该接口,且只能在24小时内调用
+ * @param replaceName 需要更新的按钮的文案
+ * @throws WxErrorException
+ */
+ void updateTemplateCardButton(List userIds, List partyIds,
+ List tagIds, Integer atAll, String responseCode,
+ String replaceName) throws WxErrorException;
+
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java
index 384a3d30c..9e9e7dea0 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java
@@ -38,4 +38,25 @@ public class WxCpTaskCardServiceImpl implements WxCpTaskCardService {
String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_TASK_CARD);
this.mainService.post(url, WxGsonBuilder.create().toJson(data));
}
+
+ @Override
+ public void updateTemplateCardButton(List userIds, List partyIds,
+ List tagIds, Integer atAll,
+ String responseCode, String replaceName) throws WxErrorException {
+ Integer agentId = this.mainService.getWxCpConfigStorage().getAgentId();
+ Map data = new HashMap<>(7);
+ data.put("userids", userIds);
+ data.put("partyids", partyIds);
+ data.put("tagids", tagIds);
+ data.put("atall", atAll);
+ data.put("agentid", agentId);
+ data.put("response_code", responseCode);
+ Map btnMap = new HashMap<>();
+ btnMap.put("replace_name", replaceName);
+ data.put("button", btnMap);
+
+ String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_TEMPLATE_CARD);
+ this.mainService.post(url, WxGsonBuilder.create().toJson(data));
+
+ }
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java
index 780305ddd..1ce367d9f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java
@@ -92,6 +92,21 @@ public class WxCpMessage implements Serializable {
*/
private String sourceDesc;
+ /**
+ * 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
+ */
+ private Integer sourceDescColor;
+
+ /**
+ * 更多操作界面的描述
+ */
+ private String actionMenuDesc;
+
+ /**
+ * 操作列表,列表长度取值范围为 [1, 3]
+ */
+ private List actionMenuActionList;
+
/**
* 一级标题,建议不超过36个字
*/
@@ -482,9 +497,22 @@ public class WxCpMessage implements Serializable {
if (StringUtils.isNotBlank(this.getSourceDesc())) {
source.addProperty("desc", this.getSourceDesc());
}
+ source.addProperty("desc_color", this.getSourceDescColor());
template.add("source", source);
}
+ if (StringUtils.isNotBlank(this.getActionMenuDesc())) {
+ JsonObject action_menu = new JsonObject();
+ action_menu.addProperty("desc", this.getActionMenuDesc());
+ JsonArray actionList = new JsonArray();
+ List actionMenuItemList = this.getActionMenuActionList();
+ for (ActionMenuItem actionItemI : actionMenuItemList) {
+ actionList.add(actionItemI.toJson());
+ }
+ action_menu.add("action_list", actionList);
+ template.add("action_menu", action_menu);
+ }
+
if (StringUtils.isNotBlank(this.getMainTitleTitle()) || StringUtils.isNotBlank(this.getMainTitleDesc())) {
JsonObject mainTitle = new JsonObject();
if (StringUtils.isNotBlank(this.getMainTitleTitle())) {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java
index 09a506d8e..866b5b7a0 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java
@@ -36,6 +36,21 @@ public class TemplateCardBuilder extends BaseBuilder {
*/
private String sourceDesc;
+ /**
+ * 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
+ */
+ private Integer sourceDescColor;
+
+ /**
+ * 更多操作界面的描述
+ */
+ private String actionMenuDesc;
+
+ /**
+ * 操作列表,列表长度取值范围为 [1, 3]
+ */
+ private List actionMenuActionList;
+
/**
* 一级标题,建议不超过36个字
*/
@@ -172,6 +187,16 @@ public class TemplateCardBuilder extends BaseBuilder {
return this;
}
+ public TemplateCardBuilder actionMenuDesc(String actionMenuDesc) {
+ this.actionMenuDesc = actionMenuDesc;
+ return this;
+ }
+
+ public TemplateCardBuilder actionMenuActionList(List actionMenuItemList) {
+ this.actionMenuActionList = actionMenuItemList;
+ return this;
+ }
+
public TemplateCardBuilder sourceIconUrl(String sourceIconUrl) {
this.sourceIconUrl = sourceIconUrl;
return this;
@@ -182,6 +207,11 @@ public class TemplateCardBuilder extends BaseBuilder {
return this;
}
+ public TemplateCardBuilder sourceDescColor(Integer sourceDescColor) {
+ this.sourceDescColor = sourceDescColor;
+ return this;
+ }
+
public TemplateCardBuilder mainTitleTitle(String mainTitleTitle) {
this.mainTitleTitle = mainTitleTitle;
return this;
@@ -294,6 +324,9 @@ public class TemplateCardBuilder extends BaseBuilder {
m.setCardType(this.cardType);
m.setSourceIconUrl(this.sourceIconUrl);
m.setSourceDesc(this.sourceDesc);
+ m.setSourceDescColor(this.sourceDescColor);
+ m.setActionMenuDesc(this.actionMenuDesc);
+ m.setActionMenuActionList(this.actionMenuActionList);
m.setMainTitleTitle(this.mainTitleTitle);
m.setMainTitleDesc(this.mainTitleDesc);
m.setCardImageUrl(this.cardImageUrl);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/ActionMenuItem.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/ActionMenuItem.java
new file mode 100644
index 000000000..54950fb82
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/ActionMenuItem.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.cp.bean.templatecard;
+
+import com.google.gson.JsonObject;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 卡片右上角更多操作按钮点击后出现的操作列表,列表长度取值范围为 [1, 3]
+ * @author xiaohe
+ * @date 2022-03-06
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ActionMenuItem implements Serializable {
+ private static final long serialVersionUID = 400885585614100693L;
+
+ /**
+ * 操作的描述文案
+ */
+ private String text;
+
+ /**
+ * 按钮key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复
+ */
+ private String key;
+
+ public JsonObject toJson() {
+ JsonObject btnObject = new JsonObject();
+ btnObject.addProperty("text", this.getText());
+ btnObject.addProperty("key", this.getKey());
+ return btnObject;
+ }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java
index 397420820..393a99dac 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java
@@ -44,6 +44,11 @@ public class HorizontalContent implements Serializable {
*/
private String media_id;
+ /**
+ * 成员详情的userid,horizontal_content_list.type是3时必填
+ */
+ private String userid;
+
public JsonObject toJson() {
JsonObject hContentJson = new JsonObject();
@@ -61,6 +66,9 @@ public class HorizontalContent implements Serializable {
if (StringUtils.isNotBlank(this.getMedia_id())) {
hContentJson.addProperty("media_id", this.getMedia_id());
}
+ if (StringUtils.isNotBlank(this.getUserid())) {
+ hContentJson.addProperty("userid", this.getUserid());
+ }
return hContentJson;
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index afef5193c..dbf78fe73 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -187,6 +187,7 @@ public interface WxCpApiPathConsts {
interface TaskCard {
String UPDATE_TASK_CARD = "/cgi-bin/message/update_taskcard";
+ String UPDATE_TEMPLATE_CARD = "/cgi-bin/message/update_template_card";
}
interface Tp {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java
index c8a367614..06c895d25 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java
@@ -166,6 +166,12 @@ public class WxCpMessageTest {
.value("企业微信.apk")
.media_id("文件的media_id")
.build();
+ HorizontalContent hContent4 = HorizontalContent.builder()
+ .type(3)
+ .keyname("员工信息")
+ .value("点击查看")
+ .userid("zhangsan")
+ .build();
TemplateCardJump jump1 = TemplateCardJump.builder()
.type(1)
@@ -178,7 +184,7 @@ public class WxCpMessageTest {
.appid("小程序的appid")
.pagepath("/index.html")
.build();
- QuoteArea quoteArea=QuoteArea.builder()
+ QuoteArea quoteArea = QuoteArea.builder()
.type(1)
.title("引用文献标题")
.appid("小程序的appid")
@@ -186,17 +192,31 @@ public class WxCpMessageTest {
.url("https://work.weixin.qq.com")
.quoteText("引用文献样式的引用文案")
.build();
+ ActionMenuItem action1 = ActionMenuItem.builder()
+ .text("接受推送")
+ .key("A")
+ .build();
+ ActionMenuItem action2 = ActionMenuItem.builder()
+ .text("不再推送")
+ .key("B")
+ .build();
WxCpMessage reply = WxCpMessage.TEMPLATECARD().toUser("OPENID")
+ .toParty("PartyID1 | PartyID2")
+ .toTag("TagID1 | TagID2")
.agentId(1000002)
.cardType(WxConsts.TemplateCardType.TEXT_NOTICE)
+ .taskId("task_id")
.sourceIconUrl("图片的url")
.sourceDesc("企业微信")
+ .sourceDescColor(1)
+ .actionMenuDesc("卡片副交互辅助文本说明")
+ .actionMenuActionList(Arrays.asList(action1, action2))
.mainTitleTitle("欢迎使用企业微信")
.mainTitleDesc("您的好友正在邀请您加入企业微信")
.emphasisContentTitle("100")
.emphasisContentDesc("核心数据")
.subTitleText("下载企业微信还能抢红包!")
- .horizontalContents(Arrays.asList(hContent1,hContent2,hContent3))
+ .horizontalContents(Arrays.asList(hContent1, hContent2, hContent3, hContent4))
.jumps(Arrays.asList(jump1,jump2))
.cardActionType(2)
.cardActionAppid("小程序的appid")
@@ -209,8 +229,7 @@ public class WxCpMessageTest {
reply.setDuplicateCheckInterval(1800);
// System.out.println(reply.toJson());
assertThat(reply.toJson())
- .isEqualTo("{\"agentid\":1000002,\"touser\":\"OPENID\",\"msgtype\":\"template_card\",\"duplicate_check_interval\":1800,\"template_card\":{\"card_type\":\"text_notice\",\"source\":{\"icon_url\":\"图片的url\",\"desc\":\"企业微信\"},\"main_title\":{\"title\":\"欢迎使用企业微信\",\"desc\":\"您的好友正在邀请您加入企业微信\"},\"emphasis_content\":{\"title\":\"100\",\"desc\":\"核心数据\"},\"sub_title_text\":\"下载企业微信还能抢红包!\",\"horizontal_content_list\":[{\"keyname\":\"邀请人\",\"value\":\"张三\"},{\"type\":1,\"keyname\":\"企业微信官网\",\"value\":\"点击访问\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"keyname\":\"企业微信下载\",\"value\":\"企业微信.apk\",\"media_id\":\"文件的media_id\"}],\"jump_list\":[{\"type\":1,\"title\":\"企业微信官网\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"title\":\"跳转小程序\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"}],\"card_action\":{\"type\":2,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"},\"quote_area\":{\"type\":1,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\",\"title\":\"引用文献标题\",\"quote_text\":\"引用文献样式的引用文案\"}}}");
-
+ .isEqualTo("{\"agentid\":1000002,\"touser\":\"OPENID\",\"msgtype\":\"template_card\",\"toparty\":\"PartyID1 | PartyID2\",\"totag\":\"TagID1 | TagID2\",\"duplicate_check_interval\":1800,\"template_card\":{\"card_type\":\"text_notice\",\"source\":{\"icon_url\":\"图片的url\",\"desc\":\"企业微信\",\"desc_color\":1},\"action_menu\":{\"desc\":\"卡片副交互辅助文本说明\",\"action_list\":[{\"text\":\"接受推送\",\"key\":\"A\"},{\"text\":\"不再推送\",\"key\":\"B\"}]},\"main_title\":{\"title\":\"欢迎使用企业微信\",\"desc\":\"您的好友正在邀请您加入企业微信\"},\"emphasis_content\":{\"title\":\"100\",\"desc\":\"核心数据\"},\"sub_title_text\":\"下载企业微信还能抢红包!\",\"task_id\":\"task_id\",\"horizontal_content_list\":[{\"keyname\":\"邀请人\",\"value\":\"张三\"},{\"type\":1,\"keyname\":\"企业微信官网\",\"value\":\"点击访问\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"keyname\":\"企业微信下载\",\"value\":\"企业微信.apk\",\"media_id\":\"文件的media_id\"},{\"type\":3,\"keyname\":\"员工信息\",\"value\":\"点击查看\",\"userid\":\"zhangsan\"}],\"jump_list\":[{\"type\":1,\"title\":\"企业微信官网\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"title\":\"跳转小程序\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"}],\"card_action\":{\"type\":2,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"},\"quote_area\":{\"type\":1,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\",\"title\":\"引用文献标题\",\"quote_text\":\"引用文献样式的引用文案\"}}}");
}
/**
@@ -404,13 +423,13 @@ public class WxCpMessageTest {
.question_key("question_key1")
.title("选择器标签1")
.selected_id("selection_id1")
- .options(Arrays.asList(option1,option2))
+ .options(Arrays.asList(option1, option2))
.build();
MultipleSelect mSelect2 = MultipleSelect.builder()
.question_key("question_key2")
.title("选择器标签2")
.selected_id("selection_id3")
- .options(Arrays.asList(option3,option4))
+ .options(Arrays.asList(option3, option4))
.build();