From 65c9aa260e4b592fef09115747b0245beae58a47 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:29:59 +0000 Subject: [PATCH 01/10] Initial plan From dccb214cb30798acd3d8d7a1906490e5f418b901 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:35:28 +0000 Subject: [PATCH 02/10] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E6=96=87=E6=A1=A3?= =?UTF-8?q?=EF=BC=9A=E6=B7=BB=E5=8A=A0=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=AE=A1?= =?UTF-8?q?=E6=A0=B8=E9=A2=9D=E5=BA=A6=E7=AE=A1=E7=90=86=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E5=92=8C=E6=9C=80=E4=BD=B3=E5=AE=9E=E8=B7=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- weixin-java-open/README.md | 30 ++ .../weixin/open/api/WxOpenMaService.java | 66 +++- .../message/WxOpenMaSubmitAuditMessage.java | 31 ++ .../bean/result/WxOpenMaQueryQuotaResult.java | 38 ++- .../api/impl/WxOpenMaServiceImplTest.java | 130 ++++++++ ...00\344\275\263\345\256\236\350\267\265.md" | 312 ++++++++++++++++++ 6 files changed, 602 insertions(+), 5 deletions(-) create mode 100644 "weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" diff --git a/weixin-java-open/README.md b/weixin-java-open/README.md index 6ca65dfef3..d43ee1912d 100644 --- a/weixin-java-open/README.md +++ b/weixin-java-open/README.md @@ -31,6 +31,36 @@ --- +## 重要提示:小程序审核额度限制 + +**在使用第三方平台代小程序提交审核时,请注意以下限制:** + +### 审核额度说明 + +- **默认额度**: 每个第三方平台账号每月默认有 **20 个** 审核额度 +- **消耗规则**: 每次调用 `submitAudit()` 提交一个小程序审核,会消耗 **1 个** 审核额度 +- **重置周期**: 额度每月初自动重置 +- **额度查询**: 使用 `queryQuota()` 方法查询剩余额度 + +### 最佳实践 + +```java +// 1. 先查询剩余额度 +WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); +if (quota.getRest() <= 0) { + throw new RuntimeException("审核额度不足,剩余:" + quota.getRest()); +} + +// 2. 提交审核 +WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage(); +message.setItemList(itemList); +WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message); +``` + +**详细说明**: 请参考 [审核额度管理最佳实践.md](审核额度管理最佳实践.md) + +--- + ## 代码示例 消息机制未实现,下面为通知回调中设置的代码部分 diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java index ab229ba537..a9fd79ed46 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java @@ -539,10 +539,36 @@ WxOpenMaDomainResult modifyDomainDirectly(String action, List requestDom /** * 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) + *

+ * 重要提示:审核额度限制 + *

+ * + *

+ * 最佳实践: + *

+ *
{@code
+   * // 1. 先查询剩余额度
+   * WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota();
+   * if (quota.getRest() <= 0) {
+   *   throw new RuntimeException("审核额度不足,剩余:" + quota.getRest());
+   * }
+   *
+   * // 2. 提交审核
+   * WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage();
+   * message.setItemList(itemList);
+   * WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message);
+   * }
* * @param submitAuditMessage the submit audit message * @return the wx open ma submit audit result * @throws WxErrorException the wx error exception + * @see #queryQuota() 查询审核额度 + * @see #speedAudit(Long) 加急审核 */ WxOpenMaSubmitAuditResult submitAudit(WxOpenMaSubmitAuditMessage submitAuditMessage) throws WxErrorException; @@ -691,10 +717,42 @@ WxOpenMaDomainResult modifyDomainDirectly(String action, List requestDom /** * 查询服务商的当月提审限额和加急次数(Quota) - * https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/query_quota.html - * - * @return the wx open ma query quota result - * @throws WxErrorException the wx error exception + *

+ * 文档地址: + * 查询额度 + *

+ *

+ * 返回字段说明: + *

+ * + *

+ * 重要说明: + *

+ * + *

+ * 使用示例: + *

+ *
{@code
+   * WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota();
+   * System.out.println("剩余审核次数:" + quota.getRest());
+   * System.out.println("审核额度上限:" + quota.getLimit());
+   * System.out.println("剩余加急次数:" + quota.getSpeedupRest());
+   * }
+ * + * @return 审核额度信息 + * @throws WxErrorException 调用微信接口失败时抛出 + * @see #submitAudit(WxOpenMaSubmitAuditMessage) 提交审核 + * @see #speedAudit(Long) 加急审核 */ WxOpenMaQueryQuotaResult queryQuota() throws WxErrorException; diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java index d8c1461d67..8497603c07 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java @@ -10,8 +10,39 @@ /** * 微信小程序代码包提交审核(仅供第三方开发者代小程序调用) + *

+ * 重要提示:审核额度限制 + *

+ * + *

+ * 使用示例: + *

+ *
{@code
+ * // 1. 构建审核项
+ * WxMaCodeSubmitAuditItem item = new WxMaCodeSubmitAuditItem();
+ * item.setAddress("index");
+ * item.setTag("游戏");
+ * item.setFirstClass("游戏");
+ * item.setSecondClass("休闲游戏");
+ * item.setTitle("首页");
+ *
+ * // 2. 构建提审消息
+ * WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage();
+ * message.setItemList(Collections.singletonList(item));
+ * message.setVersionDesc("版本描述");
+ *
+ * // 3. 提交审核
+ * WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message);
+ * System.out.println("审核ID: " + result.getAuditId());
+ * }
* * @author yqx + * @see me.chanjar.weixin.open.api.WxOpenMaService#submitAudit(WxOpenMaSubmitAuditMessage) + * @see me.chanjar.weixin.open.api.WxOpenMaService#queryQuota() * created on 2018/9/13 */ @Data diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java index 3b02906242..11df123f91 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java @@ -6,7 +6,31 @@ import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; /** - * 微信开放平台小程序当前分阶段发布详情 + * 微信开放平台小程序提审额度查询结果 + *

+ * 用于查询第三方平台服务商的当月提审限额和加急次数 + *

+ *

+ * 字段说明: + *

+ * + *

+ * 重要提示: + *

+ * + * + * @see me.chanjar.weixin.open.api.WxOpenMaService#queryQuota() + * @see me.chanjar.weixin.open.api.WxOpenMaService#submitAudit(me.chanjar.weixin.open.bean.message.WxOpenMaSubmitAuditMessage) */ @Data @EqualsAndHashCode(callSuper = true) @@ -14,15 +38,27 @@ public class WxOpenMaQueryQuotaResult extends WxOpenResult { private static final long serialVersionUID = 5915265985261653007L; + /** + * 当月剩余提审次数 + */ @SerializedName("rest") private Integer rest; + /** + * 当月提审额度上限 + */ @SerializedName("limit") private Integer limit; + /** + * 剩余加急次数 + */ @SerializedName("speedup_rest") private Integer speedupRest; + /** + * 加急额度上限 + */ @SerializedName("speedup_limit") private Integer speedupLimit; diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java index 4d8e41b59e..6449958497 100644 --- a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java @@ -306,6 +306,136 @@ public void testGetGrayReleasePlan() { @Test public void testQueryQuota() { + // 此测试方法演示如何使用审核额度查询功能 + // 注意:实际运行需要真实的微信 API 凭据 + /* + try { + // 查询当前审核额度 + WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); + + System.out.println("审核额度信息:"); + System.out.println(" 当月剩余提审次数: " + quota.getRest()); + System.out.println(" 当月提审额度上限: " + quota.getLimit()); + System.out.println(" 剩余加急次数: " + quota.getSpeedupRest()); + System.out.println(" 加急额度上限: " + quota.getSpeedupLimit()); + + // 检查额度是否充足 + if (quota.getRest() <= 0) { + System.err.println("警告:审核额度已用尽!"); + } else if (quota.getRest() <= 5) { + System.out.println("提示:审核额度即将用尽,请注意!"); + } + } catch (WxErrorException e) { + e.printStackTrace(); + } + */ + } + + /** + * 演示提交审核前检查额度的最佳实践 + *

+ * 这是一个完整的示例,展示如何在提交审核前检查额度,避免额度不足导致的失败 + *

+ */ + @Test + public void testSubmitAuditWithQuotaCheck() { + // 此测试方法演示提交审核前的额度检查最佳实践 + // 注意:实际运行需要真实的微信 API 凭据 + /* + try { + // 步骤1:检查审核额度 + WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); + System.out.println("当前剩余审核额度: " + quota.getRest()); + + if (quota.getRest() <= 0) { + throw new RuntimeException("审核额度不足,无法提交审核。剩余额度: " + quota.getRest()); + } + + // 步骤2:准备审核数据 + WxMaCodeSubmitAuditItem item = new WxMaCodeSubmitAuditItem(); + item.setAddress("index"); + item.setTag("工具"); + item.setFirstClass("工具"); + item.setSecondClass("效率"); + item.setTitle("首页"); + + WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage(); + message.setItemList(Collections.singletonList(item)); + message.setVersionDesc("修复若干已知问题,优化用户体验"); + + // 步骤3:提交审核 + WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message); + System.out.println("提交审核成功,审核ID: " + result.getAuditId()); + + // 步骤4:再次查询额度,确认已消耗 + quota = wxOpenMaService.queryQuota(); + System.out.println("提交后剩余审核额度: " + quota.getRest()); + + } catch (WxErrorException e) { + System.err.println("提交审核失败: " + e.getMessage()); + e.printStackTrace(); + } + */ + } + + /** + * 演示批量提交审核时的额度管理策略 + *

+ * 当需要为多个小程序提交审核时,应该先统一检查额度是否充足 + *

+ */ + @Test + public void testBatchSubmitAuditWithQuotaManagement() { + // 此测试方法演示批量提交审核时的额度管理策略 + // 注意:实际运行需要真实的微信 API 凭据 + /* + try { + // 假设需要为多个小程序提交审核 + List appIds = Arrays.asList("appid1", "appid2", "appid3"); + + // 步骤1:检查总体额度是否充足 + WxOpenMaQueryQuotaResult quota = wxOpenComponentService.queryQuota(); + System.out.println("当前剩余审核额度: " + quota.getRest()); + + if (quota.getRest() < appIds.size()) { + System.err.println("警告:审核额度不足!"); + System.err.println(" 需要提交: " + appIds.size() + " 个"); + System.err.println(" 剩余额度: " + quota.getRest()); + System.err.println(" 缺少额度: " + (appIds.size() - quota.getRest())); + return; + } + + // 步骤2:依次提交审核 + int successCount = 0; + for (String appId : appIds) { + try { + WxOpenMaService maService = wxOpenComponentService.getWxMaServiceByAppid(appId); + + WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage(); + // ... 设置审核信息 + + WxOpenMaSubmitAuditResult result = maService.submitAudit(message); + System.out.println("AppId: " + appId + " 提交成功,审核ID: " + result.getAuditId()); + successCount++; + + } catch (WxErrorException e) { + System.err.println("AppId: " + appId + " 提交失败: " + e.getMessage()); + } + } + + // 步骤3:输出统计信息 + System.out.println("批量提交完成:"); + System.out.println(" 成功: " + successCount); + System.out.println(" 失败: " + (appIds.size() - successCount)); + + // 步骤4:查询剩余额度 + quota = wxOpenComponentService.queryQuota(); + System.out.println(" 剩余额度: " + quota.getRest()); + + } catch (Exception e) { + e.printStackTrace(); + } + */ } @Test diff --git "a/weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" "b/weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" new file mode 100644 index 0000000000..af51578163 --- /dev/null +++ "b/weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" @@ -0,0 +1,312 @@ +# 微信开放平台小程序审核额度管理最佳实践 + +## 问题背景 + +在使用微信开放平台第三方服务为多个授权小程序提交审核时,需要注意以下重要限制: + +### 审核额度限制 + +- **默认额度**: 每个第三方平台账号每月默认有 **20 个** 审核额度 +- **消耗规则**: 每次调用 `submitAudit()` 提交一个小程序审核,会消耗 **1 个** 审核额度 +- **重置周期**: 额度每月初自动重置 +- **不可返还**: 审核撤回(undoCodeAudit)不会返还已消耗的额度 +- **增加额度**: 如需更多额度,需要联系微信开放平台客服申请 + +### 常见问题 + +**问题**: 开放平台是每个 appId 都要这样提交审核吗?额度不够吧? + +**回答**: 是的,每个授权的小程序(appId)都需要单独调用 `submitAudit()` 提交审核,每次提交会消耗 1 个审核额度。默认的 20 个额度对于管理大量小程序的第三方平台来说可能不够用,建议: +1. 提交审核前先查询剩余额度 +2. 合理规划审核计划,避免重复提审 +3. 联系微信开放平台申请增加额度 + +## API 使用说明 + +### 1. 查询审核额度 + +```java +// 查询当前审核额度 +WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); + +System.out.println("当月剩余提审次数: " + quota.getRest()); // 剩余额度 +System.out.println("当月提审额度上限: " + quota.getLimit()); // 总额度 +System.out.println("剩余加急次数: " + quota.getSpeedupRest()); // 剩余加急次数 +System.out.println("加急额度上限: " + quota.getSpeedupLimit()); // 加急额度上限 +``` + +**返回字段说明**: +- `rest`: 当月剩余提审次数 +- `limit`: 当月提审额度上限(默认 20) +- `speedupRest`: 剩余加急次数 +- `speedupLimit`: 加急额度上限 + +### 2. 提交审核 + +```java +// 构建审核项 +WxMaCodeSubmitAuditItem item = new WxMaCodeSubmitAuditItem(); +item.setAddress("index"); // 页面路径 +item.setTag("工具"); // 标签 +item.setFirstClass("工具"); // 一级类目 +item.setSecondClass("效率"); // 二级类目 +item.setTitle("首页"); // 页面标题 + +// 构建提审消息 +WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage(); +message.setItemList(Collections.singletonList(item)); +message.setVersionDesc("版本描述"); + +// 提交审核 +WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message); +System.out.println("审核ID: " + result.getAuditId()); +``` + +## 最佳实践 + +### 方案一:单个小程序提交前检查额度 + +这是最基本的做法,适用于偶尔提交审核的场景。 + +```java +import me.chanjar.weixin.open.api.WxOpenMaService; +import me.chanjar.weixin.open.bean.message.WxOpenMaSubmitAuditMessage; +import me.chanjar.weixin.open.bean.result.WxOpenMaQueryQuotaResult; +import me.chanjar.weixin.open.bean.result.WxOpenMaSubmitAuditResult; +import me.chanjar.weixin.common.error.WxErrorException; + +public class AuditSubmitter { + + /** + * 提交审核前检查额度 + */ + public WxOpenMaSubmitAuditResult submitWithQuotaCheck( + WxOpenMaService wxOpenMaService, + WxOpenMaSubmitAuditMessage message) throws WxErrorException { + + // 1. 检查审核额度 + WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); + System.out.println("当前剩余审核额度: " + quota.getRest()); + + if (quota.getRest() <= 0) { + throw new RuntimeException("审核额度不足,无法提交审核。剩余额度: " + quota.getRest()); + } + + // 2. 提交审核 + WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message); + System.out.println("提交审核成功,审核ID: " + result.getAuditId()); + + // 3. 再次查询额度(可选) + quota = wxOpenMaService.queryQuota(); + System.out.println("提交后剩余审核额度: " + quota.getRest()); + + return result; + } +} +``` + +### 方案二:批量提交审核的额度管理 + +适用于需要同时为多个小程序提交审核的场景。 + +```java +import me.chanjar.weixin.open.api.WxOpenComponentService; +import me.chanjar.weixin.open.api.WxOpenMaService; +import me.chanjar.weixin.open.bean.message.WxOpenMaSubmitAuditMessage; +import me.chanjar.weixin.open.bean.result.WxOpenMaQueryQuotaResult; +import me.chanjar.weixin.open.bean.result.WxOpenMaSubmitAuditResult; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class BatchAuditSubmitter { + + /** + * 批量提交审核结果 + */ + public static class BatchSubmitResult { + private int successCount; // 成功数量 + private int failCount; // 失败数量 + private int skipCount; // 跳过数量(额度不足) + private List failedAppIds; // 失败的 appId + + // getters and setters... + } + + /** + * 批量提交审核,带额度检查 + */ + public BatchSubmitResult batchSubmitWithQuotaCheck( + WxOpenComponentService wxOpenComponentService, + Map appIdToMessageMap) { + + BatchSubmitResult result = new BatchSubmitResult(); + result.setFailedAppIds(new ArrayList<>()); + + try { + // 1. 检查总体额度是否充足 + WxOpenMaQueryQuotaResult quota = wxOpenComponentService + .getWxMaServiceByAppid(appIdToMessageMap.keySet().iterator().next()) + .queryQuota(); + + System.out.println("=== 批量提交审核开始 ==="); + System.out.println("待提交数量: " + appIdToMessageMap.size()); + System.out.println("当前剩余审核额度: " + quota.getRest()); + + if (quota.getRest() < appIdToMessageMap.size()) { + System.err.println("警告:审核额度不足!"); + System.err.println(" 需要提交: " + appIdToMessageMap.size() + " 个"); + System.err.println(" 剩余额度: " + quota.getRest()); + System.err.println(" 缺少额度: " + (appIdToMessageMap.size() - quota.getRest())); + System.err.println("将仅提交前 " + quota.getRest() + " 个小程序"); + } + + // 2. 依次提交审核 + int count = 0; + for (Map.Entry entry : appIdToMessageMap.entrySet()) { + String appId = entry.getKey(); + WxOpenMaSubmitAuditMessage message = entry.getValue(); + + // 检查是否还有额度 + if (count >= quota.getRest()) { + System.out.println("AppId: " + appId + " 跳过(额度不足)"); + result.setSkipCount(result.getSkipCount() + 1); + continue; + } + + try { + WxOpenMaService maService = wxOpenComponentService.getWxMaServiceByAppid(appId); + WxOpenMaSubmitAuditResult submitResult = maService.submitAudit(message); + + System.out.println("AppId: " + appId + " 提交成功,审核ID: " + submitResult.getAuditId()); + result.setSuccessCount(result.getSuccessCount() + 1); + count++; + + } catch (WxErrorException e) { + System.err.println("AppId: " + appId + " 提交失败: " + e.getMessage()); + result.setFailCount(result.getFailCount() + 1); + result.getFailedAppIds().add(appId); + } + } + + // 3. 输出统计信息 + System.out.println("=== 批量提交审核完成 ==="); + System.out.println("成功: " + result.getSuccessCount()); + System.out.println("失败: " + result.getFailCount()); + System.out.println("跳过: " + result.getSkipCount()); + + // 4. 查询剩余额度 + quota = wxOpenComponentService + .getWxMaServiceByAppid(appIdToMessageMap.keySet().iterator().next()) + .queryQuota(); + System.out.println("剩余额度: " + quota.getRest()); + + } catch (WxErrorException e) { + System.err.println("批量提交审核失败: " + e.getMessage()); + e.printStackTrace(); + } + + return result; + } +} +``` + +### 方案三:审核额度监控和告警 + +建议实现一个审核额度监控机制,及时发现额度不足的情况。 + +```java +import me.chanjar.weixin.open.api.WxOpenMaService; +import me.chanjar.weixin.open.bean.result.WxOpenMaQueryQuotaResult; +import me.chanjar.weixin.common.error.WxErrorException; + +public class QuotaMonitor { + + /** + * 检查审核额度并发出告警 + */ + public void checkAndAlert(WxOpenMaService wxOpenMaService) { + try { + WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); + + int rest = quota.getRest(); + int limit = quota.getLimit(); + double percentage = (double) rest / limit * 100; + + System.out.println("审核额度状态:"); + System.out.println(" 剩余: " + rest + " / " + limit); + System.out.println(" 使用率: " + String.format("%.1f", 100 - percentage) + "%"); + + // 根据剩余额度发出不同级别的告警 + if (rest <= 0) { + sendCriticalAlert("审核额度已用尽!无法提交新的审核。"); + } else if (rest <= 3) { + sendWarningAlert("审核额度严重不足!剩余额度: " + rest); + } else if (percentage < 30) { + sendInfoAlert("审核额度偏低,剩余: " + rest + " (" + String.format("%.1f", percentage) + "%)"); + } + + } catch (WxErrorException e) { + System.err.println("查询审核额度失败: " + e.getMessage()); + } + } + + private void sendCriticalAlert(String message) { + // 发送紧急告警(如:发送邮件、短信、钉钉消息等) + System.err.println("[严重] " + message); + } + + private void sendWarningAlert(String message) { + // 发送警告(如:发送邮件、企业微信消息等) + System.out.println("[警告] " + message); + } + + private void sendInfoAlert(String message) { + // 发送普通提示 + System.out.println("[提示] " + message); + } +} +``` + +## 常见问题 FAQ + +### Q1: 审核额度什么时候重置? +A: 审核额度在每月初自动重置为默认值(通常是 20 个)。 + +### Q2: 审核撤回会返还额度吗? +A: 不会。调用 `undoCodeAudit()` 撤回审核不会返还已消耗的额度。 + +### Q3: 如何增加审核额度? +A: 需要联系微信开放平台客服申请增加额度。具体联系方式请参考微信开放平台官方文档。 + +### Q4: 审核失败会消耗额度吗? +A: 会。只要调用了 `submitAudit()` 接口提交审核,无论审核是否通过,都会消耗 1 个额度。 + +### Q5: 加急审核会额外消耗额度吗? +A: 加急审核(`speedAudit()`)使用的是单独的加急额度(`speedupRest`),不会消耗普通审核额度。但加急审核的前提是已经提交了审核,所以提交审核时仍会消耗 1 个普通审核额度。 + +### Q6: 多个小程序共享审核额度吗? +A: 是的。同一个第三方平台账号下,所有授权的小程序共享审核额度。每提交一个小程序审核,都会消耗该第三方平台的 1 个审核额度。 + +### Q7: 如何避免审核额度不足? +A: 建议采取以下措施: +- 在批量提交审核前,先调用 `queryQuota()` 检查剩余额度 +- 实现审核额度监控和告警机制 +- 合理规划审核计划,避免不必要的重复提审 +- 提高代码质量,减少审核不通过的情况 +- 联系微信开放平台申请增加额度 + +### Q8: 能否查询历史审核额度使用情况? +A: 微信开放平台 API 目前只提供当前剩余额度查询,不提供历史使用记录。如需统计历史使用情况,需要自行记录每次调用 `submitAudit()` 的时间和次数。 + +## 相关文档 + +- [微信开放平台官方文档 - 查询额度](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/query_quota.html) +- [微信开放平台官方文档 - 提交审核](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/submit_audit.html) +- [微信开放平台官方文档 - 加急审核](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/speedup_audit.html) + +## 技术支持 + +如有问题,请提交 Issue 到 [WxJava GitHub 仓库](https://github.com/binarywang/WxJava/issues)。 From 6a76a798ee798df7caa65a2061f98a7038aa1f1e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:40:05 +0000 Subject: [PATCH 03/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=B3=A8=E9=87=8A=E4=B8=AD=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=A4=BA=E4=BE=8B=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E6=9D=A5=E6=BA=90=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- .../open/api/impl/WxOpenMaServiceImplTest.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java index 6449958497..0fb837a630 100644 --- a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java @@ -387,14 +387,19 @@ public void testSubmitAuditWithQuotaCheck() { @Test public void testBatchSubmitAuditWithQuotaManagement() { // 此测试方法演示批量提交审核时的额度管理策略 - // 注意:实际运行需要真实的微信 API 凭据 + // 注意:实际运行需要真实的微信 API 凭据,以及 WxOpenComponentService 实例 /* + // 假设已经初始化了 wxOpenComponentService + // WxOpenComponentService wxOpenComponentService = ...; + try { // 假设需要为多个小程序提交审核 List appIds = Arrays.asList("appid1", "appid2", "appid3"); - // 步骤1:检查总体额度是否充足 - WxOpenMaQueryQuotaResult quota = wxOpenComponentService.queryQuota(); + // 步骤1:通过任意一个小程序服务查询总体额度 + // 注意:审核额度是第三方平台级别的,所有授权小程序共享 + WxOpenMaService firstMaService = wxOpenComponentService.getWxMaServiceByAppid(appIds.get(0)); + WxOpenMaQueryQuotaResult quota = firstMaService.queryQuota(); System.out.println("当前剩余审核额度: " + quota.getRest()); if (quota.getRest() < appIds.size()) { @@ -429,7 +434,7 @@ public void testBatchSubmitAuditWithQuotaManagement() { System.out.println(" 失败: " + (appIds.size() - successCount)); // 步骤4:查询剩余额度 - quota = wxOpenComponentService.queryQuota(); + quota = firstMaService.queryQuota(); System.out.println(" 剩余额度: " + quota.getRest()); } catch (Exception e) { From 5b41f4960615ea8405a7fa75a55942442ec8a84a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:41:32 +0000 Subject: [PATCH 04/10] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E6=96=87=E4=BB=B6=E4=B8=BA=E8=8B=B1=E6=96=87=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E4=BB=A5=E6=8F=90=E9=AB=98=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- .../AUDIT_QUOTA_MANAGEMENT_GUIDE.md | 0 weixin-java-open/README.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename "weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" => weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md (100%) diff --git "a/weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md similarity index 100% rename from "weixin-java-open/\345\256\241\346\240\270\351\242\235\345\272\246\347\256\241\347\220\206\346\234\200\344\275\263\345\256\236\350\267\265.md" rename to weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md diff --git a/weixin-java-open/README.md b/weixin-java-open/README.md index d43ee1912d..ad7f3d0109 100644 --- a/weixin-java-open/README.md +++ b/weixin-java-open/README.md @@ -57,7 +57,7 @@ message.setItemList(itemList); WxOpenMaSubmitAuditResult result = wxOpenMaService.submitAudit(message); ``` -**详细说明**: 请参考 [审核额度管理最佳实践.md](审核额度管理最佳实践.md) +**详细说明**: 请参考 [AUDIT_QUOTA_MANAGEMENT_GUIDE.md](AUDIT_QUOTA_MANAGEMENT_GUIDE.md) --- From b70a4637b3fd33b8830e0c2f60a45af2785a179f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:44:13 +0000 Subject: [PATCH 05/10] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E6=9C=AF=E8=AF=AD?= =?UTF-8?q?=EF=BC=9A=E5=B0=86"=E6=8F=90=E5=AE=A1"=E6=94=B9=E4=B8=BA"?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=AE=A1=E6=A0=B8"=E4=BB=A5=E6=8F=90?= =?UTF-8?q?=E9=AB=98=E6=96=87=E6=A1=A3=E4=B8=80=E8=87=B4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md | 8 ++++---- .../me/chanjar/weixin/open/api/WxOpenMaService.java | 6 +++--- .../open/bean/result/WxOpenMaQueryQuotaResult.java | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md index af51578163..5f7c756888 100644 --- a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md +++ b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md @@ -29,15 +29,15 @@ // 查询当前审核额度 WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); -System.out.println("当月剩余提审次数: " + quota.getRest()); // 剩余额度 -System.out.println("当月提审额度上限: " + quota.getLimit()); // 总额度 +System.out.println("当月剩余提交审核次数: " + quota.getRest()); // 剩余额度 +System.out.println("当月提交审核额度上限: " + quota.getLimit()); // 总额度 System.out.println("剩余加急次数: " + quota.getSpeedupRest()); // 剩余加急次数 System.out.println("加急额度上限: " + quota.getSpeedupLimit()); // 加急额度上限 ``` **返回字段说明**: -- `rest`: 当月剩余提审次数 -- `limit`: 当月提审额度上限(默认 20) +- `rest`: 当月剩余提交审核次数 +- `limit`: 当月提交审核额度上限(默认 20) - `speedupRest`: 剩余加急次数 - `speedupLimit`: 加急额度上限 diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java index a9fd79ed46..1033b57a16 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java @@ -716,7 +716,7 @@ WxOpenMaDomainResult modifyDomainDirectly(String action, List requestDom WxOpenMaGetCodePrivacyInfoResult getCodePrivacyInfo() throws WxErrorException; /** - * 查询服务商的当月提审限额和加急次数(Quota) + * 查询服务商的当月提交审核限额和加急次数(Quota) *

* 文档地址: * 查询额度 @@ -725,8 +725,8 @@ WxOpenMaDomainResult modifyDomainDirectly(String action, List requestDom * 返回字段说明: *

*
    - *
  • rest: 当月剩余提审次数
  • - *
  • limit: 当月提审额度上限(默认20次)
  • + *
  • rest: 当月剩余提交审核次数
  • + *
  • limit: 当月提交审核额度上限(默认20次)
  • *
  • speedup_rest: 剩余加急次数
  • *
  • speedup_limit: 加急额度上限
  • *
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java index 11df123f91..0f964b5f44 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenMaQueryQuotaResult.java @@ -6,16 +6,16 @@ import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; /** - * 微信开放平台小程序提审额度查询结果 + * 微信开放平台小程序提交审核额度查询结果 *

- * 用于查询第三方平台服务商的当月提审限额和加急次数 + * 用于查询第三方平台服务商的当月提交审核限额和加急次数 *

*

* 字段说明: *

*
    - *
  • rest: 当月剩余提审次数
  • - *
  • limit: 当月提审额度上限(默认20次,可联系微信开放平台增加)
  • + *
  • rest: 当月剩余提交审核次数
  • + *
  • limit: 当月提交审核额度上限(默认20次,可联系微信开放平台增加)
  • *
  • speedupRest: 剩余加急次数
  • *
  • speedupLimit: 加急额度上限
  • *
@@ -39,13 +39,13 @@ public class WxOpenMaQueryQuotaResult extends WxOpenResult { private static final long serialVersionUID = 5915265985261653007L; /** - * 当月剩余提审次数 + * 当月剩余提交审核次数 */ @SerializedName("rest") private Integer rest; /** - * 当月提审额度上限 + * 当月提交审核额度上限 */ @SerializedName("limit") private Integer limit; From f08b30e022226b9d1c8de6d102418ff8502a4f82 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sun, 21 Dec 2025 21:47:16 +0800 Subject: [PATCH 06/10] Update weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java index 0fb837a630..1de6ffe2d6 100644 --- a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImplTest.java @@ -314,8 +314,8 @@ public void testQueryQuota() { WxOpenMaQueryQuotaResult quota = wxOpenMaService.queryQuota(); System.out.println("审核额度信息:"); - System.out.println(" 当月剩余提审次数: " + quota.getRest()); - System.out.println(" 当月提审额度上限: " + quota.getLimit()); + System.out.println(" 当月剩余提交审核次数: " + quota.getRest()); + System.out.println(" 当月提交审核额度上限: " + quota.getLimit()); System.out.println(" 剩余加急次数: " + quota.getSpeedupRest()); System.out.println(" 加急额度上限: " + quota.getSpeedupLimit()); From 00040b63f46553c536c3b817ad8f8e43e8eba288 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sun, 21 Dec 2025 21:47:43 +0800 Subject: [PATCH 07/10] Update weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md index 5f7c756888..5f71540c7d 100644 --- a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md +++ b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md @@ -188,6 +188,7 @@ public class BatchAuditSubmitter { System.err.println("AppId: " + appId + " 提交失败: " + e.getMessage()); result.setFailCount(result.getFailCount() + 1); result.getFailedAppIds().add(appId); + count++; } } From 037a1b738b910e2ab17ba147b56252b79d799b7a Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sun, 21 Dec 2025 21:48:00 +0800 Subject: [PATCH 08/10] Update weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md index 5f71540c7d..5433fd54f4 100644 --- a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md +++ b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md @@ -145,8 +145,16 @@ public class BatchAuditSubmitter { BatchSubmitResult result = new BatchSubmitResult(); result.setFailedAppIds(new ArrayList<>()); + // 基本参数校验:避免空指针和空集合导致的 NoSuchElementException + if (appIdToMessageMap == null || appIdToMessageMap.isEmpty()) { + System.err.println("错误:待提交的小程序列表为空,未执行任何审核提交"); + return result; + } + try { // 1. 检查总体额度是否充足 + // 使用任意一个已授权的小程序 appId 获取 WxMaService 来查询审核额度。 + // 注意:审核额度是以第三方平台维度统计的,因此这里选择任意一个 appId 即可。 WxOpenMaQueryQuotaResult quota = wxOpenComponentService .getWxMaServiceByAppid(appIdToMessageMap.keySet().iterator().next()) .queryQuota(); From 9466e24564130d42e67dbe63583d6522f88c0361 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sun, 21 Dec 2025 21:48:11 +0800 Subject: [PATCH 09/10] Update weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java index 8497603c07..79400aa968 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java @@ -30,7 +30,7 @@ * item.setSecondClass("休闲游戏"); * item.setTitle("首页"); * - * // 2. 构建提审消息 + * // 2. 构建提交审核消息 * WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage(); * message.setItemList(Collections.singletonList(item)); * message.setVersionDesc("版本描述"); From 9ed04c7bcac9802bf2cd5d72a073fba0f481a229 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 13:52:17 +0000 Subject: [PATCH 10/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E4=B8=AD=E6=AE=8B=E7=95=99=E7=9A=84"=E6=8F=90=E5=AE=A1"?= =?UTF-8?q?=E6=9C=AF=E8=AF=AD=EF=BC=8C=E7=BB=9F=E4=B8=80=E4=B8=BA"?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=AE=A1=E6=A0=B8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md index 5433fd54f4..d84932034a 100644 --- a/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md +++ b/weixin-java-open/AUDIT_QUOTA_MANAGEMENT_GUIDE.md @@ -18,7 +18,7 @@ **回答**: 是的,每个授权的小程序(appId)都需要单独调用 `submitAudit()` 提交审核,每次提交会消耗 1 个审核额度。默认的 20 个额度对于管理大量小程序的第三方平台来说可能不够用,建议: 1. 提交审核前先查询剩余额度 -2. 合理规划审核计划,避免重复提审 +2. 合理规划审核计划,避免重复提交审核 3. 联系微信开放平台申请增加额度 ## API 使用说明 @@ -52,7 +52,7 @@ item.setFirstClass("工具"); // 一级类目 item.setSecondClass("效率"); // 二级类目 item.setTitle("首页"); // 页面标题 -// 构建提审消息 +// 构建提交审核消息 WxOpenMaSubmitAuditMessage message = new WxOpenMaSubmitAuditMessage(); message.setItemList(Collections.singletonList(item)); message.setVersionDesc("版本描述"); @@ -303,7 +303,7 @@ A: 是的。同一个第三方平台账号下,所有授权的小程序共享 A: 建议采取以下措施: - 在批量提交审核前,先调用 `queryQuota()` 检查剩余额度 - 实现审核额度监控和告警机制 -- 合理规划审核计划,避免不必要的重复提审 +- 合理规划审核计划,避免不必要的重复提交审核 - 提高代码质量,减少审核不通过的情况 - 联系微信开放平台申请增加额度