diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java index 2b3a17b87..8c0ea9685 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java @@ -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 JoeCao */ public interface WxCpExternalContactService { + + /** + * 配置客户联系「联系我」方式 + *
+   * 企业可以在管理后台-客户联系中配置成员的「联系我」的二维码或者小程序按钮,客户通过扫描二维码或点击小程序上的按钮,即可获取成员联系方式,主动联系到成员。
+   * 企业可通过此接口为具有客户联系功能的成员生成专属的「联系我」二维码或者「联系我」按钮。
+   * 如果配置的是「联系我」按钮,需要开发者的小程序接入小程序插件。
+   *
+   * 注意:
+   * 通过API添加的「联系我」不会在管理端进行展示,每个企业可通过API最多配置50万个「联系我」。
+   * 用户需要妥善存储返回的config_id,config_id丢失可能导致用户无法编辑或删除「联系我」。
+   * 临时会话模式不占用「联系我」数量,但每日最多添加10万个,并且仅支持单人。
+   * 临时会话模式的二维码,添加好友完成后该二维码即刻失效。
+   * 
+ * + * @param info 客户联系「联系我」方式 + * @return + * @throws WxErrorException + */ + WxCpContactWayResult addContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException; + + /** + * 获取企业已配置的「联系我」方式 + * + *
+   * 批量获取企业配置的「联系我」二维码和「联系我」小程序按钮。
+   * 
+ * + * @param configId 联系方式的配置id,必填 + * @return + * @throws WxErrorException + */ + WxCpContactWayInfo getContactWay(@NonNull String configId) throws WxErrorException; + + /** + * 更新企业已配置的「联系我」方式 + * + *
+   * 更新企业配置的「联系我」二维码和「联系我」小程序按钮中的信息,如使用人员和备注等。
+   * 
+ * + * @param info 客户联系「联系我」方式 + * @return + * @throws WxErrorException + */ + WxCpBaseResp updateContactWay(@NonNull WxCpContactWayInfo info) throws WxErrorException; + + /** + * 删除企业已配置的「联系我」方式 + * + *
+   * 删除一个已配置的「联系我」二维码或者「联系我」小程序按钮。
+   * 
+ * + * @param configId 企业联系方式的配置id,必填 + * @return + * @throws WxErrorException + */ + WxCpBaseResp deleteContactWay(@NonNull String configId) throws WxErrorException; + + /** + * 结束临时会话 + * + *
+   * 将指定的企业成员和客户之前的临时会话断开,断开前会自动下发已配置的结束语。
+   *
+   * 注意:请保证传入的企业成员和客户之间有仍然有效的临时会话, 通过其他方式的添加外部联系人无法通过此接口关闭会话。
+   * 
+ * + * @param userId + * @param externalUserId + * @return + * @throws WxErrorException + */ + WxCpBaseResp closeTempChat(@NonNull String userId, @NonNull String externalUserId) throws WxErrorException; + + /** * 获取外部联系人详情. *
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java
index 982c11550..371015b41 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java
@@ -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);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpContactWayInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpContactWayInfo.java
new file mode 100644
index 000000000..3f62e4f0e
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpContactWayInfo.java
@@ -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;
+
+  /**
+   * 
+   * 必填
+   * 联系方式类型,1-单人, 2-多人
+   * 
+ */ + private TYPE type; + + /** + *
+   * 必填
+   * 场景,1-在小程序中联系,2-通过二维码联系
+   * 
+ */ + private SCENE scene; + + /** + *
+   * 非必填
+   * 在小程序中联系时使用的控件样式
+   * 单人样式(type=1)时可选1,2,3
+   * 多人样式(type=2)时可选1,2
+   * 
+ */ + private Integer style; + + /** + *
+   * 非必填
+   * 联系方式的备注信息,用于助记,不超过30个字符
+   * 
+ */ + private String remark; + + /** + *
+   * 非必填
+   * 外部客户添加时是否无需验证,默认为true
+   * 
+ */ + @SerializedName("skip_verify") + private Boolean skipVerify = Boolean.TRUE; + + /** + *
+   * 非必填
+   * 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情(WxCpExternalContactService.getContactDetail)”  时会返回该参数值,不超过30个字符
+   * 
+ */ + private String state; + + /** + *
+   * 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个
+   * 
+ */ + @SerializedName("user") + private List users; + + + /** + *
+   * 非必填
+   * 使用该联系方式的部门id列表,只在type为2时有效
+   * 
+ */ + @SerializedName("party") + private List partys; + + /** + *
+   * 非必填
+   * 是否临时会话模式,true表示使用临时会话模式,默认为false
+   * 
+ */ + @SerializedName("is_temp") + private Boolean isTemp = Boolean.FALSE; + + /** + *
+   * 非必填
+   * 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天
+   * 
+ */ + @SerializedName("expires_in") + private Integer expiresIn; + + /** + *
+   * 非必填
+   * 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时
+   * 
+ */ + @SerializedName("chat_expires_in") + private Integer chatExpiresIn; + + /** + *
+   * 非必填
+   * 可进行临时会话的客户unionid,该参数仅在is_temp为true时有效,如不指定则不进行限制
+   * 
+ */ + @SerializedName("unionid") + private String unionId; + + /** + *
+   * 非必填
+   * 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效
+   * 
+ */ + 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; + + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpContactWayResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpContactWayResult.java new file mode 100644 index 000000000..89d58454d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpContactWayResult.java @@ -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); + } +} 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 24debae39..72ababe77 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 @@ -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="; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpConclusionAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpConclusionAdapter.java new file mode 100644 index 000000000..1a9aab8bf --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpConclusionAdapter.java @@ -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, JsonDeserializer { + @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; + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java index 309b14bc2..da04bc6c0 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java @@ -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(); diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java index 4d1c2b136..4b496b30d 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java @@ -208,6 +208,13 @@ public interface WxOpenConfigStorage { */ void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken); + /** + * setAuthorizerRefreshToken(String appId, String authorizerRefreshToken) 方法重载方法 + * @param appId the app id + * @param authorizerRefreshToken the authorizer refresh token + */ + void updateAuthorizerRefreshToken(String appId, String authorizerRefreshToken); + /** * Gets authorizer access token. * diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java index fe2a782e4..80961921f 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java @@ -311,7 +311,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService { authorizationInfo.getAuthorizerAccessToken(), authorizationInfo.getExpiresIn()); } if (authorizationInfo.getAuthorizerRefreshToken() != null) { - getWxOpenConfigStorage().setAuthorizerRefreshToken(authorizationInfo.getAuthorizerAppid(), authorizationInfo.getAuthorizerRefreshToken()); + getWxOpenConfigStorage().updateAuthorizerRefreshToken(authorizationInfo.getAuthorizerAppid(), authorizationInfo.getAuthorizerRefreshToken()); } return queryAuth; } @@ -340,7 +340,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService { String authorizerAppid = data.get("authorizer_appid"); String refreshToken = data.get("refresh_token"); if (authorizerAppid != null && refreshToken != null) { - this.getWxOpenConfigStorage().setAuthorizerRefreshToken(authorizerAppid, refreshToken); + this.getWxOpenConfigStorage().updateAuthorizerRefreshToken(authorizerAppid, refreshToken); } } } @@ -391,6 +391,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService { WxOpenAuthorizerAccessToken wxOpenAuthorizerAccessToken = WxOpenAuthorizerAccessToken.fromJson(responseContent); config.updateAuthorizerAccessToken(appId, wxOpenAuthorizerAccessToken); + config.updateAuthorizerRefreshToken(appId,wxOpenAuthorizerAccessToken.getAuthorizerRefreshToken()); return config.getAuthorizerAccessToken(appId); } catch (InterruptedException e) { throw new RuntimeException(e); diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java index 723ec3806..a4859ba18 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java @@ -142,7 +142,7 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage { map.put(key, token); } token.token = tokenString; - if (expiresInSeconds != null) { + if (expiresInSeconds != null && expiresInSeconds != -1) { token.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; } } @@ -157,6 +157,11 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage { updateToken(authorizerRefreshTokens, appId, authorizerRefreshToken, null); } + @Override + public void updateAuthorizerRefreshToken(String appId, String authorizerRefreshToken) { + this.setAuthorizerRefreshToken(appId, authorizerRefreshToken); + } + @Override public String getAuthorizerAccessToken(String appId) { return getTokenString(authorizerAccessTokens, appId); diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenAuthorizerAccessToken.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenAuthorizerAccessToken.java index 9b86412bb..9a558ab77 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenAuthorizerAccessToken.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenAuthorizerAccessToken.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.open.bean; +import lombok.Data; import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; import java.io.Serializable; @@ -7,30 +8,17 @@ import java.io.Serializable; /** * @author 007 */ +@Data public class WxOpenAuthorizerAccessToken implements Serializable { private static final long serialVersionUID = -4069745419280727420L; private String authorizerAccessToken; + private String authorizerRefreshToken; + private int expiresIn = -1; public static WxOpenAuthorizerAccessToken fromJson(String json) { return WxOpenGsonBuilder.create().fromJson(json, WxOpenAuthorizerAccessToken.class); } - - public String getAuthorizerAccessToken() { - return authorizerAccessToken; - } - - public void setAuthorizerAccessToken(String authorizerAccessToken) { - this.authorizerAccessToken = authorizerAccessToken; - } - - public int getExpiresIn() { - return expiresIn; - } - - public void setExpiresIn(int expiresIn) { - this.expiresIn = expiresIn; - } } diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerAccessTokenGsonAdapter.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerAccessTokenGsonAdapter.java index 82a04b9ba..6932d2573 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerAccessTokenGsonAdapter.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerAccessTokenGsonAdapter.java @@ -15,6 +15,7 @@ public class WxOpenAuthorizerAccessTokenGsonAdapter implements JsonDeserializer< WxOpenAuthorizerAccessToken authorizerAccessToken = new WxOpenAuthorizerAccessToken(); JsonObject jsonObject = jsonElement.getAsJsonObject(); authorizerAccessToken.setAuthorizerAccessToken(GsonHelper.getString(jsonObject, "authorizer_access_token")); + authorizerAccessToken.setAuthorizerRefreshToken(GsonHelper.getString(jsonObject, "authorizer_refresh_token")); authorizerAccessToken.setExpiresIn(GsonHelper.getPrimitiveInteger(jsonObject, "expires_in")); return authorizerAccessToken; }