2025-03-28
工具运维
0

目录

WxJava 简介
主要特性
核心模块介绍
环境配置与快速开始
依赖配置
基础配置
核心功能与使用示例
服务接入认证
消息加解密
素材管理
网页授权与用户信息
微信授权实战
高级特性与最佳实践
消息路由机制
缓存策略优化
异常处理
开发建议
总结

强大的 Java 工具包,让微信开发变得简单高效

WxJava 简介

WxJava 是一款开源的微信开发 Java SDK,支持包括微信支付、开放平台、公众号、企业微信/企业号、小程序等微信功能的后端开发。该项目基于 chanjarster 的 weixin-java-tools 发展而来,经过多次优化和重构,使得接口更易使用,方便开发者快速集成微信各项功能。

GIT: https://gitee.com/binary/weixin-java-tools

主要特性

  • 不依赖任何 MVC 框架,也不依赖 Servlet,可轻松嵌入到任何系统里

  • 模块化设计,结构清晰,只需引入需要的模块即可

  • 仅仅作为工具使用,可轻松嵌入到任何系统里

  • 支持企业号、公众号、小程序以及微信支付开发

  • 丰富的文档和社区支持,持续更新维护

核心模块介绍

WxJava 包含 6 个主要模块,每个模块针对不同的微信开发场景:

模块名称功能描述
weixin-java-common基础工具类与通用接口(如消息加解密、HTTP请求封装)
weixin-java-mp公众号(订阅号和服务号)SDK
weixin-java-miniapp微信小程序 SDK
weixin-java-pay微信支付 SDK
weixin-java-cp企业号/企业微信 SDK
weixin-java-open微信开放平台(第三方平台)SDK

环境配置与快速开始

依赖配置

对于 Spring Boot 项目,只需添加对应模块的 starter 依赖

xml
<!-- 微信应用开发 --> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>wx-java-mp-spring-boot-starter</artifactId> <version>4.7.0</version> </dependency>

对于非 Spring Boot 项目:

xml
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>4.7.0</version> </dependency>

基础配置

在 application.yml 或 application.properties 中配置微信公众号参数:

yaml
# 公众号配置(必填) wx: mp: appId: your_app_id secret: your_app_secret token: your_token # 存储配置redis(可选),默认是内存 config-storage: type: redistemplate redis: host: 127.0.0.1 port: 6379

核心功能与使用示例

服务接入认证

微信公众号开发首先需要完成服务器验证,以下是一个简单的验证接口实现:

java
@RestController public class WxController { @Autowired private WxMpService wxMpService; /** * 微信服务验证 */ @RequestMapping("/wx") public void wx(HttpServletRequest request, HttpServletResponse response) throws IOException { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); log.info("微信服务器的认证消息:signature :{},timestamp:{},nonce:{},echostr:{}", signature, timestamp, nonce, echostr); if (!wxMpService.checkSignature(timestamp, nonce, signature)) { log.error("消息不合法"); return; } PrintWriter writer = response.getWriter(); try { writer.println(echostr); log.info("验证成功,给微信服务返回消息:{}", echostr); } finally { writer.close(); } } }

消息加解密

WxJava 内置了消息加解密功能,确保与微信服务器通信的安全:

java
public String decryptMsg(String msgSignature, String timestamp, String nonce, String encryptMsg) { // 1. 签名校验 String calSignature = SHA1.gen(..., token, timestamp, nonce); if(!msgSignature.equals(calSignature)) throw new Exception; // 2. AES解密 byte[] aesKey = Base64.decode(encodingAesKey); AES aes = new AES(Mode.CBC, Padding.PKCS7, aesKey, iv); return aes.decrypt(encryptMsg); }

素材管理

WxJava 提供了简洁的 API 来管理微信公众号的素材:

java
// 上传临时素材 @GetMapping("/saveTemporaryMaterial") public String saveTemporaryMaterial() { File file = new File("path/to/image.jpg"); WxMediaUploadResult result = wxService.getMaterialService() .mediaUpload(WxConsts.MediaFileType.IMAGE, file); return "上传成功,mediaId: " + result.getMediaId(); } // 上传永久素材 @GetMapping("/savePerpetualMaterial") public String savePerpetualMaterial() { File file = new File("path/to/image.jpg"); WxMpMaterial wxMpMaterial = new WxMpMaterial(); wxMpMaterial.setFile(file); wxMpMaterial.setName("logo"); WxMpMaterialUploadResult result = wxService.getMaterialService() .materialFileUpload(WxConsts.MediaFileType.IMAGE, wxMpMaterial); return "上传成功,mediaId: " + result.getMediaId(); }

网页授权与用户信息

获取用户信息是微信公众号开发的常见需求

java
// 获取用户信息 WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code); WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(wxOAuth2AccessToken, null);

微信授权实战

场景:PC网站上提供二维码,通过微信扫码授权登录,获取微信授权的用户信息

  1. 构建授权的URL,给前端返回 base64 的二维码,缓存 state 标识1分钟,设置为待处理
  2. 前端循环检查登录状态,如果是过期,则前端重新获取二维码,如果是待处理,则跳过,如果是登录成功,则清除缓存状态,前端跳转到网站页面(可同时返回 Token 登录)
  3. 微信服务授权后的回调,根据 code 获取用户信息,同时更新 state 为成功,调整成功的页面
java
@Slf4j @RestController public class WxController { @Autowired private WxMpService wxMpService; @Resource private ImUsersService imUsersService; /** * 获取授权URL,生成二维码并转成 base64 */ @GetMapping("/login/qrcode") public QrCodeResponse authorizationUrl() { // 获取重定向URL String oauth2RedirectUrl = wxMpService.getWxMpConfigStorage().getOauth2RedirectUrl(); // 生成回调的state String state = IdUtil.fastUUID(); // 构建授权URL String authorizationUrl = wxMpService.getOAuth2Service().buildAuthorizationUrl(oauth2RedirectUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, state); log.info("微信服务授权URL:{}", authorizationUrl); // 生成二维码 String qrCode = QrCodeUtil.generateAsBase64(authorizationUrl, new QrConfig(200, 200), ImgUtil.IMAGE_TYPE_JPG); // 缓存state,有效期1分钟 if (!RedisCacheUtil.setIfAbsent(String.format(RedisKeyDefine.LOGIN_STATE, state), LoginStateEnum.PENDING.name(), 1, TimeUnit.MINUTES)) { return this.authorizationUrl(); } return new QrCodeResponse(state, qrCode); } /** * 检查登录状态 */ @GetMapping("/login/check") public LoginStateEnum checkLoginStatus(@RequestParam("state") String state) { String value = RedisCacheUtil.get(String.format(RedisKeyDefine.LOGIN_STATE, state)); if (value == null) { return LoginStateEnum.EXPIRED; } else if (LoginStateEnum.PENDING.name().equals(value)) { return LoginStateEnum.PENDING; } // 登录成功,返回token并清除state RedisCacheUtil.delete(String.format(RedisKeyDefine.LOGIN_STATE, state)); return LoginStateEnum.SUCCESS; } /** * 微信服务授权后的回调 */ @GetMapping("/callback") public String callback(@RequestParam(name = "code") String code, @RequestParam(name = "state") String state) throws WxErrorException { log.info("微信服务回调:code:{}", code); // 获取用户信息 WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code); WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(wxOAuth2AccessToken, null); log.info("微信服务回调:userInfo:{}", userInfo); // 更新state,二维码等回调呢 RedisCacheUtil.set(String.format(RedisKeyDefine.LOGIN_STATE, state), LoginStateEnum.SUCCESS.name()); // 初始化账户 imUsersService.initUser(userInfo); // 返回响应成功的页面 return "/success"; } /** * 微信服务验证 */ @RequestMapping("/wx") public void wx(HttpServletRequest request, HttpServletResponse response) throws IOException { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); log.info("微信服务器的认证消息:signature :{},timestamp:{},nonce:{},echostr:{}", signature, timestamp, nonce, echostr); if (!wxMpService.checkSignature(timestamp, nonce, signature)) { log.error("消息不合法"); return; } PrintWriter writer = response.getWriter(); try { writer.println(echostr); log.info("验证成功,给微信服务返回消息:{}", echostr); } finally { writer.close(); } } }

配置信息

java
@Configuration @EnableConfigurationProperties({WxMpProperties.class, EchoIMProperties.class}) public class WxMpConfiguration { @Bean public WxMpService wxMpService(WxMpConfigStorage configStorage) { WxMpService wxMpService = new WxMpServiceImpl(); wxMpService.setWxMpConfigStorage(configStorage); return wxMpService; } @Bean public WxMpConfigStorage wxMpConfigStorage(WxMpProperties wxMpProperties, EchoIMProperties echoIMProperties) { WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl(); configStorage.setAppId(wxMpProperties.getAppId()); configStorage.setSecret(wxMpProperties.getSecret()); configStorage.setToken(wxMpProperties.getToken()); configStorage.setAesKey(wxMpProperties.getAesKey()); // 回调地址 configStorage.setOauth2RedirectUrl(echoIMProperties.url() + "/callback"); return configStorage; } }

高级特性与最佳实践

消息路由机制

WxJava 提供了强大的消息路由功能,可以根据消息类型、内容等条件将消息路由到不同的处理器:

java
// 初始化消息路由器 WxMpMessageRouter router = new WxMpMessageRouter(wxMpService); // 配置路由规则 router.rule() .msgType(WxConsts.XmlMsgType.TEXT) .handler(textHandler) .end() .rule() .msgType(WxConsts.XmlMsgType.IMAGE) .handler(imageHandler) .end(); // 处理微信消息 WxMpXmlMessage message = ...; WxMpXmlOutMessage response = router.route(message);

缓存策略优化

为了提高性能,WxJava 支持多种缓存策略,推荐使用 Redis 缓存 access_token 等敏感信息:

java
// JSAPI ticket 缓存示例 public String getJsapiTicket() { String ticket = cache.get("jsapi_ticket"); if (ticket == null || isExpired(ticket)) { ticket = refreshTicket(); // 预留 5 分钟缓冲时间 cache.set("jsapi_ticket", ticket, 7200 - 300); } return ticket; }

异常处理

WxJava 使用 WxErrorException 来封装微信接口返回的错误信息,便于统一异常处理:

java
try { // 调用微信 API WxMpUser user = wxMpService.getUserService().userInfo(openId, lang); } catch (WxErrorException e) { // 处理微信接口错误 log.error("微信接口调用失败,错误码:{},错误信息:{}", e.getError().getErrorCode(), e.getError().getErrorMsg()); // 根据不同的错误码进行特定处理 }

开发建议

根据实践经验,以下是使用 WxJava 的几点开发建议:

  • 自定义消息处理器应遵循单一职责原则

  • 敏感操作建议实现二次验证机制

  • 分布式部署时注意 access_token 同步问题

  • 定期关注微信官方接口更新,及时升级 SDK 版本

总结

WxJava 作为一款功能全面、设计优雅的微信开发 Java SDK,极大地简化了微信生态各类应用的开发工作。其模块化设计、丰富的功能覆盖和活跃的社区支持,使其成为 Java 开发者进行微信开发的首选工具包。

无论是初学者还是经验丰富的开发者,都能通过 WxJava 快速构建稳定、高效的微信应用。随着微信生态的不断发展,WxJava 也在持续更新迭代,为开发者提供更好的开发体验和更强大的功能支持。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!