From 0247486b13c7eeec18caabb9e81acd52694970f9 Mon Sep 17 00:00:00 2001 From: Charming Date: Thu, 26 Apr 2018 23:02:22 +0800 Subject: [PATCH] =?UTF-8?q?#562=20=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BB=A3=E7=A0=81=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API --- .../wx/miniapp/api/WxMaCodeService.java | 140 ++++++++++++ .../wx/miniapp/api/WxMaService.java | 7 + .../miniapp/api/impl/WxMaCodeServiceImpl.java | 148 +++++++++++++ .../wx/miniapp/api/impl/WxMaServiceImpl.java | 34 +-- .../wx/miniapp/bean/code/WxMaCategory.java | 62 ++++++ .../bean/code/WxMaCodeAuditStatus.java | 37 ++++ .../bean/code/WxMaCodeCommitRequest.java | 39 ++++ .../miniapp/bean/code/WxMaCodeExtConfig.java | 199 ++++++++++++++++++ .../bean/code/WxMaCodeSubmitAuditRequest.java | 30 +++ .../code/WxMaCodeVersionDistribution.java | 30 +++ .../wx/miniapp/bean/code/package-info.java | 7 + .../WxMaCodeCommitRequestGsonAdapter.java | 28 +++ ...xMaCodeVersionDistributionGsonAdapter.java | 50 +++++ .../wx/miniapp/util/json/WxMaGsonBuilder.java | 4 + .../api/impl/WxMaCodeServiceImplTest.java | 156 ++++++++++++++ .../bean/code/WxMaCodeCommitRequestTest.java | 25 +++ .../code/WxMaCodeSubmitAuditRequestTest.java | 30 +++ .../code/WxMaCodeVersionDistributionTest.java | 15 ++ 18 files changed, 1027 insertions(+), 14 deletions(-) create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCategory.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java create mode 100755 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeCommitRequestGsonAdapter.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeVersionDistributionGsonAdapter.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequestTest.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequestTest.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistributionTest.java diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java new file mode 100644 index 00000000..37e850ee --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java @@ -0,0 +1,140 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.code.WxMaCategory; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.util.List; + +/** + * 小程序代码管理相关 API(大部分只能是第三方平台调用) + * 文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=&lang=zh_CN + * + * @author Charming + * @since 2018-04-26 19:43 + */ +public interface WxMaCodeService { + /** + * 为授权的小程序帐号上传小程序代码 + */ + String COMMIT_URL = "https://api.weixin.qq.com/wxa/commit"; + String GET_QRCODE_URL = "https://api.weixin.qq.com/wxa/get_qrcode"; + String GET_CATEGORY_URL = "https://api.weixin.qq.com/wxa/get_category"; + String GET_PAGE_URL = "https://api.weixin.qq.com/wxa/get_page"; + String SUBMIT_AUDIT_URL = "https://api.weixin.qq.com/wxa/submit_audit"; + String GET_AUDIT_STATUS_URL = "https://api.weixin.qq.com/wxa/get_auditstatus"; + String GET_LATEST_AUDIT_STATUS_URL = "https://api.weixin.qq.com/wxa/get_latest_auditstatus"; + String RELEASE_URL = "https://api.weixin.qq.com/wxa/release"; + String CHANGE_VISIT_STATUS_URL = "https://api.weixin.qq.com/wxa/change_visitstatus"; + String REVERT_CODE_RELEASE_URL = "https://api.weixin.qq.com/wxa/revertcoderelease"; + String GET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion"; + String SET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion"; + String UNDO_CODE_AUDIT_URL = "https://api.weixin.qq.com/wxa/undocodeaudit"; + + /** + * 为授权的小程序帐号上传小程序代码(仅仅支持第三方开放平台) + * + * @param commitRequest 参数 + * @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档 + */ + void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException; + + /** + * 获取体验小程序的体验二维码 + * + * @return 二维码 bytes + * @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档 + */ + byte[] getQrCode() throws WxErrorException; + + /** + * 获取授权小程序帐号的可选类目 + * + * @return List + * @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档 + */ + List getCategory() throws WxErrorException; + + /** + * 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) + * + * @return page_list 页面配置列表 + * @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档 + */ + List getPage() throws WxErrorException; + + /** + * 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) + * + * @param auditRequest 提交审核参数 + * @return 审核编号 + * @throws WxErrorException 提交失败时返回,具体错误码请看此接口的注释文档 + */ + long submitAudit(WxMaCodeSubmitAuditRequest auditRequest) throws WxErrorException; + + /** + * 查询某个指定版本的审核状态(仅供第三方代小程序调用) + * + * @param auditId 提交审核时获得的审核id + * @return 审核状态 + * @throws WxErrorException 查询失败时返回,具体错误码请看此接口的注释文档 + */ + WxMaCodeAuditStatus getAuditStatus(long auditId) throws WxErrorException; + + /** + * 查询最新一次提交的审核状态(仅供第三方代小程序调用) + * + * @return 审核状态 + * @throws WxErrorException 查询失败时返回,具体错误码请看此接口的注释文档 + */ + WxMaCodeAuditStatus getLatestAuditStatus() throws WxErrorException; + + /** + * 发布已通过审核的小程序(仅供第三方代小程序调用) + * + * @throws WxErrorException 发布失败时抛出,具体错误码请看此接口的注释文档 + */ + void release() throws WxErrorException; + + /** + * 修改小程序线上代码的可见状态(仅供第三方代小程序调用) + * + * @param action 设置可访问状态,发布后默认可访问,close为不可见,open为可见 + * @throws WxErrorException 发布失败时抛出,具体错误码请看此接口的注释文档 + */ + void changeVisitStatus(String action) throws WxErrorException; + + /** + * 小程序版本回退(仅供第三方代小程序调用) + * + * @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 + */ + void revertCodeRelease() throws WxErrorException; + + /** + * 查询当前设置的最低基础库版本及各版本用户占比 (仅供第三方代小程序调用) + * + * @return 小程序版本分布信息 + * @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 + */ + WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException; + + /** + * 设置最低基础库版本(仅供第三方代小程序调用) + * + * @param version 版本 + * @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 + */ + void setSupportVersion(String version) throws WxErrorException; + + /** + * 小程序审核撤回 + * 单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次 + * + * @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 + */ + void undoCodeAudit() throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java index c437966e..000fda0b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java @@ -135,6 +135,13 @@ public interface WxMaService { */ WxMaTemplateService getTemplateService(); + /** + * 返回代码操作相关的 API + * + * @return WxMaCodeService + */ + WxMaCodeService getCodeService(); + /** * 初始化http请求对象. */ diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java new file mode 100644 index 00000000..0cd40f6d --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java @@ -0,0 +1,148 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaCodeService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.code.WxMaCategory; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.json.GsonHelper; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +/** + * @author Charming + * @since 2018-04-26 20:00 + */ +public class WxMaCodeServiceImpl implements WxMaCodeService { + private static final JsonParser JSON_PARSER = new JsonParser(); + private WxMaService wxMaService; + + public WxMaCodeServiceImpl(WxMaService wxMaService) { + this.wxMaService = wxMaService; + } + + @Override + public void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException { + this.wxMaService.post(COMMIT_URL, commitRequest.toJson()); + } + + @Override + public byte[] getQrCode() throws WxErrorException { + String appId = this.wxMaService.getWxMaConfig().getAppid(); + Path qrCodeFilePath = null; + try { + RequestExecutor executor = BaseMediaDownloadRequestExecutor + .create(this.wxMaService.getRequestHttp(), Files.createTempDirectory("weixin-java-tools-ma-" + appId).toFile()); + qrCodeFilePath = this.wxMaService.execute(executor, GET_QRCODE_URL, null).toPath(); + return Files.readAllBytes(qrCodeFilePath); + } catch (IOException e) { + throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); + } finally { + if (qrCodeFilePath != null) { + try { + // 及时删除二维码文件,避免积压过多缓存文件 + Files.delete(qrCodeFilePath); + } catch (Exception ignored) { + } + } + } + } + + @Override + public List getCategory() throws WxErrorException { + String responseContent = this.wxMaService.get(GET_CATEGORY_URL, null); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + boolean hasCategoryList = jsonObject.has("category_list"); + if (hasCategoryList) { + return WxMaGsonBuilder.create().fromJson(jsonObject.getAsJsonArray("category_list"), + new TypeToken>() { + }.getType()); + } else { + return null; + } + } + + @Override + public List getPage() throws WxErrorException { + String responseContent = this.wxMaService.get(GET_PAGE_URL, null); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + boolean hasPageList = jsonObject.has("page_list"); + if (hasPageList) { + return WxMaGsonBuilder.create().fromJson(jsonObject.getAsJsonArray("page_list"), + new TypeToken>() { + }.getType()); + } else { + return null; + } + } + + @Override + public long submitAudit(WxMaCodeSubmitAuditRequest auditRequest) throws WxErrorException { + String responseContent = this.wxMaService.post(SUBMIT_AUDIT_URL, auditRequest.toJson()); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + return GsonHelper.getLong(jsonObject, "auditid"); + } + + @Override + public WxMaCodeAuditStatus getAuditStatus(long auditId) throws WxErrorException { + JsonObject param = new JsonObject(); + param.addProperty("auditid", auditId); + String responseContent = this.wxMaService.post(GET_AUDIT_STATUS_URL, param.toString()); + return WxMaCodeAuditStatus.fromJson(responseContent); + } + + @Override + public WxMaCodeAuditStatus getLatestAuditStatus() throws WxErrorException { + String responseContent = this.wxMaService.get(GET_LATEST_AUDIT_STATUS_URL, null); + return WxMaCodeAuditStatus.fromJson(responseContent); + } + + @Override + public void release() throws WxErrorException { + this.wxMaService.post(RELEASE_URL, "{}"); + } + + @Override + public void changeVisitStatus(String action) throws WxErrorException { + JsonObject param = new JsonObject(); + param.addProperty("action", action); + this.wxMaService.post(CHANGE_VISIT_STATUS_URL, param.toString()); + } + + @Override + public void revertCodeRelease() throws WxErrorException { + this.wxMaService.get(REVERT_CODE_RELEASE_URL, null); + } + + @Override + public WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException { + String responseContent = this.wxMaService.post(GET_SUPPORT_VERSION_URL, "{}"); + return WxMaCodeVersionDistribution.fromJson(responseContent); + } + + @Override + public void setSupportVersion(String version) throws WxErrorException { + JsonObject param = new JsonObject(); + param.addProperty("version", version); + this.wxMaService.post(SET_SUPPORT_VERSION_URL, param.toString()); + } + + @Override + public void undoCodeAudit() throws WxErrorException { + this.wxMaService.get(UNDO_CODE_AUDIT_URL, null); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java index 1ec7801d..d3be4a73 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java @@ -1,19 +1,6 @@ package cn.binarywang.wx.miniapp.api.impl; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.locks.Lock; - -import org.apache.http.HttpHost; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import cn.binarywang.wx.miniapp.api.WxMaCodeService; import cn.binarywang.wx.miniapp.api.WxMaMediaService; import cn.binarywang.wx.miniapp.api.WxMaMsgService; import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; @@ -35,6 +22,19 @@ import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import org.apache.http.HttpHost; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; /** * @author Binary Wang @@ -51,6 +51,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttpCharming + * @since 2018-04-26 19:44 + */ +@Data +@Builder +public class WxMaCategory implements Serializable { + private static final long serialVersionUID = -7663757440028175135L; + /** + * 一级类目名称 + */ + @SerializedName("first_class") + private String firstClass; + /** + * 二级类目名称 + */ + @SerializedName("second_class") + private String secondClass; + /** + * 三级类目名称 + */ + @SerializedName("third_class") + private String thirdClass; + /** + * 一级类目的ID编号 + */ + @SerializedName("first_id") + private Long firstId; + /** + * 二级类目的ID编号 + */ + @SerializedName("second_id") + private Long secondId; + /** + * 三级类目的ID编号 + */ + @SerializedName("third_id") + private Long thirdId; + + /** + * 小程序的页面,可通过“获取小程序的第三方提交代码的页面配置”接口获得 + */ + private String address; + /** + * 小程序的标签,多个标签用空格分隔,标签不能多于10个,标签长度不超过20 + */ + private String tag; + /** + * 小程序页面的标题,标题长度不超过32 + */ + private String title; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java new file mode 100644 index 00000000..36c33eaf --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeAuditStatus.java @@ -0,0 +1,37 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * 小程序代码审核状态 + * + * @author Charming + * @since 2018-04-26 19:44:39 + */ +@Data +@Builder +public class WxMaCodeAuditStatus implements Serializable { + private static final long serialVersionUID = 4655119308692217268L; + /** + * 审核 ID + */ + @SerializedName(value = "auditId", alternate = {"auditid"}) + private Long auditId; + /** + * 审核状态,其中0为审核成功,1为审核失败,2为审核中 + */ + private Integer status; + /** + * 当status=1,审核被拒绝时,返回的拒绝原因 + */ + private String reason; + + public static WxMaCodeAuditStatus fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaCodeAuditStatus.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java new file mode 100644 index 00000000..ec64da59 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequest.java @@ -0,0 +1,39 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * 微信代码请求上传参数 + * + * @author Charming + * @since 2018-04-26 19:44:47 + */ +@Data +@Builder +public class WxMaCodeCommitRequest implements Serializable { + private static final long serialVersionUID = 7495157056049312108L; + /** + * 代码库中的代码模版ID + */ + private Long templateId; + /** + * 第三方自定义的配置 + */ + private WxMaCodeExtConfig extConfig; + /** + * 代码版本号,开发者可自定义 + */ + private String userVersion; + /** + * 代码描述,开发者可自定义 + */ + private String userDesc; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java new file mode 100644 index 00000000..51211123 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeExtConfig.java @@ -0,0 +1,199 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * 上传代码需要用到的第三方自定义的配置 + * + * @author Charming + * @since 2018-04-26 19:44 + */ +@Data +@Builder +public class WxMaCodeExtConfig implements Serializable { + private static final long serialVersionUID = -7666911367458178753L; + /** + * 配置 ext.json 是否生效 + * 必填:是 + */ + private boolean extEnable; + /** + * 配置 extAppid + * 必填:是 + */ + private String extAppid; + /** + * 开发自定义的数据字段 + * 必填:否 + */ + private Object ext; + /** + * 单独设置每个页面的 json + * 必填:否 + * key: page 名称,如 pages/logs/logs + * value: page 配置 + */ + private Map extPages; + /** + * 是否直接提交到待审核列表 + * 必填:否 + */ + private Boolean directCommit; + /** + * 设置页面路径(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private List pages; + /** + * 设置默认页面的窗口表现(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private PageConfig window; + /** + * 设置各种网络请求的超时时间(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private NetworkTimeout networkTimeout; + /** + * 设置是否开启 debug 模式(同 app.json 相同的字段,填写会覆盖 app.json) + * 必填:否 + */ + private Boolean debug; + + /** + * page.json 配置,页面配置 + * 文档:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html + */ + @Data + @Builder + public static class PageConfig { + /** + * 导航栏背景颜色,如"#000000" HexColor + * 默认:#000000 + */ + private String navigationBarBackgroundColor; + /** + * 导航栏标题颜色,仅支持 black/white + * 默认:white + */ + private String navigationBarTextStyle; + /** + * 导航栏标题文字内容 + */ + private String navigationBarTitleText; + /** + * 窗口的背景色 HexColor + * 默认:#ffffff + */ + private String backgroundColor; + /** + * 下拉背景字体、loading 图的样式,仅支持 dark/light + * 默认:dark + */ + private String backgroundTextStyle; + /** + * 是否开启下拉刷新,详见页面相关事件处理函数 + * 默认:false + */ + private String enablePullDownRefresh; + /** + * 设置为 true 则页面整体不能上下滚动;只在 page.json 中有效,无法在 app.json 中设置该项 + * 默认:false + */ + private Boolean disableScroll; + /** + * 页面上拉触底事件触发时距页面底部距离,单位为px + * 默认:50 + */ + private Integer onReachBottomDistance; + } + + /** + * tabBar 配置 + */ + @Data + @Builder + public static class TabBar { + /** + * HexColor, tab 上的文字默认颜色 + */ + private String color; + /** + * HexColor, tab 上的文字选中时的颜色 + */ + private String selectedColor; + /** + * HexColor, tab 的背景色 + */ + private String backgroundColor; + /** + * tabbar 上边框的颜色,仅支持 black/white + */ + private String borderStyle; + /** + * tab 的列表,最少2个、最多5个 tab + */ + private List list; + /** + * 可选值 bottom、top + */ + private String position; + + /** + * list item + */ + @Data + @Builder + public static class Item { + /** + * 是 页面路径,必须在 pages 中先定义 + */ + private String pagePath; + /** + * tab 上按钮文字 + */ + private String text; + /** + * 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 postion 为 top 时,此参数无效,不支持网络图片 + */ + private String iconPath; + /** + * 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 postion 为 top 时,此参数无效 + */ + private String selectedIconPath; + } + } + + /** + * 各种网络请求的超时时间 + */ + @Data + @Builder + public static class NetworkTimeout { + /** + * wx.request的超时时间,单位毫秒,默认为:60000 + * 必填:否 + */ + private Integer request; + /** + * wx.connectSocket的超时时间,单位毫秒,默认为:60000 + * 必填:否 + */ + private Integer connectSocket; + /** + * wx.uploadFile的超时时间,单位毫秒,默认为:60000 + * 必填:否 + */ + private Integer uploadFile; + /** + * wx.downloadFile的超时时间,单位毫秒,默认为:60000 + * 必填:否 + */ + private Integer downloadFile; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java new file mode 100644 index 00000000..5b784dbd --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequest.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 提交审核的请求 + * + * @author Charming + * @since 2018-04-26 19:45 + */ +@Data +@Builder +public class WxMaCodeSubmitAuditRequest implements Serializable { + private static final long serialVersionUID = 8854979405505241314L; + /** + * 提交审核项的一个列表(至少填写1项,至多填写5项) + */ + @SerializedName("item_list") + private List itemList; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java new file mode 100644 index 00000000..4c0f0964 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistribution.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; + +import java.util.Map; + +/** + * 小程序代码版本号分布 + * + * @author Charming + * @since 2018-04-26 19:45 + */ +@Data +public class WxMaCodeVersionDistribution { + /** + * 当前版本 + */ + private String nowVersion; + /** + * 受影响用户占比 + * key: version, 版本号 + * value: percentage, 受影响比例 + */ + private Map uvInfo; + + public static WxMaCodeVersionDistribution fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaCodeVersionDistribution.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java new file mode 100644 index 00000000..01f6496b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/package-info.java @@ -0,0 +1,7 @@ +/** + * 微信小程序代码管理相关的 bean + * + * @author Charming + * @since 2018-04-26 19:44 + */ +package cn.binarywang.wx.miniapp.bean.code; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeCommitRequestGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeCommitRequestGsonAdapter.java new file mode 100755 index 00000000..410f86ca --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeCommitRequestGsonAdapter.java @@ -0,0 +1,28 @@ +package cn.binarywang.wx.miniapp.util.json; + +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + +/** + * @author Charming + * @since 2018-04-26 19:47 + */ +public class WxMaCodeCommitRequestGsonAdapter implements JsonSerializer { + + @Override + public JsonElement serialize(WxMaCodeCommitRequest request, Type typeOfSrc, JsonSerializationContext context) { + JsonObject requestJson = new JsonObject(); + requestJson.addProperty("template_id", request.getTemplateId()); + requestJson.addProperty("user_version", request.getUserVersion()); + requestJson.addProperty("user_desc", request.getUserDesc()); + if (request.getExtConfig() != null) { + requestJson.addProperty("ext_json", WxMaGsonBuilder.create().toJson(request.getExtConfig())); + } + return requestJson; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeVersionDistributionGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeVersionDistributionGsonAdapter.java new file mode 100644 index 00000000..027ca6a9 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaCodeVersionDistributionGsonAdapter.java @@ -0,0 +1,50 @@ +package cn.binarywang.wx.miniapp.util.json; + +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import me.chanjar.weixin.common.util.json.GsonHelper; + +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Charming + * @since 2018-04-26 19:47 + */ +public class WxMaCodeVersionDistributionGsonAdapter implements JsonDeserializer { + @Override + public WxMaCodeVersionDistribution deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + if (json == null) { + return null; + } + + WxMaCodeVersionDistribution distribution = new WxMaCodeVersionDistribution(); + JsonObject object = json.getAsJsonObject(); + distribution.setNowVersion(GsonHelper.getString(object, "now_version")); + distribution.setUvInfo(getAsMap(object.getAsJsonObject("uv_info"), "items")); + return distribution; + } + + private Map getAsMap(JsonObject object, String memberName) { + JsonArray array = object.getAsJsonArray(memberName); + if (array != null && array.size() > 0) { + Map map = new LinkedHashMap<>(array.size()); + for (JsonElement element : array) { + JsonObject elementObject = element.getAsJsonObject(); + String version = GsonHelper.getString(elementObject, "version"); + if (version != null) { + Float percentage = GsonHelper.getFloat(elementObject, "percentage"); + map.put(version, percentage); + } + } + return map; + } + return null; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java index 5a08a39a..a11e8e6c 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java @@ -1,6 +1,8 @@ package cn.binarywang.wx.miniapp.util.json; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -13,6 +15,8 @@ public class WxMaGsonBuilder { static { INSTANCE.disableHtmlEscaping(); INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMaCodeCommitRequest.class, new WxMaCodeCommitRequestGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMaCodeVersionDistribution.class, new WxMaCodeVersionDistributionGsonAdapter()); } public static Gson create() { diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java new file mode 100644 index 00000000..34c78899 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java @@ -0,0 +1,156 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaCodeService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.code.WxMaCategory; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeExtConfig; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest; +import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; +import cn.binarywang.wx.miniapp.config.WxMaConfig; +import cn.binarywang.wx.miniapp.test.ApiTestModule; +import com.google.inject.Inject; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +/** + * @author Charming + * @since 2018-04-26 20:18 + */ +@Test +@Guice(modules = ApiTestModule.class) +public class WxMaCodeServiceImplTest { + @Inject + private WxMaService wxService; + @Inject + private WxMaConfig wxMaConfig; + + @Test + public void testGetCategory() throws Exception { + List categories = wxService.getCodeService().getCategory(); + System.out.println(String.valueOf(categories)); + } + + @Test + public void testCommit() throws Exception { + String themeColor = "#0074d9"; + String themeFontColor = "#ffffff"; + + Map ext = new HashMap<>(); + ext.put("appName", "xxx"); + ext.put("verified", true); + ext.put("navigationBarBackgroundColor", themeColor); + ext.put("navigationBarTextStyle", themeFontColor); + ext.put("companyId", 4128); + ext.put("companyFullName", "xxx有限公司"); + + WxMaCodeService wxMaCodeService = wxService.getCodeService(); + WxMaCodeCommitRequest commitRequest = WxMaCodeCommitRequest + .builder() + .templateId(6L) + .userVersion("v0.1.0") + .userDesc("init") + .extConfig(WxMaCodeExtConfig.builder() + .extAppid(wxMaConfig.getAppid()) + .extEnable(true) + .ext(ext) + .window( + WxMaCodeExtConfig.PageConfig + .builder() + .navigationBarBackgroundColor(themeColor) + .navigationBarTextStyle(themeFontColor) + .build() + ) + .build()) + .build(); + wxMaCodeService.commit(commitRequest); + } + + @Test + public void testGetQrCode() throws Exception { + byte[] qrCode = wxService.getCodeService().getQrCode(); + assertTrue(qrCode.length > 0); + } + + @Test + public void testGetPage() throws Exception { + List pageList = wxService.getCodeService().getPage(); + System.out.println(String.valueOf(pageList)); + } + + @Test + public void testSubmitAudit() throws Exception { + WxMaCodeSubmitAuditRequest auditRequest = WxMaCodeSubmitAuditRequest + .builder() + .itemList(Arrays.asList( + WxMaCategory + .builder() + .address("pages/logs/logs") + .tag("工具 效率") + .firstClass("工具") + .firstId(287L) + .secondClass("效率") + .secondId(616L) + .title("日志") + .build() + )).build(); + long auditId = wxService.getCodeService().submitAudit(auditRequest); + assertTrue(auditId > 0); + // 421937937 + System.out.println(auditId); + } + + @Test + public void testGetAuditStatus() throws Exception { + WxMaCodeAuditStatus auditStatus = wxService.getCodeService().getAuditStatus(421937937L); + System.out.println(auditStatus); + assertNotNull(auditStatus); + } + + @Test + public void testGetLatestAuditStatus() throws Exception { + WxMaCodeAuditStatus auditStatus = wxService.getCodeService().getLatestAuditStatus(); + System.out.println(auditStatus); + assertNotNull(auditStatus); + } + + @Test + public void testRelease() throws Exception { + wxService.getCodeService().release(); + } + + @Test + public void testChangeVisitStatus() throws Exception { + wxService.getCodeService().changeVisitStatus("open"); + } + + @Test + public void testRevertCodeRelease() throws Exception { + wxService.getCodeService().revertCodeRelease(); + } + + @Test + public void testGetSupportVersion() throws Exception { + WxMaCodeVersionDistribution distribution = wxService.getCodeService().getSupportVersion(); + System.out.println(distribution); + } + + @Test + public void testSetSupportVersion() throws Exception { + wxService.getCodeService().setSupportVersion("1.2.0"); + } + + @Test + public void testUndoCodeAudit() throws Exception { + + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequestTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequestTest.java new file mode 100644 index 00000000..36cf1c48 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeCommitRequestTest.java @@ -0,0 +1,25 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Charming + * @since 2018-04-26 19:54 + */ +public class WxMaCodeCommitRequestTest { + @Test + public void testToJson() { + WxMaCodeCommitRequest commitRequest = WxMaCodeCommitRequest.builder() + .templateId(1L) + .userVersion("v0.1.0") + .userDesc("init") + .extConfig(WxMaCodeExtConfig.builder() + .extAppid("app123") + .extEnable(true) + .build()) + .build(); + assertEquals(commitRequest.toJson(), "{\"template_id\":1,\"user_version\":\"v0.1.0\",\"user_desc\":\"init\",\"ext_json\":\"{\\\"extEnable\\\":true,\\\"extAppid\\\":\\\"app123\\\"}\"}"); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequestTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequestTest.java new file mode 100644 index 00000000..1f962087 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeSubmitAuditRequestTest.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import org.testng.annotations.Test; + +import java.util.Arrays; + +/** + * @author Charming + * @since 2018-04-26 19:55 + */ +public class WxMaCodeSubmitAuditRequestTest { + @Test + public void testToJson() { + WxMaCodeSubmitAuditRequest request = WxMaCodeSubmitAuditRequest + .builder() + .itemList(Arrays.asList( + WxMaCategory + .builder() + .address("pages/logs/logs") + .tag("工具 效率") + .firstClass("工具") + .firstId(287L) + .secondClass("效率") + .secondId(616L) + .title("日志") + .build() + )).build(); + System.out.println(request.toJson()); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistributionTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistributionTest.java new file mode 100644 index 00000000..da02972e --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionDistributionTest.java @@ -0,0 +1,15 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import org.testng.annotations.Test; + +/** + * @author Charming + * @since 2018-04-26 19:58 + */ +public class WxMaCodeVersionDistributionTest { + @Test + public void testFromJson() { + String json = "{\"errcode\":0,\"errmsg\":\"ok\",\"now_version\":\"1.2.0\",\"uv_info\":{\"items\":[{\"version\":\"0.0.0\",\"percentage\":0},{\"version\":\"1.0.0\",\"percentage\":0},{\"version\":\"1.0.1\",\"percentage\":0},{\"version\":\"1.1.0\",\"percentage\":0},{\"version\":\"1.1.1\",\"percentage\":0},{\"version\":\"1.2.0\",\"percentage\":0},{\"version\":\"1.2.1\",\"percentage\":0},{\"version\":\"1.2.2\",\"percentage\":0},{\"version\":\"1.2.3\",\"percentage\":0},{\"version\":\"1.2.4\",\"percentage\":0},{\"version\":\"1.2.5\",\"percentage\":0},{\"version\":\"1.2.6\",\"percentage\":0},{\"version\":\"1.3.0\",\"percentage\":0},{\"version\":\"1.4.0\",\"percentage\":0},{\"version\":\"1.4.1\",\"percentage\":0},{\"version\":\"1.4.2\",\"percentage\":0},{\"version\":\"1.4.3\",\"percentage\":0},{\"version\":\"1.4.4\",\"percentage\":0},{\"version\":\"1.5.0\",\"percentage\":0},{\"version\":\"1.5.1\",\"percentage\":0},{\"version\":\"1.5.2\",\"percentage\":0},{\"version\":\"1.5.3\",\"percentage\":0},{\"version\":\"1.5.4\",\"percentage\":0},{\"version\":\"1.5.5\",\"percentage\":0},{\"version\":\"1.5.6\",\"percentage\":0},{\"version\":\"1.5.7\",\"percentage\":0},{\"version\":\"1.5.8\",\"percentage\":0},{\"version\":\"1.6.0\",\"percentage\":0.0132},{\"version\":\"1.6.1\",\"percentage\":0.0132},{\"version\":\"1.6.2\",\"percentage\":0.0132},{\"version\":\"1.6.3\",\"percentage\":0.0132},{\"version\":\"1.6.4\",\"percentage\":0.0132},{\"version\":\"1.6.5\",\"percentage\":0.0132},{\"version\":\"1.6.6\",\"percentage\":0.0132},{\"version\":\"1.6.7\",\"percentage\":0.1711},{\"version\":\"1.6.8\",\"percentage\":0.1711},{\"version\":\"1.7.0\",\"percentage\":0.1842},{\"version\":\"1.7.1\",\"percentage\":0.25},{\"version\":\"1.7.2\",\"percentage\":0.5263},{\"version\":\"1.7.3\",\"percentage\":0.5263},{\"version\":\"1.7.4\",\"percentage\":0.6711}]}}\n"; + System.out.println(WxMaCodeVersionDistribution.fromJson(json)); + } +}