mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-11-01 03:25:35 +08:00 
			
		
		
		
	* #1474 新增客户联系「联系我」管理接口 * fix #1590 提及的me.chanjar.weixin.open.api.impl.WxOpenComponentServiceImpl#getAuthorizerAccessToken()刷新AccessToken后没有同步对应的refreshToken * 补充 me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage#updateToken 方法对 expireInSeconds 边界判断
This commit is contained in:
		| @ -1,5 +1,6 @@ | ||||
| package me.chanjar.weixin.cp.api; | ||||
|  | ||||
| import lombok.NonNull; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.cp.bean.*; | ||||
|  | ||||
| @ -15,6 +16,83 @@ import java.util.List; | ||||
|  * @author <a href="https://github.com/JoeCao">JoeCao</a> | ||||
|  */ | ||||
| public interface WxCpExternalContactService { | ||||
|  | ||||
|   /** | ||||
|    * 配置客户联系「联系我」方式 | ||||
|    * <pre> | ||||
|    * 企业可以在管理后台-客户联系中配置成员的「联系我」的二维码或者小程序按钮,客户通过扫描二维码或点击小程序上的按钮,即可获取成员联系方式,主动联系到成员。 | ||||
|    * 企业可通过此接口为具有客户联系功能的成员生成专属的「联系我」二维码或者「联系我」按钮。 | ||||
|    * 如果配置的是「联系我」按钮,需要开发者的小程序接入小程序插件。 | ||||
|    * | ||||
|    * 注意: | ||||
|    * 通过API添加的「联系我」不会在管理端进行展示,每个企业可通过API最多配置50万个「联系我」。 | ||||
|    * 用户需要妥善存储返回的config_id,config_id丢失可能导致用户无法编辑或删除「联系我」。 | ||||
|    * 临时会话模式不占用「联系我」数量,但每日最多添加10万个,并且仅支持单人。 | ||||
|    * 临时会话模式的二维码,添加好友完成后该二维码即刻失效。 | ||||
|    * </pre> | ||||
|    * | ||||
|    * @param info 客户联系「联系我」方式 | ||||
|    * @return | ||||
|    * @throws WxErrorException | ||||
|    */ | ||||
|   WxCpContactWayResult addContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException; | ||||
|  | ||||
|   /** | ||||
|    * 获取企业已配置的「联系我」方式 | ||||
|    * | ||||
|    * <pre> | ||||
|    * <b>批量</b>获取企业配置的「联系我」二维码和「联系我」小程序按钮。 | ||||
|    * </pre> | ||||
|    * | ||||
|    * @param configId 联系方式的配置id,必填 | ||||
|    * @return | ||||
|    * @throws WxErrorException | ||||
|    */ | ||||
|   WxCpContactWayInfo getContactWay(@NonNull String configId) throws WxErrorException; | ||||
|  | ||||
|   /** | ||||
|    * 更新企业已配置的「联系我」方式 | ||||
|    * | ||||
|    * <pre> | ||||
|    * 更新企业配置的「联系我」二维码和「联系我」小程序按钮中的信息,如使用人员和备注等。 | ||||
|    * </pre> | ||||
|    * | ||||
|    * @param info 客户联系「联系我」方式 | ||||
|    * @return | ||||
|    * @throws WxErrorException | ||||
|    */ | ||||
|   WxCpBaseResp updateContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException; | ||||
|  | ||||
|   /** | ||||
|    * 删除企业已配置的「联系我」方式 | ||||
|    * | ||||
|    * <pre> | ||||
|    * 删除一个已配置的「联系我」二维码或者「联系我」小程序按钮。 | ||||
|    * </pre> | ||||
|    * | ||||
|    * @param configId 企业联系方式的配置id,必填 | ||||
|    * @return | ||||
|    * @throws WxErrorException | ||||
|    */ | ||||
|   WxCpBaseResp deleteContactWay(@NonNull String configId) throws WxErrorException; | ||||
|  | ||||
|   /** | ||||
|    * 结束临时会话 | ||||
|    * | ||||
|    * <pre> | ||||
|    * 将指定的企业成员和客户之前的临时会话断开,断开前会自动下发已配置的结束语。 | ||||
|    * | ||||
|    * 注意:请保证传入的企业成员和客户之间有仍然有效的临时会话, 通过<b>其他方式的添加外部联系人无法通过此接口关闭会话</b>。 | ||||
|    * </pre> | ||||
|    * | ||||
|    * @param userId | ||||
|    * @param externalUserId | ||||
|    * @return | ||||
|    * @throws WxErrorException | ||||
|    */ | ||||
|   WxCpBaseResp closeTempChat(@NonNull String userId, @NonNull String externalUserId) throws WxErrorException; | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * 获取外部联系人详情. | ||||
|    * <pre> | ||||
|  | ||||
| @ -2,6 +2,7 @@ package me.chanjar.weixin.cp.api.impl; | ||||
|  | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonObject; | ||||
| import lombok.NonNull; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import me.chanjar.weixin.common.error.WxCpErrorMsgEnum; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | ||||
| @ -9,6 +10,7 @@ import me.chanjar.weixin.cp.api.WxCpExternalContactService; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.*; | ||||
| import org.apache.commons.lang3.ArrayUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
|  | ||||
| import java.util.Collections; | ||||
| import java.util.Date; | ||||
| @ -23,6 +25,70 @@ import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.ExternalContact.*; | ||||
| public class WxCpExternalContactServiceImpl implements WxCpExternalContactService { | ||||
|   private final WxCpService mainService; | ||||
|  | ||||
|   @Override | ||||
|   public WxCpContactWayResult addContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException { | ||||
|  | ||||
|     if (info.getUsers() != null && info.getUsers().size() > 100) { | ||||
|       throw new RuntimeException("「联系我」使用人数默认限制不超过100人(包括部门展开后的人数)"); | ||||
|     } | ||||
|  | ||||
|     final String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_CONTACT_WAY); | ||||
|     String responseContent = this.mainService.post(url, info.toJson()); | ||||
|  | ||||
|     return WxCpContactWayResult.fromJson(responseContent); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxCpContactWayInfo getContactWay(@NonNull String configId) throws WxErrorException { | ||||
|     JsonObject json = new JsonObject(); | ||||
|     json.addProperty("config_id", configId); | ||||
|  | ||||
|     final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_CONTACT_WAY); | ||||
|     String responseContent = this.mainService.post(url, json.toString()); | ||||
|  | ||||
|     return WxCpContactWayInfo.fromJson(responseContent); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxCpBaseResp updateContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException { | ||||
|     if (StringUtils.isBlank(info.getConfigId())) { | ||||
|       throw new RuntimeException("更新「联系我」方式需要指定configId"); | ||||
|     } | ||||
|     if (info.getUsers() != null && info.getUsers().size() > 100) { | ||||
|       throw new RuntimeException("「联系我」使用人数默认限制不超过100人(包括部门展开后的人数)"); | ||||
|     } | ||||
|  | ||||
|     final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_CONTACT_WAY); | ||||
|     String responseContent = this.mainService.post(url, info.toJson()); | ||||
|  | ||||
|     return WxCpBaseResp.fromJson(responseContent); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxCpBaseResp deleteContactWay(@NonNull String configId) throws WxErrorException { | ||||
|     JsonObject json = new JsonObject(); | ||||
|     json.addProperty("config_id",configId); | ||||
|  | ||||
|     final String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEL_CONTACT_WAY); | ||||
|     String responseContent = this.mainService.post(url, json.toString()); | ||||
|  | ||||
|     return WxCpBaseResp.fromJson(responseContent); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxCpBaseResp closeTempChat(@NonNull String userId, @NonNull String externalUserId) throws WxErrorException { | ||||
|  | ||||
|     JsonObject json = new JsonObject(); | ||||
|     json.addProperty("userid",userId); | ||||
|     json.addProperty("external_userid",externalUserId); | ||||
|  | ||||
|  | ||||
|     final String url = this.mainService.getWxCpConfigStorage().getApiUrl(CLOSE_TEMP_CHAT); | ||||
|     String responseContent = this.mainService.post(url, json.toString()); | ||||
|  | ||||
|     return WxCpBaseResp.fromJson(responseContent); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException { | ||||
|     final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_EXTERNAL_CONTACT + userId); | ||||
|  | ||||
| @ -0,0 +1,198 @@ | ||||
| package me.chanjar.weixin.cp.bean; | ||||
|  | ||||
| import com.google.gson.annotations.JsonAdapter; | ||||
| import com.google.gson.annotations.SerializedName; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpConclusionAdapter; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 「联系我」方式 对象 | ||||
|  * | ||||
|  * @author element | ||||
|  */ | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| public class WxCpContactWayInfo { | ||||
|  | ||||
|   /** | ||||
|    * 联系方式的配置id | ||||
|    */ | ||||
|   @SerializedName("config_id") | ||||
|   private String configId; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 必填 | ||||
|    * 联系方式类型,1-单人, 2-多人 | ||||
|    * </pre> | ||||
|    */ | ||||
|   private TYPE type; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 必填 | ||||
|    * 场景,1-在小程序中联系,2-通过二维码联系 | ||||
|    * </pre> | ||||
|    */ | ||||
|   private SCENE scene; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 在小程序中联系时使用的控件样式 | ||||
|    * <b>单人样式(type=1)时可选1,2,3</b> | ||||
|    * <b>多人样式(type=2)时可选1,2</b> | ||||
|    * </pre> | ||||
|    */ | ||||
|   private Integer style; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 联系方式的备注信息,用于助记,不超过30个字符 | ||||
|    * </pre> | ||||
|    */ | ||||
|   private String remark; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 外部客户添加时是否无需验证,默认为true | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("skip_verify") | ||||
|   private Boolean skipVerify = Boolean.TRUE; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情(WxCpExternalContactService.getContactDetail)”  时会返回该参数值,不超过30个字符 | ||||
|    * </pre> | ||||
|    */ | ||||
|   private String state; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个 | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("user") | ||||
|   private List<String> users; | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 使用该联系方式的部门id列表,只在type为2时有效 | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("party") | ||||
|   private List<String> partys; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 是否临时会话模式,true表示使用临时会话模式,默认为false | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("is_temp") | ||||
|   private Boolean isTemp = Boolean.FALSE; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天 | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("expires_in") | ||||
|   private Integer expiresIn; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时 | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("chat_expires_in") | ||||
|   private Integer chatExpiresIn; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 可进行临时会话的客户unionid,该参数仅在is_temp为true时有效,如不指定则不进行限制 | ||||
|    * </pre> | ||||
|    */ | ||||
|   @SerializedName("unionid") | ||||
|   private String unionId; | ||||
|  | ||||
|   /** | ||||
|    * <pre> | ||||
|    * 非必填 | ||||
|    * 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效 | ||||
|    * </pre> | ||||
|    */ | ||||
|   private Conclusion conclusions; | ||||
|  | ||||
|   public static WxCpContactWayInfo fromJson(String json) { | ||||
|     return WxCpGsonBuilder.create().fromJson(json, WxCpContactWayInfo.class); | ||||
|   } | ||||
|  | ||||
|   public String toJson() { | ||||
|     return WxCpGsonBuilder.create().toJson(this); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * 结束语定义 | ||||
|    */ | ||||
|   @Data | ||||
|   @JsonAdapter(WxCpConclusionAdapter.class) | ||||
|   public static class Conclusion { | ||||
|     private String textContent; | ||||
|     private String imgMediaId; | ||||
|     private String imgPicUrl; | ||||
|     private String linkTitle; | ||||
|     private String linkPicUrl; | ||||
|     private String linkDesc; | ||||
|     private String linkUrl; | ||||
|     private String miniProgramTitle; | ||||
|     private String miniProgramPicMediaId; | ||||
|     private String miniProgramAppId; | ||||
|     private String miniProgramPage; | ||||
|   } | ||||
|  | ||||
|   public enum TYPE { | ||||
|     /** | ||||
|      * 单人 | ||||
|      */ | ||||
|     @SerializedName("1") | ||||
|     SIGLE, | ||||
|  | ||||
|     /** | ||||
|      * 多人 | ||||
|      */ | ||||
|     @SerializedName("2") | ||||
|     MULTI; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   public enum SCENE { | ||||
|  | ||||
|     /** | ||||
|      * 在小程序中联系 | ||||
|      */ | ||||
|     @SerializedName("1") | ||||
|     MINIPROGRAM, | ||||
|  | ||||
|     /** | ||||
|      * 通过二维码联系 | ||||
|      */ | ||||
|     @SerializedName("2") | ||||
|     QRCODE; | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| package me.chanjar.weixin.cp.bean; | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName; | ||||
| import lombok.Data; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | ||||
|  | ||||
| /** | ||||
|  * 「联系我」方式 处理结果 | ||||
|  */ | ||||
| @Data | ||||
| public class WxCpContactWayResult extends WxCpBaseResp { | ||||
|   @SerializedName("config_id") | ||||
|   private String configId; | ||||
|  | ||||
|   public static WxCpContactWayResult fromJson(String json) { | ||||
|     return WxCpGsonBuilder.create().fromJson(json, WxCpContactWayResult.class); | ||||
|   } | ||||
| } | ||||
| @ -117,6 +117,11 @@ public final class WxCpApiPathConsts { | ||||
|     @Deprecated | ||||
|     public static final String GET_EXTERNAL_CONTACT = "/cgi-bin/crm/get_external_contact?external_userid="; | ||||
|  | ||||
|     public static final String ADD_CONTACT_WAY = "/cgi-bin/externalcontact/add_contact_way"; | ||||
|     public static final String GET_CONTACT_WAY = "/cgi-bin/externalcontact/get_contact_way"; | ||||
|     public static final String UPDATE_CONTACT_WAY = "/cgi-bin/externalcontact/update_contact_way"; | ||||
|     public static final String DEL_CONTACT_WAY = "/cgi-bin/externalcontact/del_contact_way"; | ||||
|     public static final String CLOSE_TEMP_CHAT = "/cgi-bin/externalcontact/close_temp_chat"; | ||||
|     public static final String GET_FOLLOW_USER_LIST = "/cgi-bin/externalcontact/get_follow_user_list"; | ||||
|     public static final String GET_CONTACT_DETAIL = "/cgi-bin/externalcontact/get?external_userid="; | ||||
|     public static final String LIST_EXTERNAL_CONTACT = "/cgi-bin/externalcontact/list?userid="; | ||||
|  | ||||
| @ -0,0 +1,123 @@ | ||||
| package me.chanjar.weixin.cp.util.json; | ||||
|  | ||||
| import com.google.gson.*; | ||||
| import me.chanjar.weixin.cp.bean.WxCpContactWayInfo; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
|  | ||||
| import java.lang.reflect.Type; | ||||
|  | ||||
| /** | ||||
|  * 结束语序列化转换器 | ||||
|  * | ||||
|  * @author element | ||||
|  */ | ||||
| public class WxCpConclusionAdapter implements JsonSerializer<WxCpContactWayInfo.Conclusion>, JsonDeserializer<WxCpContactWayInfo.Conclusion> { | ||||
|   @Override | ||||
|   public WxCpContactWayInfo.Conclusion deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | ||||
|     JsonObject jsonObject = json.getAsJsonObject(); | ||||
|  | ||||
|     WxCpContactWayInfo.Conclusion conclusion = new WxCpContactWayInfo.Conclusion(); | ||||
|  | ||||
|     if (jsonObject.get("text") != null) { | ||||
|       JsonObject jsonText = jsonObject.get("text").getAsJsonObject(); | ||||
|  | ||||
|       if (jsonText.get("content") != null) { | ||||
|         conclusion.setTextContent(jsonText.get("content").getAsString()); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (jsonObject.get("image") != null) { | ||||
|       JsonObject jsonImage = jsonObject.get("image").getAsJsonObject(); | ||||
|  | ||||
|       if (jsonImage.get("media_id") != null) { | ||||
|         conclusion.setImgMediaId(jsonImage.get("media_id").getAsString()); | ||||
|       } | ||||
|  | ||||
|       if (jsonImage.get("pic_url") != null) { | ||||
|         conclusion.setImgPicUrl(jsonImage.get("pic_url").getAsString()); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (jsonObject.get("link") != null) { | ||||
|       JsonObject jsonLink = jsonObject.get("link").getAsJsonObject(); | ||||
|  | ||||
|       if (jsonLink.get("title") != null) { | ||||
|         conclusion.setLinkTitle(jsonLink.get("title").getAsString()); | ||||
|       } | ||||
|       if (jsonLink.get("picurl") != null) { | ||||
|         conclusion.setLinkPicUrl(jsonLink.get("picurl").getAsString()); | ||||
|       } | ||||
|       if (jsonLink.get("desc") != null) { | ||||
|         conclusion.setLinkDesc(jsonLink.get("desc").getAsString()); | ||||
|       } | ||||
|       if (jsonLink.get("url") != null) { | ||||
|         conclusion.setLinkUrl(jsonLink.get("url").getAsString()); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (jsonObject.get("miniprogram") != null) { | ||||
|  | ||||
|       JsonObject jsonMiniProgram = jsonObject.get("miniprogram").getAsJsonObject(); | ||||
|       if (jsonMiniProgram.get("title") != null) { | ||||
|         conclusion.setMiniProgramTitle(jsonMiniProgram.get("title").getAsString()); | ||||
|       } | ||||
|       if (jsonMiniProgram.get("pic_media_id") != null) { | ||||
|         conclusion.setMiniProgramPicMediaId(jsonMiniProgram.get("pic_media_id").getAsString()); | ||||
|       } | ||||
|       if (jsonMiniProgram.get("appid") != null) { | ||||
|         conclusion.setMiniProgramAppId(jsonMiniProgram.get("appid").getAsString()); | ||||
|       } | ||||
|       if (jsonMiniProgram.get("page") != null) { | ||||
|         conclusion.setMiniProgramPage(jsonMiniProgram.get("page").getAsString()); | ||||
|       } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     return conclusion; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public JsonElement serialize(WxCpContactWayInfo.Conclusion src, Type typeOfSrc, JsonSerializationContext context) { | ||||
|     JsonObject json = new JsonObject(); | ||||
|     if (StringUtils.isNotBlank(src.getTextContent())) { | ||||
|       JsonObject jsonText = new JsonObject(); | ||||
|       jsonText.addProperty("content", src.getTextContent()); | ||||
|       json.add("text", jsonText); | ||||
|     } | ||||
|  | ||||
|     if (StringUtils.isNotBlank(src.getImgMediaId()) || StringUtils.isNotBlank(src.getImgPicUrl())) { | ||||
|       JsonObject jsonImg = new JsonObject(); | ||||
|       jsonImg.addProperty("media_id", src.getImgMediaId()); | ||||
|       jsonImg.addProperty("pic_url", src.getImgPicUrl()); | ||||
|       json.add("image", jsonImg); | ||||
|     } | ||||
|  | ||||
|     if (StringUtils.isNotBlank(src.getLinkTitle()) | ||||
|       || StringUtils.isNotBlank(src.getLinkPicUrl()) | ||||
|       || StringUtils.isNotBlank(src.getLinkDesc()) | ||||
|       || StringUtils.isNotBlank(src.getLinkUrl()) | ||||
|     ) { | ||||
|       JsonObject jsonLink = new JsonObject(); | ||||
|       jsonLink.addProperty("title", src.getLinkTitle()); | ||||
|       jsonLink.addProperty("picurl", src.getLinkPicUrl()); | ||||
|       jsonLink.addProperty("desc", src.getLinkDesc()); | ||||
|       jsonLink.addProperty("url", src.getLinkUrl()); | ||||
|       json.add("link", jsonLink); | ||||
|     } | ||||
|  | ||||
|     if (StringUtils.isNotBlank(src.getMiniProgramTitle()) | ||||
|       || StringUtils.isNotBlank(src.getMiniProgramPicMediaId()) | ||||
|       || StringUtils.isNotBlank(src.getMiniProgramAppId()) | ||||
|       || StringUtils.isNotBlank(src.getMiniProgramPage()) | ||||
|     ) { | ||||
|       JsonObject jsonMiniProgram = new JsonObject(); | ||||
|       jsonMiniProgram.addProperty("title", src.getMiniProgramTitle()); | ||||
|       jsonMiniProgram.addProperty("pic_media_id", src.getMiniProgramPicMediaId()); | ||||
|       jsonMiniProgram.addProperty("appid", src.getMiniProgramAppId()); | ||||
|       jsonMiniProgram.addProperty("page", src.getMiniProgramPage()); | ||||
|       json.add("miniprogram", jsonMiniProgram); | ||||
|     } | ||||
|  | ||||
|     return json; | ||||
|   } | ||||
| } | ||||
| @ -1,13 +1,18 @@ | ||||
| package me.chanjar.weixin.cp.api.impl; | ||||
|  | ||||
| import com.google.common.collect.Lists; | ||||
| import com.google.inject.Inject; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.cp.api.ApiTestModule; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpBaseResp; | ||||
| import me.chanjar.weixin.cp.bean.WxCpContactWayInfo; | ||||
| import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; | ||||
| import org.apache.commons.lang3.time.DateFormatUtils; | ||||
| import org.testng.annotations.Guice; | ||||
| import org.testng.annotations.Test; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| import static org.testng.Assert.assertNotNull; | ||||
| @ -28,6 +33,55 @@ public class WxCpExternalContactServiceImplTest { | ||||
|     assertNotNull(result); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testAddContactWay() throws WxErrorException { | ||||
|  | ||||
|     final String concatUserId = "符合要求的userId"; | ||||
|  | ||||
|     WxCpContactWayInfo info = new WxCpContactWayInfo(); | ||||
|     info.setType(WxCpContactWayInfo.TYPE.SIGLE); | ||||
|     info.setScene(WxCpContactWayInfo.SCENE.MINIPROGRAM); | ||||
|     info.setUsers(Lists.newArrayList(concatUserId)); | ||||
|     info.setRemark("CreateDate:" + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(new Date())); | ||||
|     this.wxCpService.getExternalContactService().addContactWay(info); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetContactWay() throws WxErrorException { | ||||
|     final String configId = "2d7a68c657663afbd1d90db19a4b5ee9"; | ||||
|     WxCpContactWayInfo contactWayInfo = this.wxCpService.getExternalContactService().getContactWay(configId); | ||||
|     System.out.println(contactWayInfo); | ||||
|     assertNotNull(contactWayInfo); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testUpdateContactWay() throws WxErrorException { | ||||
|     final String configId = "2d7a68c657663afbd1d90db19a4b5ee9"; | ||||
|     final String concatUserId = "符合要求的userId"; | ||||
|     WxCpContactWayInfo info = new WxCpContactWayInfo(); | ||||
|     info.setConfigId(configId); | ||||
|     info.setUsers(Lists.newArrayList(concatUserId)); | ||||
|     info.setRemark("CreateDate:" + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(new Date())); | ||||
|     WxCpBaseResp resp = this.wxCpService.getExternalContactService().updateContactWay(info); | ||||
|     System.out.println(resp); | ||||
|     assertNotNull(resp); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testDelContactWay() throws WxErrorException { | ||||
|     final String configId = "2d7a68c657663afbd1d90db19a4b5ee9"; | ||||
|     WxCpBaseResp resp = this.wxCpService.getExternalContactService().deleteContactWay(configId); | ||||
|     System.out.println(resp); | ||||
|     assertNotNull(resp); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testCloseTempChat() throws WxErrorException { | ||||
|     final String externalUserId = "externalUserId"; | ||||
|     WxCpBaseResp resp = this.wxCpService.getExternalContactService().closeTempChat(userId, externalUserId); | ||||
|     System.out.println(resp); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testListExternalContacts() throws WxErrorException { | ||||
|     String userId = this.configStorage.getUserId(); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 爱因斯唐
					爱因斯唐