{"owner":"binarywang","repo":"WxJava","hasSkills":true,"totalSkillsCount":30,"totalTokensCount":22335,"categories":["copilot-instructions","root-instruction","anthropic-skill","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":[".github/copilot-instructions.md","AGENTS.md","skills/wxjava-api-contributor/SKILL.md","skills/wxjava-api-contributor/agents/openai.yaml","skills/wxjava-api-contributor/references/contribution.md","skills/wxjava-integration-guide/SKILL.md","skills/wxjava-integration-guide/agents/openai.yaml","skills/wxjava-integration-guide/references/integration.md","skills/wxjava-module-selector/SKILL.md","skills/wxjava-module-selector/agents/openai.yaml","skills/wxjava-module-selector/references/modules.md","skills/wxjava-troubleshooter/SKILL.md","skills/wxjava-troubleshooter/agents/openai.yaml","skills/wxjava-troubleshooter/references/diagnostics.md","skills/wxjava-upgrade-guide/SKILL.md","skills/wxjava-upgrade-guide/agents/openai.yaml","skills/wxjava-upgrade-guide/references/migration.md","solon-plugins/wx-java-channel-multi-solon-plugin/README.md","solon-plugins/wx-java-channel-solon-plugin/README.md","solon-plugins/wx-java-cp-multi-solon-plugin/README.md","solon-plugins/wx-java-cp-solon-plugin/README.md","solon-plugins/wx-java-miniapp-multi-solon-plugin/README.md","solon-plugins/wx-java-miniapp-solon-plugin/README.md","solon-plugins/wx-java-mp-multi-solon-plugin/README.md","solon-plugins/wx-java-mp-solon-plugin/README.md","solon-plugins/wx-java-open-solon-plugin/README.md","solon-plugins/wx-java-pay-solon-plugin/README.md","solon-plugins/wx-java-qidian-solon-plugin/README.md","solon-plugins/wx-java-store-multi-solon-plugin/README.md","solon-plugins/wx-java-store-solon-plugin/README.md"],"skills":{".github/copilot-instructions.md":"# Copilot Instruction\n请始终使用中文生成 Pull Request 的标题、描述和提交信息\n\n\n# WxJava - 微信 Java SDK 开发说明\n\nWxJava 是一个支持多种微信平台的完整 Java SDK，包含公众号、小程序、微信支付、企业微信、开放平台、视频号、企点等多种功能模块。\n\n**请始终优先参考本说明，只有在遇到与此内容不一致的意外信息时，才退而使用搜索或 bash 命令。**\n\n## 高效开发指南\n\n### 前置条件与环境准备\n- **Java 要求**：JDK 8+（项目最低目标为 Java 8）\n- **Maven**：推荐 Maven 3.6+（已验证 Maven 3.9.11）\n- **IDE**：推荐使用 IntelliJ IDEA（项目针对 IDEA 优化）\n\n### 引导、构建与校验\n克隆仓库后按顺序执行以下命令：\n\n```bash\n# 1. 基础编译（请勿中断 - 约需 4-5 分钟）\nmvn clean compile -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 8 分钟以上。实际时间：约 4 分钟\n\n# 2. 完整打包（请勿中断 - 约需 2-3 分钟）  \nmvn clean package -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 5 分钟以上。实际时间：约 2 分钟\n\n# 3. 代码质量校验（请勿中断 - 约需 45-60 秒）\nmvn checkstyle:check --no-transfer-progress\n# 超时时间：建议设置 3 分钟以上。实际时间：约 50 秒\n```\n\n重要时间说明：\n- 绝对不要中断任意 Maven 构建命令\n- 编译阶段耗时最长（约 4 分钟），原因是项目包含 34 个模块\n- 后续构建会更快，因为存在增量编译\n- 始终使用 `--no-transfer-progress` 以减少日志噪音\n\n### 测试结构\n- **测试框架**：TestNG（非 JUnit）\n- **测试文件**：共有 298 个测试文件\n- **默认行为**：pom.xml 中默认禁用测试（`<skip>true</skip>`）\n- **测试配置**：测试需要通过 test-config.xml 提供真实的微信 API 凭据\n- **注意**：没有真实微信 API 凭据请不要尝试运行测试，测试将会失败\n\n## 项目结构与导航\n\n### 核心 SDK 模块（主要开发区）\n- `weixin-java-common/` - 通用工具与基础类（最重要）\n- `weixin-java-mp/` - 公众号 SDK\n- `weixin-java-pay/` - 微信支付 SDK\n- `weixin-java-miniapp/` - 小程序 SDK\n- `weixin-java-cp/` - 企业微信 SDK\n- `weixin-java-open/` - 开放平台 SDK\n- `weixin-java-channel/` - 视频号 / Channel SDK\n- `weixin-java-qidian/` - 企点 SDK\n\n### 框架集成模块\n- `spring-boot-starters/` - Spring Boot 自动配置 starter\n- `solon-plugins/` - Solon 框架插件\n- `weixin-graal/` - GraalVM 本地镜像支持\n\n### 配置与质量控制\n- `quality-checks/google_checks.xml` - Checkstyle 配置\n- `.editorconfig` - 代码格式规则（2 个空格等于 1 个制表）\n- `pom.xml` - 根级 Maven 配置\n\n## 开发工作流\n\n### 修改代码的流程\n1. 修改前务必先构建以建立干净基线：\n   ```bash\n   mvn clean compile --no-transfer-progress\n   ```\n\n2. 遵循代码风格（由 checkstyle 强制）：\n   - 缩进使用 2 个空格（不要用制表符）\n   - 遵循 Google Java 风格指南\n   - 在 IDE 中安装 EditorConfig 插件\n\n3. 增量验证修改：\n   ```bash\n   # 每次修改后运行：\n   mvn compile --no-transfer-progress\n   mvn checkstyle:check --no-transfer-progress\n   ```\n\n### 提交修改前的必须校验\n请务必按顺序完成以下校验步骤：\n\n1. 代码风格校验：\n   ```bash\n   mvn checkstyle:check --no-transfer-progress\n   # 必须通过 - 约需 50 秒\n   ```\n\n2. 完整清理构建：\n   ```bash\n   mvn clean package -DskipTests=true --no-transfer-progress  \n   # 必须成功 - 约需 2 分钟\n   ```\n\n3. 文档：为公共方法和类补充或更新 javadoc\n4. 贡献规范：遵循 `CONTRIBUTING.md`，Pull Request 必须以 `develop` 分支为目标\n\n## 模块依赖与构建顺序\n\n### 核心模块依赖（构建顺序）\n1. `weixin-graal`（GraalVM 支持）\n2. `weixin-java-common`（所有模块的基础）\n3. 核心 SDK 模块（mp、pay、miniapp、cp、open、channel、qidian）\n4. 框架集成（spring-boot-starters、solon-plugins）\n\n### 主要关系模式\n- 所有 SDK 模块都依赖于 `weixin-java-common`\n- Spring Boot starters 依赖对应的 SDK 模块\n- Solon 插件遵循与 Spring Boot starters 相同的依赖模式\n- 每个模块都有单账号与多账号配置支持\n\n## 常见任务与命令\n\n### 验证指定模块\n```bash\n# 构建单个模块（将 'weixin-java-mp' 替换为目标模块）：\ncd weixin-java-mp\nmvn clean compile --no-transfer-progress\n```\n\n### 检查依赖\n```bash\n# 分析依赖树：\nmvn dependency:tree --no-transfer-progress\n\n# 检查依赖更新：  \n./others/check-dependency-updates.sh\n```\n\n### 发布与发布准备\n```bash\n# 版本检查：\nmvn versions:display-property-updates --no-transfer-progress\n\n# 部署（需要凭据）：\nmvn clean deploy -P release --no-transfer-progress\n```\n\n## 重要文件与位置\n\n### 配置文件\n- `pom.xml` - 根级 Maven 配置与依赖管理\n- `quality-checks/google_checks.xml` - Checkstyle 规则\n- `.editorconfig` - IDE 格式化配置\n- `.github/workflows/maven-publish.yml` - CI/CD 工作流\n\n### 文档\n- `README.md` - 项目概览与使用说明（中文）\n- `CONTRIBUTING.md` - 贡献指南\n- `demo.md` - 示例项目与演示链接\n- 每个模块均有单独的文档与示例\n\n### 测试资源\n- `*/src/test/resources/test-config.sample.xml` - 测试配置模板\n- 测试运行需要真实的微信 API 凭据\n\n## SDK 使用模式\n\n### Maven 依赖示例\n```xml\n<dependency>\n  <groupId>com.github.binarywang</groupId>\n  <artifactId>weixin-java-mp</artifactId>  <!-- 或其他模块 -->\n  <version>4.7.0</version>\n</dependency>\n```\n\n### 常见开发区域\n- **API 客户端实现**：位于 `*/service/impl/` 目录\n- **模型类**：位于 `*/bean/` 目录\n- **配置**：位于 `*/config/` 目录\n- **工具类**：位于 `weixin-java-common` 的 `*/util/` 目录\n\n## 故障排查\n\n### 构建问题\n- **OutOfMemoryError**：增加 Maven 内存：`export MAVEN_OPTS=\"-Xmx2g\"`\n- **编译失败**：通常为依赖问题 - 先执行 `mvn clean`\n- **Checkstyle 失败**：检查 IDE 的 `.editorconfig` 设置\n\n### 常见陷阱\n- **测试默认跳过**：这是正常现象 — 测试需要微信 API 凭据\n- **多模块变更**：总是在仓库根目录构建，而不是单独模块\n- **分支目标**：Pull Request 必须以 `develop` 分支为目标，而不是 `master` 或 `release`\n\n## 性能说明\n- **首次构建**：由于依赖下载，耗时 4-5 分钟\n- **增量构建**：通常更快（约 30-60 秒）\n- **Checkstyle**：运行迅速（约 50 秒），应当经常运行\n- **IDE 性能**：项目使用 Lombok，请确保启用注解处理\n\n注意：本项目为 SDK 库项目，而非可运行应用。修改应以 API 功能为主，不要改动应用级行为。\n","AGENTS.md":"# WxJava Agent 指南\n\n## 适用范围与指令优先级\n\n- 本文件适用于整个仓库，供本地编码 Agent、自动化 Agent 和 Pull Request Review Agent 使用。\n- 开始工作前先阅读与任务直接相关的 `README.md`、`CONTRIBUTING.md`、模块 `pom.xml`、现有实现和测试；不要仅凭通用经验推断项目约定。\n- 若子目录存在更具体的 `AGENTS.md`，处理该目录文件时优先遵循距离目标文件最近的说明。\n- 用户的明确要求优先于本文件；若要求与兼容性、安全性或仓库约定冲突，应先说明风险，不要静默偏离。\n- 只修改完成任务所必需的文件，不处理无关格式、重构或历史遗留问题。\n\n## 项目概览\n\n- WxJava 是面向微信生态的 Java SDK，采用 Maven 多模块结构。\n- 当前根项目要求 Java 8（`maven.compiler.source` 和 `maven.compiler.target` 均为 `1.8`）。除非任务明确要求升级，否则新增代码、依赖和 API 必须保持 Java 8 兼容。\n- 主要 SDK 模块包括：\n  - `weixin-java-common`：各模块共用的基础类型、工具、异常、HTTP 与配置能力。\n  - `weixin-java-mp`：微信公众号。\n  - `weixin-java-miniapp`：微信小程序。\n  - `weixin-java-pay`：微信支付。\n  - `weixin-java-cp`：企业微信。\n  - `weixin-java-open`：微信开放平台。\n  - `weixin-java-channel`：微信视频号、微信小店。\n  - `weixin-java-qidian`：微信客服相关能力。\n  - `weixin-java-aispeech`：微信智能语音。\n  - `weixin-graal`：GraalVM 相关支持。\n- 集成模块主要位于：\n  - `spring-boot-starters`：Spring Boot Starter 及多账号 Starter。\n  - `solon-plugins`：Solon 插件及多账号插件。\n  - `wx-java-bom`：统一管理对外模块版本的 BOM。\n- `README.md` 说明整体能力和使用方式，`CONTRIBUTING.md` 规定代码贡献要求，`docs` 保存补充文档。\n\n## 开发流程\n\n1. 确认任务涉及的微信产品和 Maven 模块，先查找同模块中的相似接口、Bean、实现类和测试。\n2. 阅读目标模块及其父级 `pom.xml`，确认依赖、测试框架和已有实现方式。\n3. 优先沿用现有的包结构、命名、序列化、HTTP 执行器、异常处理及配置模式。\n4. 以最小变更完成任务；不要在功能修改中夹带依赖升级、全局格式化或无关重构。\n5. 为修复或新增行为添加有针对性的测试，并先运行受影响模块的验证。\n6. 交付前检查 diff、测试结果、兼容性和文档影响，明确报告未执行或无法执行的验证。\n\n## 代码风格与兼容性\n\n- 遵循 `.editorconfig`：使用空格缩进、缩进宽度为 2、UTF-8、LF、文件末尾保留换行，并清除非 Markdown 文件的行尾空格。\n- 保持目标文件现有代码风格；避免仅为个人偏好调整 import、换行、注释或成员顺序。\n- 不使用 Java 9 及以上语言特性或仅在新版本 JDK 中存在的 API。\n- 项目使用 Lombok；新增或修改 Lombok 用法时遵循相邻代码模式，不要在同一变更中无理由改写为手工样板代码。\n- 公共 API、序列化字段、枚举值、常量、默认实现和依赖范围都可能影响下游用户，修改时优先保持源码、二进制和行为兼容。\n- 不要随意改变已有异常类型、空值语义、默认 HTTP 客户端、JSON/XML 映射或配置加载行为。\n- 新增依赖前先确认现有依赖能否满足需求；依赖版本应在合适的父 POM 或 BOM 中统一管理，避免模块间版本漂移。\n\n## API 与实现约定\n\n- 对接微信接口时，以对应产品的官方接口定义和仓库内现有同类实现为依据，核对请求路径、HTTP 方法、字段名、必填项和返回结构。\n- Java 字段名可以符合项目命名习惯，但传输层字段名必须与微信接口保持一致；需要时使用项目现有的 Gson、Jackson 或 XStream 映射方式。\n- 新增 Service API 时同步检查接口、实现类、请求/响应 Bean、URL 常量、序列化适配器和测试是否都需要更新。\n- 涉及多个 HTTP 客户端实现时，保持 Apache HttpClient、HttpComponents、OkHttp 和 Jodd 等现有实现的能力一致；不要只修复其中一种而遗漏其他可选实现。\n- 涉及 Starter 或插件时，检查单账号与多账号版本以及自动配置、配置属性和示例测试是否需要同步。\n- 公共方法需要清晰的 Javadoc，至少准确描述参数、返回值、异常和必要约束；不要编写与实现不一致的模板化注释。\n- 不吞掉异常，不使用空 `catch`，不在日志中泄露 token、secret、密钥、签名原文或用户敏感数据。\n\n## 测试与验证\n\n- 项目测试主要使用 TestNG；沿用目标模块已有测试基类、数据提供器、Mock 方式和资源布局。\n- 修复 bug 时应添加能够复现旧行为并验证修复结果的回归测试；新增公共方法必须配套单元测试。\n- 优先执行受影响模块及其依赖的测试：\n\n```shell\nmvn -pl <module> -am test\n```\n\n- 运行单个测试类时，可在对应模块范围内执行：\n\n```shell\nmvn -pl <module> -am -Dtest=<TestClass> -Dsurefire.failIfNoSpecifiedTests=false test\n```\n\n- 跨公共模块、父 POM、BOM 或多个产品模块的变更应扩大验证范围；条件允许时执行：\n\n```shell\nmvn test\n```\n\n- 对仅需确认编译且测试依赖外部凭据的场景，可执行模块级编译或打包，但不得把跳过测试的构建描述为“测试通过”。\n- 部分测试可能依赖微信凭据、网络或本地配置。不得提交真实凭据；无法运行时应说明原因以及已完成的替代验证。\n- 完成前至少运行 `git diff --check`，并人工检查 `git diff`，确认没有意外文件、调试代码、生成物或敏感信息。\n\n## 文档与依赖变更\n\n- 用户可见的 API、配置项、模块使用方式或兼容性发生变化时，同步更新相关 Javadoc、README 或 `docs` 文档。\n- 示例中的版本号、模块名和配置键应与当前项目保持一致；不要复制未经验证的外部示例。\n- 修改根 POM、父 POM 或 `wx-java-bom` 时，检查所有子模块和对外依赖管理的影响。\n- 不提交构建输出、IDE 临时文件、测试报告、真实配置文件或本地备份文件。\n\n## Git 与 Pull Request 规范\n\n- 贡献目标分支为 `develop`；`release` 用于正式版本发布，不应作为常规 Pull Request 的目标分支。\n- 提交前保持工作区变更聚焦，不覆盖或回退用户已有的无关修改。\n- Commit 和 Pull Request 应说明变更动机、影响模块、兼容性风险和验证方式；关联已有 Issue 时写明编号。\n- 不得在未经用户明确授权的情况下执行 `git push`、创建或合并 Pull Request、改写历史或执行破坏性 Git 操作。\n- 不要使用 `git reset --hard`、强制 checkout 等方式清理不属于当前任务的改动。\n\n## 安全与敏感数据\n\n- 禁止提交 AppID 对应的 secret、access token、API v3 密钥、商户私钥、证书私钥、用户数据或其他真实凭据。\n- 测试和文档使用明显的占位值或脱敏数据；日志应避免输出查询串、请求体或响应体中的敏感字段。\n- 涉及签名、验签、加解密、证书、回调通知和支付金额时，重点检查字符编码、字段排序、精度、时区、重放风险和资源关闭。\n- 涉及网络请求、文件或流时，检查超时、异常路径、资源释放、响应关闭和大数据量下的内存行为。\n\n## Review 指南\n\n- 重点检查空指针、并发、资源释放、兼容性问题。\n- 不要只做代码风格建议，优先指出真实 bug 和回归风险。\n- 所有 Pull Request Review 的总结、结论和行内评论必须使用简体中文。\n- 技术标识符、类名、方法名、变量名、日志、错误信息及代码片段保持原文，不要翻译。\n- 严重程度标识可以保留 `P0`、`P1`、`P2` 等英文缩写。\n- 如果没有发现需要阻止合并的问题，也必须使用简体中文给出结论。\n- Review 结论必须基于当前 diff 和仓库中可验证的行为；不确定时明确说明假设，不要把推测写成确定缺陷。\n- 仅报告由本次变更引入或暴露、且作者可以采取行动的问题，并指出具体文件、位置、触发条件和影响。\n- 重点关注微信接口契约、Java 8 兼容性、公共 API 兼容性、序列化字段、HTTP 客户端实现一致性、Starter 多账号场景及敏感信息泄露。\n- 不要仅因缺少全仓库测试、个人风格偏好或与本次变更无关的历史代码而阻止合并。\n\n## Agent 完成检查清单\n\n- 已确认并遵循相关模块、相邻代码和更具体的 `AGENTS.md`。\n- 变更范围与任务直接相关，没有覆盖用户的无关修改。\n- 新增代码保持 Java 8、公共 API 和序列化兼容性。\n- 必要的测试与文档已经更新。\n- 已执行与风险匹配的构建或测试，并如实记录结果。\n- 已检查完整 diff、格式、生成物和敏感信息。\n- 最终回复使用简体中文，简要列出修改内容、验证结果和任何剩余风险。\n","skills/wxjava-api-contributor/SKILL.md":"---\nname: wxjava-api-contributor\ndescription: 按 WxJava 的 Maven 多模块、Java 8、公共 API 兼容性和 TestNG 约定，为微信官方接口新增或维护 SDK 支持。适用于新增 Service API、请求响应 Bean、序列化、HTTP 实现、Starter 配置或回归测试时。\n---\n\n# WxJava 接口贡献\n\n1. 先搜索开放与已关闭 Issue，确认需求是否已有讨论、实现、回归用例或官方接口变动；再确认微信产品和目标模块。\n2. 阅读对应 README、POM、相似接口、实现与测试，并读取 [贡献约定](references/contribution.md)。\n3. 将官方接口契约映射到 Service、实现、Bean、URL、序列化和测试；列出所有可能受影响的 HTTP 客户端和 Starter。\n4. 只做完成需求所需的最小改动；更新必要 Javadoc、测试与用户可见文档。\n5. 执行 `mvn -pl <module> -am test`，并检查 `git diff --check`。\n\n保持 Java 8 与公共 API、异常语义、JSON/XML 字段兼容性。涉及多 HTTP 客户端、单/多账号 Starter 或 Solon 插件时，检查等价实现是否需要同步。PR 应关联对应 Issue，目标分支为 `develop`。\n","skills/wxjava-api-contributor/agents/openai.yaml":"interface:\n  display_name: \"WxJava 接口贡献\"\n  short_description: \"按 WxJava 项目约定新增或维护 SDK 接口能力\"\n  default_prompt: \"使用 $wxjava-api-contributor 为 WxJava 新增微信接口支持。\"\n","skills/wxjava-api-contributor/references/contribution.md":"# 贡献约定\n\n以微信官方接口定义和本仓库同类实现为准，核对路径、方法、字段名、必填项和响应结构。优先复用既有 HTTP 执行器、异常、配置、Gson/Jackson/XStream 映射和 TestNG 测试模式。\n\n公共方法需要准确 Javadoc。不要吞异常、记录敏感值或无关重构。新增公开方法和 bug 修复均应有针对性测试；涉及公共模块、BOM 或多模块时扩大验证范围。\n\n## 接口增量检查表\n\n1. 从微信官方文档和相关 Issue 中确认接口可用条件、HTTP 方法、URL、必填字段、签名/加密要求和响应示例。\n2. 搜索同产品的相邻能力，复用其 Service 分层、Bean 命名、请求执行和错误处理模式；不要只新增 Bean 而遗漏 Service 暴露。\n3. 若接口尚未支持，优先使用现有通用执行能力；MP/CP Wiki 说明通用执行器会处理 access token 刷新及 `errcode` 到异常的转换。\n4. 为字段边界、空值、JSON/XML 映射和异常路径添加 TestNG 回归测试。API 路径或字段问题是历史 bug 的高频来源，例如 [#3982](https://github.com/binarywang/WxJava/issues/3982)、[#4000](https://github.com/binarywang/WxJava/issues/4000)。\n5. 按 [贡献指南](https://github.com/binarywang/WxJava/blob/develop/CONTRIBUTING.md) 使用 `develop` 作为 PR 目标；说明 Issue、兼容性影响和验证命令。\n\n## 一手资料入口\n\n- [如何调用 MP 未支持接口](https://github.com/binarywang/WxJava/wiki/MP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [如何调用 CP 未支持接口](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [关闭的新接口 Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3A%E6%96%B0%E6%8E%A5%E5%8F%A3)\n","skills/wxjava-integration-guide/SKILL.md":"---\nname: wxjava-integration-guide\ndescription: 为 Java、Spring Boot 或 Solon 项目生成可验证的 WxJava 接入方案，包括模块选择、BOM、配置、最小调用代码以及单/多账号集成。适用于用户要求接入公众号、小程序、支付、企业微信、开放平台、视频号或微信小店时。\n---\n\n# WxJava 接入指南\n\n1. 确认微信产品、框架、单/多账号、部署形态和首个 API 调用。\n2. 读取 [接入约束](references/integration.md)，选择模块和配置方式。\n3. 先输出依赖与配置，再输出最小调用；每段示例注明应放置的位置和所依赖的模块。\n4. 输出脱敏配置和最小服务端代码；凭据一律用占位符。\n5. 给出本地验证步骤与安全提醒；支付、回调和证书示例不得直接用于生产。\n\n保持 Java 8 兼容。生产集群必须使用可共享的配置存储或 token 存储；不要把内存实现当作多节点部署方案。引用已有 Demo、Wiki 或 README 作为继续阅读入口；不虚构配置键、SDK 方法或版本号。\n","skills/wxjava-integration-guide/agents/openai.yaml":"interface:\n  display_name: \"WxJava 接入指南\"\n  short_description: \"生成可验证的 WxJava 最小接入方案与配置示例\"\n  default_prompt: \"使用 $wxjava-integration-guide 为我的项目生成 WxJava 接入代码。\"\n","skills/wxjava-integration-guide/references/integration.md":"# 接入约束\n\n优先通过 `wx-java-bom` 统一管理多个 WxJava 模块版本。核心 SDK 模块是 MP、MiniApp、Pay、CP、Open、Channel、Qidian、Aispeech；框架集成模块位于 `spring-boot-starters` 与 `solon-plugins`。\n\n查阅相应模块 README、根目录 [demo.md](https://github.com/binarywang/WxJava/blob/develop/demo.md) 和目标模块测试中的示例，确认配置属性与初始化模式。所有 `appId`、`secret`、商户私钥、API v3 密钥和证书均使用占位符，不得输出到日志。\n\n## 实施检查表\n\n1. 先完成一条只读或低风险 API 调用，再接入消息、支付或异步回调。\n2. 单实例可使用默认配置存储；多实例或集群需使用共享的 token/config storage，避免节点各自刷新 access token。\n3. 公众号、企业微信等回调必须先按平台要求校验消息合法性，再进入业务路由；支付回调还必须按商户单号实现幂等。\n4. 需要代理或私有网络出口时，明确区分正向代理与反向代理。支付 V3 的签名路径不能因反向代理路径前缀而被错误改写。\n5. HTTP 客户端类型、Starter 配置键和 Service 实现必须取自目标模块的当前 README、POM 或相邻 Demo；不要混用不同产品模块的配置前缀。\n6. Starter 自动配置与 Demo 手动初始化必须二选一后再给示例。发生空 key、注入为空或 NPE 时，先核对启动模块、profile、配置前缀和当前 `*Properties` 类；历史 [#2177](https://github.com/binarywang/WxJava/issues/2177) 是混用两种配置模型的案例。\n7. Quarkus 或 GraalVM 场景转到 [Quarkus 支持文档](https://github.com/binarywang/WxJava/blob/develop/docs/QUARKUS_SUPPORT.md)，不要套用 Spring Boot Starter 配置。\n\n## 一手资料入口\n\n- [MP Quick Start](https://github.com/binarywang/WxJava/wiki/MP_Quick-Start)\n- [微信支付说明](https://github.com/binarywang/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98)\n- [SDK 正反向代理支持](https://github.com/binarywang/WxJava/wiki/SDK-%E9%92%88%E5%AF%B9%E5%BE%AE%E4%BF%A1-%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E5%92%8C%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%94%AF%E6%8C%81)\n- [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md)\n","skills/wxjava-module-selector/SKILL.md":"---\nname: wxjava-module-selector\ndescription: 根据微信公众号、小程序、微信支付、企业微信、开放平台、视频号或微信小店、腾讯企点和微信智能对话等业务场景，为用户选择合适的 WxJava Maven 模块、BOM 和示例入口。适用于用户询问“该用哪个模块”、依赖坐标、产品边界或单/多账号 Starter 选择时。\n---\n\n# WxJava 模块选择\n\n1. 识别微信产品、服务端框架、是否多账号、是否包含支付或回调；信息不足时只询问必要问题。\n2. 读取 [模块映射](references/modules.md)，给出一个主推荐，以及组合模块的理由。\n3. 先区分产品边界，再选择核心 SDK；仅当项目确实依赖框架自动配置时才额外推荐 Starter 或 Solon 插件。\n4. 优先推荐 BOM；给出准确的 `groupId`、`artifactId`、相应 Demo、Wiki 或仓库文档入口。\n5. 说明服务端 SDK 的边界：移动端登录、分享等能力仍需微信官方客户端 SDK。\n6. 不臆测版本号；建议以 Maven Central 或项目 README 的当前版本为准。\n\n使用“场景 → 模块 → 集成选项 → 下一步”的简短结构。涉及多账号时说明单账号与 multi Starter 的区别；不要在示例中泄露凭据。支付和回调场景必须提醒用户验证通知 URL、验签与幂等处理。\n","skills/wxjava-module-selector/agents/openai.yaml":"interface:\n  display_name: \"WxJava 模块选择\"\n  short_description: \"按微信业务场景选择 WxJava 模块、依赖与示例\"\n  default_prompt: \"使用 $wxjava-module-selector 为我的微信业务选择合适的 WxJava 模块。\"\n","skills/wxjava-module-selector/references/modules.md":"# WxJava 模块映射\n\n| 场景 | 核心模块 |\n| --- | --- |\n| 微信公众号 | `weixin-java-mp` |\n| 微信小程序 | `weixin-java-miniapp` |\n| 微信支付 | `weixin-java-pay` |\n| 企业微信 | `weixin-java-cp` |\n| 微信开放平台／第三方平台 | `weixin-java-open` |\n| 视频号／微信小店 | `weixin-java-channel` |\n| 腾讯企点／微信客服 | `weixin-java-qidian` |\n| 微信智能对话／智能语音 | `weixin-java-aispeech` |\n\n多个模块并用时优先使用 `com.github.binarywang:wx-java-bom`。Spring Boot 集成从 `spring-boot-starters` 选择；Solon 集成从 `solon-plugins` 选择。\n\n## 多账号集成范围\n\n只有多个独立微信应用配置时才选择 multi 集成，并先按框架与产品核对目录是否存在：\n\n- Spring Boot：MP、MiniApp、CP、自建/第三方 CP、Pay、Open、Channel 都有相应 multi Starter。\n- Solon：仅 MP、MiniApp、CP、Channel 有 multi 插件；Pay、Open、Qidian 目前只有单账号插件，不要推荐不存在的 multi artifact。\n\n## 选择检查点\n\n- 公众号、小程序和企业微信的消息回调、token 与加解密配置彼此独立；不要因同属一个公司而复用不兼容的凭据或配置对象。\n- 企业微信的多应用应使用独立的 `WxCpConfigStorage` 与 `WxCpServiceImpl`；Wiki 明确指出复用 token、AES key 和 URL 会造成安全边界问题。\n- 支付能力通常与 MP、MiniApp 或 Open 同时使用：前者处理业务身份和消息，`weixin-java-pay` 处理商户签名、证书与支付回调。\n- 视频号／微信小店接口属于 `weixin-java-channel`；不要误归入 MP 或 Pay。\n- 腾讯企点与微信智能对话是独立 SDK 模块；不要将客服或智能对话需求默认归入 MP、CP 或 Channel。\n- 当能力在 MP 与 Open 等模块可能重叠时，按授权主体、官方 API 域和回调场景选择，不要只按“移动端”或“登录”字样判断。先在当前源码和 Issue 中确认覆盖状态，并标注“已确认 / 待查 / 需自行调用底层接口”。\n- BOM 适合同时使用多个 WxJava 模块。若项目还导入 Spring Boot 等上游 BOM，升级后执行 `mvn help:effective-pom` 与 `mvn dependency:tree`；历史 [#4058](https://github.com/binarywang/WxJava/issues/4058) 表明依赖管理顺序可能影响 Spring Data Redis 等依赖。\n\n## 一手资料入口\n\n- [WxJava Wiki 首页](https://github.com/binarywang/WxJava/wiki)\n- [企业微信多应用配置](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E6%94%AF%E6%8C%81%E5%A4%9A%E4%B8%AA%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8%E6%88%96%E4%BC%81%E4%B8%9A%E5%8F%B7)\n- [视频号／微信小店开发文档](https://github.com/binarywang/WxJava/wiki/0_%E8%A7%86%E9%A2%91%E5%8F%B7_%E5%BE%AE%E4%BF%A1%E5%B0%8F%E5%BA%97%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)\n","skills/wxjava-troubleshooter/SKILL.md":"---\nname: wxjava-troubleshooter\ndescription: 排查 WxJava 在配置初始化、access token、签名验签、支付证书、回调通知、序列化、网络请求和多账号隔离方面的问题。适用于用户提供异常、日志、请求响应或“WxJava 为什么不能调用”的场景。\n---\n\n# WxJava 故障排查\n\n1. 收集最小复现：产品模块、SDK 版本、JDK、框架、依赖树、异常堆栈、请求 ID 与脱敏后的配置形状。\n2. 将故障归类为依赖/初始化、token 与存储、请求契约、HTTP/代理、回调验签、支付证书或并发与生命周期。\n3. 依据 [诊断清单](references/diagnostics.md)，按最低成本、最可验证的顺序排查。\n4. 每次只提出一个可验证根因，给出最小修复、预期现象和回归验证动作。\n5. 签名、支付、回调和加密场景须核对编码、字段排序、金额精度、时间戳、证书链和重放保护。\n\n要求遮蔽 secret、token、私钥、证书、签名原文和个人数据。不要建议关闭 TLS 校验或验签；区分已证实结论与待验证假设。遇到历史同类问题时，给出对应 Issue 或 Wiki 链接，但必须检查当前版本的实现后再套用修复。\n","skills/wxjava-troubleshooter/agents/openai.yaml":"interface:\n  display_name: \"WxJava 故障排查\"\n  short_description: \"定位 WxJava 配置、回调、签名与接口调用问题\"\n  default_prompt: \"使用 $wxjava-troubleshooter 排查我的 WxJava 调用异常。\"\n","skills/wxjava-troubleshooter/references/diagnostics.md":"# 诊断清单\n\n- 配置：模块是否正确，应用标识和凭据是否配对，多账号配置是否被正确选择。\n- 请求：HTTP 方法、路径、必填字段和 JSON/XML 映射是否符合微信接口契约。\n- 认证：token 缓存、签名字段、时间戳、nonce、证书和密钥格式是否有效。\n- 网络：DNS、代理、超时、TLS 证书校验和响应关闭是否正常。\n- 回调：回调 URL 可访问、验签参数完整、幂等处理和资源释放是否存在。\n\n从精确异常和最小请求入手，不用“重试”替代根因分析。\n\n## 高频场景\n\n| 症状 | 优先检查 | 依据 |\n| --- | --- | --- |\n| 多节点间歇性 token 失效 | 是否共享 token/config storage，是否让各节点并发刷新 | Wiki 的 MP/CP 配置存储说明与集群案例 |\n| `NoClassDefFoundError`、`NoSuchMethodError` | `mvn dependency:tree`、HttpClient/commons-lang/xstream 冲突及 BOM 是否统一版本 | Wiki 的异常排查页与 HTTP 客户端升级指南 |\n| 回调验签或重复处理 | 原始请求体、时间戳/nonce/签名、回调 URL、业务幂等键 | MP 合法性校验与支付回调说明 |\n| HTTP 连接、超时或代理问题 | 连接/读取超时、代理、TLS、正反向代理是否混用 | Wiki 的 HttpClient 参数与代理文档 |\n| 企业微信会话存档崩溃 | 是否仍手动销毁旧 SDK 实例，是否已迁移安全 API | [会话存档安全使用指南](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_SDK_SAFE_USAGE.md) |\n| 视频号/小店接口 404 或字段不匹配 | 当前官方路径与请求字段、目标 SDK 版本、历史 Issue 是否已修复 | 关闭的 bug Issue，如 [#3982](https://github.com/binarywang/WxJava/issues/3982) |\n\n## 一手资料入口\n\n- [常见异常首页](https://github.com/binarywang/WxJava/wiki)\n- [MP 消息合法性验证](https://github.com/binarywang/WxJava/wiki/MP_%E9%AA%8C%E8%AF%81%E6%B6%88%E6%81%AF%E5%90%88%E6%B3%95%E6%80%A7)\n- [HttpClient 参数配置](https://github.com/binarywang/WxJava/wiki/HttpClient%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0%E7%9A%84%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%B3%95)\n- [关闭的 bug Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3Abug)\n","skills/wxjava-upgrade-guide/SKILL.md":"---\nname: wxjava-upgrade-guide\ndescription: 规划 WxJava 的版本升级与迁移，检查 BOM、模块依赖、Java 版本、配置与公共 API 兼容性，并提供可回滚的验证步骤。适用于用户从旧版升级、切换依赖管理方式、处理兼容性告警或制定升级发布计划时。\n---\n\n# WxJava 升级迁移\n\n1. 收集当前与目标版本、已用模块、JDK、框架、BOM 使用情况、依赖树、代理配置和关键调用路径。\n2. 读取 [迁移检查表](references/migration.md)，识别版本、依赖和配置边界。\n3. 按 HTTP 客户端、BOM、支付/回调、多账号、企业微信会话存档等变化类型选择迁移分支。\n4. 输出分阶段变更：依赖调整、编译、关键回归测试、灰度与明确回滚条件。\n5. 将不确定项标为待查，并引导查看目标版本的 release notes、README、Javadoc 与变更记录。\n\n不要猜测废弃 API 或破坏性变更；以官方发布信息、当前代码与实际编译结果为准。默认保持 Java 8，除非目标版本明确改变此约束。不能以关闭验签、固定 token 或跳过测试作为回滚方案。\n","skills/wxjava-upgrade-guide/agents/openai.yaml":"interface:\n  display_name: \"WxJava 升级迁移\"\n  short_description: \"规划 WxJava 版本升级、依赖调整与兼容性迁移\"\n  default_prompt: \"使用 $wxjava-upgrade-guide 制定 WxJava 版本升级方案。\"\n","skills/wxjava-upgrade-guide/references/migration.md":"# 迁移检查表\n\n- 使用多个 WxJava 模块时，优先迁移到 `wx-java-bom`，避免模块版本漂移。\n- 清点 MP、MiniApp、Pay、CP、Open、Channel 及框架 Starter/插件的实际依赖。\n- 更新后先执行编译和受影响模块测试，再验证 token、回调、支付和关键业务链路。\n- 为依赖版本保留可快速恢复的变更记录；按灰度策略验证生产环境，且不将凭据写入代码或日志。\n\n## 升级分支\n\n### HTTP 客户端\n\n从 4.7.x 起，项目支持并推荐 Apache HttpClient 5.x，同时保留部分 4.x 兼容性。先按 [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md) 核对模块、依赖与 `http-client-type`，再检查代理 host、port、username、password 的完整性。历史 [#3836](https://github.com/binarywang/WxJava/issues/3836) 表明可选代理配置也需要回归。\n\n### BOM 与依赖冲突\n\n`wx-java-bom` 从 4.8.3.B 起提供。导入 BOM 前后均执行：\n\n```shell\nmvn help:effective-pom\nmvn dependency:tree\n```\n\n特别回归由 Spring Boot BOM 管理的 Redis、HTTP 客户端和序列化依赖；[#4058](https://github.com/binarywang/WxJava/issues/4058) 是历史冲突案例。\n\n### 企业微信会话存档\n\n升级到 4.8.0 或更高版本时，查找旧的 `getChatDatas`、`getDecryptData`、`getChatPlainText`、`getMediaFile` 和手动 `Finance.DestroySdk()`。按 [ThreadLocal 生命周期迁移文档](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_THREADLOCAL_LIFECYCLE_REFACTOR.md) 切换至新 API，并做并发验证。\n\nThreadLocal SDK 不会在线程结束时自动释放。在线程池、定时任务或一次性线程中，必须在任务的 `finally` 块调用 `msgAuditService.closeThreadLocalSdk()`；应用停止时再用 `closeAllSdks()` 做全局兜底。不要在业务代码中直接调用 `Finance.DestroySdk()`。\n\n### 回调与支付\n\n验证不止于 HTTP 2xx：分别覆盖 token 获取、签名/证书校验、重复回调、业务状态转换和多账号路由。多账号异步任务必须显式传递 appId 或服务上下文，不能假定 ThreadLocal 自动继承。\n\n## 验证与回滚\n\n按“编译和单测 → 非生产凭据冒烟 → 灰度和监控”执行。出现依赖树冲突、验签/证书异常、回调错误或 native 崩溃时停止扩大灰度，恢复上一个已验证依赖组合后再以最小复现定位。\n","solon-plugins/wx-java-channel-multi-solon-plugin/README.md":"# wx-java-channel-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.channel.apps.tenantId1.app-id=@appId\n    wx.channel.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId1.use-stable-access-token=false\n    wx.channel.apps.tenantId1.token=\n    wx.channel.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.channel.apps.tenantId2.app-id=@appId\n    wx.channel.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId2.use-stable-access-token=false\n    wx.channel.apps.tenantId2.token=\n    wx.channel.apps.tenantId2.aes-key=\n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel:multi(默认)\n    wx.channel.config-storage.key-prefix=wx:channel:multi\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxChannelMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.channel.service.WxChannelMultiServices;\n    import me.chanjar.weixin.channel.api.WxChannelService;\n    import me.chanjar.weixin.channel.api.WxFinderLiveService;\n    import me.chanjar.weixin.channel.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n    \n    @Component\n    public class DemoService {\n      @Inject\n      private WxChannelMultiServices wxChannelMultiServices;\n    \n      public void test() throws WxErrorException {\n        // 应用 1 的 WxChannelService\n        WxChannelService wxChannelService1 = wxChannelMultiServices.getWxChannelService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxChannelService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 2 的 WxChannelService\n        WxChannelService wxChannelService2 = wxChannelMultiServices.getWxChannelService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxChannelService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 3 的 WxChannelService\n        WxChannelService wxChannelService3 = wxChannelMultiServices.getWxChannelService(\"tenantId3\");\n        // 判断是否为空\n        if (wxChannelService3 == null) {\n          // todo wxChannelService3 为空，请先配置 tenantId3 微信视频号应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxChannelService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n","solon-plugins/wx-java-channel-solon-plugin/README.md":"# wx-java-channel-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 视频号小店的appId和secret\n    wx.channel.app-id=@appId\n    wx.channel.secret=@secret\n    # 视频号配置 选填\n    ## 设置视频号小店消息服务器配置的token\n    wx.channel.token=@token\n    ## 设置视频号小店消息服务器配置的EncodingAESKey\n    wx.channel.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.channel.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.channel.use-stable-access-token=false\n    \n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel(默认)\n    wx.channel.config-storage.key-prefix=wx:channel\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n \n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxChannelService`\n- `WxChannelConfig`\n4. 使用样例\n\n```java\nimport me.chanjar.weixin.channel.api.WxChannelService;\nimport me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;\nimport me.chanjar.weixin.channel.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxChannelService wxChannelService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxChannelService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n\n","solon-plugins/wx-java-cp-multi-solon-plugin/README.md":"# wx-java-cp-multi-solon-plugin\n\n企业微信多账号配置\n\n- 实现多 WxCpService 初始化。\n- 未实现 WxCpTpService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n- 未实现 WxCpCgService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n\n## 关于 corp-secret 的说明\n\n企业微信中不同功能模块对应不同的 `corp-secret`，每种 Secret 只对对应模块的接口具有调用权限：\n\n| Secret 类型 | 获取位置 | 可调用的接口 | 是否需要 agent-id |\n|---|---|---|---|\n| 自建应用 Secret | 应用管理 → 自建应用 → 选择应用 → 查看 Secret | 该应用有权限的接口 | **必填** |\n| 通讯录同步 Secret | 管理工具 → 通讯录同步 → 查看 Secret | 部门/成员增删改查等通讯录接口 | **不填** |\n| 客户联系 Secret | 客户联系 → API → Secret | 客户联系相关接口 | 不填 |\n\n> **常见问题**：\n> - 使用自建应用 Secret + agent-id 可以获取部门列表，但**无法更新部门**（因为写接口需要通讯录同步权限）\n> - 使用通讯录同步 Secret 可以同步部门，但**调用某些需要 agent-id 的应用接口会报错**\n\n如需同时使用多种权限范围，可在 `wx.cp.corps` 下配置多个条目，每个条目使用对应权限的 Secret，通过不同的 `tenantId` 区分后使用。\n\n> **注意**：\n> 当前插件实现会校验同一 `corp-id` 下的 `agent-id` **必须唯一**，并且 **只能有一个条目不填写 `agent-id`**。\n> 如果在同一 `corp-id` 下同时配置多个未填写 `agent-id` 的条目，会因 token/ticket 缓存 key 冲突而在启动时直接抛异常。\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 自建应用 1 配置（使用自建应用 Secret，需填写 agent-id）\n    wx.cp.corps.app1.corp-id = @corp-id\n    wx.cp.corps.app1.corp-secret = @自建应用的Secret（在\"应用管理-自建应用\"中查看）\n    wx.cp.corps.app1.agent-id = @自建应用的AgentId\n    ## 选填\n    wx.cp.corps.app1.token = @token\n    wx.cp.corps.app1.aes-key = @aes-key\n    wx.cp.corps.app1.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.corps.app1.msg-audit-lib-path = @msg-audit-lib-path\n\n    # 通讯录同步配置（使用通讯录同步 Secret，不需要填写 agent-id）\n    # 此配置用于部门、成员的增删改查等通讯录管理操作\n    wx.cp.corps.contact.corp-id = @corp-id\n    wx.cp.corps.contact.corp-secret = @通讯录同步的Secret（在\"管理工具-通讯录同步\"中查看）\n    ## agent-id 不填，通讯录同步不需要 agentId\n\n    # 公共配置\n    ## ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    ## http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.cp.config-storage.http-client-type=http_client\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.cp_multi.service.WxCpMultiServices;\nimport me.chanjar.weixin.cp.api.WxCpDepartmentService;\nimport me.chanjar.weixin.cp.api.WxCpService;\nimport me.chanjar.weixin.cp.api.WxCpUserService;\nimport me.chanjar.weixin.cp.bean.WxCpDepart;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxCpMultiServices wxCpMultiServices;\n\n  public void test() {\n    // 使用自建应用的 WxCpService（对应 corp-secret 为自建应用 Secret）\n    WxCpService appService = wxCpMultiServices.getWxCpService(\"app1\");\n    WxCpUserService userService = appService.getUserService();\n    userService.getUserId(\"xxx\");\n    // todo ...\n\n    // 使用通讯录同步的 WxCpService（对应 corp-secret 为通讯录同步 Secret）\n    // 通讯录同步 Secret 具有部门/成员增删改查等权限\n    WxCpService contactService = wxCpMultiServices.getWxCpService(\"contact\");\n    WxCpDepartmentService departmentService = contactService.getDepartmentService();\n    // 更新部门示例（WxCpDepart 包含 id、name、parentId 等字段）\n    WxCpDepart depart = new WxCpDepart();\n    depart.setId(100L);\n    depart.setName(\"新部门名称\");\n    departmentService.update(depart);\n    // todo ...\n  }\n}\n```\n","solon-plugins/wx-java-cp-solon-plugin/README.md":"# wx-java-cp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 企业微信号配置(必填)\n    wx.cp.corp-id = @corp-id\n    wx.cp.corp-secret = @corp-secret\n    # 选填\n    wx.cp.agent-id = @agent-id\n    wx.cp.token = @token\n    wx.cp.aes-key = @aes-key\n    wx.cp.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.msg-audit-lib-path = @msg-audit-lib-path\n    # ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    # http 客户端配置（选填）\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpService`, `WxCpConfigStorage`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n\n- WxCpService\n- WxCpConfigStorage\n","solon-plugins/wx-java-miniapp-multi-solon-plugin/README.md":"# wx-java-miniapp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.ma.apps.tenantId1.app-id=appId\n    wx.ma.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.ma.apps.tenantId1.token=@token\n    wx.ma.apps.tenantId1.aes-key=@aesKey\n    wx.ma.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.ma.apps.tenantId2.app-id=@appId\n    wx.ma.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.ma.apps.tenantId2.token=@token\n    wx.ma.apps.tenantId2.aes-key=@aesKey\n    wx.ma.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson\n    wx.ma.config-storage.type=memory\n    ## 相关redis前缀配置: wx:ma:multi(默认)\n    wx.ma.config-storage.key-prefix=wx:ma:multi\n    wx.ma.config-storage.redis.host=127.0.0.1\n    wx.ma.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.ma.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.ma.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.ma.config-storage.http-client-type=http_client\n    wx.ma.config-storage.http-proxy-host=\n    wx.ma.config-storage.http-proxy-port=\n    wx.ma.config-storage.http-proxy-username=\n    wx.ma.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.ma.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.ma.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxMaMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.miniapp.service.WxMaMultiServices;\nimport cn.binarywang.wx.miniapp.api.WxMaService;\nimport cn.binarywang.wx.miniapp.api.WxMaUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMaMultiServices wxMaMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMaService\n    WxMaService wxMaService1 = wxMaMultiServices.getWxMaService(\"tenantId1\");\n    WxMaUserService userService1 = wxMaService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMaService\n    WxMaService wxMaService2 = wxMaMultiServices.getWxMaService(\"tenantId2\");\n    WxMaUserService userService2 = wxMaService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMaService\n    WxMaService wxMaService3 = wxMaMultiServices.getWxMaService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMaService3 == null) {\n      // todo wxMaService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMaUserService userService3 = wxMaService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n","solon-plugins/wx-java-miniapp-solon-plugin/README.md":"# wx-java-miniapp-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.miniapp.appid = appId\n    wx.miniapp.secret = @secret\n    wx.miniapp.token = @token\n    wx.miniapp.aesKey = @aesKey\n    wx.miniapp.msgDataFormat = @msgDataFormat                  # 消息格式，XML或者JSON.\n    # 存储配置redis(可选)\n    # 注意: 指定redis.host值后不会使用容器注入的redis连接(JedisPool)\n    wx.miniapp.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.miniapp.config-storage.key-prefix = wa                  # 相关redis前缀配置: wa(默认)\n    wx.miniapp.config-storage.redis.host = 127.0.0.1\n    wx.miniapp.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.miniapp.config-storage.http-client-type=HttpClient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.miniapp.config-storage.http-proxy-host=\n    wx.miniapp.config-storage.http-proxy-port=\n    wx.miniapp.config-storage.http-proxy-username=\n    wx.miniapp.config-storage.http-proxy-password=\n    ```\n3. 自动注入的类型\n- `WxMaService`\n- `WxMaConfig`\n\n","solon-plugins/wx-java-mp-multi-solon-plugin/README.md":"# wx-java-mp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.mp.apps.tenantId1.app-id=appId\n    wx.mp.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.mp.apps.tenantId1.token=@token\n    wx.mp.apps.tenantId1.aes-key=@aesKey\n    wx.mp.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.mp.apps.tenantId2.app-id=@appId\n    wx.mp.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.mp.apps.tenantId2.token=@token\n    wx.mp.apps.tenantId2.aes-key=@aesKey\n    wx.mp.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.mp.config-storage.type=memory\n    ## 相关redis前缀配置: wx:mp:multi(默认)\n    wx.mp.config-storage.key-prefix=wx:mp:multi\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.mp.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.mp.config-storage.http-client-type=http_client\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.mp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.mp.config-storage.retry-sleep-millis=1000\n   \n\t  # 公众号地址 host 配置\n\t  # wx.mp.hosts.api-host=http://proxy.com/\n\t  # wx.mp.hosts.open-host=http://proxy.com/\n\t  # wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型：`WxMpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.mp_multi.service.WxMpMultiServices;\nimport me.chanjar.weixin.mp.api.WxMpService;\nimport me.chanjar.weixin.mp.api.WxMpUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMpMultiServices wxMpMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMpService\n    WxMpService wxMpService1 = wxMpMultiServices.getWxMpService(\"tenantId1\");\n    WxMpUserService userService1 = wxMpService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMpService\n    WxMpService wxMpService2 = wxMpMultiServices.getWxMpService(\"tenantId2\");\n    WxMpUserService userService2 = wxMpService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMpService\n    WxMpService wxMpService3 = wxMpMultiServices.getWxMpService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMpService3 == null) {\n      // todo wxMpService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMpUserService userService3 = wxMpService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n","solon-plugins/wx-java-mp-solon-plugin/README.md":"# wx-java-mp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.mp.app-id=appId\n    wx.mp.secret=@secret\n    wx.mp.token=@token\n    wx.mp.aes-key=@aesKey\n    wx.mp.use-stable-access-token=@useStableAccessToken\n    # 存储配置redis(可选)\n    wx.mp.config-storage.type= edis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.mp.config-storage.key-prefix=wx                  # 相关redis前缀配置: wx(默认)\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  #单机和sentinel同时存在时，优先使用sentinel配置\n\t  #wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  #wx.mp.config-storage.redis.sentinel-name=mymaster\n    # http客户端配置\n    wx.mp.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n\t  # 公众号地址host配置\n\t  #wx.mp.hosts.api-host=http://proxy.com/\n\t  #wx.mp.hosts.open-host=http://proxy.com/\n\t  #wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型\n\n- `WxMpService`\n- `WxMpConfigStorage`\n\n4、参考demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n","solon-plugins/wx-java-open-solon-plugin/README.md":"# wx-java-open-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-open-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.open.appId = appId\n    wx.open.secret = @secret\n    wx.open.token = @token\n    wx.open.aesKey = @aesKey\n    # 存储配置redis(可选)\n    # 优先注入容器的(JedisPool, RedissonClient), 当配置了wx.open.config-storage.redis.host, 不会使用容器注入redis连接配置\n    wx.open.config-storage.type = redis                     # 配置类型: memory(默认), redis(jedis), jedis, redisson, redistemplate\n    wx.open.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n    wx.open.config-storage.redis.host = 127.0.0.1\n    wx.open.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.open.config-storage.http-client-type=httpclient      # http客户端类型: httpclient(默认)\n    wx.open.config-storage.http-proxy-host=\n    wx.open.config-storage.http-proxy-port=\n    wx.open.config-storage.http-proxy-username=\n    wx.open.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.open.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.open.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxOpenService, WxOpenMessageRouter, WxOpenComponentService`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n  - WxOpenConfigStorage\n  - WxOpenService\n","solon-plugins/wx-java-pay-solon-plugin/README.md":"# 使用说明\n1. 在自己的Solon项目里，引入maven依赖\n```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-pay-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n ```\n2. 添加配置(app.yml)\n###### 1）V2版本\n```yml\nwx:\n  pay:\n    appId: \n    mchId: \n    mchKey: \n    keyPath:\n```\n###### 2）V3版本\n```yml\nwx:\n  pay:\n    appId: xxxxxxxxxxx\n    mchId: 15xxxxxxxxx #商户id\n    apiHostUrl: http://10.0.0.1:3128 # 可选：代理主机\n    apiHostUrlPath: /api-weixin # 可选：代理入口前缀\n    apiV3Key: Dc1DBwSc094jACxxxxxxxxxxxxxxx #V3密钥\n    certSerialNo: 62C6CEAA360BCxxxxxxxxxxxxxxx\n    privateKeyPath: classpath:cert/apiclient_key.pem #apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径\n    privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n###### 3）V3服务商版本\n```yml\nwx:\n  pay: #微信服务商支付\n    configs:\n    - appId: wxe97b2x9c2b3d #spAppId\n      mchId: 16486610 #服务商商户\n      subAppId: wx118cexxe3c07679 #子appId\n      subMchId: 16496705 #子商户\n      apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr #apiV3密钥\n      privateKeyPath: classpath:cert/apiclient_key.pem #服务商证书文件，apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径（可以配置绝对路径）\n      privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n","solon-plugins/wx-java-qidian-solon-plugin/README.md":"# wx-java-qidian-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n   ```xml\n   <dependency>\n       <groupId>com.github.binarywang</groupId>\n       <artifactId>wx-java-qidian-solon-plugin</artifactId>\n       <version>${version}</version>\n   </dependency>\n   ```\n2. 添加配置(app.properties)\n   ```properties\n   # 公众号配置(必填)\n   wx.qidian.appId = appId\n   wx.qidian.secret = @secret\n   wx.qidian.token = @token\n   wx.qidian.aesKey = @aesKey\n   # 存储配置redis(可选)\n   wx.qidian.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n   wx.qidian.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n   wx.qidian.config-storage.redis.host = 127.0.0.1\n   wx.qidian.config-storage.redis.port = 6379\n   #单机和sentinel同时存在时，优先使用sentinel配置\n   #wx.qidian.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n   #wx.qidian.config-storage.redis.sentinel-name=mymaster\n   # http客户端配置\n   wx.qidian.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n   wx.qidian.config-storage.http-proxy-host=\n   wx.qidian.config-storage.http-proxy-port=\n   wx.qidian.config-storage.http-proxy-username=\n   wx.qidian.config-storage.http-proxy-password=\n   # 公众号地址host配置\n   #wx.qidian.hosts.api-host=http://proxy.com/\n   #wx.qidian.hosts.open-host=http://proxy.com/\n   #wx.qidian.hosts.mp-host=http://proxy.com/\n   ```\n3. 自动注入的类型\n\n- `WxQidianService`\n- `WxQidianConfigStorage`\n\n4、参考 demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n","solon-plugins/wx-java-store-multi-solon-plugin/README.md":"# wx-java-store-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.store.apps.tenantId1.app-id=@appId\n    wx.store.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId1.use-stable-access-token=false\n    wx.store.apps.tenantId1.token=\n    wx.store.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.store.apps.tenantId2.app-id=@appId\n    wx.store.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId2.use-stable-access-token=false\n    wx.store.apps.tenantId2.token=\n    wx.store.apps.tenantId2.aes-key=\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store:multi(默认)\n    wx.store.config-storage.key-prefix=wx:store:multi\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxStoreMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.store.service.WxStoreMultiServices;\n    import com.binarywang.wxjava.store.api.WxStoreService;\n    import com.binarywang.wxjava.store.api.WxFinderLiveService;\n    import com.binarywang.wxjava.store.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n\n    @Component\n    public class DemoService {\n      @Inject\n      private WxStoreMultiServices wxStoreMultiServices;\n\n      public void test() throws WxErrorException {\n        // 应用 1 的 WxStoreService\n        WxStoreService wxStoreService1 = wxStoreMultiServices.getWxStoreService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxStoreService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 2 的 WxStoreService\n        WxStoreService wxStoreService2 = wxStoreMultiServices.getWxStoreService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxStoreService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 3 的 WxStoreService\n        WxStoreService wxStoreService3 = wxStoreMultiServices.getWxStoreService(\"tenantId3\");\n        // 判断是否为空\n        if (wxStoreService3 == null) {\n          // todo wxStoreService3 为空，请先配置 tenantId3 微信小店应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxStoreService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n","solon-plugins/wx-java-store-solon-plugin/README.md":"# wx-java-store-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 微信小店的appId和secret\n    wx.store.app-id=@appId\n    wx.store.secret=@secret\n    # 视频号配置 选填\n    ## 设置微信小店消息服务器配置的token\n    wx.store.token=@token\n    ## 设置微信小店消息服务器配置的EncodingAESKey\n    wx.store.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.store.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.store.use-stable-access-token=false\n\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store(默认)\n    wx.store.config-storage.key-prefix=wx:store\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxStoreService`\n- `WxStoreConfig`\n4. 使用样例\n\n```java\nimport com.binarywang.wxjava.store.api.WxStoreService;\nimport com.binarywang.wxjava.store.bean.shop.ShopInfoResponse;\nimport com.binarywang.wxjava.store.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxStoreService wxStoreService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxStoreService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n"},"files":{".github/copilot-instructions.md":"# Copilot Instruction\n请始终使用中文生成 Pull Request 的标题、描述和提交信息\n\n\n# WxJava - 微信 Java SDK 开发说明\n\nWxJava 是一个支持多种微信平台的完整 Java SDK，包含公众号、小程序、微信支付、企业微信、开放平台、视频号、企点等多种功能模块。\n\n**请始终优先参考本说明，只有在遇到与此内容不一致的意外信息时，才退而使用搜索或 bash 命令。**\n\n## 高效开发指南\n\n### 前置条件与环境准备\n- **Java 要求**：JDK 8+（项目最低目标为 Java 8）\n- **Maven**：推荐 Maven 3.6+（已验证 Maven 3.9.11）\n- **IDE**：推荐使用 IntelliJ IDEA（项目针对 IDEA 优化）\n\n### 引导、构建与校验\n克隆仓库后按顺序执行以下命令：\n\n```bash\n# 1. 基础编译（请勿中断 - 约需 4-5 分钟）\nmvn clean compile -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 8 分钟以上。实际时间：约 4 分钟\n\n# 2. 完整打包（请勿中断 - 约需 2-3 分钟）  \nmvn clean package -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 5 分钟以上。实际时间：约 2 分钟\n\n# 3. 代码质量校验（请勿中断 - 约需 45-60 秒）\nmvn checkstyle:check --no-transfer-progress\n# 超时时间：建议设置 3 分钟以上。实际时间：约 50 秒\n```\n\n重要时间说明：\n- 绝对不要中断任意 Maven 构建命令\n- 编译阶段耗时最长（约 4 分钟），原因是项目包含 34 个模块\n- 后续构建会更快，因为存在增量编译\n- 始终使用 `--no-transfer-progress` 以减少日志噪音\n\n### 测试结构\n- **测试框架**：TestNG（非 JUnit）\n- **测试文件**：共有 298 个测试文件\n- **默认行为**：pom.xml 中默认禁用测试（`<skip>true</skip>`）\n- **测试配置**：测试需要通过 test-config.xml 提供真实的微信 API 凭据\n- **注意**：没有真实微信 API 凭据请不要尝试运行测试，测试将会失败\n\n## 项目结构与导航\n\n### 核心 SDK 模块（主要开发区）\n- `weixin-java-common/` - 通用工具与基础类（最重要）\n- `weixin-java-mp/` - 公众号 SDK\n- `weixin-java-pay/` - 微信支付 SDK\n- `weixin-java-miniapp/` - 小程序 SDK\n- `weixin-java-cp/` - 企业微信 SDK\n- `weixin-java-open/` - 开放平台 SDK\n- `weixin-java-channel/` - 视频号 / Channel SDK\n- `weixin-java-qidian/` - 企点 SDK\n\n### 框架集成模块\n- `spring-boot-starters/` - Spring Boot 自动配置 starter\n- `solon-plugins/` - Solon 框架插件\n- `weixin-graal/` - GraalVM 本地镜像支持\n\n### 配置与质量控制\n- `quality-checks/google_checks.xml` - Checkstyle 配置\n- `.editorconfig` - 代码格式规则（2 个空格等于 1 个制表）\n- `pom.xml` - 根级 Maven 配置\n\n## 开发工作流\n\n### 修改代码的流程\n1. 修改前务必先构建以建立干净基线：\n   ```bash\n   mvn clean compile --no-transfer-progress\n   ```\n\n2. 遵循代码风格（由 checkstyle 强制）：\n   - 缩进使用 2 个空格（不要用制表符）\n   - 遵循 Google Java 风格指南\n   - 在 IDE 中安装 EditorConfig 插件\n\n3. 增量验证修改：\n   ```bash\n   # 每次修改后运行：\n   mvn compile --no-transfer-progress\n   mvn checkstyle:check --no-transfer-progress\n   ```\n\n### 提交修改前的必须校验\n请务必按顺序完成以下校验步骤：\n\n1. 代码风格校验：\n   ```bash\n   mvn checkstyle:check --no-transfer-progress\n   # 必须通过 - 约需 50 秒\n   ```\n\n2. 完整清理构建：\n   ```bash\n   mvn clean package -DskipTests=true --no-transfer-progress  \n   # 必须成功 - 约需 2 分钟\n   ```\n\n3. 文档：为公共方法和类补充或更新 javadoc\n4. 贡献规范：遵循 `CONTRIBUTING.md`，Pull Request 必须以 `develop` 分支为目标\n\n## 模块依赖与构建顺序\n\n### 核心模块依赖（构建顺序）\n1. `weixin-graal`（GraalVM 支持）\n2. `weixin-java-common`（所有模块的基础）\n3. 核心 SDK 模块（mp、pay、miniapp、cp、open、channel、qidian）\n4. 框架集成（spring-boot-starters、solon-plugins）\n\n### 主要关系模式\n- 所有 SDK 模块都依赖于 `weixin-java-common`\n- Spring Boot starters 依赖对应的 SDK 模块\n- Solon 插件遵循与 Spring Boot starters 相同的依赖模式\n- 每个模块都有单账号与多账号配置支持\n\n## 常见任务与命令\n\n### 验证指定模块\n```bash\n# 构建单个模块（将 'weixin-java-mp' 替换为目标模块）：\ncd weixin-java-mp\nmvn clean compile --no-transfer-progress\n```\n\n### 检查依赖\n```bash\n# 分析依赖树：\nmvn dependency:tree --no-transfer-progress\n\n# 检查依赖更新：  \n./others/check-dependency-updates.sh\n```\n\n### 发布与发布准备\n```bash\n# 版本检查：\nmvn versions:display-property-updates --no-transfer-progress\n\n# 部署（需要凭据）：\nmvn clean deploy -P release --no-transfer-progress\n```\n\n## 重要文件与位置\n\n### 配置文件\n- `pom.xml` - 根级 Maven 配置与依赖管理\n- `quality-checks/google_checks.xml` - Checkstyle 规则\n- `.editorconfig` - IDE 格式化配置\n- `.github/workflows/maven-publish.yml` - CI/CD 工作流\n\n### 文档\n- `README.md` - 项目概览与使用说明（中文）\n- `CONTRIBUTING.md` - 贡献指南\n- `demo.md` - 示例项目与演示链接\n- 每个模块均有单独的文档与示例\n\n### 测试资源\n- `*/src/test/resources/test-config.sample.xml` - 测试配置模板\n- 测试运行需要真实的微信 API 凭据\n\n## SDK 使用模式\n\n### Maven 依赖示例\n```xml\n<dependency>\n  <groupId>com.github.binarywang</groupId>\n  <artifactId>weixin-java-mp</artifactId>  <!-- 或其他模块 -->\n  <version>4.7.0</version>\n</dependency>\n```\n\n### 常见开发区域\n- **API 客户端实现**：位于 `*/service/impl/` 目录\n- **模型类**：位于 `*/bean/` 目录\n- **配置**：位于 `*/config/` 目录\n- **工具类**：位于 `weixin-java-common` 的 `*/util/` 目录\n\n## 故障排查\n\n### 构建问题\n- **OutOfMemoryError**：增加 Maven 内存：`export MAVEN_OPTS=\"-Xmx2g\"`\n- **编译失败**：通常为依赖问题 - 先执行 `mvn clean`\n- **Checkstyle 失败**：检查 IDE 的 `.editorconfig` 设置\n\n### 常见陷阱\n- **测试默认跳过**：这是正常现象 — 测试需要微信 API 凭据\n- **多模块变更**：总是在仓库根目录构建，而不是单独模块\n- **分支目标**：Pull Request 必须以 `develop` 分支为目标，而不是 `master` 或 `release`\n\n## 性能说明\n- **首次构建**：由于依赖下载，耗时 4-5 分钟\n- **增量构建**：通常更快（约 30-60 秒）\n- **Checkstyle**：运行迅速（约 50 秒），应当经常运行\n- **IDE 性能**：项目使用 Lombok，请确保启用注解处理\n\n注意：本项目为 SDK 库项目，而非可运行应用。修改应以 API 功能为主，不要改动应用级行为。\n","AGENTS.md":"# WxJava Agent 指南\n\n## 适用范围与指令优先级\n\n- 本文件适用于整个仓库，供本地编码 Agent、自动化 Agent 和 Pull Request Review Agent 使用。\n- 开始工作前先阅读与任务直接相关的 `README.md`、`CONTRIBUTING.md`、模块 `pom.xml`、现有实现和测试；不要仅凭通用经验推断项目约定。\n- 若子目录存在更具体的 `AGENTS.md`，处理该目录文件时优先遵循距离目标文件最近的说明。\n- 用户的明确要求优先于本文件；若要求与兼容性、安全性或仓库约定冲突，应先说明风险，不要静默偏离。\n- 只修改完成任务所必需的文件，不处理无关格式、重构或历史遗留问题。\n\n## 项目概览\n\n- WxJava 是面向微信生态的 Java SDK，采用 Maven 多模块结构。\n- 当前根项目要求 Java 8（`maven.compiler.source` 和 `maven.compiler.target` 均为 `1.8`）。除非任务明确要求升级，否则新增代码、依赖和 API 必须保持 Java 8 兼容。\n- 主要 SDK 模块包括：\n  - `weixin-java-common`：各模块共用的基础类型、工具、异常、HTTP 与配置能力。\n  - `weixin-java-mp`：微信公众号。\n  - `weixin-java-miniapp`：微信小程序。\n  - `weixin-java-pay`：微信支付。\n  - `weixin-java-cp`：企业微信。\n  - `weixin-java-open`：微信开放平台。\n  - `weixin-java-channel`：微信视频号、微信小店。\n  - `weixin-java-qidian`：微信客服相关能力。\n  - `weixin-java-aispeech`：微信智能语音。\n  - `weixin-graal`：GraalVM 相关支持。\n- 集成模块主要位于：\n  - `spring-boot-starters`：Spring Boot Starter 及多账号 Starter。\n  - `solon-plugins`：Solon 插件及多账号插件。\n  - `wx-java-bom`：统一管理对外模块版本的 BOM。\n- `README.md` 说明整体能力和使用方式，`CONTRIBUTING.md` 规定代码贡献要求，`docs` 保存补充文档。\n\n## 开发流程\n\n1. 确认任务涉及的微信产品和 Maven 模块，先查找同模块中的相似接口、Bean、实现类和测试。\n2. 阅读目标模块及其父级 `pom.xml`，确认依赖、测试框架和已有实现方式。\n3. 优先沿用现有的包结构、命名、序列化、HTTP 执行器、异常处理及配置模式。\n4. 以最小变更完成任务；不要在功能修改中夹带依赖升级、全局格式化或无关重构。\n5. 为修复或新增行为添加有针对性的测试，并先运行受影响模块的验证。\n6. 交付前检查 diff、测试结果、兼容性和文档影响，明确报告未执行或无法执行的验证。\n\n## 代码风格与兼容性\n\n- 遵循 `.editorconfig`：使用空格缩进、缩进宽度为 2、UTF-8、LF、文件末尾保留换行，并清除非 Markdown 文件的行尾空格。\n- 保持目标文件现有代码风格；避免仅为个人偏好调整 import、换行、注释或成员顺序。\n- 不使用 Java 9 及以上语言特性或仅在新版本 JDK 中存在的 API。\n- 项目使用 Lombok；新增或修改 Lombok 用法时遵循相邻代码模式，不要在同一变更中无理由改写为手工样板代码。\n- 公共 API、序列化字段、枚举值、常量、默认实现和依赖范围都可能影响下游用户，修改时优先保持源码、二进制和行为兼容。\n- 不要随意改变已有异常类型、空值语义、默认 HTTP 客户端、JSON/XML 映射或配置加载行为。\n- 新增依赖前先确认现有依赖能否满足需求；依赖版本应在合适的父 POM 或 BOM 中统一管理，避免模块间版本漂移。\n\n## API 与实现约定\n\n- 对接微信接口时，以对应产品的官方接口定义和仓库内现有同类实现为依据，核对请求路径、HTTP 方法、字段名、必填项和返回结构。\n- Java 字段名可以符合项目命名习惯，但传输层字段名必须与微信接口保持一致；需要时使用项目现有的 Gson、Jackson 或 XStream 映射方式。\n- 新增 Service API 时同步检查接口、实现类、请求/响应 Bean、URL 常量、序列化适配器和测试是否都需要更新。\n- 涉及多个 HTTP 客户端实现时，保持 Apache HttpClient、HttpComponents、OkHttp 和 Jodd 等现有实现的能力一致；不要只修复其中一种而遗漏其他可选实现。\n- 涉及 Starter 或插件时，检查单账号与多账号版本以及自动配置、配置属性和示例测试是否需要同步。\n- 公共方法需要清晰的 Javadoc，至少准确描述参数、返回值、异常和必要约束；不要编写与实现不一致的模板化注释。\n- 不吞掉异常，不使用空 `catch`，不在日志中泄露 token、secret、密钥、签名原文或用户敏感数据。\n\n## 测试与验证\n\n- 项目测试主要使用 TestNG；沿用目标模块已有测试基类、数据提供器、Mock 方式和资源布局。\n- 修复 bug 时应添加能够复现旧行为并验证修复结果的回归测试；新增公共方法必须配套单元测试。\n- 优先执行受影响模块及其依赖的测试：\n\n```shell\nmvn -pl <module> -am test\n```\n\n- 运行单个测试类时，可在对应模块范围内执行：\n\n```shell\nmvn -pl <module> -am -Dtest=<TestClass> -Dsurefire.failIfNoSpecifiedTests=false test\n```\n\n- 跨公共模块、父 POM、BOM 或多个产品模块的变更应扩大验证范围；条件允许时执行：\n\n```shell\nmvn test\n```\n\n- 对仅需确认编译且测试依赖外部凭据的场景，可执行模块级编译或打包，但不得把跳过测试的构建描述为“测试通过”。\n- 部分测试可能依赖微信凭据、网络或本地配置。不得提交真实凭据；无法运行时应说明原因以及已完成的替代验证。\n- 完成前至少运行 `git diff --check`，并人工检查 `git diff`，确认没有意外文件、调试代码、生成物或敏感信息。\n\n## 文档与依赖变更\n\n- 用户可见的 API、配置项、模块使用方式或兼容性发生变化时，同步更新相关 Javadoc、README 或 `docs` 文档。\n- 示例中的版本号、模块名和配置键应与当前项目保持一致；不要复制未经验证的外部示例。\n- 修改根 POM、父 POM 或 `wx-java-bom` 时，检查所有子模块和对外依赖管理的影响。\n- 不提交构建输出、IDE 临时文件、测试报告、真实配置文件或本地备份文件。\n\n## Git 与 Pull Request 规范\n\n- 贡献目标分支为 `develop`；`release` 用于正式版本发布，不应作为常规 Pull Request 的目标分支。\n- 提交前保持工作区变更聚焦，不覆盖或回退用户已有的无关修改。\n- Commit 和 Pull Request 应说明变更动机、影响模块、兼容性风险和验证方式；关联已有 Issue 时写明编号。\n- 不得在未经用户明确授权的情况下执行 `git push`、创建或合并 Pull Request、改写历史或执行破坏性 Git 操作。\n- 不要使用 `git reset --hard`、强制 checkout 等方式清理不属于当前任务的改动。\n\n## 安全与敏感数据\n\n- 禁止提交 AppID 对应的 secret、access token、API v3 密钥、商户私钥、证书私钥、用户数据或其他真实凭据。\n- 测试和文档使用明显的占位值或脱敏数据；日志应避免输出查询串、请求体或响应体中的敏感字段。\n- 涉及签名、验签、加解密、证书、回调通知和支付金额时，重点检查字符编码、字段排序、精度、时区、重放风险和资源关闭。\n- 涉及网络请求、文件或流时，检查超时、异常路径、资源释放、响应关闭和大数据量下的内存行为。\n\n## Review 指南\n\n- 重点检查空指针、并发、资源释放、兼容性问题。\n- 不要只做代码风格建议，优先指出真实 bug 和回归风险。\n- 所有 Pull Request Review 的总结、结论和行内评论必须使用简体中文。\n- 技术标识符、类名、方法名、变量名、日志、错误信息及代码片段保持原文，不要翻译。\n- 严重程度标识可以保留 `P0`、`P1`、`P2` 等英文缩写。\n- 如果没有发现需要阻止合并的问题，也必须使用简体中文给出结论。\n- Review 结论必须基于当前 diff 和仓库中可验证的行为；不确定时明确说明假设，不要把推测写成确定缺陷。\n- 仅报告由本次变更引入或暴露、且作者可以采取行动的问题，并指出具体文件、位置、触发条件和影响。\n- 重点关注微信接口契约、Java 8 兼容性、公共 API 兼容性、序列化字段、HTTP 客户端实现一致性、Starter 多账号场景及敏感信息泄露。\n- 不要仅因缺少全仓库测试、个人风格偏好或与本次变更无关的历史代码而阻止合并。\n\n## Agent 完成检查清单\n\n- 已确认并遵循相关模块、相邻代码和更具体的 `AGENTS.md`。\n- 变更范围与任务直接相关，没有覆盖用户的无关修改。\n- 新增代码保持 Java 8、公共 API 和序列化兼容性。\n- 必要的测试与文档已经更新。\n- 已执行与风险匹配的构建或测试，并如实记录结果。\n- 已检查完整 diff、格式、生成物和敏感信息。\n- 最终回复使用简体中文，简要列出修改内容、验证结果和任何剩余风险。\n","skills/wxjava-api-contributor/SKILL.md":"---\nname: wxjava-api-contributor\ndescription: 按 WxJava 的 Maven 多模块、Java 8、公共 API 兼容性和 TestNG 约定，为微信官方接口新增或维护 SDK 支持。适用于新增 Service API、请求响应 Bean、序列化、HTTP 实现、Starter 配置或回归测试时。\n---\n\n# WxJava 接口贡献\n\n1. 先搜索开放与已关闭 Issue，确认需求是否已有讨论、实现、回归用例或官方接口变动；再确认微信产品和目标模块。\n2. 阅读对应 README、POM、相似接口、实现与测试，并读取 [贡献约定](references/contribution.md)。\n3. 将官方接口契约映射到 Service、实现、Bean、URL、序列化和测试；列出所有可能受影响的 HTTP 客户端和 Starter。\n4. 只做完成需求所需的最小改动；更新必要 Javadoc、测试与用户可见文档。\n5. 执行 `mvn -pl <module> -am test`，并检查 `git diff --check`。\n\n保持 Java 8 与公共 API、异常语义、JSON/XML 字段兼容性。涉及多 HTTP 客户端、单/多账号 Starter 或 Solon 插件时，检查等价实现是否需要同步。PR 应关联对应 Issue，目标分支为 `develop`。\n","skills/wxjava-api-contributor/agents/openai.yaml":"interface:\n  display_name: \"WxJava 接口贡献\"\n  short_description: \"按 WxJava 项目约定新增或维护 SDK 接口能力\"\n  default_prompt: \"使用 $wxjava-api-contributor 为 WxJava 新增微信接口支持。\"\n","skills/wxjava-api-contributor/references/contribution.md":"# 贡献约定\n\n以微信官方接口定义和本仓库同类实现为准，核对路径、方法、字段名、必填项和响应结构。优先复用既有 HTTP 执行器、异常、配置、Gson/Jackson/XStream 映射和 TestNG 测试模式。\n\n公共方法需要准确 Javadoc。不要吞异常、记录敏感值或无关重构。新增公开方法和 bug 修复均应有针对性测试；涉及公共模块、BOM 或多模块时扩大验证范围。\n\n## 接口增量检查表\n\n1. 从微信官方文档和相关 Issue 中确认接口可用条件、HTTP 方法、URL、必填字段、签名/加密要求和响应示例。\n2. 搜索同产品的相邻能力，复用其 Service 分层、Bean 命名、请求执行和错误处理模式；不要只新增 Bean 而遗漏 Service 暴露。\n3. 若接口尚未支持，优先使用现有通用执行能力；MP/CP Wiki 说明通用执行器会处理 access token 刷新及 `errcode` 到异常的转换。\n4. 为字段边界、空值、JSON/XML 映射和异常路径添加 TestNG 回归测试。API 路径或字段问题是历史 bug 的高频来源，例如 [#3982](https://github.com/binarywang/WxJava/issues/3982)、[#4000](https://github.com/binarywang/WxJava/issues/4000)。\n5. 按 [贡献指南](https://github.com/binarywang/WxJava/blob/develop/CONTRIBUTING.md) 使用 `develop` 作为 PR 目标；说明 Issue、兼容性影响和验证命令。\n\n## 一手资料入口\n\n- [如何调用 MP 未支持接口](https://github.com/binarywang/WxJava/wiki/MP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [如何调用 CP 未支持接口](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [关闭的新接口 Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3A%E6%96%B0%E6%8E%A5%E5%8F%A3)\n","skills/wxjava-integration-guide/SKILL.md":"---\nname: wxjava-integration-guide\ndescription: 为 Java、Spring Boot 或 Solon 项目生成可验证的 WxJava 接入方案，包括模块选择、BOM、配置、最小调用代码以及单/多账号集成。适用于用户要求接入公众号、小程序、支付、企业微信、开放平台、视频号或微信小店时。\n---\n\n# WxJava 接入指南\n\n1. 确认微信产品、框架、单/多账号、部署形态和首个 API 调用。\n2. 读取 [接入约束](references/integration.md)，选择模块和配置方式。\n3. 先输出依赖与配置，再输出最小调用；每段示例注明应放置的位置和所依赖的模块。\n4. 输出脱敏配置和最小服务端代码；凭据一律用占位符。\n5. 给出本地验证步骤与安全提醒；支付、回调和证书示例不得直接用于生产。\n\n保持 Java 8 兼容。生产集群必须使用可共享的配置存储或 token 存储；不要把内存实现当作多节点部署方案。引用已有 Demo、Wiki 或 README 作为继续阅读入口；不虚构配置键、SDK 方法或版本号。\n","skills/wxjava-integration-guide/agents/openai.yaml":"interface:\n  display_name: \"WxJava 接入指南\"\n  short_description: \"生成可验证的 WxJava 最小接入方案与配置示例\"\n  default_prompt: \"使用 $wxjava-integration-guide 为我的项目生成 WxJava 接入代码。\"\n","skills/wxjava-integration-guide/references/integration.md":"# 接入约束\n\n优先通过 `wx-java-bom` 统一管理多个 WxJava 模块版本。核心 SDK 模块是 MP、MiniApp、Pay、CP、Open、Channel、Qidian、Aispeech；框架集成模块位于 `spring-boot-starters` 与 `solon-plugins`。\n\n查阅相应模块 README、根目录 [demo.md](https://github.com/binarywang/WxJava/blob/develop/demo.md) 和目标模块测试中的示例，确认配置属性与初始化模式。所有 `appId`、`secret`、商户私钥、API v3 密钥和证书均使用占位符，不得输出到日志。\n\n## 实施检查表\n\n1. 先完成一条只读或低风险 API 调用，再接入消息、支付或异步回调。\n2. 单实例可使用默认配置存储；多实例或集群需使用共享的 token/config storage，避免节点各自刷新 access token。\n3. 公众号、企业微信等回调必须先按平台要求校验消息合法性，再进入业务路由；支付回调还必须按商户单号实现幂等。\n4. 需要代理或私有网络出口时，明确区分正向代理与反向代理。支付 V3 的签名路径不能因反向代理路径前缀而被错误改写。\n5. HTTP 客户端类型、Starter 配置键和 Service 实现必须取自目标模块的当前 README、POM 或相邻 Demo；不要混用不同产品模块的配置前缀。\n6. Starter 自动配置与 Demo 手动初始化必须二选一后再给示例。发生空 key、注入为空或 NPE 时，先核对启动模块、profile、配置前缀和当前 `*Properties` 类；历史 [#2177](https://github.com/binarywang/WxJava/issues/2177) 是混用两种配置模型的案例。\n7. Quarkus 或 GraalVM 场景转到 [Quarkus 支持文档](https://github.com/binarywang/WxJava/blob/develop/docs/QUARKUS_SUPPORT.md)，不要套用 Spring Boot Starter 配置。\n\n## 一手资料入口\n\n- [MP Quick Start](https://github.com/binarywang/WxJava/wiki/MP_Quick-Start)\n- [微信支付说明](https://github.com/binarywang/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98)\n- [SDK 正反向代理支持](https://github.com/binarywang/WxJava/wiki/SDK-%E9%92%88%E5%AF%B9%E5%BE%AE%E4%BF%A1-%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E5%92%8C%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%94%AF%E6%8C%81)\n- [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md)\n","skills/wxjava-module-selector/SKILL.md":"---\nname: wxjava-module-selector\ndescription: 根据微信公众号、小程序、微信支付、企业微信、开放平台、视频号或微信小店、腾讯企点和微信智能对话等业务场景，为用户选择合适的 WxJava Maven 模块、BOM 和示例入口。适用于用户询问“该用哪个模块”、依赖坐标、产品边界或单/多账号 Starter 选择时。\n---\n\n# WxJava 模块选择\n\n1. 识别微信产品、服务端框架、是否多账号、是否包含支付或回调；信息不足时只询问必要问题。\n2. 读取 [模块映射](references/modules.md)，给出一个主推荐，以及组合模块的理由。\n3. 先区分产品边界，再选择核心 SDK；仅当项目确实依赖框架自动配置时才额外推荐 Starter 或 Solon 插件。\n4. 优先推荐 BOM；给出准确的 `groupId`、`artifactId`、相应 Demo、Wiki 或仓库文档入口。\n5. 说明服务端 SDK 的边界：移动端登录、分享等能力仍需微信官方客户端 SDK。\n6. 不臆测版本号；建议以 Maven Central 或项目 README 的当前版本为准。\n\n使用“场景 → 模块 → 集成选项 → 下一步”的简短结构。涉及多账号时说明单账号与 multi Starter 的区别；不要在示例中泄露凭据。支付和回调场景必须提醒用户验证通知 URL、验签与幂等处理。\n","skills/wxjava-module-selector/agents/openai.yaml":"interface:\n  display_name: \"WxJava 模块选择\"\n  short_description: \"按微信业务场景选择 WxJava 模块、依赖与示例\"\n  default_prompt: \"使用 $wxjava-module-selector 为我的微信业务选择合适的 WxJava 模块。\"\n","skills/wxjava-module-selector/references/modules.md":"# WxJava 模块映射\n\n| 场景 | 核心模块 |\n| --- | --- |\n| 微信公众号 | `weixin-java-mp` |\n| 微信小程序 | `weixin-java-miniapp` |\n| 微信支付 | `weixin-java-pay` |\n| 企业微信 | `weixin-java-cp` |\n| 微信开放平台／第三方平台 | `weixin-java-open` |\n| 视频号／微信小店 | `weixin-java-channel` |\n| 腾讯企点／微信客服 | `weixin-java-qidian` |\n| 微信智能对话／智能语音 | `weixin-java-aispeech` |\n\n多个模块并用时优先使用 `com.github.binarywang:wx-java-bom`。Spring Boot 集成从 `spring-boot-starters` 选择；Solon 集成从 `solon-plugins` 选择。\n\n## 多账号集成范围\n\n只有多个独立微信应用配置时才选择 multi 集成，并先按框架与产品核对目录是否存在：\n\n- Spring Boot：MP、MiniApp、CP、自建/第三方 CP、Pay、Open、Channel 都有相应 multi Starter。\n- Solon：仅 MP、MiniApp、CP、Channel 有 multi 插件；Pay、Open、Qidian 目前只有单账号插件，不要推荐不存在的 multi artifact。\n\n## 选择检查点\n\n- 公众号、小程序和企业微信的消息回调、token 与加解密配置彼此独立；不要因同属一个公司而复用不兼容的凭据或配置对象。\n- 企业微信的多应用应使用独立的 `WxCpConfigStorage` 与 `WxCpServiceImpl`；Wiki 明确指出复用 token、AES key 和 URL 会造成安全边界问题。\n- 支付能力通常与 MP、MiniApp 或 Open 同时使用：前者处理业务身份和消息，`weixin-java-pay` 处理商户签名、证书与支付回调。\n- 视频号／微信小店接口属于 `weixin-java-channel`；不要误归入 MP 或 Pay。\n- 腾讯企点与微信智能对话是独立 SDK 模块；不要将客服或智能对话需求默认归入 MP、CP 或 Channel。\n- 当能力在 MP 与 Open 等模块可能重叠时，按授权主体、官方 API 域和回调场景选择，不要只按“移动端”或“登录”字样判断。先在当前源码和 Issue 中确认覆盖状态，并标注“已确认 / 待查 / 需自行调用底层接口”。\n- BOM 适合同时使用多个 WxJava 模块。若项目还导入 Spring Boot 等上游 BOM，升级后执行 `mvn help:effective-pom` 与 `mvn dependency:tree`；历史 [#4058](https://github.com/binarywang/WxJava/issues/4058) 表明依赖管理顺序可能影响 Spring Data Redis 等依赖。\n\n## 一手资料入口\n\n- [WxJava Wiki 首页](https://github.com/binarywang/WxJava/wiki)\n- [企业微信多应用配置](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E6%94%AF%E6%8C%81%E5%A4%9A%E4%B8%AA%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8%E6%88%96%E4%BC%81%E4%B8%9A%E5%8F%B7)\n- [视频号／微信小店开发文档](https://github.com/binarywang/WxJava/wiki/0_%E8%A7%86%E9%A2%91%E5%8F%B7_%E5%BE%AE%E4%BF%A1%E5%B0%8F%E5%BA%97%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)\n","skills/wxjava-troubleshooter/SKILL.md":"---\nname: wxjava-troubleshooter\ndescription: 排查 WxJava 在配置初始化、access token、签名验签、支付证书、回调通知、序列化、网络请求和多账号隔离方面的问题。适用于用户提供异常、日志、请求响应或“WxJava 为什么不能调用”的场景。\n---\n\n# WxJava 故障排查\n\n1. 收集最小复现：产品模块、SDK 版本、JDK、框架、依赖树、异常堆栈、请求 ID 与脱敏后的配置形状。\n2. 将故障归类为依赖/初始化、token 与存储、请求契约、HTTP/代理、回调验签、支付证书或并发与生命周期。\n3. 依据 [诊断清单](references/diagnostics.md)，按最低成本、最可验证的顺序排查。\n4. 每次只提出一个可验证根因，给出最小修复、预期现象和回归验证动作。\n5. 签名、支付、回调和加密场景须核对编码、字段排序、金额精度、时间戳、证书链和重放保护。\n\n要求遮蔽 secret、token、私钥、证书、签名原文和个人数据。不要建议关闭 TLS 校验或验签；区分已证实结论与待验证假设。遇到历史同类问题时，给出对应 Issue 或 Wiki 链接，但必须检查当前版本的实现后再套用修复。\n","skills/wxjava-troubleshooter/agents/openai.yaml":"interface:\n  display_name: \"WxJava 故障排查\"\n  short_description: \"定位 WxJava 配置、回调、签名与接口调用问题\"\n  default_prompt: \"使用 $wxjava-troubleshooter 排查我的 WxJava 调用异常。\"\n","skills/wxjava-troubleshooter/references/diagnostics.md":"# 诊断清单\n\n- 配置：模块是否正确，应用标识和凭据是否配对，多账号配置是否被正确选择。\n- 请求：HTTP 方法、路径、必填字段和 JSON/XML 映射是否符合微信接口契约。\n- 认证：token 缓存、签名字段、时间戳、nonce、证书和密钥格式是否有效。\n- 网络：DNS、代理、超时、TLS 证书校验和响应关闭是否正常。\n- 回调：回调 URL 可访问、验签参数完整、幂等处理和资源释放是否存在。\n\n从精确异常和最小请求入手，不用“重试”替代根因分析。\n\n## 高频场景\n\n| 症状 | 优先检查 | 依据 |\n| --- | --- | --- |\n| 多节点间歇性 token 失效 | 是否共享 token/config storage，是否让各节点并发刷新 | Wiki 的 MP/CP 配置存储说明与集群案例 |\n| `NoClassDefFoundError`、`NoSuchMethodError` | `mvn dependency:tree`、HttpClient/commons-lang/xstream 冲突及 BOM 是否统一版本 | Wiki 的异常排查页与 HTTP 客户端升级指南 |\n| 回调验签或重复处理 | 原始请求体、时间戳/nonce/签名、回调 URL、业务幂等键 | MP 合法性校验与支付回调说明 |\n| HTTP 连接、超时或代理问题 | 连接/读取超时、代理、TLS、正反向代理是否混用 | Wiki 的 HttpClient 参数与代理文档 |\n| 企业微信会话存档崩溃 | 是否仍手动销毁旧 SDK 实例，是否已迁移安全 API | [会话存档安全使用指南](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_SDK_SAFE_USAGE.md) |\n| 视频号/小店接口 404 或字段不匹配 | 当前官方路径与请求字段、目标 SDK 版本、历史 Issue 是否已修复 | 关闭的 bug Issue，如 [#3982](https://github.com/binarywang/WxJava/issues/3982) |\n\n## 一手资料入口\n\n- [常见异常首页](https://github.com/binarywang/WxJava/wiki)\n- [MP 消息合法性验证](https://github.com/binarywang/WxJava/wiki/MP_%E9%AA%8C%E8%AF%81%E6%B6%88%E6%81%AF%E5%90%88%E6%B3%95%E6%80%A7)\n- [HttpClient 参数配置](https://github.com/binarywang/WxJava/wiki/HttpClient%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0%E7%9A%84%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%B3%95)\n- [关闭的 bug Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3Abug)\n","skills/wxjava-upgrade-guide/SKILL.md":"---\nname: wxjava-upgrade-guide\ndescription: 规划 WxJava 的版本升级与迁移，检查 BOM、模块依赖、Java 版本、配置与公共 API 兼容性，并提供可回滚的验证步骤。适用于用户从旧版升级、切换依赖管理方式、处理兼容性告警或制定升级发布计划时。\n---\n\n# WxJava 升级迁移\n\n1. 收集当前与目标版本、已用模块、JDK、框架、BOM 使用情况、依赖树、代理配置和关键调用路径。\n2. 读取 [迁移检查表](references/migration.md)，识别版本、依赖和配置边界。\n3. 按 HTTP 客户端、BOM、支付/回调、多账号、企业微信会话存档等变化类型选择迁移分支。\n4. 输出分阶段变更：依赖调整、编译、关键回归测试、灰度与明确回滚条件。\n5. 将不确定项标为待查，并引导查看目标版本的 release notes、README、Javadoc 与变更记录。\n\n不要猜测废弃 API 或破坏性变更；以官方发布信息、当前代码与实际编译结果为准。默认保持 Java 8，除非目标版本明确改变此约束。不能以关闭验签、固定 token 或跳过测试作为回滚方案。\n","skills/wxjava-upgrade-guide/agents/openai.yaml":"interface:\n  display_name: \"WxJava 升级迁移\"\n  short_description: \"规划 WxJava 版本升级、依赖调整与兼容性迁移\"\n  default_prompt: \"使用 $wxjava-upgrade-guide 制定 WxJava 版本升级方案。\"\n","skills/wxjava-upgrade-guide/references/migration.md":"# 迁移检查表\n\n- 使用多个 WxJava 模块时，优先迁移到 `wx-java-bom`，避免模块版本漂移。\n- 清点 MP、MiniApp、Pay、CP、Open、Channel 及框架 Starter/插件的实际依赖。\n- 更新后先执行编译和受影响模块测试，再验证 token、回调、支付和关键业务链路。\n- 为依赖版本保留可快速恢复的变更记录；按灰度策略验证生产环境，且不将凭据写入代码或日志。\n\n## 升级分支\n\n### HTTP 客户端\n\n从 4.7.x 起，项目支持并推荐 Apache HttpClient 5.x，同时保留部分 4.x 兼容性。先按 [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md) 核对模块、依赖与 `http-client-type`，再检查代理 host、port、username、password 的完整性。历史 [#3836](https://github.com/binarywang/WxJava/issues/3836) 表明可选代理配置也需要回归。\n\n### BOM 与依赖冲突\n\n`wx-java-bom` 从 4.8.3.B 起提供。导入 BOM 前后均执行：\n\n```shell\nmvn help:effective-pom\nmvn dependency:tree\n```\n\n特别回归由 Spring Boot BOM 管理的 Redis、HTTP 客户端和序列化依赖；[#4058](https://github.com/binarywang/WxJava/issues/4058) 是历史冲突案例。\n\n### 企业微信会话存档\n\n升级到 4.8.0 或更高版本时，查找旧的 `getChatDatas`、`getDecryptData`、`getChatPlainText`、`getMediaFile` 和手动 `Finance.DestroySdk()`。按 [ThreadLocal 生命周期迁移文档](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_THREADLOCAL_LIFECYCLE_REFACTOR.md) 切换至新 API，并做并发验证。\n\nThreadLocal SDK 不会在线程结束时自动释放。在线程池、定时任务或一次性线程中，必须在任务的 `finally` 块调用 `msgAuditService.closeThreadLocalSdk()`；应用停止时再用 `closeAllSdks()` 做全局兜底。不要在业务代码中直接调用 `Finance.DestroySdk()`。\n\n### 回调与支付\n\n验证不止于 HTTP 2xx：分别覆盖 token 获取、签名/证书校验、重复回调、业务状态转换和多账号路由。多账号异步任务必须显式传递 appId 或服务上下文，不能假定 ThreadLocal 自动继承。\n\n## 验证与回滚\n\n按“编译和单测 → 非生产凭据冒烟 → 灰度和监控”执行。出现依赖树冲突、验签/证书异常、回调错误或 native 崩溃时停止扩大灰度，恢复上一个已验证依赖组合后再以最小复现定位。\n","solon-plugins/wx-java-channel-multi-solon-plugin/README.md":"# wx-java-channel-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.channel.apps.tenantId1.app-id=@appId\n    wx.channel.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId1.use-stable-access-token=false\n    wx.channel.apps.tenantId1.token=\n    wx.channel.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.channel.apps.tenantId2.app-id=@appId\n    wx.channel.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId2.use-stable-access-token=false\n    wx.channel.apps.tenantId2.token=\n    wx.channel.apps.tenantId2.aes-key=\n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel:multi(默认)\n    wx.channel.config-storage.key-prefix=wx:channel:multi\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxChannelMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.channel.service.WxChannelMultiServices;\n    import me.chanjar.weixin.channel.api.WxChannelService;\n    import me.chanjar.weixin.channel.api.WxFinderLiveService;\n    import me.chanjar.weixin.channel.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n    \n    @Component\n    public class DemoService {\n      @Inject\n      private WxChannelMultiServices wxChannelMultiServices;\n    \n      public void test() throws WxErrorException {\n        // 应用 1 的 WxChannelService\n        WxChannelService wxChannelService1 = wxChannelMultiServices.getWxChannelService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxChannelService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 2 的 WxChannelService\n        WxChannelService wxChannelService2 = wxChannelMultiServices.getWxChannelService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxChannelService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 3 的 WxChannelService\n        WxChannelService wxChannelService3 = wxChannelMultiServices.getWxChannelService(\"tenantId3\");\n        // 判断是否为空\n        if (wxChannelService3 == null) {\n          // todo wxChannelService3 为空，请先配置 tenantId3 微信视频号应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxChannelService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n","solon-plugins/wx-java-channel-solon-plugin/README.md":"# wx-java-channel-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 视频号小店的appId和secret\n    wx.channel.app-id=@appId\n    wx.channel.secret=@secret\n    # 视频号配置 选填\n    ## 设置视频号小店消息服务器配置的token\n    wx.channel.token=@token\n    ## 设置视频号小店消息服务器配置的EncodingAESKey\n    wx.channel.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.channel.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.channel.use-stable-access-token=false\n    \n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel(默认)\n    wx.channel.config-storage.key-prefix=wx:channel\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n \n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxChannelService`\n- `WxChannelConfig`\n4. 使用样例\n\n```java\nimport me.chanjar.weixin.channel.api.WxChannelService;\nimport me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;\nimport me.chanjar.weixin.channel.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxChannelService wxChannelService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxChannelService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n\n","solon-plugins/wx-java-cp-multi-solon-plugin/README.md":"# wx-java-cp-multi-solon-plugin\n\n企业微信多账号配置\n\n- 实现多 WxCpService 初始化。\n- 未实现 WxCpTpService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n- 未实现 WxCpCgService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n\n## 关于 corp-secret 的说明\n\n企业微信中不同功能模块对应不同的 `corp-secret`，每种 Secret 只对对应模块的接口具有调用权限：\n\n| Secret 类型 | 获取位置 | 可调用的接口 | 是否需要 agent-id |\n|---|---|---|---|\n| 自建应用 Secret | 应用管理 → 自建应用 → 选择应用 → 查看 Secret | 该应用有权限的接口 | **必填** |\n| 通讯录同步 Secret | 管理工具 → 通讯录同步 → 查看 Secret | 部门/成员增删改查等通讯录接口 | **不填** |\n| 客户联系 Secret | 客户联系 → API → Secret | 客户联系相关接口 | 不填 |\n\n> **常见问题**：\n> - 使用自建应用 Secret + agent-id 可以获取部门列表，但**无法更新部门**（因为写接口需要通讯录同步权限）\n> - 使用通讯录同步 Secret 可以同步部门，但**调用某些需要 agent-id 的应用接口会报错**\n\n如需同时使用多种权限范围，可在 `wx.cp.corps` 下配置多个条目，每个条目使用对应权限的 Secret，通过不同的 `tenantId` 区分后使用。\n\n> **注意**：\n> 当前插件实现会校验同一 `corp-id` 下的 `agent-id` **必须唯一**，并且 **只能有一个条目不填写 `agent-id`**。\n> 如果在同一 `corp-id` 下同时配置多个未填写 `agent-id` 的条目，会因 token/ticket 缓存 key 冲突而在启动时直接抛异常。\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 自建应用 1 配置（使用自建应用 Secret，需填写 agent-id）\n    wx.cp.corps.app1.corp-id = @corp-id\n    wx.cp.corps.app1.corp-secret = @自建应用的Secret（在\"应用管理-自建应用\"中查看）\n    wx.cp.corps.app1.agent-id = @自建应用的AgentId\n    ## 选填\n    wx.cp.corps.app1.token = @token\n    wx.cp.corps.app1.aes-key = @aes-key\n    wx.cp.corps.app1.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.corps.app1.msg-audit-lib-path = @msg-audit-lib-path\n\n    # 通讯录同步配置（使用通讯录同步 Secret，不需要填写 agent-id）\n    # 此配置用于部门、成员的增删改查等通讯录管理操作\n    wx.cp.corps.contact.corp-id = @corp-id\n    wx.cp.corps.contact.corp-secret = @通讯录同步的Secret（在\"管理工具-通讯录同步\"中查看）\n    ## agent-id 不填，通讯录同步不需要 agentId\n\n    # 公共配置\n    ## ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    ## http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.cp.config-storage.http-client-type=http_client\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.cp_multi.service.WxCpMultiServices;\nimport me.chanjar.weixin.cp.api.WxCpDepartmentService;\nimport me.chanjar.weixin.cp.api.WxCpService;\nimport me.chanjar.weixin.cp.api.WxCpUserService;\nimport me.chanjar.weixin.cp.bean.WxCpDepart;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxCpMultiServices wxCpMultiServices;\n\n  public void test() {\n    // 使用自建应用的 WxCpService（对应 corp-secret 为自建应用 Secret）\n    WxCpService appService = wxCpMultiServices.getWxCpService(\"app1\");\n    WxCpUserService userService = appService.getUserService();\n    userService.getUserId(\"xxx\");\n    // todo ...\n\n    // 使用通讯录同步的 WxCpService（对应 corp-secret 为通讯录同步 Secret）\n    // 通讯录同步 Secret 具有部门/成员增删改查等权限\n    WxCpService contactService = wxCpMultiServices.getWxCpService(\"contact\");\n    WxCpDepartmentService departmentService = contactService.getDepartmentService();\n    // 更新部门示例（WxCpDepart 包含 id、name、parentId 等字段）\n    WxCpDepart depart = new WxCpDepart();\n    depart.setId(100L);\n    depart.setName(\"新部门名称\");\n    departmentService.update(depart);\n    // todo ...\n  }\n}\n```\n","solon-plugins/wx-java-cp-solon-plugin/README.md":"# wx-java-cp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 企业微信号配置(必填)\n    wx.cp.corp-id = @corp-id\n    wx.cp.corp-secret = @corp-secret\n    # 选填\n    wx.cp.agent-id = @agent-id\n    wx.cp.token = @token\n    wx.cp.aes-key = @aes-key\n    wx.cp.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.msg-audit-lib-path = @msg-audit-lib-path\n    # ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    # http 客户端配置（选填）\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpService`, `WxCpConfigStorage`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n\n- WxCpService\n- WxCpConfigStorage\n","solon-plugins/wx-java-miniapp-multi-solon-plugin/README.md":"# wx-java-miniapp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.ma.apps.tenantId1.app-id=appId\n    wx.ma.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.ma.apps.tenantId1.token=@token\n    wx.ma.apps.tenantId1.aes-key=@aesKey\n    wx.ma.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.ma.apps.tenantId2.app-id=@appId\n    wx.ma.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.ma.apps.tenantId2.token=@token\n    wx.ma.apps.tenantId2.aes-key=@aesKey\n    wx.ma.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson\n    wx.ma.config-storage.type=memory\n    ## 相关redis前缀配置: wx:ma:multi(默认)\n    wx.ma.config-storage.key-prefix=wx:ma:multi\n    wx.ma.config-storage.redis.host=127.0.0.1\n    wx.ma.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.ma.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.ma.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.ma.config-storage.http-client-type=http_client\n    wx.ma.config-storage.http-proxy-host=\n    wx.ma.config-storage.http-proxy-port=\n    wx.ma.config-storage.http-proxy-username=\n    wx.ma.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.ma.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.ma.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxMaMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.miniapp.service.WxMaMultiServices;\nimport cn.binarywang.wx.miniapp.api.WxMaService;\nimport cn.binarywang.wx.miniapp.api.WxMaUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMaMultiServices wxMaMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMaService\n    WxMaService wxMaService1 = wxMaMultiServices.getWxMaService(\"tenantId1\");\n    WxMaUserService userService1 = wxMaService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMaService\n    WxMaService wxMaService2 = wxMaMultiServices.getWxMaService(\"tenantId2\");\n    WxMaUserService userService2 = wxMaService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMaService\n    WxMaService wxMaService3 = wxMaMultiServices.getWxMaService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMaService3 == null) {\n      // todo wxMaService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMaUserService userService3 = wxMaService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n","solon-plugins/wx-java-miniapp-solon-plugin/README.md":"# wx-java-miniapp-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.miniapp.appid = appId\n    wx.miniapp.secret = @secret\n    wx.miniapp.token = @token\n    wx.miniapp.aesKey = @aesKey\n    wx.miniapp.msgDataFormat = @msgDataFormat                  # 消息格式，XML或者JSON.\n    # 存储配置redis(可选)\n    # 注意: 指定redis.host值后不会使用容器注入的redis连接(JedisPool)\n    wx.miniapp.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.miniapp.config-storage.key-prefix = wa                  # 相关redis前缀配置: wa(默认)\n    wx.miniapp.config-storage.redis.host = 127.0.0.1\n    wx.miniapp.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.miniapp.config-storage.http-client-type=HttpClient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.miniapp.config-storage.http-proxy-host=\n    wx.miniapp.config-storage.http-proxy-port=\n    wx.miniapp.config-storage.http-proxy-username=\n    wx.miniapp.config-storage.http-proxy-password=\n    ```\n3. 自动注入的类型\n- `WxMaService`\n- `WxMaConfig`\n\n","solon-plugins/wx-java-mp-multi-solon-plugin/README.md":"# wx-java-mp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.mp.apps.tenantId1.app-id=appId\n    wx.mp.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.mp.apps.tenantId1.token=@token\n    wx.mp.apps.tenantId1.aes-key=@aesKey\n    wx.mp.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.mp.apps.tenantId2.app-id=@appId\n    wx.mp.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.mp.apps.tenantId2.token=@token\n    wx.mp.apps.tenantId2.aes-key=@aesKey\n    wx.mp.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.mp.config-storage.type=memory\n    ## 相关redis前缀配置: wx:mp:multi(默认)\n    wx.mp.config-storage.key-prefix=wx:mp:multi\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.mp.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.mp.config-storage.http-client-type=http_client\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.mp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.mp.config-storage.retry-sleep-millis=1000\n   \n\t  # 公众号地址 host 配置\n\t  # wx.mp.hosts.api-host=http://proxy.com/\n\t  # wx.mp.hosts.open-host=http://proxy.com/\n\t  # wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型：`WxMpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.mp_multi.service.WxMpMultiServices;\nimport me.chanjar.weixin.mp.api.WxMpService;\nimport me.chanjar.weixin.mp.api.WxMpUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMpMultiServices wxMpMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMpService\n    WxMpService wxMpService1 = wxMpMultiServices.getWxMpService(\"tenantId1\");\n    WxMpUserService userService1 = wxMpService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMpService\n    WxMpService wxMpService2 = wxMpMultiServices.getWxMpService(\"tenantId2\");\n    WxMpUserService userService2 = wxMpService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMpService\n    WxMpService wxMpService3 = wxMpMultiServices.getWxMpService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMpService3 == null) {\n      // todo wxMpService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMpUserService userService3 = wxMpService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n","solon-plugins/wx-java-mp-solon-plugin/README.md":"# wx-java-mp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.mp.app-id=appId\n    wx.mp.secret=@secret\n    wx.mp.token=@token\n    wx.mp.aes-key=@aesKey\n    wx.mp.use-stable-access-token=@useStableAccessToken\n    # 存储配置redis(可选)\n    wx.mp.config-storage.type= edis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.mp.config-storage.key-prefix=wx                  # 相关redis前缀配置: wx(默认)\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  #单机和sentinel同时存在时，优先使用sentinel配置\n\t  #wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  #wx.mp.config-storage.redis.sentinel-name=mymaster\n    # http客户端配置\n    wx.mp.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n\t  # 公众号地址host配置\n\t  #wx.mp.hosts.api-host=http://proxy.com/\n\t  #wx.mp.hosts.open-host=http://proxy.com/\n\t  #wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型\n\n- `WxMpService`\n- `WxMpConfigStorage`\n\n4、参考demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n","solon-plugins/wx-java-open-solon-plugin/README.md":"# wx-java-open-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-open-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.open.appId = appId\n    wx.open.secret = @secret\n    wx.open.token = @token\n    wx.open.aesKey = @aesKey\n    # 存储配置redis(可选)\n    # 优先注入容器的(JedisPool, RedissonClient), 当配置了wx.open.config-storage.redis.host, 不会使用容器注入redis连接配置\n    wx.open.config-storage.type = redis                     # 配置类型: memory(默认), redis(jedis), jedis, redisson, redistemplate\n    wx.open.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n    wx.open.config-storage.redis.host = 127.0.0.1\n    wx.open.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.open.config-storage.http-client-type=httpclient      # http客户端类型: httpclient(默认)\n    wx.open.config-storage.http-proxy-host=\n    wx.open.config-storage.http-proxy-port=\n    wx.open.config-storage.http-proxy-username=\n    wx.open.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.open.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.open.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxOpenService, WxOpenMessageRouter, WxOpenComponentService`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n  - WxOpenConfigStorage\n  - WxOpenService\n","solon-plugins/wx-java-pay-solon-plugin/README.md":"# 使用说明\n1. 在自己的Solon项目里，引入maven依赖\n```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-pay-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n ```\n2. 添加配置(app.yml)\n###### 1）V2版本\n```yml\nwx:\n  pay:\n    appId: \n    mchId: \n    mchKey: \n    keyPath:\n```\n###### 2）V3版本\n```yml\nwx:\n  pay:\n    appId: xxxxxxxxxxx\n    mchId: 15xxxxxxxxx #商户id\n    apiHostUrl: http://10.0.0.1:3128 # 可选：代理主机\n    apiHostUrlPath: /api-weixin # 可选：代理入口前缀\n    apiV3Key: Dc1DBwSc094jACxxxxxxxxxxxxxxx #V3密钥\n    certSerialNo: 62C6CEAA360BCxxxxxxxxxxxxxxx\n    privateKeyPath: classpath:cert/apiclient_key.pem #apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径\n    privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n###### 3）V3服务商版本\n```yml\nwx:\n  pay: #微信服务商支付\n    configs:\n    - appId: wxe97b2x9c2b3d #spAppId\n      mchId: 16486610 #服务商商户\n      subAppId: wx118cexxe3c07679 #子appId\n      subMchId: 16496705 #子商户\n      apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr #apiV3密钥\n      privateKeyPath: classpath:cert/apiclient_key.pem #服务商证书文件，apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径（可以配置绝对路径）\n      privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n","solon-plugins/wx-java-qidian-solon-plugin/README.md":"# wx-java-qidian-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n   ```xml\n   <dependency>\n       <groupId>com.github.binarywang</groupId>\n       <artifactId>wx-java-qidian-solon-plugin</artifactId>\n       <version>${version}</version>\n   </dependency>\n   ```\n2. 添加配置(app.properties)\n   ```properties\n   # 公众号配置(必填)\n   wx.qidian.appId = appId\n   wx.qidian.secret = @secret\n   wx.qidian.token = @token\n   wx.qidian.aesKey = @aesKey\n   # 存储配置redis(可选)\n   wx.qidian.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n   wx.qidian.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n   wx.qidian.config-storage.redis.host = 127.0.0.1\n   wx.qidian.config-storage.redis.port = 6379\n   #单机和sentinel同时存在时，优先使用sentinel配置\n   #wx.qidian.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n   #wx.qidian.config-storage.redis.sentinel-name=mymaster\n   # http客户端配置\n   wx.qidian.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n   wx.qidian.config-storage.http-proxy-host=\n   wx.qidian.config-storage.http-proxy-port=\n   wx.qidian.config-storage.http-proxy-username=\n   wx.qidian.config-storage.http-proxy-password=\n   # 公众号地址host配置\n   #wx.qidian.hosts.api-host=http://proxy.com/\n   #wx.qidian.hosts.open-host=http://proxy.com/\n   #wx.qidian.hosts.mp-host=http://proxy.com/\n   ```\n3. 自动注入的类型\n\n- `WxQidianService`\n- `WxQidianConfigStorage`\n\n4、参考 demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n","solon-plugins/wx-java-store-multi-solon-plugin/README.md":"# wx-java-store-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.store.apps.tenantId1.app-id=@appId\n    wx.store.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId1.use-stable-access-token=false\n    wx.store.apps.tenantId1.token=\n    wx.store.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.store.apps.tenantId2.app-id=@appId\n    wx.store.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId2.use-stable-access-token=false\n    wx.store.apps.tenantId2.token=\n    wx.store.apps.tenantId2.aes-key=\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store:multi(默认)\n    wx.store.config-storage.key-prefix=wx:store:multi\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxStoreMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.store.service.WxStoreMultiServices;\n    import com.binarywang.wxjava.store.api.WxStoreService;\n    import com.binarywang.wxjava.store.api.WxFinderLiveService;\n    import com.binarywang.wxjava.store.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n\n    @Component\n    public class DemoService {\n      @Inject\n      private WxStoreMultiServices wxStoreMultiServices;\n\n      public void test() throws WxErrorException {\n        // 应用 1 的 WxStoreService\n        WxStoreService wxStoreService1 = wxStoreMultiServices.getWxStoreService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxStoreService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 2 的 WxStoreService\n        WxStoreService wxStoreService2 = wxStoreMultiServices.getWxStoreService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxStoreService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 3 的 WxStoreService\n        WxStoreService wxStoreService3 = wxStoreMultiServices.getWxStoreService(\"tenantId3\");\n        // 判断是否为空\n        if (wxStoreService3 == null) {\n          // todo wxStoreService3 为空，请先配置 tenantId3 微信小店应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxStoreService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n","solon-plugins/wx-java-store-solon-plugin/README.md":"# wx-java-store-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 微信小店的appId和secret\n    wx.store.app-id=@appId\n    wx.store.secret=@secret\n    # 视频号配置 选填\n    ## 设置微信小店消息服务器配置的token\n    wx.store.token=@token\n    ## 设置微信小店消息服务器配置的EncodingAESKey\n    wx.store.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.store.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.store.use-stable-access-token=false\n\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store(默认)\n    wx.store.config-storage.key-prefix=wx:store\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxStoreService`\n- `WxStoreConfig`\n4. 使用样例\n\n```java\nimport com.binarywang.wxjava.store.api.WxStoreService;\nimport com.binarywang.wxjava.store.bean.shop.ShopInfoResponse;\nimport com.binarywang.wxjava.store.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxStoreService wxStoreService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxStoreService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# WxJava Agent 指南\n\n## 适用范围与指令优先级\n\n- 本文件适用于整个仓库，供本地编码 Agent、自动化 Agent 和 Pull Request Review Agent 使用。\n- 开始工作前先阅读与任务直接相关的 `README.md`、`CONTRIBUTING.md`、模块 `pom.xml`、现有实现和测试；不要仅凭通用经验推断项目约定。\n- 若子目录存在更具体的 `AGENTS.md`，处理该目录文件时优先遵循距离目标文件最近的说明。\n- 用户的明确要求优先于本文件；若要求与兼容性、安全性或仓库约定冲突，应先说明风险，不要静默偏离。\n- 只修改完成任务所必需的文件，不处理无关格式、重构或历史遗留问题。\n\n## 项目概览\n\n- WxJava 是面向微信生态的 Java SDK，采用 Maven 多模块结构。\n- 当前根项目要求 Java 8（`maven.compiler.source` 和 `maven.compiler.target` 均为 `1.8`）。除非任务明确要求升级，否则新增代码、依赖和 API 必须保持 Java 8 兼容。\n- 主要 SDK 模块包括：\n  - `weixin-java-common`：各模块共用的基础类型、工具、异常、HTTP 与配置能力。\n  - `weixin-java-mp`：微信公众号。\n  - `weixin-java-miniapp`：微信小程序。\n  - `weixin-java-pay`：微信支付。\n  - `weixin-java-cp`：企业微信。\n  - `weixin-java-open`：微信开放平台。\n  - `weixin-java-channel`：微信视频号、微信小店。\n  - `weixin-java-qidian`：微信客服相关能力。\n  - `weixin-java-aispeech`：微信智能语音。\n  - `weixin-graal`：GraalVM 相关支持。\n- 集成模块主要位于：\n  - `spring-boot-starters`：Spring Boot Starter 及多账号 Starter。\n  - `solon-plugins`：Solon 插件及多账号插件。\n  - `wx-java-bom`：统一管理对外模块版本的 BOM。\n- `README.md` 说明整体能力和使用方式，`CONTRIBUTING.md` 规定代码贡献要求，`docs` 保存补充文档。\n\n## 开发流程\n\n1. 确认任务涉及的微信产品和 Maven 模块，先查找同模块中的相似接口、Bean、实现类和测试。\n2. 阅读目标模块及其父级 `pom.xml`，确认依赖、测试框架和已有实现方式。\n3. 优先沿用现有的包结构、命名、序列化、HTTP 执行器、异常处理及配置模式。\n4. 以最小变更完成任务；不要在功能修改中夹带依赖升级、全局格式化或无关重构。\n5. 为修复或新增行为添加有针对性的测试，并先运行受影响模块的验证。\n6. 交付前检查 diff、测试结果、兼容性和文档影响，明确报告未执行或无法执行的验证。\n\n## 代码风格与兼容性\n\n- 遵循 `.editorconfig`：使用空格缩进、缩进宽度为 2、UTF-8、LF、文件末尾保留换行，并清除非 Markdown 文件的行尾空格。\n- 保持目标文件现有代码风格；避免仅为个人偏好调整 import、换行、注释或成员顺序。\n- 不使用 Java 9 及以上语言特性或仅在新版本 JDK 中存在的 API。\n- 项目使用 Lombok；新增或修改 Lombok 用法时遵循相邻代码模式，不要在同一变更中无理由改写为手工样板代码。\n- 公共 API、序列化字段、枚举值、常量、默认实现和依赖范围都可能影响下游用户，修改时优先保持源码、二进制和行为兼容。\n- 不要随意改变已有异常类型、空值语义、默认 HTTP 客户端、JSON/XML 映射或配置加载行为。\n- 新增依赖前先确认现有依赖能否满足需求；依赖版本应在合适的父 POM 或 BOM 中统一管理，避免模块间版本漂移。\n\n## API 与实现约定\n\n- 对接微信接口时，以对应产品的官方接口定义和仓库内现有同类实现为依据，核对请求路径、HTTP 方法、字段名、必填项和返回结构。\n- Java 字段名可以符合项目命名习惯，但传输层字段名必须与微信接口保持一致；需要时使用项目现有的 Gson、Jackson 或 XStream 映射方式。\n- 新增 Service API 时同步检查接口、实现类、请求/响应 Bean、URL 常量、序列化适配器和测试是否都需要更新。\n- 涉及多个 HTTP 客户端实现时，保持 Apache HttpClient、HttpComponents、OkHttp 和 Jodd 等现有实现的能力一致；不要只修复其中一种而遗漏其他可选实现。\n- 涉及 Starter 或插件时，检查单账号与多账号版本以及自动配置、配置属性和示例测试是否需要同步。\n- 公共方法需要清晰的 Javadoc，至少准确描述参数、返回值、异常和必要约束；不要编写与实现不一致的模板化注释。\n- 不吞掉异常，不使用空 `catch`，不在日志中泄露 token、secret、密钥、签名原文或用户敏感数据。\n\n## 测试与验证\n\n- 项目测试主要使用 TestNG；沿用目标模块已有测试基类、数据提供器、Mock 方式和资源布局。\n- 修复 bug 时应添加能够复现旧行为并验证修复结果的回归测试；新增公共方法必须配套单元测试。\n- 优先执行受影响模块及其依赖的测试：\n\n```shell\nmvn -pl <module> -am test\n```\n\n- 运行单个测试类时，可在对应模块范围内执行：\n\n```shell\nmvn -pl <module> -am -Dtest=<TestClass> -Dsurefire.failIfNoSpecifiedTests=false test\n```\n\n- 跨公共模块、父 POM、BOM 或多个产品模块的变更应扩大验证范围；条件允许时执行：\n\n```shell\nmvn test\n```\n\n- 对仅需确认编译且测试依赖外部凭据的场景，可执行模块级编译或打包，但不得把跳过测试的构建描述为“测试通过”。\n- 部分测试可能依赖微信凭据、网络或本地配置。不得提交真实凭据；无法运行时应说明原因以及已完成的替代验证。\n- 完成前至少运行 `git diff --check`，并人工检查 `git diff`，确认没有意外文件、调试代码、生成物或敏感信息。\n\n## 文档与依赖变更\n\n- 用户可见的 API、配置项、模块使用方式或兼容性发生变化时，同步更新相关 Javadoc、README 或 `docs` 文档。\n- 示例中的版本号、模块名和配置键应与当前项目保持一致；不要复制未经验证的外部示例。\n- 修改根 POM、父 POM 或 `wx-java-bom` 时，检查所有子模块和对外依赖管理的影响。\n- 不提交构建输出、IDE 临时文件、测试报告、真实配置文件或本地备份文件。\n\n## Git 与 Pull Request 规范\n\n- 贡献目标分支为 `develop`；`release` 用于正式版本发布，不应作为常规 Pull Request 的目标分支。\n- 提交前保持工作区变更聚焦，不覆盖或回退用户已有的无关修改。\n- Commit 和 Pull Request 应说明变更动机、影响模块、兼容性风险和验证方式；关联已有 Issue 时写明编号。\n- 不得在未经用户明确授权的情况下执行 `git push`、创建或合并 Pull Request、改写历史或执行破坏性 Git 操作。\n- 不要使用 `git reset --hard`、强制 checkout 等方式清理不属于当前任务的改动。\n\n## 安全与敏感数据\n\n- 禁止提交 AppID 对应的 secret、access token、API v3 密钥、商户私钥、证书私钥、用户数据或其他真实凭据。\n- 测试和文档使用明显的占位值或脱敏数据；日志应避免输出查询串、请求体或响应体中的敏感字段。\n- 涉及签名、验签、加解密、证书、回调通知和支付金额时，重点检查字符编码、字段排序、精度、时区、重放风险和资源关闭。\n- 涉及网络请求、文件或流时，检查超时、异常路径、资源释放、响应关闭和大数据量下的内存行为。\n\n## Review 指南\n\n- 重点检查空指针、并发、资源释放、兼容性问题。\n- 不要只做代码风格建议，优先指出真实 bug 和回归风险。\n- 所有 Pull Request Review 的总结、结论和行内评论必须使用简体中文。\n- 技术标识符、类名、方法名、变量名、日志、错误信息及代码片段保持原文，不要翻译。\n- 严重程度标识可以保留 `P0`、`P1`、`P2` 等英文缩写。\n- 如果没有发现需要阻止合并的问题，也必须使用简体中文给出结论。\n- Review 结论必须基于当前 diff 和仓库中可验证的行为；不确定时明确说明假设，不要把推测写成确定缺陷。\n- 仅报告由本次变更引入或暴露、且作者可以采取行动的问题，并指出具体文件、位置、触发条件和影响。\n- 重点关注微信接口契约、Java 8 兼容性、公共 API 兼容性、序列化字段、HTTP 客户端实现一致性、Starter 多账号场景及敏感信息泄露。\n- 不要仅因缺少全仓库测试、个人风格偏好或与本次变更无关的历史代码而阻止合并。\n\n## Agent 完成检查清单\n\n- 已确认并遵循相关模块、相邻代码和更具体的 `AGENTS.md`。\n- 变更范围与任务直接相关，没有覆盖用户的无关修改。\n- 新增代码保持 Java 8、公共 API 和序列化兼容性。\n- 必要的测试与文档已经更新。\n- 已执行与风险匹配的构建或测试，并如实记录结果。\n- 已检查完整 diff、格式、生成物和敏感信息。\n- 最终回复使用简体中文，简要列出修改内容、验证结果和任何剩余风险。\n","isInternal":false,"tokens":3123,"sizeBytes":9188},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/.github/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"# Copilot Instruction\n请始终使用中文生成 Pull Request 的标题、描述和提交信息\n\n\n# WxJava - 微信 Java SDK 开发说明\n\nWxJava 是一个支持多种微信平台的完整 Java SDK，包含公众号、小程序、微信支付、企业微信、开放平台、视频号、企点等多种功能模块。\n\n**请始终优先参考本说明，只有在遇到与此内容不一致的意外信息时，才退而使用搜索或 bash 命令。**\n\n## 高效开发指南\n\n### 前置条件与环境准备\n- **Java 要求**：JDK 8+（项目最低目标为 Java 8）\n- **Maven**：推荐 Maven 3.6+（已验证 Maven 3.9.11）\n- **IDE**：推荐使用 IntelliJ IDEA（项目针对 IDEA 优化）\n\n### 引导、构建与校验\n克隆仓库后按顺序执行以下命令：\n\n```bash\n# 1. 基础编译（请勿中断 - 约需 4-5 分钟）\nmvn clean compile -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 8 分钟以上。实际时间：约 4 分钟\n\n# 2. 完整打包（请勿中断 - 约需 2-3 分钟）  \nmvn clean package -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 5 分钟以上。实际时间：约 2 分钟\n\n# 3. 代码质量校验（请勿中断 - 约需 45-60 秒）\nmvn checkstyle:check --no-transfer-progress\n# 超时时间：建议设置 3 分钟以上。实际时间：约 50 秒\n```\n\n重要时间说明：\n- 绝对不要中断任意 Maven 构建命令\n- 编译阶段耗时最长（约 4 分钟），原因是项目包含 34 个模块\n- 后续构建会更快，因为存在增量编译\n- 始终使用 `--no-transfer-progress` 以减少日志噪音\n\n### 测试结构\n- **测试框架**：TestNG（非 JUnit）\n- **测试文件**：共有 298 个测试文件\n- **默认行为**：pom.xml 中默认禁用测试（`<skip>true</skip>`）\n- **测试配置**：测试需要通过 test-config.xml 提供真实的微信 API 凭据\n- **注意**：没有真实微信 API 凭据请不要尝试运行测试，测试将会失败\n\n## 项目结构与导航\n\n### 核心 SDK 模块（主要开发区）\n- `weixin-java-common/` - 通用工具与基础类（最重要）\n- `weixin-java-mp/` - 公众号 SDK\n- `weixin-java-pay/` - 微信支付 SDK\n- `weixin-java-miniapp/` - 小程序 SDK\n- `weixin-java-cp/` - 企业微信 SDK\n- `weixin-java-open/` - 开放平台 SDK\n- `weixin-java-channel/` - 视频号 / Channel SDK\n- `weixin-java-qidian/` - 企点 SDK\n\n### 框架集成模块\n- `spring-boot-starters/` - Spring Boot 自动配置 starter\n- `solon-plugins/` - Solon 框架插件\n- `weixin-graal/` - GraalVM 本地镜像支持\n\n### 配置与质量控制\n- `quality-checks/google_checks.xml` - Checkstyle 配置\n- `.editorconfig` - 代码格式规则（2 个空格等于 1 个制表）\n- `pom.xml` - 根级 Maven 配置\n\n## 开发工作流\n\n### 修改代码的流程\n1. 修改前务必先构建以建立干净基线：\n   ```bash\n   mvn clean compile --no-transfer-progress\n   ```\n\n2. 遵循代码风格（由 checkstyle 强制）：\n   - 缩进使用 2 个空格（不要用制表符）\n   - 遵循 Google Java 风格指南\n   - 在 IDE 中安装 EditorConfig 插件\n\n3. 增量验证修改：\n   ```bash\n   # 每次修改后运行：\n   mvn compile --no-transfer-progress\n   mvn checkstyle:check --no-transfer-progress\n   ```\n\n### 提交修改前的必须校验\n请务必按顺序完成以下校验步骤：\n\n1. 代码风格校验：\n   ```bash\n   mvn checkstyle:check --no-transfer-progress\n   # 必须通过 - 约需 50 秒\n   ```\n\n2. 完整清理构建：\n   ```bash\n   mvn clean package -DskipTests=true --no-transfer-progress  \n   # 必须成功 - 约需 2 分钟\n   ```\n\n3. 文档：为公共方法和类补充或更新 javadoc\n4. 贡献规范：遵循 `CONTRIBUTING.md`，Pull Request 必须以 `develop` 分支为目标\n\n## 模块依赖与构建顺序\n\n### 核心模块依赖（构建顺序）\n1. `weixin-graal`（GraalVM 支持）\n2. `weixin-java-common`（所有模块的基础）\n3. 核心 SDK 模块（mp、pay、miniapp、cp、open、channel、qidian）\n4. 框架集成（spring-boot-starters、solon-plugins）\n\n### 主要关系模式\n- 所有 SDK 模块都依赖于 `weixin-java-common`\n- Spring Boot starters 依赖对应的 SDK 模块\n- Solon 插件遵循与 Spring Boot starters 相同的依赖模式\n- 每个模块都有单账号与多账号配置支持\n\n## 常见任务与命令\n\n### 验证指定模块\n```bash\n# 构建单个模块（将 'weixin-java-mp' 替换为目标模块）：\ncd weixin-java-mp\nmvn clean compile --no-transfer-progress\n```\n\n### 检查依赖\n```bash\n# 分析依赖树：\nmvn dependency:tree --no-transfer-progress\n\n# 检查依赖更新：  \n./others/check-dependency-updates.sh\n```\n\n### 发布与发布准备\n```bash\n# 版本检查：\nmvn versions:display-property-updates --no-transfer-progress\n\n# 部署（需要凭据）：\nmvn clean deploy -P release --no-transfer-progress\n```\n\n## 重要文件与位置\n\n### 配置文件\n- `pom.xml` - 根级 Maven 配置与依赖管理\n- `quality-checks/google_checks.xml` - Checkstyle 规则\n- `.editorconfig` - IDE 格式化配置\n- `.github/workflows/maven-publish.yml` - CI/CD 工作流\n\n### 文档\n- `README.md` - 项目概览与使用说明（中文）\n- `CONTRIBUTING.md` - 贡献指南\n- `demo.md` - 示例项目与演示链接\n- 每个模块均有单独的文档与示例\n\n### 测试资源\n- `*/src/test/resources/test-config.sample.xml` - 测试配置模板\n- 测试运行需要真实的微信 API 凭据\n\n## SDK 使用模式\n\n### Maven 依赖示例\n```xml\n<dependency>\n  <groupId>com.github.binarywang</groupId>\n  <artifactId>weixin-java-mp</artifactId>  <!-- 或其他模块 -->\n  <version>4.7.0</version>\n</dependency>\n```\n\n### 常见开发区域\n- **API 客户端实现**：位于 `*/service/impl/` 目录\n- **模型类**：位于 `*/bean/` 目录\n- **配置**：位于 `*/config/` 目录\n- **工具类**：位于 `weixin-java-common` 的 `*/util/` 目录\n\n## 故障排查\n\n### 构建问题\n- **OutOfMemoryError**：增加 Maven 内存：`export MAVEN_OPTS=\"-Xmx2g\"`\n- **编译失败**：通常为依赖问题 - 先执行 `mvn clean`\n- **Checkstyle 失败**：检查 IDE 的 `.editorconfig` 设置\n\n### 常见陷阱\n- **测试默认跳过**：这是正常现象 — 测试需要微信 API 凭据\n- **多模块变更**：总是在仓库根目录构建，而不是单独模块\n- **分支目标**：Pull Request 必须以 `develop` 分支为目标，而不是 `master` 或 `release`\n\n## 性能说明\n- **首次构建**：由于依赖下载，耗时 4-5 分钟\n- **增量构建**：通常更快（约 30-60 秒）\n- **Checkstyle**：运行迅速（约 50 秒），应当经常运行\n- **IDE 性能**：项目使用 Lombok，请确保启用注解处理\n\n注意：本项目为 SDK 库项目，而非可运行应用。修改应以 API 功能为主，不要改动应用级行为。\n","isInternal":false,"tokens":2434,"sizeBytes":6815},{"name":"openai.yaml","path":"skills/wxjava-api-contributor/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-api-contributor/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"WxJava 接口贡献\"\n  short_description: \"按 WxJava 项目约定新增或维护 SDK 接口能力\"\n  default_prompt: \"使用 $wxjava-api-contributor 为 WxJava 新增微信接口支持。\"\n","isInternal":false,"tokens":72,"sizeBytes":218},{"name":"contribution.md","path":"skills/wxjava-api-contributor/references/contribution.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-api-contributor/references/contribution.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# 贡献约定\n\n以微信官方接口定义和本仓库同类实现为准，核对路径、方法、字段名、必填项和响应结构。优先复用既有 HTTP 执行器、异常、配置、Gson/Jackson/XStream 映射和 TestNG 测试模式。\n\n公共方法需要准确 Javadoc。不要吞异常、记录敏感值或无关重构。新增公开方法和 bug 修复均应有针对性测试；涉及公共模块、BOM 或多模块时扩大验证范围。\n\n## 接口增量检查表\n\n1. 从微信官方文档和相关 Issue 中确认接口可用条件、HTTP 方法、URL、必填字段、签名/加密要求和响应示例。\n2. 搜索同产品的相邻能力，复用其 Service 分层、Bean 命名、请求执行和错误处理模式；不要只新增 Bean 而遗漏 Service 暴露。\n3. 若接口尚未支持，优先使用现有通用执行能力；MP/CP Wiki 说明通用执行器会处理 access token 刷新及 `errcode` 到异常的转换。\n4. 为字段边界、空值、JSON/XML 映射和异常路径添加 TestNG 回归测试。API 路径或字段问题是历史 bug 的高频来源，例如 [#3982](https://github.com/binarywang/WxJava/issues/3982)、[#4000](https://github.com/binarywang/WxJava/issues/4000)。\n5. 按 [贡献指南](https://github.com/binarywang/WxJava/blob/develop/CONTRIBUTING.md) 使用 `develop` 作为 PR 目标；说明 Issue、兼容性影响和验证命令。\n\n## 一手资料入口\n\n- [如何调用 MP 未支持接口](https://github.com/binarywang/WxJava/wiki/MP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [如何调用 CP 未支持接口](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [关闭的新接口 Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3A%E6%96%B0%E6%8E%A5%E5%8F%A3)\n","isInternal":false,"tokens":725,"sizeBytes":1910},{"name":"SKILL.md","path":"skills/wxjava-api-contributor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-api-contributor/SKILL.md","title":"wxjava-api-contributor","category":"anthropic-skill","format":"markdown","content":"---\nname: wxjava-api-contributor\ndescription: 按 WxJava 的 Maven 多模块、Java 8、公共 API 兼容性和 TestNG 约定，为微信官方接口新增或维护 SDK 支持。适用于新增 Service API、请求响应 Bean、序列化、HTTP 实现、Starter 配置或回归测试时。\n---\n\n# WxJava 接口贡献\n\n1. 先搜索开放与已关闭 Issue，确认需求是否已有讨论、实现、回归用例或官方接口变动；再确认微信产品和目标模块。\n2. 阅读对应 README、POM、相似接口、实现与测试，并读取 [贡献约定](references/contribution.md)。\n3. 将官方接口契约映射到 Service、实现、Bean、URL、序列化和测试；列出所有可能受影响的 HTTP 客户端和 Starter。\n4. 只做完成需求所需的最小改动；更新必要 Javadoc、测试与用户可见文档。\n5. 执行 `mvn -pl <module> -am test`，并检查 `git diff --check`。\n\n保持 Java 8 与公共 API、异常语义、JSON/XML 字段兼容性。涉及多 HTTP 客户端、单/多账号 Starter 或 Solon 插件时，检查等价实现是否需要同步。PR 应关联对应 Issue，目标分支为 `develop`。\n","frontmatter":{"name":"wxjava-api-contributor","description":"按 WxJava 的 Maven 多模块、Java 8、公共 API 兼容性和 TestNG 约定，为微信官方接口新增或维护 SDK 支持。适用于新增 Service API、请求响应 Bean、序列化、HTTP 实现、Starter 配置或回归测试时。"},"isInternal":false,"tokens":389,"sizeBytes":1152},{"name":"openai.yaml","path":"skills/wxjava-integration-guide/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-integration-guide/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"WxJava 接入指南\"\n  short_description: \"生成可验证的 WxJava 最小接入方案与配置示例\"\n  default_prompt: \"使用 $wxjava-integration-guide 为我的项目生成 WxJava 接入代码。\"\n","isInternal":false,"tokens":65,"sizeBytes":230},{"name":"integration.md","path":"skills/wxjava-integration-guide/references/integration.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-integration-guide/references/integration.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# 接入约束\n\n优先通过 `wx-java-bom` 统一管理多个 WxJava 模块版本。核心 SDK 模块是 MP、MiniApp、Pay、CP、Open、Channel、Qidian、Aispeech；框架集成模块位于 `spring-boot-starters` 与 `solon-plugins`。\n\n查阅相应模块 README、根目录 [demo.md](https://github.com/binarywang/WxJava/blob/develop/demo.md) 和目标模块测试中的示例，确认配置属性与初始化模式。所有 `appId`、`secret`、商户私钥、API v3 密钥和证书均使用占位符，不得输出到日志。\n\n## 实施检查表\n\n1. 先完成一条只读或低风险 API 调用，再接入消息、支付或异步回调。\n2. 单实例可使用默认配置存储；多实例或集群需使用共享的 token/config storage，避免节点各自刷新 access token。\n3. 公众号、企业微信等回调必须先按平台要求校验消息合法性，再进入业务路由；支付回调还必须按商户单号实现幂等。\n4. 需要代理或私有网络出口时，明确区分正向代理与反向代理。支付 V3 的签名路径不能因反向代理路径前缀而被错误改写。\n5. HTTP 客户端类型、Starter 配置键和 Service 实现必须取自目标模块的当前 README、POM 或相邻 Demo；不要混用不同产品模块的配置前缀。\n6. Starter 自动配置与 Demo 手动初始化必须二选一后再给示例。发生空 key、注入为空或 NPE 时，先核对启动模块、profile、配置前缀和当前 `*Properties` 类；历史 [#2177](https://github.com/binarywang/WxJava/issues/2177) 是混用两种配置模型的案例。\n7. Quarkus 或 GraalVM 场景转到 [Quarkus 支持文档](https://github.com/binarywang/WxJava/blob/develop/docs/QUARKUS_SUPPORT.md)，不要套用 Spring Boot Starter 配置。\n\n## 一手资料入口\n\n- [MP Quick Start](https://github.com/binarywang/WxJava/wiki/MP_Quick-Start)\n- [微信支付说明](https://github.com/binarywang/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98)\n- [SDK 正反向代理支持](https://github.com/binarywang/WxJava/wiki/SDK-%E9%92%88%E5%AF%B9%E5%BE%AE%E4%BF%A1-%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E5%92%8C%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%94%AF%E6%8C%81)\n- [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md)\n","isInternal":false,"tokens":822,"sizeBytes":2303},{"name":"SKILL.md","path":"skills/wxjava-integration-guide/SKILL.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-integration-guide/SKILL.md","title":"wxjava-integration-guide","category":"anthropic-skill","format":"markdown","content":"---\nname: wxjava-integration-guide\ndescription: 为 Java、Spring Boot 或 Solon 项目生成可验证的 WxJava 接入方案，包括模块选择、BOM、配置、最小调用代码以及单/多账号集成。适用于用户要求接入公众号、小程序、支付、企业微信、开放平台、视频号或微信小店时。\n---\n\n# WxJava 接入指南\n\n1. 确认微信产品、框架、单/多账号、部署形态和首个 API 调用。\n2. 读取 [接入约束](references/integration.md)，选择模块和配置方式。\n3. 先输出依赖与配置，再输出最小调用；每段示例注明应放置的位置和所依赖的模块。\n4. 输出脱敏配置和最小服务端代码；凭据一律用占位符。\n5. 给出本地验证步骤与安全提醒；支付、回调和证书示例不得直接用于生产。\n\n保持 Java 8 兼容。生产集群必须使用可共享的配置存储或 token 存储；不要把内存实现当作多节点部署方案。引用已有 Demo、Wiki 或 README 作为继续阅读入口；不虚构配置键、SDK 方法或版本号。\n","frontmatter":{"name":"wxjava-integration-guide","description":"为 Java、Spring Boot 或 Solon 项目生成可验证的 WxJava 接入方案，包括模块选择、BOM、配置、最小调用代码以及单/多账号集成。适用于用户要求接入公众号、小程序、支付、企业微信、开放平台、视频号或微信小店时。"},"isInternal":false,"tokens":364,"sizeBytes":1075},{"name":"openai.yaml","path":"skills/wxjava-module-selector/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-module-selector/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"WxJava 模块选择\"\n  short_description: \"按微信业务场景选择 WxJava 模块、依赖与示例\"\n  default_prompt: \"使用 $wxjava-module-selector 为我的微信业务选择合适的 WxJava 模块。\"\n","isInternal":false,"tokens":77,"sizeBytes":237},{"name":"modules.md","path":"skills/wxjava-module-selector/references/modules.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-module-selector/references/modules.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# WxJava 模块映射\n\n| 场景 | 核心模块 |\n| --- | --- |\n| 微信公众号 | `weixin-java-mp` |\n| 微信小程序 | `weixin-java-miniapp` |\n| 微信支付 | `weixin-java-pay` |\n| 企业微信 | `weixin-java-cp` |\n| 微信开放平台／第三方平台 | `weixin-java-open` |\n| 视频号／微信小店 | `weixin-java-channel` |\n| 腾讯企点／微信客服 | `weixin-java-qidian` |\n| 微信智能对话／智能语音 | `weixin-java-aispeech` |\n\n多个模块并用时优先使用 `com.github.binarywang:wx-java-bom`。Spring Boot 集成从 `spring-boot-starters` 选择；Solon 集成从 `solon-plugins` 选择。\n\n## 多账号集成范围\n\n只有多个独立微信应用配置时才选择 multi 集成，并先按框架与产品核对目录是否存在：\n\n- Spring Boot：MP、MiniApp、CP、自建/第三方 CP、Pay、Open、Channel 都有相应 multi Starter。\n- Solon：仅 MP、MiniApp、CP、Channel 有 multi 插件；Pay、Open、Qidian 目前只有单账号插件，不要推荐不存在的 multi artifact。\n\n## 选择检查点\n\n- 公众号、小程序和企业微信的消息回调、token 与加解密配置彼此独立；不要因同属一个公司而复用不兼容的凭据或配置对象。\n- 企业微信的多应用应使用独立的 `WxCpConfigStorage` 与 `WxCpServiceImpl`；Wiki 明确指出复用 token、AES key 和 URL 会造成安全边界问题。\n- 支付能力通常与 MP、MiniApp 或 Open 同时使用：前者处理业务身份和消息，`weixin-java-pay` 处理商户签名、证书与支付回调。\n- 视频号／微信小店接口属于 `weixin-java-channel`；不要误归入 MP 或 Pay。\n- 腾讯企点与微信智能对话是独立 SDK 模块；不要将客服或智能对话需求默认归入 MP、CP 或 Channel。\n- 当能力在 MP 与 Open 等模块可能重叠时，按授权主体、官方 API 域和回调场景选择，不要只按“移动端”或“登录”字样判断。先在当前源码和 Issue 中确认覆盖状态，并标注“已确认 / 待查 / 需自行调用底层接口”。\n- BOM 适合同时使用多个 WxJava 模块。若项目还导入 Spring Boot 等上游 BOM，升级后执行 `mvn help:effective-pom` 与 `mvn dependency:tree`；历史 [#4058](https://github.com/binarywang/WxJava/issues/4058) 表明依赖管理顺序可能影响 Spring Data Redis 等依赖。\n\n## 一手资料入口\n\n- [WxJava Wiki 首页](https://github.com/binarywang/WxJava/wiki)\n- [企业微信多应用配置](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E6%94%AF%E6%8C%81%E5%A4%9A%E4%B8%AA%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8%E6%88%96%E4%BC%81%E4%B8%9A%E5%8F%B7)\n- [视频号／微信小店开发文档](https://github.com/binarywang/WxJava/wiki/0_%E8%A7%86%E9%A2%91%E5%8F%B7_%E5%BE%AE%E4%BF%A1%E5%B0%8F%E5%BA%97%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)\n","isInternal":false,"tokens":1077,"sizeBytes":2842},{"name":"SKILL.md","path":"skills/wxjava-module-selector/SKILL.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-module-selector/SKILL.md","title":"wxjava-module-selector","category":"anthropic-skill","format":"markdown","content":"---\nname: wxjava-module-selector\ndescription: 根据微信公众号、小程序、微信支付、企业微信、开放平台、视频号或微信小店、腾讯企点和微信智能对话等业务场景，为用户选择合适的 WxJava Maven 模块、BOM 和示例入口。适用于用户询问“该用哪个模块”、依赖坐标、产品边界或单/多账号 Starter 选择时。\n---\n\n# WxJava 模块选择\n\n1. 识别微信产品、服务端框架、是否多账号、是否包含支付或回调；信息不足时只询问必要问题。\n2. 读取 [模块映射](references/modules.md)，给出一个主推荐，以及组合模块的理由。\n3. 先区分产品边界，再选择核心 SDK；仅当项目确实依赖框架自动配置时才额外推荐 Starter 或 Solon 插件。\n4. 优先推荐 BOM；给出准确的 `groupId`、`artifactId`、相应 Demo、Wiki 或仓库文档入口。\n5. 说明服务端 SDK 的边界：移动端登录、分享等能力仍需微信官方客户端 SDK。\n6. 不臆测版本号；建议以 Maven Central 或项目 README 的当前版本为准。\n\n使用“场景 → 模块 → 集成选项 → 下一步”的简短结构。涉及多账号时说明单账号与 multi Starter 的区别；不要在示例中泄露凭据。支付和回调场景必须提醒用户验证通知 URL、验签与幂等处理。\n","frontmatter":{"name":"wxjava-module-selector","description":"根据微信公众号、小程序、微信支付、企业微信、开放平台、视频号或微信小店、腾讯企点和微信智能对话等业务场景，为用户选择合适的 WxJava Maven 模块、BOM 和示例入口。适用于用户询问“该用哪个模块”、依赖坐标、产品边界或单/多账号 Starter 选择时。"},"isInternal":false,"tokens":458,"sizeBytes":1348},{"name":"openai.yaml","path":"skills/wxjava-troubleshooter/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-troubleshooter/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"WxJava 故障排查\"\n  short_description: \"定位 WxJava 配置、回调、签名与接口调用问题\"\n  default_prompt: \"使用 $wxjava-troubleshooter 排查我的 WxJava 调用异常。\"\n","isInternal":false,"tokens":70,"sizeBytes":218},{"name":"diagnostics.md","path":"skills/wxjava-troubleshooter/references/diagnostics.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-troubleshooter/references/diagnostics.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# 诊断清单\n\n- 配置：模块是否正确，应用标识和凭据是否配对，多账号配置是否被正确选择。\n- 请求：HTTP 方法、路径、必填字段和 JSON/XML 映射是否符合微信接口契约。\n- 认证：token 缓存、签名字段、时间戳、nonce、证书和密钥格式是否有效。\n- 网络：DNS、代理、超时、TLS 证书校验和响应关闭是否正常。\n- 回调：回调 URL 可访问、验签参数完整、幂等处理和资源释放是否存在。\n\n从精确异常和最小请求入手，不用“重试”替代根因分析。\n\n## 高频场景\n\n| 症状 | 优先检查 | 依据 |\n| --- | --- | --- |\n| 多节点间歇性 token 失效 | 是否共享 token/config storage，是否让各节点并发刷新 | Wiki 的 MP/CP 配置存储说明与集群案例 |\n| `NoClassDefFoundError`、`NoSuchMethodError` | `mvn dependency:tree`、HttpClient/commons-lang/xstream 冲突及 BOM 是否统一版本 | Wiki 的异常排查页与 HTTP 客户端升级指南 |\n| 回调验签或重复处理 | 原始请求体、时间戳/nonce/签名、回调 URL、业务幂等键 | MP 合法性校验与支付回调说明 |\n| HTTP 连接、超时或代理问题 | 连接/读取超时、代理、TLS、正反向代理是否混用 | Wiki 的 HttpClient 参数与代理文档 |\n| 企业微信会话存档崩溃 | 是否仍手动销毁旧 SDK 实例，是否已迁移安全 API | [会话存档安全使用指南](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_SDK_SAFE_USAGE.md) |\n| 视频号/小店接口 404 或字段不匹配 | 当前官方路径与请求字段、目标 SDK 版本、历史 Issue 是否已修复 | 关闭的 bug Issue，如 [#3982](https://github.com/binarywang/WxJava/issues/3982) |\n\n## 一手资料入口\n\n- [常见异常首页](https://github.com/binarywang/WxJava/wiki)\n- [MP 消息合法性验证](https://github.com/binarywang/WxJava/wiki/MP_%E9%AA%8C%E8%AF%81%E6%B6%88%E6%81%AF%E5%90%88%E6%B3%95%E6%80%A7)\n- [HttpClient 参数配置](https://github.com/binarywang/WxJava/wiki/HttpClient%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0%E7%9A%84%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%B3%95)\n- [关闭的 bug Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3Abug)\n","isInternal":false,"tokens":791,"sizeBytes":2256},{"name":"SKILL.md","path":"skills/wxjava-troubleshooter/SKILL.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-troubleshooter/SKILL.md","title":"wxjava-troubleshooter","category":"anthropic-skill","format":"markdown","content":"---\nname: wxjava-troubleshooter\ndescription: 排查 WxJava 在配置初始化、access token、签名验签、支付证书、回调通知、序列化、网络请求和多账号隔离方面的问题。适用于用户提供异常、日志、请求响应或“WxJava 为什么不能调用”的场景。\n---\n\n# WxJava 故障排查\n\n1. 收集最小复现：产品模块、SDK 版本、JDK、框架、依赖树、异常堆栈、请求 ID 与脱敏后的配置形状。\n2. 将故障归类为依赖/初始化、token 与存储、请求契约、HTTP/代理、回调验签、支付证书或并发与生命周期。\n3. 依据 [诊断清单](references/diagnostics.md)，按最低成本、最可验证的顺序排查。\n4. 每次只提出一个可验证根因，给出最小修复、预期现象和回归验证动作。\n5. 签名、支付、回调和加密场景须核对编码、字段排序、金额精度、时间戳、证书链和重放保护。\n\n要求遮蔽 secret、token、私钥、证书、签名原文和个人数据。不要建议关闭 TLS 校验或验签；区分已证实结论与待验证假设。遇到历史同类问题时，给出对应 Issue 或 Wiki 链接，但必须检查当前版本的实现后再套用修复。\n","frontmatter":{"name":"wxjava-troubleshooter","description":"排查 WxJava 在配置初始化、access token、签名验签、支付证书、回调通知、序列化、网络请求和多账号隔离方面的问题。适用于用户提供异常、日志、请求响应或“WxJava 为什么不能调用”的场景。"},"isInternal":false,"tokens":422,"sizeBytes":1226},{"name":"openai.yaml","path":"skills/wxjava-upgrade-guide/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-upgrade-guide/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"WxJava 升级迁移\"\n  short_description: \"规划 WxJava 版本升级、依赖调整与兼容性迁移\"\n  default_prompt: \"使用 $wxjava-upgrade-guide 制定 WxJava 版本升级方案。\"\n","isInternal":false,"tokens":78,"sizeBytes":217},{"name":"migration.md","path":"skills/wxjava-upgrade-guide/references/migration.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-upgrade-guide/references/migration.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# 迁移检查表\n\n- 使用多个 WxJava 模块时，优先迁移到 `wx-java-bom`，避免模块版本漂移。\n- 清点 MP、MiniApp、Pay、CP、Open、Channel 及框架 Starter/插件的实际依赖。\n- 更新后先执行编译和受影响模块测试，再验证 token、回调、支付和关键业务链路。\n- 为依赖版本保留可快速恢复的变更记录；按灰度策略验证生产环境，且不将凭据写入代码或日志。\n\n## 升级分支\n\n### HTTP 客户端\n\n从 4.7.x 起，项目支持并推荐 Apache HttpClient 5.x，同时保留部分 4.x 兼容性。先按 [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md) 核对模块、依赖与 `http-client-type`，再检查代理 host、port、username、password 的完整性。历史 [#3836](https://github.com/binarywang/WxJava/issues/3836) 表明可选代理配置也需要回归。\n\n### BOM 与依赖冲突\n\n`wx-java-bom` 从 4.8.3.B 起提供。导入 BOM 前后均执行：\n\n```shell\nmvn help:effective-pom\nmvn dependency:tree\n```\n\n特别回归由 Spring Boot BOM 管理的 Redis、HTTP 客户端和序列化依赖；[#4058](https://github.com/binarywang/WxJava/issues/4058) 是历史冲突案例。\n\n### 企业微信会话存档\n\n升级到 4.8.0 或更高版本时，查找旧的 `getChatDatas`、`getDecryptData`、`getChatPlainText`、`getMediaFile` 和手动 `Finance.DestroySdk()`。按 [ThreadLocal 生命周期迁移文档](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_THREADLOCAL_LIFECYCLE_REFACTOR.md) 切换至新 API，并做并发验证。\n\nThreadLocal SDK 不会在线程结束时自动释放。在线程池、定时任务或一次性线程中，必须在任务的 `finally` 块调用 `msgAuditService.closeThreadLocalSdk()`；应用停止时再用 `closeAllSdks()` 做全局兜底。不要在业务代码中直接调用 `Finance.DestroySdk()`。\n\n### 回调与支付\n\n验证不止于 HTTP 2xx：分别覆盖 token 获取、签名/证书校验、重复回调、业务状态转换和多账号路由。多账号异步任务必须显式传递 appId 或服务上下文，不能假定 ThreadLocal 自动继承。\n\n## 验证与回滚\n\n按“编译和单测 → 非生产凭据冒烟 → 灰度和监控”执行。出现依赖树冲突、验签/证书异常、回调错误或 native 崩溃时停止扩大灰度，恢复上一个已验证依赖组合后再以最小复现定位。\n","isInternal":false,"tokens":863,"sizeBytes":2453},{"name":"SKILL.md","path":"skills/wxjava-upgrade-guide/SKILL.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/skills/wxjava-upgrade-guide/SKILL.md","title":"wxjava-upgrade-guide","category":"anthropic-skill","format":"markdown","content":"---\nname: wxjava-upgrade-guide\ndescription: 规划 WxJava 的版本升级与迁移，检查 BOM、模块依赖、Java 版本、配置与公共 API 兼容性，并提供可回滚的验证步骤。适用于用户从旧版升级、切换依赖管理方式、处理兼容性告警或制定升级发布计划时。\n---\n\n# WxJava 升级迁移\n\n1. 收集当前与目标版本、已用模块、JDK、框架、BOM 使用情况、依赖树、代理配置和关键调用路径。\n2. 读取 [迁移检查表](references/migration.md)，识别版本、依赖和配置边界。\n3. 按 HTTP 客户端、BOM、支付/回调、多账号、企业微信会话存档等变化类型选择迁移分支。\n4. 输出分阶段变更：依赖调整、编译、关键回归测试、灰度与明确回滚条件。\n5. 将不确定项标为待查，并引导查看目标版本的 release notes、README、Javadoc 与变更记录。\n\n不要猜测废弃 API 或破坏性变更；以官方发布信息、当前代码与实际编译结果为准。默认保持 Java 8，除非目标版本明确改变此约束。不能以关闭验签、固定 token 或跳过测试作为回滚方案。\n","frontmatter":{"name":"wxjava-upgrade-guide","description":"规划 WxJava 的版本升级与迁移，检查 BOM、模块依赖、Java 版本、配置与公共 API 兼容性，并提供可回滚的验证步骤。适用于用户从旧版升级、切换依赖管理方式、处理兼容性告警或制定升级发布计划时。"},"isInternal":false,"tokens":407,"sizeBytes":1151},{"name":"README.md","path":"solon-plugins/wx-java-channel-multi-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-channel-multi-solon-plugin/README.md","title":"wx-java-channel-multi-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-channel-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.channel.apps.tenantId1.app-id=@appId\n    wx.channel.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId1.use-stable-access-token=false\n    wx.channel.apps.tenantId1.token=\n    wx.channel.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.channel.apps.tenantId2.app-id=@appId\n    wx.channel.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId2.use-stable-access-token=false\n    wx.channel.apps.tenantId2.token=\n    wx.channel.apps.tenantId2.aes-key=\n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel:multi(默认)\n    wx.channel.config-storage.key-prefix=wx:channel:multi\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxChannelMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.channel.service.WxChannelMultiServices;\n    import me.chanjar.weixin.channel.api.WxChannelService;\n    import me.chanjar.weixin.channel.api.WxFinderLiveService;\n    import me.chanjar.weixin.channel.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n    \n    @Component\n    public class DemoService {\n      @Inject\n      private WxChannelMultiServices wxChannelMultiServices;\n    \n      public void test() throws WxErrorException {\n        // 应用 1 的 WxChannelService\n        WxChannelService wxChannelService1 = wxChannelMultiServices.getWxChannelService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxChannelService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 2 的 WxChannelService\n        WxChannelService wxChannelService2 = wxChannelMultiServices.getWxChannelService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxChannelService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 3 的 WxChannelService\n        WxChannelService wxChannelService3 = wxChannelMultiServices.getWxChannelService(\"tenantId3\");\n        // 判断是否为空\n        if (wxChannelService3 == null) {\n          // todo wxChannelService3 为空，请先配置 tenantId3 微信视频号应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxChannelService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n","isInternal":false,"tokens":1099,"sizeBytes":4416},{"name":"README.md","path":"solon-plugins/wx-java-channel-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-channel-solon-plugin/README.md","title":"wx-java-channel-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-channel-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 视频号小店的appId和secret\n    wx.channel.app-id=@appId\n    wx.channel.secret=@secret\n    # 视频号配置 选填\n    ## 设置视频号小店消息服务器配置的token\n    wx.channel.token=@token\n    ## 设置视频号小店消息服务器配置的EncodingAESKey\n    wx.channel.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.channel.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.channel.use-stable-access-token=false\n    \n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel(默认)\n    wx.channel.config-storage.key-prefix=wx:channel\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n \n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxChannelService`\n- `WxChannelConfig`\n4. 使用样例\n\n```java\nimport me.chanjar.weixin.channel.api.WxChannelService;\nimport me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;\nimport me.chanjar.weixin.channel.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxChannelService wxChannelService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxChannelService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n\n","isInternal":false,"tokens":805,"sizeBytes":3187},{"name":"README.md","path":"solon-plugins/wx-java-cp-multi-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-cp-multi-solon-plugin/README.md","title":"wx-java-cp-multi-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-cp-multi-solon-plugin\n\n企业微信多账号配置\n\n- 实现多 WxCpService 初始化。\n- 未实现 WxCpTpService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n- 未实现 WxCpCgService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n\n## 关于 corp-secret 的说明\n\n企业微信中不同功能模块对应不同的 `corp-secret`，每种 Secret 只对对应模块的接口具有调用权限：\n\n| Secret 类型 | 获取位置 | 可调用的接口 | 是否需要 agent-id |\n|---|---|---|---|\n| 自建应用 Secret | 应用管理 → 自建应用 → 选择应用 → 查看 Secret | 该应用有权限的接口 | **必填** |\n| 通讯录同步 Secret | 管理工具 → 通讯录同步 → 查看 Secret | 部门/成员增删改查等通讯录接口 | **不填** |\n| 客户联系 Secret | 客户联系 → API → Secret | 客户联系相关接口 | 不填 |\n\n> **常见问题**：\n> - 使用自建应用 Secret + agent-id 可以获取部门列表，但**无法更新部门**（因为写接口需要通讯录同步权限）\n> - 使用通讯录同步 Secret 可以同步部门，但**调用某些需要 agent-id 的应用接口会报错**\n\n如需同时使用多种权限范围，可在 `wx.cp.corps` 下配置多个条目，每个条目使用对应权限的 Secret，通过不同的 `tenantId` 区分后使用。\n\n> **注意**：\n> 当前插件实现会校验同一 `corp-id` 下的 `agent-id` **必须唯一**，并且 **只能有一个条目不填写 `agent-id`**。\n> 如果在同一 `corp-id` 下同时配置多个未填写 `agent-id` 的条目，会因 token/ticket 缓存 key 冲突而在启动时直接抛异常。\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 自建应用 1 配置（使用自建应用 Secret，需填写 agent-id）\n    wx.cp.corps.app1.corp-id = @corp-id\n    wx.cp.corps.app1.corp-secret = @自建应用的Secret（在\"应用管理-自建应用\"中查看）\n    wx.cp.corps.app1.agent-id = @自建应用的AgentId\n    ## 选填\n    wx.cp.corps.app1.token = @token\n    wx.cp.corps.app1.aes-key = @aes-key\n    wx.cp.corps.app1.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.corps.app1.msg-audit-lib-path = @msg-audit-lib-path\n\n    # 通讯录同步配置（使用通讯录同步 Secret，不需要填写 agent-id）\n    # 此配置用于部门、成员的增删改查等通讯录管理操作\n    wx.cp.corps.contact.corp-id = @corp-id\n    wx.cp.corps.contact.corp-secret = @通讯录同步的Secret（在\"管理工具-通讯录同步\"中查看）\n    ## agent-id 不填，通讯录同步不需要 agentId\n\n    # 公共配置\n    ## ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    ## http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.cp.config-storage.http-client-type=http_client\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.cp_multi.service.WxCpMultiServices;\nimport me.chanjar.weixin.cp.api.WxCpDepartmentService;\nimport me.chanjar.weixin.cp.api.WxCpService;\nimport me.chanjar.weixin.cp.api.WxCpUserService;\nimport me.chanjar.weixin.cp.bean.WxCpDepart;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxCpMultiServices wxCpMultiServices;\n\n  public void test() {\n    // 使用自建应用的 WxCpService（对应 corp-secret 为自建应用 Secret）\n    WxCpService appService = wxCpMultiServices.getWxCpService(\"app1\");\n    WxCpUserService userService = appService.getUserService();\n    userService.getUserId(\"xxx\");\n    // todo ...\n\n    // 使用通讯录同步的 WxCpService（对应 corp-secret 为通讯录同步 Secret）\n    // 通讯录同步 Secret 具有部门/成员增删改查等权限\n    WxCpService contactService = wxCpMultiServices.getWxCpService(\"contact\");\n    WxCpDepartmentService departmentService = contactService.getDepartmentService();\n    // 更新部门示例（WxCpDepart 包含 id、name、parentId 等字段）\n    WxCpDepart depart = new WxCpDepart();\n    depart.setId(100L);\n    depart.setName(\"新部门名称\");\n    departmentService.update(depart);\n    // todo ...\n  }\n}\n```\n","isInternal":false,"tokens":1496,"sizeBytes":5005},{"name":"README.md","path":"solon-plugins/wx-java-cp-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-cp-solon-plugin/README.md","title":"wx-java-cp-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-cp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 企业微信号配置(必填)\n    wx.cp.corp-id = @corp-id\n    wx.cp.corp-secret = @corp-secret\n    # 选填\n    wx.cp.agent-id = @agent-id\n    wx.cp.token = @token\n    wx.cp.aes-key = @aes-key\n    wx.cp.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.msg-audit-lib-path = @msg-audit-lib-path\n    # ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    # http 客户端配置（选填）\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpService`, `WxCpConfigStorage`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n\n- WxCpService\n- WxCpConfigStorage\n","isInternal":false,"tokens":426,"sizeBytes":1388},{"name":"README.md","path":"solon-plugins/wx-java-miniapp-multi-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-miniapp-multi-solon-plugin/README.md","title":"wx-java-miniapp-multi-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-miniapp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.ma.apps.tenantId1.app-id=appId\n    wx.ma.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.ma.apps.tenantId1.token=@token\n    wx.ma.apps.tenantId1.aes-key=@aesKey\n    wx.ma.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.ma.apps.tenantId2.app-id=@appId\n    wx.ma.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.ma.apps.tenantId2.token=@token\n    wx.ma.apps.tenantId2.aes-key=@aesKey\n    wx.ma.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson\n    wx.ma.config-storage.type=memory\n    ## 相关redis前缀配置: wx:ma:multi(默认)\n    wx.ma.config-storage.key-prefix=wx:ma:multi\n    wx.ma.config-storage.redis.host=127.0.0.1\n    wx.ma.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.ma.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.ma.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.ma.config-storage.http-client-type=http_client\n    wx.ma.config-storage.http-proxy-host=\n    wx.ma.config-storage.http-proxy-port=\n    wx.ma.config-storage.http-proxy-username=\n    wx.ma.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.ma.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.ma.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxMaMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.miniapp.service.WxMaMultiServices;\nimport cn.binarywang.wx.miniapp.api.WxMaService;\nimport cn.binarywang.wx.miniapp.api.WxMaUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMaMultiServices wxMaMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMaService\n    WxMaService wxMaService1 = wxMaMultiServices.getWxMaService(\"tenantId1\");\n    WxMaUserService userService1 = wxMaService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMaService\n    WxMaService wxMaService2 = wxMaMultiServices.getWxMaService(\"tenantId2\");\n    WxMaUserService userService2 = wxMaService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMaService\n    WxMaService wxMaService3 = wxMaMultiServices.getWxMaService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMaService3 == null) {\n      // todo wxMaService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMaUserService userService3 = wxMaService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n","isInternal":false,"tokens":971,"sizeBytes":3338},{"name":"README.md","path":"solon-plugins/wx-java-miniapp-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-miniapp-solon-plugin/README.md","title":"wx-java-miniapp-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-miniapp-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.miniapp.appid = appId\n    wx.miniapp.secret = @secret\n    wx.miniapp.token = @token\n    wx.miniapp.aesKey = @aesKey\n    wx.miniapp.msgDataFormat = @msgDataFormat                  # 消息格式，XML或者JSON.\n    # 存储配置redis(可选)\n    # 注意: 指定redis.host值后不会使用容器注入的redis连接(JedisPool)\n    wx.miniapp.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.miniapp.config-storage.key-prefix = wa                  # 相关redis前缀配置: wa(默认)\n    wx.miniapp.config-storage.redis.host = 127.0.0.1\n    wx.miniapp.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.miniapp.config-storage.http-client-type=HttpClient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.miniapp.config-storage.http-proxy-host=\n    wx.miniapp.config-storage.http-proxy-port=\n    wx.miniapp.config-storage.http-proxy-username=\n    wx.miniapp.config-storage.http-proxy-password=\n    ```\n3. 自动注入的类型\n- `WxMaService`\n- `WxMaConfig`\n\n","isInternal":false,"tokens":399,"sizeBytes":1410},{"name":"README.md","path":"solon-plugins/wx-java-mp-multi-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-mp-multi-solon-plugin/README.md","title":"wx-java-mp-multi-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-mp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.mp.apps.tenantId1.app-id=appId\n    wx.mp.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.mp.apps.tenantId1.token=@token\n    wx.mp.apps.tenantId1.aes-key=@aesKey\n    wx.mp.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.mp.apps.tenantId2.app-id=@appId\n    wx.mp.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.mp.apps.tenantId2.token=@token\n    wx.mp.apps.tenantId2.aes-key=@aesKey\n    wx.mp.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.mp.config-storage.type=memory\n    ## 相关redis前缀配置: wx:mp:multi(默认)\n    wx.mp.config-storage.key-prefix=wx:mp:multi\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.mp.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.mp.config-storage.http-client-type=http_client\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.mp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.mp.config-storage.retry-sleep-millis=1000\n   \n\t  # 公众号地址 host 配置\n\t  # wx.mp.hosts.api-host=http://proxy.com/\n\t  # wx.mp.hosts.open-host=http://proxy.com/\n\t  # wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型：`WxMpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.mp_multi.service.WxMpMultiServices;\nimport me.chanjar.weixin.mp.api.WxMpService;\nimport me.chanjar.weixin.mp.api.WxMpUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMpMultiServices wxMpMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMpService\n    WxMpService wxMpService1 = wxMpMultiServices.getWxMpService(\"tenantId1\");\n    WxMpUserService userService1 = wxMpService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMpService\n    WxMpService wxMpService2 = wxMpMultiServices.getWxMpService(\"tenantId2\");\n    WxMpUserService userService2 = wxMpService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMpService\n    WxMpService wxMpService3 = wxMpMultiServices.getWxMpService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMpService3 == null) {\n      // todo wxMpService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMpUserService userService3 = wxMpService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n","isInternal":false,"tokens":1023,"sizeBytes":3506},{"name":"README.md","path":"solon-plugins/wx-java-mp-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-mp-solon-plugin/README.md","title":"wx-java-mp-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-mp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.mp.app-id=appId\n    wx.mp.secret=@secret\n    wx.mp.token=@token\n    wx.mp.aes-key=@aesKey\n    wx.mp.use-stable-access-token=@useStableAccessToken\n    # 存储配置redis(可选)\n    wx.mp.config-storage.type= edis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.mp.config-storage.key-prefix=wx                  # 相关redis前缀配置: wx(默认)\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  #单机和sentinel同时存在时，优先使用sentinel配置\n\t  #wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  #wx.mp.config-storage.redis.sentinel-name=mymaster\n    # http客户端配置\n    wx.mp.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n\t  # 公众号地址host配置\n\t  #wx.mp.hosts.api-host=http://proxy.com/\n\t  #wx.mp.hosts.open-host=http://proxy.com/\n\t  #wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型\n\n- `WxMpService`\n- `WxMpConfigStorage`\n\n4、参考demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n","isInternal":false,"tokens":467,"sizeBytes":1626},{"name":"README.md","path":"solon-plugins/wx-java-open-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-open-solon-plugin/README.md","title":"wx-java-open-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-open-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-open-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.open.appId = appId\n    wx.open.secret = @secret\n    wx.open.token = @token\n    wx.open.aesKey = @aesKey\n    # 存储配置redis(可选)\n    # 优先注入容器的(JedisPool, RedissonClient), 当配置了wx.open.config-storage.redis.host, 不会使用容器注入redis连接配置\n    wx.open.config-storage.type = redis                     # 配置类型: memory(默认), redis(jedis), jedis, redisson, redistemplate\n    wx.open.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n    wx.open.config-storage.redis.host = 127.0.0.1\n    wx.open.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.open.config-storage.http-client-type=httpclient      # http客户端类型: httpclient(默认)\n    wx.open.config-storage.http-proxy-host=\n    wx.open.config-storage.http-proxy-port=\n    wx.open.config-storage.http-proxy-username=\n    wx.open.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.open.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.open.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxOpenService, WxOpenMessageRouter, WxOpenComponentService`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n  - WxOpenConfigStorage\n  - WxOpenService\n","isInternal":false,"tokens":491,"sizeBytes":1735},{"name":"README.md","path":"solon-plugins/wx-java-pay-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-pay-solon-plugin/README.md","title":"wx-java-pay-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# 使用说明\n1. 在自己的Solon项目里，引入maven依赖\n```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-pay-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n ```\n2. 添加配置(app.yml)\n###### 1）V2版本\n```yml\nwx:\n  pay:\n    appId: \n    mchId: \n    mchKey: \n    keyPath:\n```\n###### 2）V3版本\n```yml\nwx:\n  pay:\n    appId: xxxxxxxxxxx\n    mchId: 15xxxxxxxxx #商户id\n    apiHostUrl: http://10.0.0.1:3128 # 可选：代理主机\n    apiHostUrlPath: /api-weixin # 可选：代理入口前缀\n    apiV3Key: Dc1DBwSc094jACxxxxxxxxxxxxxxx #V3密钥\n    certSerialNo: 62C6CEAA360BCxxxxxxxxxxxxxxx\n    privateKeyPath: classpath:cert/apiclient_key.pem #apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径\n    privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n###### 3）V3服务商版本\n```yml\nwx:\n  pay: #微信服务商支付\n    configs:\n    - appId: wxe97b2x9c2b3d #spAppId\n      mchId: 16486610 #服务商商户\n      subAppId: wx118cexxe3c07679 #子appId\n      subMchId: 16496705 #子商户\n      apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr #apiV3密钥\n      privateKeyPath: classpath:cert/apiclient_key.pem #服务商证书文件，apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径（可以配置绝对路径）\n      privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n","isInternal":false,"tokens":547,"sizeBytes":1604},{"name":"README.md","path":"solon-plugins/wx-java-qidian-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-qidian-solon-plugin/README.md","title":"wx-java-qidian-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-qidian-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n   ```xml\n   <dependency>\n       <groupId>com.github.binarywang</groupId>\n       <artifactId>wx-java-qidian-solon-plugin</artifactId>\n       <version>${version}</version>\n   </dependency>\n   ```\n2. 添加配置(app.properties)\n   ```properties\n   # 公众号配置(必填)\n   wx.qidian.appId = appId\n   wx.qidian.secret = @secret\n   wx.qidian.token = @token\n   wx.qidian.aesKey = @aesKey\n   # 存储配置redis(可选)\n   wx.qidian.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n   wx.qidian.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n   wx.qidian.config-storage.redis.host = 127.0.0.1\n   wx.qidian.config-storage.redis.port = 6379\n   #单机和sentinel同时存在时，优先使用sentinel配置\n   #wx.qidian.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n   #wx.qidian.config-storage.redis.sentinel-name=mymaster\n   # http客户端配置\n   wx.qidian.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n   wx.qidian.config-storage.http-proxy-host=\n   wx.qidian.config-storage.http-proxy-port=\n   wx.qidian.config-storage.http-proxy-username=\n   wx.qidian.config-storage.http-proxy-password=\n   # 公众号地址host配置\n   #wx.qidian.hosts.api-host=http://proxy.com/\n   #wx.qidian.hosts.open-host=http://proxy.com/\n   #wx.qidian.hosts.mp-host=http://proxy.com/\n   ```\n3. 自动注入的类型\n\n- `WxQidianService`\n- `WxQidianConfigStorage`\n\n4、参考 demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n","isInternal":false,"tokens":479,"sizeBytes":1648},{"name":"README.md","path":"solon-plugins/wx-java-store-multi-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-store-multi-solon-plugin/README.md","title":"wx-java-store-multi-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-store-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.store.apps.tenantId1.app-id=@appId\n    wx.store.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId1.use-stable-access-token=false\n    wx.store.apps.tenantId1.token=\n    wx.store.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.store.apps.tenantId2.app-id=@appId\n    wx.store.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId2.use-stable-access-token=false\n    wx.store.apps.tenantId2.token=\n    wx.store.apps.tenantId2.aes-key=\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store:multi(默认)\n    wx.store.config-storage.key-prefix=wx:store:multi\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxStoreMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.store.service.WxStoreMultiServices;\n    import com.binarywang.wxjava.store.api.WxStoreService;\n    import com.binarywang.wxjava.store.api.WxFinderLiveService;\n    import com.binarywang.wxjava.store.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n\n    @Component\n    public class DemoService {\n      @Inject\n      private WxStoreMultiServices wxStoreMultiServices;\n\n      public void test() throws WxErrorException {\n        // 应用 1 的 WxStoreService\n        WxStoreService wxStoreService1 = wxStoreMultiServices.getWxStoreService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxStoreService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 2 的 WxStoreService\n        WxStoreService wxStoreService2 = wxStoreMultiServices.getWxStoreService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxStoreService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 3 的 WxStoreService\n        WxStoreService wxStoreService3 = wxStoreMultiServices.getWxStoreService(\"tenantId3\");\n        // 判断是否为空\n        if (wxStoreService3 == null) {\n          // todo wxStoreService3 为空，请先配置 tenantId3 微信小店应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxStoreService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n","isInternal":false,"tokens":1093,"sizeBytes":4288},{"name":"README.md","path":"solon-plugins/wx-java-store-solon-plugin/README.md","rawUrl":"https://raw.githubusercontent.com/binarywang/WxJava/HEAD/solon-plugins/wx-java-store-solon-plugin/README.md","title":"wx-java-store-solon-plugin Documentation","category":"plugin-manifest","format":"markdown","content":"# wx-java-store-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 微信小店的appId和secret\n    wx.store.app-id=@appId\n    wx.store.secret=@secret\n    # 视频号配置 选填\n    ## 设置微信小店消息服务器配置的token\n    wx.store.token=@token\n    ## 设置微信小店消息服务器配置的EncodingAESKey\n    wx.store.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.store.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.store.use-stable-access-token=false\n\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store(默认)\n    wx.store.config-storage.key-prefix=wx:store\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxStoreService`\n- `WxStoreConfig`\n4. 使用样例\n\n```java\nimport com.binarywang.wxjava.store.api.WxStoreService;\nimport com.binarywang.wxjava.store.bean.shop.ShopInfoResponse;\nimport com.binarywang.wxjava.store.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxStoreService wxStoreService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxStoreService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n","isInternal":false,"tokens":802,"sizeBytes":3111}],"systemPromptSnippet":"<yakaai_skills repo=\"binarywang/WxJava\">\n<!-- File: AGENTS.md (Tokens: ~3123 | Category: root-instruction) -->\n# WxJava Agent 指南\n\n## 适用范围与指令优先级\n\n- 本文件适用于整个仓库，供本地编码 Agent、自动化 Agent 和 Pull Request Review Agent 使用。\n- 开始工作前先阅读与任务直接相关的 `README.md`、`CONTRIBUTING.md`、模块 `pom.xml`、现有实现和测试；不要仅凭通用经验推断项目约定。\n- 若子目录存在更具体的 `AGENTS.md`，处理该目录文件时优先遵循距离目标文件最近的说明。\n- 用户的明确要求优先于本文件；若要求与兼容性、安全性或仓库约定冲突，应先说明风险，不要静默偏离。\n- 只修改完成任务所必需的文件，不处理无关格式、重构或历史遗留问题。\n\n## 项目概览\n\n- WxJava 是面向微信生态的 Java SDK，采用 Maven 多模块结构。\n- 当前根项目要求 Java 8（`maven.compiler.source` 和 `maven.compiler.target` 均为 `1.8`）。除非任务明确要求升级，否则新增代码、依赖和 API 必须保持 Java 8 兼容。\n- 主要 SDK 模块包括：\n  - `weixin-java-common`：各模块共用的基础类型、工具、异常、HTTP 与配置能力。\n  - `weixin-java-mp`：微信公众号。\n  - `weixin-java-miniapp`：微信小程序。\n  - `weixin-java-pay`：微信支付。\n  - `weixin-java-cp`：企业微信。\n  - `weixin-java-open`：微信开放平台。\n  - `weixin-java-channel`：微信视频号、微信小店。\n  - `weixin-java-qidian`：微信客服相关能力。\n  - `weixin-java-aispeech`：微信智能语音。\n  - `weixin-graal`：GraalVM 相关支持。\n- 集成模块主要位于：\n  - `spring-boot-starters`：Spring Boot Starter 及多账号 Starter。\n  - `solon-plugins`：Solon 插件及多账号插件。\n  - `wx-java-bom`：统一管理对外模块版本的 BOM。\n- `README.md` 说明整体能力和使用方式，`CONTRIBUTING.md` 规定代码贡献要求，`docs` 保存补充文档。\n\n## 开发流程\n\n1. 确认任务涉及的微信产品和 Maven 模块，先查找同模块中的相似接口、Bean、实现类和测试。\n2. 阅读目标模块及其父级 `pom.xml`，确认依赖、测试框架和已有实现方式。\n3. 优先沿用现有的包结构、命名、序列化、HTTP 执行器、异常处理及配置模式。\n4. 以最小变更完成任务；不要在功能修改中夹带依赖升级、全局格式化或无关重构。\n5. 为修复或新增行为添加有针对性的测试，并先运行受影响模块的验证。\n6. 交付前检查 diff、测试结果、兼容性和文档影响，明确报告未执行或无法执行的验证。\n\n## 代码风格与兼容性\n\n- 遵循 `.editorconfig`：使用空格缩进、缩进宽度为 2、UTF-8、LF、文件末尾保留换行，并清除非 Markdown 文件的行尾空格。\n- 保持目标文件现有代码风格；避免仅为个人偏好调整 import、换行、注释或成员顺序。\n- 不使用 Java 9 及以上语言特性或仅在新版本 JDK 中存在的 API。\n- 项目使用 Lombok；新增或修改 Lombok 用法时遵循相邻代码模式，不要在同一变更中无理由改写为手工样板代码。\n- 公共 API、序列化字段、枚举值、常量、默认实现和依赖范围都可能影响下游用户，修改时优先保持源码、二进制和行为兼容。\n- 不要随意改变已有异常类型、空值语义、默认 HTTP 客户端、JSON/XML 映射或配置加载行为。\n- 新增依赖前先确认现有依赖能否满足需求；依赖版本应在合适的父 POM 或 BOM 中统一管理，避免模块间版本漂移。\n\n## API 与实现约定\n\n- 对接微信接口时，以对应产品的官方接口定义和仓库内现有同类实现为依据，核对请求路径、HTTP 方法、字段名、必填项和返回结构。\n- Java 字段名可以符合项目命名习惯，但传输层字段名必须与微信接口保持一致；需要时使用项目现有的 Gson、Jackson 或 XStream 映射方式。\n- 新增 Service API 时同步检查接口、实现类、请求/响应 Bean、URL 常量、序列化适配器和测试是否都需要更新。\n- 涉及多个 HTTP 客户端实现时，保持 Apache HttpClient、HttpComponents、OkHttp 和 Jodd 等现有实现的能力一致；不要只修复其中一种而遗漏其他可选实现。\n- 涉及 Starter 或插件时，检查单账号与多账号版本以及自动配置、配置属性和示例测试是否需要同步。\n- 公共方法需要清晰的 Javadoc，至少准确描述参数、返回值、异常和必要约束；不要编写与实现不一致的模板化注释。\n- 不吞掉异常，不使用空 `catch`，不在日志中泄露 token、secret、密钥、签名原文或用户敏感数据。\n\n## 测试与验证\n\n- 项目测试主要使用 TestNG；沿用目标模块已有测试基类、数据提供器、Mock 方式和资源布局。\n- 修复 bug 时应添加能够复现旧行为并验证修复结果的回归测试；新增公共方法必须配套单元测试。\n- 优先执行受影响模块及其依赖的测试：\n\n```shell\nmvn -pl <module> -am test\n```\n\n- 运行单个测试类时，可在对应模块范围内执行：\n\n```shell\nmvn -pl <module> -am -Dtest=<TestClass> -Dsurefire.failIfNoSpecifiedTests=false test\n```\n\n- 跨公共模块、父 POM、BOM 或多个产品模块的变更应扩大验证范围；条件允许时执行：\n\n```shell\nmvn test\n```\n\n- 对仅需确认编译且测试依赖外部凭据的场景，可执行模块级编译或打包，但不得把跳过测试的构建描述为“测试通过”。\n- 部分测试可能依赖微信凭据、网络或本地配置。不得提交真实凭据；无法运行时应说明原因以及已完成的替代验证。\n- 完成前至少运行 `git diff --check`，并人工检查 `git diff`，确认没有意外文件、调试代码、生成物或敏感信息。\n\n## 文档与依赖变更\n\n- 用户可见的 API、配置项、模块使用方式或兼容性发生变化时，同步更新相关 Javadoc、README 或 `docs` 文档。\n- 示例中的版本号、模块名和配置键应与当前项目保持一致；不要复制未经验证的外部示例。\n- 修改根 POM、父 POM 或 `wx-java-bom` 时，检查所有子模块和对外依赖管理的影响。\n- 不提交构建输出、IDE 临时文件、测试报告、真实配置文件或本地备份文件。\n\n## Git 与 Pull Request 规范\n\n- 贡献目标分支为 `develop`；`release` 用于正式版本发布，不应作为常规 Pull Request 的目标分支。\n- 提交前保持工作区变更聚焦，不覆盖或回退用户已有的无关修改。\n- Commit 和 Pull Request 应说明变更动机、影响模块、兼容性风险和验证方式；关联已有 Issue 时写明编号。\n- 不得在未经用户明确授权的情况下执行 `git push`、创建或合并 Pull Request、改写历史或执行破坏性 Git 操作。\n- 不要使用 `git reset --hard`、强制 checkout 等方式清理不属于当前任务的改动。\n\n## 安全与敏感数据\n\n- 禁止提交 AppID 对应的 secret、access token、API v3 密钥、商户私钥、证书私钥、用户数据或其他真实凭据。\n- 测试和文档使用明显的占位值或脱敏数据；日志应避免输出查询串、请求体或响应体中的敏感字段。\n- 涉及签名、验签、加解密、证书、回调通知和支付金额时，重点检查字符编码、字段排序、精度、时区、重放风险和资源关闭。\n- 涉及网络请求、文件或流时，检查超时、异常路径、资源释放、响应关闭和大数据量下的内存行为。\n\n## Review 指南\n\n- 重点检查空指针、并发、资源释放、兼容性问题。\n- 不要只做代码风格建议，优先指出真实 bug 和回归风险。\n- 所有 Pull Request Review 的总结、结论和行内评论必须使用简体中文。\n- 技术标识符、类名、方法名、变量名、日志、错误信息及代码片段保持原文，不要翻译。\n- 严重程度标识可以保留 `P0`、`P1`、`P2` 等英文缩写。\n- 如果没有发现需要阻止合并的问题，也必须使用简体中文给出结论。\n- Review 结论必须基于当前 diff 和仓库中可验证的行为；不确定时明确说明假设，不要把推测写成确定缺陷。\n- 仅报告由本次变更引入或暴露、且作者可以采取行动的问题，并指出具体文件、位置、触发条件和影响。\n- 重点关注微信接口契约、Java 8 兼容性、公共 API 兼容性、序列化字段、HTTP 客户端实现一致性、Starter 多账号场景及敏感信息泄露。\n- 不要仅因缺少全仓库测试、个人风格偏好或与本次变更无关的历史代码而阻止合并。\n\n## Agent 完成检查清单\n\n- 已确认并遵循相关模块、相邻代码和更具体的 `AGENTS.md`。\n- 变更范围与任务直接相关，没有覆盖用户的无关修改。\n- 新增代码保持 Java 8、公共 API 和序列化兼容性。\n- 必要的测试与文档已经更新。\n- 已执行与风险匹配的构建或测试，并如实记录结果。\n- 已检查完整 diff、格式、生成物和敏感信息。\n- 最终回复使用简体中文，简要列出修改内容、验证结果和任何剩余风险。\n\n<!-- File: .github/copilot-instructions.md (Tokens: ~2434 | Category: copilot-instructions) -->\n# Copilot Instruction\n请始终使用中文生成 Pull Request 的标题、描述和提交信息\n\n\n# WxJava - 微信 Java SDK 开发说明\n\nWxJava 是一个支持多种微信平台的完整 Java SDK，包含公众号、小程序、微信支付、企业微信、开放平台、视频号、企点等多种功能模块。\n\n**请始终优先参考本说明，只有在遇到与此内容不一致的意外信息时，才退而使用搜索或 bash 命令。**\n\n## 高效开发指南\n\n### 前置条件与环境准备\n- **Java 要求**：JDK 8+（项目最低目标为 Java 8）\n- **Maven**：推荐 Maven 3.6+（已验证 Maven 3.9.11）\n- **IDE**：推荐使用 IntelliJ IDEA（项目针对 IDEA 优化）\n\n### 引导、构建与校验\n克隆仓库后按顺序执行以下命令：\n\n```bash\n# 1. 基础编译（请勿中断 - 约需 4-5 分钟）\nmvn clean compile -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 8 分钟以上。实际时间：约 4 分钟\n\n# 2. 完整打包（请勿中断 - 约需 2-3 分钟）  \nmvn clean package -DskipTests=true --no-transfer-progress\n# 超时时间：建议设置 5 分钟以上。实际时间：约 2 分钟\n\n# 3. 代码质量校验（请勿中断 - 约需 45-60 秒）\nmvn checkstyle:check --no-transfer-progress\n# 超时时间：建议设置 3 分钟以上。实际时间：约 50 秒\n```\n\n重要时间说明：\n- 绝对不要中断任意 Maven 构建命令\n- 编译阶段耗时最长（约 4 分钟），原因是项目包含 34 个模块\n- 后续构建会更快，因为存在增量编译\n- 始终使用 `--no-transfer-progress` 以减少日志噪音\n\n### 测试结构\n- **测试框架**：TestNG（非 JUnit）\n- **测试文件**：共有 298 个测试文件\n- **默认行为**：pom.xml 中默认禁用测试（`<skip>true</skip>`）\n- **测试配置**：测试需要通过 test-config.xml 提供真实的微信 API 凭据\n- **注意**：没有真实微信 API 凭据请不要尝试运行测试，测试将会失败\n\n## 项目结构与导航\n\n### 核心 SDK 模块（主要开发区）\n- `weixin-java-common/` - 通用工具与基础类（最重要）\n- `weixin-java-mp/` - 公众号 SDK\n- `weixin-java-pay/` - 微信支付 SDK\n- `weixin-java-miniapp/` - 小程序 SDK\n- `weixin-java-cp/` - 企业微信 SDK\n- `weixin-java-open/` - 开放平台 SDK\n- `weixin-java-channel/` - 视频号 / Channel SDK\n- `weixin-java-qidian/` - 企点 SDK\n\n### 框架集成模块\n- `spring-boot-starters/` - Spring Boot 自动配置 starter\n- `solon-plugins/` - Solon 框架插件\n- `weixin-graal/` - GraalVM 本地镜像支持\n\n### 配置与质量控制\n- `quality-checks/google_checks.xml` - Checkstyle 配置\n- `.editorconfig` - 代码格式规则（2 个空格等于 1 个制表）\n- `pom.xml` - 根级 Maven 配置\n\n## 开发工作流\n\n### 修改代码的流程\n1. 修改前务必先构建以建立干净基线：\n   ```bash\n   mvn clean compile --no-transfer-progress\n   ```\n\n2. 遵循代码风格（由 checkstyle 强制）：\n   - 缩进使用 2 个空格（不要用制表符）\n   - 遵循 Google Java 风格指南\n   - 在 IDE 中安装 EditorConfig 插件\n\n3. 增量验证修改：\n   ```bash\n   # 每次修改后运行：\n   mvn compile --no-transfer-progress\n   mvn checkstyle:check --no-transfer-progress\n   ```\n\n### 提交修改前的必须校验\n请务必按顺序完成以下校验步骤：\n\n1. 代码风格校验：\n   ```bash\n   mvn checkstyle:check --no-transfer-progress\n   # 必须通过 - 约需 50 秒\n   ```\n\n2. 完整清理构建：\n   ```bash\n   mvn clean package -DskipTests=true --no-transfer-progress  \n   # 必须成功 - 约需 2 分钟\n   ```\n\n3. 文档：为公共方法和类补充或更新 javadoc\n4. 贡献规范：遵循 `CONTRIBUTING.md`，Pull Request 必须以 `develop` 分支为目标\n\n## 模块依赖与构建顺序\n\n### 核心模块依赖（构建顺序）\n1. `weixin-graal`（GraalVM 支持）\n2. `weixin-java-common`（所有模块的基础）\n3. 核心 SDK 模块（mp、pay、miniapp、cp、open、channel、qidian）\n4. 框架集成（spring-boot-starters、solon-plugins）\n\n### 主要关系模式\n- 所有 SDK 模块都依赖于 `weixin-java-common`\n- Spring Boot starters 依赖对应的 SDK 模块\n- Solon 插件遵循与 Spring Boot starters 相同的依赖模式\n- 每个模块都有单账号与多账号配置支持\n\n## 常见任务与命令\n\n### 验证指定模块\n```bash\n# 构建单个模块（将 'weixin-java-mp' 替换为目标模块）：\ncd weixin-java-mp\nmvn clean compile --no-transfer-progress\n```\n\n### 检查依赖\n```bash\n# 分析依赖树：\nmvn dependency:tree --no-transfer-progress\n\n# 检查依赖更新：  \n./others/check-dependency-updates.sh\n```\n\n### 发布与发布准备\n```bash\n# 版本检查：\nmvn versions:display-property-updates --no-transfer-progress\n\n# 部署（需要凭据）：\nmvn clean deploy -P release --no-transfer-progress\n```\n\n## 重要文件与位置\n\n### 配置文件\n- `pom.xml` - 根级 Maven 配置与依赖管理\n- `quality-checks/google_checks.xml` - Checkstyle 规则\n- `.editorconfig` - IDE 格式化配置\n- `.github/workflows/maven-publish.yml` - CI/CD 工作流\n\n### 文档\n- `README.md` - 项目概览与使用说明（中文）\n- `CONTRIBUTING.md` - 贡献指南\n- `demo.md` - 示例项目与演示链接\n- 每个模块均有单独的文档与示例\n\n### 测试资源\n- `*/src/test/resources/test-config.sample.xml` - 测试配置模板\n- 测试运行需要真实的微信 API 凭据\n\n## SDK 使用模式\n\n### Maven 依赖示例\n```xml\n<dependency>\n  <groupId>com.github.binarywang</groupId>\n  <artifactId>weixin-java-mp</artifactId>  <!-- 或其他模块 -->\n  <version>4.7.0</version>\n</dependency>\n```\n\n### 常见开发区域\n- **API 客户端实现**：位于 `*/service/impl/` 目录\n- **模型类**：位于 `*/bean/` 目录\n- **配置**：位于 `*/config/` 目录\n- **工具类**：位于 `weixin-java-common` 的 `*/util/` 目录\n\n## 故障排查\n\n### 构建问题\n- **OutOfMemoryError**：增加 Maven 内存：`export MAVEN_OPTS=\"-Xmx2g\"`\n- **编译失败**：通常为依赖问题 - 先执行 `mvn clean`\n- **Checkstyle 失败**：检查 IDE 的 `.editorconfig` 设置\n\n### 常见陷阱\n- **测试默认跳过**：这是正常现象 — 测试需要微信 API 凭据\n- **多模块变更**：总是在仓库根目录构建，而不是单独模块\n- **分支目标**：Pull Request 必须以 `develop` 分支为目标，而不是 `master` 或 `release`\n\n## 性能说明\n- **首次构建**：由于依赖下载，耗时 4-5 分钟\n- **增量构建**：通常更快（约 30-60 秒）\n- **Checkstyle**：运行迅速（约 50 秒），应当经常运行\n- **IDE 性能**：项目使用 Lombok，请确保启用注解处理\n\n注意：本项目为 SDK 库项目，而非可运行应用。修改应以 API 功能为主，不要改动应用级行为。\n\n<!-- File: skills/wxjava-api-contributor/agents/openai.yaml (Tokens: ~72 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"WxJava 接口贡献\"\n  short_description: \"按 WxJava 项目约定新增或维护 SDK 接口能力\"\n  default_prompt: \"使用 $wxjava-api-contributor 为 WxJava 新增微信接口支持。\"\n\n<!-- File: skills/wxjava-api-contributor/references/contribution.md (Tokens: ~725 | Category: anthropic-skill) -->\n# 贡献约定\n\n以微信官方接口定义和本仓库同类实现为准，核对路径、方法、字段名、必填项和响应结构。优先复用既有 HTTP 执行器、异常、配置、Gson/Jackson/XStream 映射和 TestNG 测试模式。\n\n公共方法需要准确 Javadoc。不要吞异常、记录敏感值或无关重构。新增公开方法和 bug 修复均应有针对性测试；涉及公共模块、BOM 或多模块时扩大验证范围。\n\n## 接口增量检查表\n\n1. 从微信官方文档和相关 Issue 中确认接口可用条件、HTTP 方法、URL、必填字段、签名/加密要求和响应示例。\n2. 搜索同产品的相邻能力，复用其 Service 分层、Bean 命名、请求执行和错误处理模式；不要只新增 Bean 而遗漏 Service 暴露。\n3. 若接口尚未支持，优先使用现有通用执行能力；MP/CP Wiki 说明通用执行器会处理 access token 刷新及 `errcode` 到异常的转换。\n4. 为字段边界、空值、JSON/XML 映射和异常路径添加 TestNG 回归测试。API 路径或字段问题是历史 bug 的高频来源，例如 [#3982](https://github.com/binarywang/WxJava/issues/3982)、[#4000](https://github.com/binarywang/WxJava/issues/4000)。\n5. 按 [贡献指南](https://github.com/binarywang/WxJava/blob/develop/CONTRIBUTING.md) 使用 `develop` 作为 PR 目标；说明 Issue、兼容性影响和验证命令。\n\n## 一手资料入口\n\n- [如何调用 MP 未支持接口](https://github.com/binarywang/WxJava/wiki/MP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [如何调用 CP 未支持接口](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8%E6%9C%AA%E6%94%AF%E6%8C%81%E7%9A%84%E6%8E%A5%E5%8F%A3)\n- [关闭的新接口 Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3A%E6%96%B0%E6%8E%A5%E5%8F%A3)\n\n<!-- File: skills/wxjava-api-contributor/SKILL.md (Tokens: ~389 | Category: anthropic-skill) -->\n---\nname: wxjava-api-contributor\ndescription: 按 WxJava 的 Maven 多模块、Java 8、公共 API 兼容性和 TestNG 约定，为微信官方接口新增或维护 SDK 支持。适用于新增 Service API、请求响应 Bean、序列化、HTTP 实现、Starter 配置或回归测试时。\n---\n\n# WxJava 接口贡献\n\n1. 先搜索开放与已关闭 Issue，确认需求是否已有讨论、实现、回归用例或官方接口变动；再确认微信产品和目标模块。\n2. 阅读对应 README、POM、相似接口、实现与测试，并读取 [贡献约定](references/contribution.md)。\n3. 将官方接口契约映射到 Service、实现、Bean、URL、序列化和测试；列出所有可能受影响的 HTTP 客户端和 Starter。\n4. 只做完成需求所需的最小改动；更新必要 Javadoc、测试与用户可见文档。\n5. 执行 `mvn -pl <module> -am test`，并检查 `git diff --check`。\n\n保持 Java 8 与公共 API、异常语义、JSON/XML 字段兼容性。涉及多 HTTP 客户端、单/多账号 Starter 或 Solon 插件时，检查等价实现是否需要同步。PR 应关联对应 Issue，目标分支为 `develop`。\n\n<!-- File: skills/wxjava-integration-guide/agents/openai.yaml (Tokens: ~65 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"WxJava 接入指南\"\n  short_description: \"生成可验证的 WxJava 最小接入方案与配置示例\"\n  default_prompt: \"使用 $wxjava-integration-guide 为我的项目生成 WxJava 接入代码。\"\n\n<!-- File: skills/wxjava-integration-guide/references/integration.md (Tokens: ~822 | Category: anthropic-skill) -->\n# 接入约束\n\n优先通过 `wx-java-bom` 统一管理多个 WxJava 模块版本。核心 SDK 模块是 MP、MiniApp、Pay、CP、Open、Channel、Qidian、Aispeech；框架集成模块位于 `spring-boot-starters` 与 `solon-plugins`。\n\n查阅相应模块 README、根目录 [demo.md](https://github.com/binarywang/WxJava/blob/develop/demo.md) 和目标模块测试中的示例，确认配置属性与初始化模式。所有 `appId`、`secret`、商户私钥、API v3 密钥和证书均使用占位符，不得输出到日志。\n\n## 实施检查表\n\n1. 先完成一条只读或低风险 API 调用，再接入消息、支付或异步回调。\n2. 单实例可使用默认配置存储；多实例或集群需使用共享的 token/config storage，避免节点各自刷新 access token。\n3. 公众号、企业微信等回调必须先按平台要求校验消息合法性，再进入业务路由；支付回调还必须按商户单号实现幂等。\n4. 需要代理或私有网络出口时，明确区分正向代理与反向代理。支付 V3 的签名路径不能因反向代理路径前缀而被错误改写。\n5. HTTP 客户端类型、Starter 配置键和 Service 实现必须取自目标模块的当前 README、POM 或相邻 Demo；不要混用不同产品模块的配置前缀。\n6. Starter 自动配置与 Demo 手动初始化必须二选一后再给示例。发生空 key、注入为空或 NPE 时，先核对启动模块、profile、配置前缀和当前 `*Properties` 类；历史 [#2177](https://github.com/binarywang/WxJava/issues/2177) 是混用两种配置模型的案例。\n7. Quarkus 或 GraalVM 场景转到 [Quarkus 支持文档](https://github.com/binarywang/WxJava/blob/develop/docs/QUARKUS_SUPPORT.md)，不要套用 Spring Boot Starter 配置。\n\n## 一手资料入口\n\n- [MP Quick Start](https://github.com/binarywang/WxJava/wiki/MP_Quick-Start)\n- [微信支付说明](https://github.com/binarywang/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98)\n- [SDK 正反向代理支持](https://github.com/binarywang/WxJava/wiki/SDK-%E9%92%88%E5%AF%B9%E5%BE%AE%E4%BF%A1-%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E5%92%8C%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%94%AF%E6%8C%81)\n- [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md)\n\n<!-- File: skills/wxjava-integration-guide/SKILL.md (Tokens: ~364 | Category: anthropic-skill) -->\n---\nname: wxjava-integration-guide\ndescription: 为 Java、Spring Boot 或 Solon 项目生成可验证的 WxJava 接入方案，包括模块选择、BOM、配置、最小调用代码以及单/多账号集成。适用于用户要求接入公众号、小程序、支付、企业微信、开放平台、视频号或微信小店时。\n---\n\n# WxJava 接入指南\n\n1. 确认微信产品、框架、单/多账号、部署形态和首个 API 调用。\n2. 读取 [接入约束](references/integration.md)，选择模块和配置方式。\n3. 先输出依赖与配置，再输出最小调用；每段示例注明应放置的位置和所依赖的模块。\n4. 输出脱敏配置和最小服务端代码；凭据一律用占位符。\n5. 给出本地验证步骤与安全提醒；支付、回调和证书示例不得直接用于生产。\n\n保持 Java 8 兼容。生产集群必须使用可共享的配置存储或 token 存储；不要把内存实现当作多节点部署方案。引用已有 Demo、Wiki 或 README 作为继续阅读入口；不虚构配置键、SDK 方法或版本号。\n\n<!-- File: skills/wxjava-module-selector/agents/openai.yaml (Tokens: ~77 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"WxJava 模块选择\"\n  short_description: \"按微信业务场景选择 WxJava 模块、依赖与示例\"\n  default_prompt: \"使用 $wxjava-module-selector 为我的微信业务选择合适的 WxJava 模块。\"\n\n<!-- File: skills/wxjava-module-selector/references/modules.md (Tokens: ~1077 | Category: anthropic-skill) -->\n# WxJava 模块映射\n\n| 场景 | 核心模块 |\n| --- | --- |\n| 微信公众号 | `weixin-java-mp` |\n| 微信小程序 | `weixin-java-miniapp` |\n| 微信支付 | `weixin-java-pay` |\n| 企业微信 | `weixin-java-cp` |\n| 微信开放平台／第三方平台 | `weixin-java-open` |\n| 视频号／微信小店 | `weixin-java-channel` |\n| 腾讯企点／微信客服 | `weixin-java-qidian` |\n| 微信智能对话／智能语音 | `weixin-java-aispeech` |\n\n多个模块并用时优先使用 `com.github.binarywang:wx-java-bom`。Spring Boot 集成从 `spring-boot-starters` 选择；Solon 集成从 `solon-plugins` 选择。\n\n## 多账号集成范围\n\n只有多个独立微信应用配置时才选择 multi 集成，并先按框架与产品核对目录是否存在：\n\n- Spring Boot：MP、MiniApp、CP、自建/第三方 CP、Pay、Open、Channel 都有相应 multi Starter。\n- Solon：仅 MP、MiniApp、CP、Channel 有 multi 插件；Pay、Open、Qidian 目前只有单账号插件，不要推荐不存在的 multi artifact。\n\n## 选择检查点\n\n- 公众号、小程序和企业微信的消息回调、token 与加解密配置彼此独立；不要因同属一个公司而复用不兼容的凭据或配置对象。\n- 企业微信的多应用应使用独立的 `WxCpConfigStorage` 与 `WxCpServiceImpl`；Wiki 明确指出复用 token、AES key 和 URL 会造成安全边界问题。\n- 支付能力通常与 MP、MiniApp 或 Open 同时使用：前者处理业务身份和消息，`weixin-java-pay` 处理商户签名、证书与支付回调。\n- 视频号／微信小店接口属于 `weixin-java-channel`；不要误归入 MP 或 Pay。\n- 腾讯企点与微信智能对话是独立 SDK 模块；不要将客服或智能对话需求默认归入 MP、CP 或 Channel。\n- 当能力在 MP 与 Open 等模块可能重叠时，按授权主体、官方 API 域和回调场景选择，不要只按“移动端”或“登录”字样判断。先在当前源码和 Issue 中确认覆盖状态，并标注“已确认 / 待查 / 需自行调用底层接口”。\n- BOM 适合同时使用多个 WxJava 模块。若项目还导入 Spring Boot 等上游 BOM，升级后执行 `mvn help:effective-pom` 与 `mvn dependency:tree`；历史 [#4058](https://github.com/binarywang/WxJava/issues/4058) 表明依赖管理顺序可能影响 Spring Data Redis 等依赖。\n\n## 一手资料入口\n\n- [WxJava Wiki 首页](https://github.com/binarywang/WxJava/wiki)\n- [企业微信多应用配置](https://github.com/binarywang/WxJava/wiki/CP_%E5%A6%82%E4%BD%95%E6%94%AF%E6%8C%81%E5%A4%9A%E4%B8%AA%E4%BC%81%E4%B8%9A%E5%8F%B7%E5%BA%94%E7%94%A8%E6%88%96%E4%BC%81%E4%B8%9A%E5%8F%B7)\n- [视频号／微信小店开发文档](https://github.com/binarywang/WxJava/wiki/0_%E8%A7%86%E9%A2%91%E5%8F%B7_%E5%BE%AE%E4%BF%A1%E5%B0%8F%E5%BA%97%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)\n\n<!-- File: skills/wxjava-module-selector/SKILL.md (Tokens: ~458 | Category: anthropic-skill) -->\n---\nname: wxjava-module-selector\ndescription: 根据微信公众号、小程序、微信支付、企业微信、开放平台、视频号或微信小店、腾讯企点和微信智能对话等业务场景，为用户选择合适的 WxJava Maven 模块、BOM 和示例入口。适用于用户询问“该用哪个模块”、依赖坐标、产品边界或单/多账号 Starter 选择时。\n---\n\n# WxJava 模块选择\n\n1. 识别微信产品、服务端框架、是否多账号、是否包含支付或回调；信息不足时只询问必要问题。\n2. 读取 [模块映射](references/modules.md)，给出一个主推荐，以及组合模块的理由。\n3. 先区分产品边界，再选择核心 SDK；仅当项目确实依赖框架自动配置时才额外推荐 Starter 或 Solon 插件。\n4. 优先推荐 BOM；给出准确的 `groupId`、`artifactId`、相应 Demo、Wiki 或仓库文档入口。\n5. 说明服务端 SDK 的边界：移动端登录、分享等能力仍需微信官方客户端 SDK。\n6. 不臆测版本号；建议以 Maven Central 或项目 README 的当前版本为准。\n\n使用“场景 → 模块 → 集成选项 → 下一步”的简短结构。涉及多账号时说明单账号与 multi Starter 的区别；不要在示例中泄露凭据。支付和回调场景必须提醒用户验证通知 URL、验签与幂等处理。\n\n<!-- File: skills/wxjava-troubleshooter/agents/openai.yaml (Tokens: ~70 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"WxJava 故障排查\"\n  short_description: \"定位 WxJava 配置、回调、签名与接口调用问题\"\n  default_prompt: \"使用 $wxjava-troubleshooter 排查我的 WxJava 调用异常。\"\n\n<!-- File: skills/wxjava-troubleshooter/references/diagnostics.md (Tokens: ~791 | Category: anthropic-skill) -->\n# 诊断清单\n\n- 配置：模块是否正确，应用标识和凭据是否配对，多账号配置是否被正确选择。\n- 请求：HTTP 方法、路径、必填字段和 JSON/XML 映射是否符合微信接口契约。\n- 认证：token 缓存、签名字段、时间戳、nonce、证书和密钥格式是否有效。\n- 网络：DNS、代理、超时、TLS 证书校验和响应关闭是否正常。\n- 回调：回调 URL 可访问、验签参数完整、幂等处理和资源释放是否存在。\n\n从精确异常和最小请求入手，不用“重试”替代根因分析。\n\n## 高频场景\n\n| 症状 | 优先检查 | 依据 |\n| --- | --- | --- |\n| 多节点间歇性 token 失效 | 是否共享 token/config storage，是否让各节点并发刷新 | Wiki 的 MP/CP 配置存储说明与集群案例 |\n| `NoClassDefFoundError`、`NoSuchMethodError` | `mvn dependency:tree`、HttpClient/commons-lang/xstream 冲突及 BOM 是否统一版本 | Wiki 的异常排查页与 HTTP 客户端升级指南 |\n| 回调验签或重复处理 | 原始请求体、时间戳/nonce/签名、回调 URL、业务幂等键 | MP 合法性校验与支付回调说明 |\n| HTTP 连接、超时或代理问题 | 连接/读取超时、代理、TLS、正反向代理是否混用 | Wiki 的 HttpClient 参数与代理文档 |\n| 企业微信会话存档崩溃 | 是否仍手动销毁旧 SDK 实例，是否已迁移安全 API | [会话存档安全使用指南](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_SDK_SAFE_USAGE.md) |\n| 视频号/小店接口 404 或字段不匹配 | 当前官方路径与请求字段、目标 SDK 版本、历史 Issue 是否已修复 | 关闭的 bug Issue，如 [#3982](https://github.com/binarywang/WxJava/issues/3982) |\n\n## 一手资料入口\n\n- [常见异常首页](https://github.com/binarywang/WxJava/wiki)\n- [MP 消息合法性验证](https://github.com/binarywang/WxJava/wiki/MP_%E9%AA%8C%E8%AF%81%E6%B6%88%E6%81%AF%E5%90%88%E6%B3%95%E6%80%A7)\n- [HttpClient 参数配置](https://github.com/binarywang/WxJava/wiki/HttpClient%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0%E7%9A%84%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%B3%95)\n- [关闭的 bug Issue](https://github.com/binarywang/WxJava/issues?q=is%3Aissue%20state%3Aclosed%20label%3Abug)\n\n<!-- File: skills/wxjava-troubleshooter/SKILL.md (Tokens: ~422 | Category: anthropic-skill) -->\n---\nname: wxjava-troubleshooter\ndescription: 排查 WxJava 在配置初始化、access token、签名验签、支付证书、回调通知、序列化、网络请求和多账号隔离方面的问题。适用于用户提供异常、日志、请求响应或“WxJava 为什么不能调用”的场景。\n---\n\n# WxJava 故障排查\n\n1. 收集最小复现：产品模块、SDK 版本、JDK、框架、依赖树、异常堆栈、请求 ID 与脱敏后的配置形状。\n2. 将故障归类为依赖/初始化、token 与存储、请求契约、HTTP/代理、回调验签、支付证书或并发与生命周期。\n3. 依据 [诊断清单](references/diagnostics.md)，按最低成本、最可验证的顺序排查。\n4. 每次只提出一个可验证根因，给出最小修复、预期现象和回归验证动作。\n5. 签名、支付、回调和加密场景须核对编码、字段排序、金额精度、时间戳、证书链和重放保护。\n\n要求遮蔽 secret、token、私钥、证书、签名原文和个人数据。不要建议关闭 TLS 校验或验签；区分已证实结论与待验证假设。遇到历史同类问题时，给出对应 Issue 或 Wiki 链接，但必须检查当前版本的实现后再套用修复。\n\n<!-- File: skills/wxjava-upgrade-guide/agents/openai.yaml (Tokens: ~78 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"WxJava 升级迁移\"\n  short_description: \"规划 WxJava 版本升级、依赖调整与兼容性迁移\"\n  default_prompt: \"使用 $wxjava-upgrade-guide 制定 WxJava 版本升级方案。\"\n\n<!-- File: skills/wxjava-upgrade-guide/references/migration.md (Tokens: ~863 | Category: anthropic-skill) -->\n# 迁移检查表\n\n- 使用多个 WxJava 模块时，优先迁移到 `wx-java-bom`，避免模块版本漂移。\n- 清点 MP、MiniApp、Pay、CP、Open、Channel 及框架 Starter/插件的实际依赖。\n- 更新后先执行编译和受影响模块测试，再验证 token、回调、支付和关键业务链路。\n- 为依赖版本保留可快速恢复的变更记录；按灰度策略验证生产环境，且不将凭据写入代码或日志。\n\n## 升级分支\n\n### HTTP 客户端\n\n从 4.7.x 起，项目支持并推荐 Apache HttpClient 5.x，同时保留部分 4.x 兼容性。先按 [HTTP 客户端升级指南](https://github.com/binarywang/WxJava/blob/develop/docs/HTTPCLIENT_UPGRADE_GUIDE.md) 核对模块、依赖与 `http-client-type`，再检查代理 host、port、username、password 的完整性。历史 [#3836](https://github.com/binarywang/WxJava/issues/3836) 表明可选代理配置也需要回归。\n\n### BOM 与依赖冲突\n\n`wx-java-bom` 从 4.8.3.B 起提供。导入 BOM 前后均执行：\n\n```shell\nmvn help:effective-pom\nmvn dependency:tree\n```\n\n特别回归由 Spring Boot BOM 管理的 Redis、HTTP 客户端和序列化依赖；[#4058](https://github.com/binarywang/WxJava/issues/4058) 是历史冲突案例。\n\n### 企业微信会话存档\n\n升级到 4.8.0 或更高版本时，查找旧的 `getChatDatas`、`getDecryptData`、`getChatPlainText`、`getMediaFile` 和手动 `Finance.DestroySdk()`。按 [ThreadLocal 生命周期迁移文档](https://github.com/binarywang/WxJava/blob/develop/docs/CP_MSG_AUDIT_THREADLOCAL_LIFECYCLE_REFACTOR.md) 切换至新 API，并做并发验证。\n\nThreadLocal SDK 不会在线程结束时自动释放。在线程池、定时任务或一次性线程中，必须在任务的 `finally` 块调用 `msgAuditService.closeThreadLocalSdk()`；应用停止时再用 `closeAllSdks()` 做全局兜底。不要在业务代码中直接调用 `Finance.DestroySdk()`。\n\n### 回调与支付\n\n验证不止于 HTTP 2xx：分别覆盖 token 获取、签名/证书校验、重复回调、业务状态转换和多账号路由。多账号异步任务必须显式传递 appId 或服务上下文，不能假定 ThreadLocal 自动继承。\n\n## 验证与回滚\n\n按“编译和单测 → 非生产凭据冒烟 → 灰度和监控”执行。出现依赖树冲突、验签/证书异常、回调错误或 native 崩溃时停止扩大灰度，恢复上一个已验证依赖组合后再以最小复现定位。\n\n<!-- File: skills/wxjava-upgrade-guide/SKILL.md (Tokens: ~407 | Category: anthropic-skill) -->\n---\nname: wxjava-upgrade-guide\ndescription: 规划 WxJava 的版本升级与迁移，检查 BOM、模块依赖、Java 版本、配置与公共 API 兼容性，并提供可回滚的验证步骤。适用于用户从旧版升级、切换依赖管理方式、处理兼容性告警或制定升级发布计划时。\n---\n\n# WxJava 升级迁移\n\n1. 收集当前与目标版本、已用模块、JDK、框架、BOM 使用情况、依赖树、代理配置和关键调用路径。\n2. 读取 [迁移检查表](references/migration.md)，识别版本、依赖和配置边界。\n3. 按 HTTP 客户端、BOM、支付/回调、多账号、企业微信会话存档等变化类型选择迁移分支。\n4. 输出分阶段变更：依赖调整、编译、关键回归测试、灰度与明确回滚条件。\n5. 将不确定项标为待查，并引导查看目标版本的 release notes、README、Javadoc 与变更记录。\n\n不要猜测废弃 API 或破坏性变更；以官方发布信息、当前代码与实际编译结果为准。默认保持 Java 8，除非目标版本明确改变此约束。不能以关闭验签、固定 token 或跳过测试作为回滚方案。\n\n<!-- File: solon-plugins/wx-java-channel-multi-solon-plugin/README.md (Tokens: ~1099 | Category: plugin-manifest) -->\n# wx-java-channel-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.channel.apps.tenantId1.app-id=@appId\n    wx.channel.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId1.use-stable-access-token=false\n    wx.channel.apps.tenantId1.token=\n    wx.channel.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.channel.apps.tenantId2.app-id=@appId\n    wx.channel.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.channel.apps.tenantId2.use-stable-access-token=false\n    wx.channel.apps.tenantId2.token=\n    wx.channel.apps.tenantId2.aes-key=\n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel:multi(默认)\n    wx.channel.config-storage.key-prefix=wx:channel:multi\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxChannelMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.channel.service.WxChannelMultiServices;\n    import me.chanjar.weixin.channel.api.WxChannelService;\n    import me.chanjar.weixin.channel.api.WxFinderLiveService;\n    import me.chanjar.weixin.channel.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n    \n    @Component\n    public class DemoService {\n      @Inject\n      private WxChannelMultiServices wxChannelMultiServices;\n    \n      public void test() throws WxErrorException {\n        // 应用 1 的 WxChannelService\n        WxChannelService wxChannelService1 = wxChannelMultiServices.getWxChannelService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxChannelService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 2 的 WxChannelService\n        WxChannelService wxChannelService2 = wxChannelMultiServices.getWxChannelService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxChannelService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n    \n        // 应用 3 的 WxChannelService\n        WxChannelService wxChannelService3 = wxChannelMultiServices.getWxChannelService(\"tenantId3\");\n        // 判断是否为空\n        if (wxChannelService3 == null) {\n          // todo wxChannelService3 为空，请先配置 tenantId3 微信视频号应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxChannelService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n\n<!-- File: solon-plugins/wx-java-channel-solon-plugin/README.md (Tokens: ~805 | Category: plugin-manifest) -->\n# wx-java-channel-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-channel-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n   \n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 视频号小店的appId和secret\n    wx.channel.app-id=@appId\n    wx.channel.secret=@secret\n    # 视频号配置 选填\n    ## 设置视频号小店消息服务器配置的token\n    wx.channel.token=@token\n    ## 设置视频号小店消息服务器配置的EncodingAESKey\n    wx.channel.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.channel.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.channel.use-stable-access-token=false\n    \n    \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.channel.config-storage.type=memory\n    ## 相关redis前缀配置: wx:channel(默认)\n    wx.channel.config-storage.key-prefix=wx:channel\n    wx.channel.config-storage.redis.host=127.0.0.1\n    wx.channel.config-storage.redis.port=6379\n    wx.channel.config-storage.redis.password=123456\n \n    \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.channel.config-storage.http-client-type=http_client\n    wx.channel.config-storage.http-proxy-host=\n    wx.channel.config-storage.http-proxy-port=\n    wx.channel.config-storage.http-proxy-username=\n    wx.channel.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.channel.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.channel.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxChannelService`\n- `WxChannelConfig`\n4. 使用样例\n\n```java\nimport me.chanjar.weixin.channel.api.WxChannelService;\nimport me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;\nimport me.chanjar.weixin.channel.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxChannelService wxChannelService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxChannelService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n\n<!-- File: solon-plugins/wx-java-cp-multi-solon-plugin/README.md (Tokens: ~1496 | Category: plugin-manifest) -->\n# wx-java-cp-multi-solon-plugin\n\n企业微信多账号配置\n\n- 实现多 WxCpService 初始化。\n- 未实现 WxCpTpService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n- 未实现 WxCpCgService 初始化，需要的小伙伴可以参考多 WxCpService 配置的实现。\n\n## 关于 corp-secret 的说明\n\n企业微信中不同功能模块对应不同的 `corp-secret`，每种 Secret 只对对应模块的接口具有调用权限：\n\n| Secret 类型 | 获取位置 | 可调用的接口 | 是否需要 agent-id |\n|---|---|---|---|\n| 自建应用 Secret | 应用管理 → 自建应用 → 选择应用 → 查看 Secret | 该应用有权限的接口 | **必填** |\n| 通讯录同步 Secret | 管理工具 → 通讯录同步 → 查看 Secret | 部门/成员增删改查等通讯录接口 | **不填** |\n| 客户联系 Secret | 客户联系 → API → Secret | 客户联系相关接口 | 不填 |\n\n> **常见问题**：\n> - 使用自建应用 Secret + agent-id 可以获取部门列表，但**无法更新部门**（因为写接口需要通讯录同步权限）\n> - 使用通讯录同步 Secret 可以同步部门，但**调用某些需要 agent-id 的应用接口会报错**\n\n如需同时使用多种权限范围，可在 `wx.cp.corps` 下配置多个条目，每个条目使用对应权限的 Secret，通过不同的 `tenantId` 区分后使用。\n\n> **注意**：\n> 当前插件实现会校验同一 `corp-id` 下的 `agent-id` **必须唯一**，并且 **只能有一个条目不填写 `agent-id`**。\n> 如果在同一 `corp-id` 下同时配置多个未填写 `agent-id` 的条目，会因 token/ticket 缓存 key 冲突而在启动时直接抛异常。\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 自建应用 1 配置（使用自建应用 Secret，需填写 agent-id）\n    wx.cp.corps.app1.corp-id = @corp-id\n    wx.cp.corps.app1.corp-secret = @自建应用的Secret（在\"应用管理-自建应用\"中查看）\n    wx.cp.corps.app1.agent-id = @自建应用的AgentId\n    ## 选填\n    wx.cp.corps.app1.token = @token\n    wx.cp.corps.app1.aes-key = @aes-key\n    wx.cp.corps.app1.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.corps.app1.msg-audit-lib-path = @msg-audit-lib-path\n\n    # 通讯录同步配置（使用通讯录同步 Secret，不需要填写 agent-id）\n    # 此配置用于部门、成员的增删改查等通讯录管理操作\n    wx.cp.corps.contact.corp-id = @corp-id\n    wx.cp.corps.contact.corp-secret = @通讯录同步的Secret（在\"管理工具-通讯录同步\"中查看）\n    ## agent-id 不填，通讯录同步不需要 agentId\n\n    # 公共配置\n    ## ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    ## http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.cp.config-storage.http-client-type=http_client\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.cp_multi.service.WxCpMultiServices;\nimport me.chanjar.weixin.cp.api.WxCpDepartmentService;\nimport me.chanjar.weixin.cp.api.WxCpService;\nimport me.chanjar.weixin.cp.api.WxCpUserService;\nimport me.chanjar.weixin.cp.bean.WxCpDepart;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxCpMultiServices wxCpMultiServices;\n\n  public void test() {\n    // 使用自建应用的 WxCpService（对应 corp-secret 为自建应用 Secret）\n    WxCpService appService = wxCpMultiServices.getWxCpService(\"app1\");\n    WxCpUserService userService = appService.getUserService();\n    userService.getUserId(\"xxx\");\n    // todo ...\n\n    // 使用通讯录同步的 WxCpService（对应 corp-secret 为通讯录同步 Secret）\n    // 通讯录同步 Secret 具有部门/成员增删改查等权限\n    WxCpService contactService = wxCpMultiServices.getWxCpService(\"contact\");\n    WxCpDepartmentService departmentService = contactService.getDepartmentService();\n    // 更新部门示例（WxCpDepart 包含 id、name、parentId 等字段）\n    WxCpDepart depart = new WxCpDepart();\n    depart.setId(100L);\n    depart.setName(\"新部门名称\");\n    departmentService.update(depart);\n    // todo ...\n  }\n}\n```\n\n<!-- File: solon-plugins/wx-java-cp-solon-plugin/README.md (Tokens: ~426 | Category: plugin-manifest) -->\n# wx-java-cp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-cp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 企业微信号配置(必填)\n    wx.cp.corp-id = @corp-id\n    wx.cp.corp-secret = @corp-secret\n    # 选填\n    wx.cp.agent-id = @agent-id\n    wx.cp.token = @token\n    wx.cp.aes-key = @aes-key\n    wx.cp.msg-audit-priKey = @msg-audit-priKey\n    wx.cp.msg-audit-lib-path = @msg-audit-lib-path\n    # ConfigStorage 配置（选填）\n    wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate\n    # http 客户端配置（选填）\n    wx.cp.config-storage.http-proxy-host=\n    wx.cp.config-storage.http-proxy-port=\n    wx.cp.config-storage.http-proxy-username=\n    wx.cp.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.cp.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.cp.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxCpService`, `WxCpConfigStorage`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n\n- WxCpService\n- WxCpConfigStorage\n\n<!-- File: solon-plugins/wx-java-miniapp-multi-solon-plugin/README.md (Tokens: ~971 | Category: plugin-manifest) -->\n# wx-java-miniapp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.ma.apps.tenantId1.app-id=appId\n    wx.ma.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.ma.apps.tenantId1.token=@token\n    wx.ma.apps.tenantId1.aes-key=@aesKey\n    wx.ma.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.ma.apps.tenantId2.app-id=@appId\n    wx.ma.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.ma.apps.tenantId2.token=@token\n    wx.ma.apps.tenantId2.aes-key=@aesKey\n    wx.ma.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson\n    wx.ma.config-storage.type=memory\n    ## 相关redis前缀配置: wx:ma:multi(默认)\n    wx.ma.config-storage.key-prefix=wx:ma:multi\n    wx.ma.config-storage.redis.host=127.0.0.1\n    wx.ma.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.ma.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.ma.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.ma.config-storage.http-client-type=http_client\n    wx.ma.config-storage.http-proxy-host=\n    wx.ma.config-storage.http-proxy-port=\n    wx.ma.config-storage.http-proxy-username=\n    wx.ma.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.ma.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.ma.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxMaMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.miniapp.service.WxMaMultiServices;\nimport cn.binarywang.wx.miniapp.api.WxMaService;\nimport cn.binarywang.wx.miniapp.api.WxMaUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMaMultiServices wxMaMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMaService\n    WxMaService wxMaService1 = wxMaMultiServices.getWxMaService(\"tenantId1\");\n    WxMaUserService userService1 = wxMaService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMaService\n    WxMaService wxMaService2 = wxMaMultiServices.getWxMaService(\"tenantId2\");\n    WxMaUserService userService2 = wxMaService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMaService\n    WxMaService wxMaService3 = wxMaMultiServices.getWxMaService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMaService3 == null) {\n      // todo wxMaService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMaUserService userService3 = wxMaService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n\n<!-- File: solon-plugins/wx-java-miniapp-solon-plugin/README.md (Tokens: ~399 | Category: plugin-manifest) -->\n# wx-java-miniapp-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-miniapp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.miniapp.appid = appId\n    wx.miniapp.secret = @secret\n    wx.miniapp.token = @token\n    wx.miniapp.aesKey = @aesKey\n    wx.miniapp.msgDataFormat = @msgDataFormat                  # 消息格式，XML或者JSON.\n    # 存储配置redis(可选)\n    # 注意: 指定redis.host值后不会使用容器注入的redis连接(JedisPool)\n    wx.miniapp.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.miniapp.config-storage.key-prefix = wa                  # 相关redis前缀配置: wa(默认)\n    wx.miniapp.config-storage.redis.host = 127.0.0.1\n    wx.miniapp.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.miniapp.config-storage.http-client-type=HttpClient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.miniapp.config-storage.http-proxy-host=\n    wx.miniapp.config-storage.http-proxy-port=\n    wx.miniapp.config-storage.http-proxy-username=\n    wx.miniapp.config-storage.http-proxy-password=\n    ```\n3. 自动注入的类型\n- `WxMaService`\n- `WxMaConfig`\n\n<!-- File: solon-plugins/wx-java-mp-multi-solon-plugin/README.md (Tokens: ~1023 | Category: plugin-manifest) -->\n# wx-java-mp-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-multi-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置\n    ## 应用 1 配置(必填)\n    wx.mp.apps.tenantId1.app-id=appId\n    wx.mp.apps.tenantId1.app-secret=@secret\n    ## 选填\n    wx.mp.apps.tenantId1.token=@token\n    wx.mp.apps.tenantId1.aes-key=@aesKey\n    wx.mp.apps.tenantId1.use-stable-access-token=@useStableAccessToken\n    ## 应用 2 配置(必填)\n    wx.mp.apps.tenantId2.app-id=@appId\n    wx.mp.apps.tenantId2.app-secret =@secret\n    ## 选填\n    wx.mp.apps.tenantId2.token=@token\n    wx.mp.apps.tenantId2.aes-key=@aesKey\n    wx.mp.apps.tenantId2.use-stable-access-token=@useStableAccessToken\n   \n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.mp.config-storage.type=memory\n    ## 相关redis前缀配置: wx:mp:multi(默认)\n    wx.mp.config-storage.key-prefix=wx:mp:multi\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  ## 单机和 sentinel 同时存在时，优先使用sentinel配置\n\t  # wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  # wx.mp.config-storage.redis.sentinel-name=mymaster \n   \n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认), ok_http, jodd_http\n    wx.mp.config-storage.http-client-type=http_client\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.mp.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.mp.config-storage.retry-sleep-millis=1000\n   \n\t  # 公众号地址 host 配置\n\t  # wx.mp.hosts.api-host=http://proxy.com/\n\t  # wx.mp.hosts.open-host=http://proxy.com/\n\t  # wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型：`WxMpMultiServices`\n\n4. 使用样例\n\n```java\nimport com.binarywang.solon.wxjava.mp_multi.service.WxMpMultiServices;\nimport me.chanjar.weixin.mp.api.WxMpService;\nimport me.chanjar.weixin.mp.api.WxMpUserService;\nimport org.noear.solon.annotation.Component;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxMpMultiServices wxMpMultiServices;\n\n  public void test() {\n    // 应用 1 的 WxMpService\n    WxMpService wxMpService1 = wxMpMultiServices.getWxMpService(\"tenantId1\");\n    WxMpUserService userService1 = wxMpService1.getUserService();\n    userService1.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 2 的 WxMpService\n    WxMpService wxMpService2 = wxMpMultiServices.getWxMpService(\"tenantId2\");\n    WxMpUserService userService2 = wxMpService2.getUserService();\n    userService2.userInfo(\"xxx\");\n    // todo ...\n\n    // 应用 3 的 WxMpService\n    WxMpService wxMpService3 = wxMpMultiServices.getWxMpService(\"tenantId3\");\n    // 判断是否为空\n    if (wxMpService3 == null) {\n      // todo wxMpService3 为空，请先配置 tenantId3 微信公众号应用参数\n      return;\n    }\n    WxMpUserService userService3 = wxMpService3.getUserService();\n    userService3.userInfo(\"xxx\");\n    // todo ...\n  }\n}\n```\n\n<!-- File: solon-plugins/wx-java-mp-solon-plugin/README.md (Tokens: ~467 | Category: plugin-manifest) -->\n# wx-java-mp-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-mp-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.mp.app-id=appId\n    wx.mp.secret=@secret\n    wx.mp.token=@token\n    wx.mp.aes-key=@aesKey\n    wx.mp.use-stable-access-token=@useStableAccessToken\n    # 存储配置redis(可选)\n    wx.mp.config-storage.type= edis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n    wx.mp.config-storage.key-prefix=wx                  # 相关redis前缀配置: wx(默认)\n    wx.mp.config-storage.redis.host=127.0.0.1\n    wx.mp.config-storage.redis.port=6379\n\t  #单机和sentinel同时存在时，优先使用sentinel配置\n\t  #wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n\t  #wx.mp.config-storage.redis.sentinel-name=mymaster\n    # http客户端配置\n    wx.mp.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n    wx.mp.config-storage.http-proxy-host=\n    wx.mp.config-storage.http-proxy-port=\n    wx.mp.config-storage.http-proxy-username=\n    wx.mp.config-storage.http-proxy-password=\n\t  # 公众号地址host配置\n\t  #wx.mp.hosts.api-host=http://proxy.com/\n\t  #wx.mp.hosts.open-host=http://proxy.com/\n\t  #wx.mp.hosts.mp-host=http://proxy.com/\n    ```\n3. 自动注入的类型\n\n- `WxMpService`\n- `WxMpConfigStorage`\n\n4、参考demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n\n<!-- File: solon-plugins/wx-java-open-solon-plugin/README.md (Tokens: ~491 | Category: plugin-manifest) -->\n# wx-java-open-solon-plugin\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-open-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 公众号配置(必填)\n    wx.open.appId = appId\n    wx.open.secret = @secret\n    wx.open.token = @token\n    wx.open.aesKey = @aesKey\n    # 存储配置redis(可选)\n    # 优先注入容器的(JedisPool, RedissonClient), 当配置了wx.open.config-storage.redis.host, 不会使用容器注入redis连接配置\n    wx.open.config-storage.type = redis                     # 配置类型: memory(默认), redis(jedis), jedis, redisson, redistemplate\n    wx.open.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n    wx.open.config-storage.redis.host = 127.0.0.1\n    wx.open.config-storage.redis.port = 6379\n    # http客户端配置\n    wx.open.config-storage.http-client-type=httpclient      # http客户端类型: httpclient(默认)\n    wx.open.config-storage.http-proxy-host=\n    wx.open.config-storage.http-proxy-port=\n    wx.open.config-storage.http-proxy-username=\n    wx.open.config-storage.http-proxy-password=\n    # 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.open.config-storage.max-retry-times=5\n    # 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.open.config-storage.retry-sleep-millis=1000\n    ```\n3. 支持自动注入的类型: `WxOpenService, WxOpenMessageRouter, WxOpenComponentService`\n\n4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的\n  - WxOpenConfigStorage\n  - WxOpenService\n\n<!-- File: solon-plugins/wx-java-pay-solon-plugin/README.md (Tokens: ~547 | Category: plugin-manifest) -->\n# 使用说明\n1. 在自己的Solon项目里，引入maven依赖\n```xml\n    <dependency>\n        <groupId>com.github.binarywang</groupId>\n        <artifactId>wx-java-pay-solon-plugin</artifactId>\n        <version>${version}</version>\n    </dependency>\n ```\n2. 添加配置(app.yml)\n###### 1）V2版本\n```yml\nwx:\n  pay:\n    appId: \n    mchId: \n    mchKey: \n    keyPath:\n```\n###### 2）V3版本\n```yml\nwx:\n  pay:\n    appId: xxxxxxxxxxx\n    mchId: 15xxxxxxxxx #商户id\n    apiHostUrl: http://10.0.0.1:3128 # 可选：代理主机\n    apiHostUrlPath: /api-weixin # 可选：代理入口前缀\n    apiV3Key: Dc1DBwSc094jACxxxxxxxxxxxxxxx #V3密钥\n    certSerialNo: 62C6CEAA360BCxxxxxxxxxxxxxxx\n    privateKeyPath: classpath:cert/apiclient_key.pem #apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径\n    privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n###### 3）V3服务商版本\n```yml\nwx:\n  pay: #微信服务商支付\n    configs:\n    - appId: wxe97b2x9c2b3d #spAppId\n      mchId: 16486610 #服务商商户\n      subAppId: wx118cexxe3c07679 #子appId\n      subMchId: 16496705 #子商户\n      apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr #apiV3密钥\n      privateKeyPath: classpath:cert/apiclient_key.pem #服务商证书文件，apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径（可以配置绝对路径）\n      privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径\n```\n\n<!-- File: solon-plugins/wx-java-qidian-solon-plugin/README.md (Tokens: ~479 | Category: plugin-manifest) -->\n# wx-java-qidian-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n   ```xml\n   <dependency>\n       <groupId>com.github.binarywang</groupId>\n       <artifactId>wx-java-qidian-solon-plugin</artifactId>\n       <version>${version}</version>\n   </dependency>\n   ```\n2. 添加配置(app.properties)\n   ```properties\n   # 公众号配置(必填)\n   wx.qidian.appId = appId\n   wx.qidian.secret = @secret\n   wx.qidian.token = @token\n   wx.qidian.aesKey = @aesKey\n   # 存储配置redis(可选)\n   wx.qidian.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate\n   wx.qidian.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)\n   wx.qidian.config-storage.redis.host = 127.0.0.1\n   wx.qidian.config-storage.redis.port = 6379\n   #单机和sentinel同时存在时，优先使用sentinel配置\n   #wx.qidian.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379\n   #wx.qidian.config-storage.redis.sentinel-name=mymaster\n   # http客户端配置\n   wx.qidian.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp\n   wx.qidian.config-storage.http-proxy-host=\n   wx.qidian.config-storage.http-proxy-port=\n   wx.qidian.config-storage.http-proxy-username=\n   wx.qidian.config-storage.http-proxy-password=\n   # 公众号地址host配置\n   #wx.qidian.hosts.api-host=http://proxy.com/\n   #wx.qidian.hosts.open-host=http://proxy.com/\n   #wx.qidian.hosts.mp-host=http://proxy.com/\n   ```\n3. 自动注入的类型\n\n- `WxQidianService`\n- `WxQidianConfigStorage`\n\n4、参考 demo：\nhttps://github.com/binarywang/wx-java-mp-demo\n\n<!-- File: solon-plugins/wx-java-store-multi-solon-plugin/README.md (Tokens: ~1093 | Category: plugin-manifest) -->\n# wx-java-store-multi-solon-plugin\n\n## 快速开始\n\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-multi-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置\n    ## 应用 1 配置(必填)\n    wx.store.apps.tenantId1.app-id=@appId\n    wx.store.apps.tenantId1.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId1.use-stable-access-token=false\n    wx.store.apps.tenantId1.token=\n    wx.store.apps.tenantId1.aes-key=\n    ## 应用 2 配置(必填)\n    wx.store.apps.tenantId2.app-id=@appId\n    wx.store.apps.tenantId2.secret=@secret\n    ## 选填\n    wx.store.apps.tenantId2.use-stable-access-token=false\n    wx.store.apps.tenantId2.token=\n    wx.store.apps.tenantId2.aes-key=\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store:multi(默认)\n    wx.store.config-storage.key-prefix=wx:store:multi\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型：`WxStoreMultiServices`\n\n4. 使用样例\n\n    ```java\n    import com.binarywang.solon.wxjava.store.service.WxStoreMultiServices;\n    import com.binarywang.wxjava.store.api.WxStoreService;\n    import com.binarywang.wxjava.store.api.WxFinderLiveService;\n    import com.binarywang.wxjava.store.bean.lead.component.response.FinderAttrResponse;\n    import me.chanjar.weixin.common.error.WxErrorException;\n    import org.noear.solon.annotation.Component;\n    import org.noear.solon.annotation.Inject;\n\n    @Component\n    public class DemoService {\n      @Inject\n      private WxStoreMultiServices wxStoreMultiServices;\n\n      public void test() throws WxErrorException {\n        // 应用 1 的 WxStoreService\n        WxStoreService wxStoreService1 = wxStoreMultiServices.getWxStoreService(\"tenantId1\");\n        WxFinderLiveService finderLiveService = wxStoreService1.getFinderLiveService();\n        FinderAttrResponse response1 = finderLiveService.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 2 的 WxStoreService\n        WxStoreService wxStoreService2 = wxStoreMultiServices.getWxStoreService(\"tenantId2\");\n        WxFinderLiveService finderLiveService2 = wxStoreService2.getFinderLiveService();\n        FinderAttrResponse response2 = finderLiveService2.getFinderAttrByAppid();\n        // todo ...\n\n        // 应用 3 的 WxStoreService\n        WxStoreService wxStoreService3 = wxStoreMultiServices.getWxStoreService(\"tenantId3\");\n        // 判断是否为空\n        if (wxStoreService3 == null) {\n          // todo wxStoreService3 为空，请先配置 tenantId3 微信小店应用参数\n          return;\n        }\n        WxFinderLiveService finderLiveService3 = wxStoreService3.getFinderLiveService();\n        FinderAttrResponse response3 = finderLiveService3.getFinderAttrByAppid();\n        // todo ...\n      }\n    }\n    ```\n\n<!-- File: solon-plugins/wx-java-store-solon-plugin/README.md (Tokens: ~802 | Category: plugin-manifest) -->\n# wx-java-store-solon-plugin\n\n## 快速开始\n1. 引入依赖\n    ```xml\n    <dependencies>\n        <dependency>\n            <groupId>com.github.binarywang</groupId>\n            <artifactId>wx-java-store-solon-plugin</artifactId>\n            <version>${version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为jedis 则引入jedis -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n        </dependency>\n\n        <!-- 配置存储方式为redisson 则引入redisson -->\n        <dependency>\n            <groupId>org.redisson</groupId>\n            <artifactId>redisson</artifactId>\n            <version>${redisson.version}</version>\n        </dependency>\n    </dependencies>\n    ```\n2. 添加配置(app.properties)\n    ```properties\n    # 视频号配置(必填)\n    ## 微信小店的appId和secret\n    wx.store.app-id=@appId\n    wx.store.secret=@secret\n    # 视频号配置 选填\n    ## 设置微信小店消息服务器配置的token\n    wx.store.token=@token\n    ## 设置微信小店消息服务器配置的EncodingAESKey\n    wx.store.aes-key=\n    ## 支持JSON或者XML格式，默认JSON\n    wx.store.msg-data-format=JSON\n    ## 是否使用稳定版 Access Token\n    wx.store.use-stable-access-token=false\n\n\n    # ConfigStorage 配置（选填）\n    ## 配置类型: memory(默认), jedis, redisson, redis_template\n    wx.store.config-storage.type=memory\n    ## 相关redis前缀配置: wx:store(默认)\n    wx.store.config-storage.key-prefix=wx:store\n    wx.store.config-storage.redis.host=127.0.0.1\n    wx.store.config-storage.redis.port=6379\n    wx.store.config-storage.redis.password=123456\n\n\n    # http 客户端配置（选填）\n    ## # http客户端类型: http_client(默认)\n    wx.store.config-storage.http-client-type=http_client\n    wx.store.config-storage.http-proxy-host=\n    wx.store.config-storage.http-proxy-port=\n    wx.store.config-storage.http-proxy-username=\n    wx.store.config-storage.http-proxy-password=\n    ## 最大重试次数，默认：5 次，如果小于 0，则为 0\n    wx.store.config-storage.max-retry-times=5\n    ## 重试时间间隔步进，默认：1000 毫秒，如果小于 0，则为 1000\n    wx.store.config-storage.retry-sleep-millis=1000\n    ```\n3. 自动注入的类型\n- `WxStoreService`\n- `WxStoreConfig`\n4. 使用样例\n\n```java\nimport com.binarywang.wxjava.store.api.WxStoreService;\nimport com.binarywang.wxjava.store.bean.shop.ShopInfoResponse;\nimport com.binarywang.wxjava.store.util.JsonUtils;\nimport me.chanjar.weixin.common.error.WxErrorException;\nimport org.noear.solon.annotation.Inject;\n\n@Component\npublic class DemoService {\n  @Inject\n  private WxStoreService wxStoreService;\n\n  public String getShopInfo() throws WxErrorException {\n    // 获取店铺基本信息\n    ShopInfoResponse response = wxStoreService.getBasicService().getShopInfo();\n    // 此处为演示，如果要返回response的结果，建议自己封装一个VO，避免直接返回response\n    return JsonUtils.encode(response);\n  }\n}\n```\n</yakaai_skills>"}