| @@ -12,304 +12,43 @@ weixin-java-tools | |||||
| 5. 微信服务端繁忙自动重试的功能 | 5. 微信服务端繁忙自动重试的功能 | ||||
| 6. 提供微信错误信息的异常处理机制 | 6. 提供微信错误信息的异常处理机制 | ||||
| ## 微信消息路由器 | |||||
| # Quickstart | |||||
| 你可以使用``WxMessageRouter``来对微信推送过来的消息、事件进行路由,交给的``WxMessageHandler``处理。 | |||||
| ## 打包 | |||||
| 使用方法: | |||||
| ```java | |||||
| WxMessageRouter router = new WxMessageRouter(); | |||||
| router | |||||
| .rule() | |||||
| .msgType("MSG_TYPE") | |||||
| .event("EVENT") | |||||
| .eventKey("EVENT_KEY") | |||||
| .content("CONTENT") | |||||
| .interceptor(interceptor).handler(handler) | |||||
| .end() | |||||
| .rule() | |||||
| .msgType("MSG_TYPE") | |||||
| .handler(handler) | |||||
| .end() | |||||
| ; | |||||
| // 将WxXmlMessage交给消息路由器 | |||||
| WxXmlMessage message = WxXmlMessage.fromXml(xml); | |||||
| router.route(message); | |||||
| 如果你可以跳过单元测试直接打包: | |||||
| ```bash | |||||
| mvn clean install -Dmaven.test.skip=true | |||||
| ``` | ``` | ||||
| 1. 开发人员需实现自己的``WxMessageHandler``和``WxMessageInterceptor`` | |||||
| 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理 | |||||
| 2. 默认情况下消息只会被处理一次,除非使用 ``Rule.next()`` | |||||
| 3. 规则的结束必须用``Rule.end()``或者``Rule.next()``,否则不会生效 | |||||
| 4. 具体使用可以看源代码中的``WxMessageRouterTest``单元测试,或者查看Javadoc | |||||
| ### 同步回复 | |||||
| ``WxMessageRouter``默认使用异步的方式处理消息,如果要使用同步的方式处理消息,那么可以这样: | |||||
| ```java | |||||
| router | |||||
| .rule() | |||||
| .async(false) | |||||
| .handler(handler) | |||||
| .end() | |||||
| ; | |||||
| 如果你需要执行本项目的单元测试代码,那么你需要将 ``src/test/resources/test-config.sample.xml`` 改成 ``test-config.xml`` ,并设置appId, secret, accessToken(可选), openId,然后执行: | |||||
| WxXmlMessage message = WxXmlMessage.fromXml(xml); | |||||
| // 获得同步的返回结果 | |||||
| WxXmlMessage res = router.route(message); | |||||
| String xml = res.toXml(); | |||||
| // ... 将xml写入HttpServletResponse | |||||
| ```bash | |||||
| mvn clean install | |||||
| ``` | ``` | ||||
| 在你的maven项目中添加: | |||||
| ```xml | |||||
| <dependency> | |||||
| <groupId>chanjarster.weixin</groupId> | |||||
| <artifactId>weixin-java-tools</artifactId> | |||||
| <version>1.0.0-SNAPSHOT</version> | |||||
| </dependency> | |||||
| ``` | |||||
| ## 微信Java API | |||||
| 使用``WxService``可以调用微信API。目前已实现除“微信小店”以外的所有功能。 | |||||
| ### 构造WxService | |||||
| ``WxService``依赖于``WxConfigStorage``,``WxConfigStorage``是微信客户端配置所存储的地方,本工具提供了默认基于内存的实现:``WxInMemoryConfigStorage``。您可能在实际使用时需要提供自己的实现,比如在集群环境下存储到数据库中。 | |||||
| ## Hello World | |||||
| ```java | ```java | ||||
| WxConfigStorage config = new WxInMemoryConfigStorage(); | WxConfigStorage config = new WxInMemoryConfigStorage(); | ||||
| config.setAppId(...); | |||||
| config.setSecret(...); | |||||
| config.setToken(...); | |||||
| config.setAppId(...); // 设置微信公众号的appid | |||||
| config.setSecret(...); // 设置微信公众号的app secret | |||||
| config.setToken(...); // 设置微信公众号的token | |||||
| WxServiceImpl wxService = new WxServiceImpl(); | WxServiceImpl wxService = new WxServiceImpl(); | ||||
| wxService.setWxConfigStorage(config); | wxService.setWxConfigStorage(config); | ||||
| ``` | |||||
| ### 验证消息 | |||||
| ```java | |||||
| if(!wxService.checkSignature(timestamp, nonce, signature)) { | |||||
| // 验证失败 | |||||
| } | |||||
| ``` | |||||
| ### 刷新access_token | |||||
| ```java | |||||
| wxService.accessTokenRefresh(); | |||||
| ``` | |||||
| 刷新后的accessToken存在WxConfigStorage中。 | |||||
| ### 多媒体文件 | |||||
| #### 上传多媒体文件 | |||||
| ```java | |||||
| InputStream inputStream = ...; | |||||
| File file = ...; | |||||
| WxMediaUploadResult res = wxService.mediaUpload(mediaType, fileType, inputStream); | |||||
| // 或者 | |||||
| res = wxService.mediaUpload(mediaType, file); | |||||
| res.getType(); | |||||
| res.getCreated_at(); | |||||
| res.getMedia_id(); | |||||
| res.getThumb_media_id(); | |||||
| ``` | |||||
| #### 下载多媒体文件 | |||||
| ```java | |||||
| // 获得一个在系统临时目录的文件 | |||||
| File file = wxService.mediaDownload(media_id); | |||||
| ``` | |||||
| ### 分组管理 | |||||
| #### 创建分组 | |||||
| ```java | |||||
| WxGroup res = wxService.groupCreate("测试分组1"); | |||||
| ``` | |||||
| #### 获得分组列表 | |||||
| ```java | |||||
| List<WxGroup> groupList = wxService.groupGet(); | |||||
| ``` | |||||
| #### 更新分组名 | |||||
| ```java | |||||
| WxGroup g = new WxGroup(); | |||||
| g.setId(...); | |||||
| g.setName(...); | |||||
| wxService.groupUpdate(group); | |||||
| ``` | |||||
| ### 用户管理 | |||||
| #### 更新用户备注名 | |||||
| ```java | |||||
| wxService.userUpdateRemark(openid, "测试备注名"); | |||||
| ``` | |||||
| #### 获得用户信息 | |||||
| ```java | |||||
| String lang = "zh_CN"; //语言 | |||||
| WxUser user = wxService.userInfo(openid, lang); | |||||
| ``` | |||||
| #### 获得用户列表 | |||||
| ```java | |||||
| WxUserList wxUserList = wxService.userList(next_openid); | |||||
| ``` | |||||
| #### 查询用户所在分组 | |||||
| ```java | |||||
| long groupid = wxService.userGetGroup(openid); | |||||
| ``` | |||||
| #### 将用户移到分组 | |||||
| ```java | |||||
| wxService.userUpdateGroup(openid, to_groupid); | |||||
| ``` | |||||
| ### 发送客服消息 | |||||
| ```java | |||||
| WxCustomMessage message = new WxCustomMessage(); | |||||
| // 设置消息的内容等信息 | |||||
| // 用户的openid在下面地址获得 | |||||
| // https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=用户管理&form=获取关注者列表接口%20/user/get | |||||
| String openid = ...; | |||||
| WxCustomMessage message = WxCustomMessage.TEXT().toUser(openid).content("Hello World").build(); | |||||
| wxService.customMessageSend(message); | wxService.customMessageSend(message); | ||||
| ``` | ``` | ||||
| ### 群发消息 | |||||
| 下面用用户列表群发(``WxMassOpenIdsMessage``)做例子,如果要使用分组群发,则使用``WxMassGroupMessage``即可。 | |||||
| #### 文本消息 | |||||
| ```java | |||||
| WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage(); | |||||
| massMessage.setMsgtype(WxConsts.MASS_MSG_TEXT); | |||||
| massMessage.setContent("消息内容"); | |||||
| massMessage.getTouser().add(openid); | |||||
| WxMassSendResult massResult = wxService.massOpenIdsMessageSend(massMessage); | |||||
| ``` | |||||
| #### 视频消息 | |||||
| ```java | |||||
| WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, inputStream); | |||||
| // 把视频变成可被群发的媒体 | |||||
| WxMassVideo video = new WxMassVideo(); | |||||
| video.setTitle("测试标题"); | |||||
| video.setDescription("测试描述"); | |||||
| video.setMedia_id(uploadMediaRes.getMedia_id()); | |||||
| WxMassUploadResult uploadResult = wxService.massVideoUpload(video); | |||||
| WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage(); | |||||
| massMessage.setMsgtype(WxConsts.MASS_MSG_VIDEO); | |||||
| massMessage.setMedia_id(uploadResult.getMedia_id()); | |||||
| massMessage.getTouser().add(openid); | |||||
| WxMassSendResult massResult = wxService.massOpenIdsMessageSend(massMessage); | |||||
| ``` | |||||
| #### 图片消息 | |||||
| ```java | |||||
| WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream); | |||||
| WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage(); | |||||
| massMessage.setMsgtype(WxConsts.MASS_MSG_IMAGE); | |||||
| massMessage.setMedia_id(uploadMediaRes.getMedia_id()); | |||||
| massMessage.getTouser().add(openid); | |||||
| WxMassSendResult massResult = wxService.massOpenIdsMessageSend(massMessage); | |||||
| ``` | |||||
| #### 语音消息 | |||||
| ```java | |||||
| WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, inputStream); | |||||
| WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage(); | |||||
| massMessage.setMsgtype(WxConsts.MASS_MSG_VOICE); | |||||
| massMessage.setMedia_id(uploadMediaRes.getMedia_id()); | |||||
| massMessage.getTouser().add(openid); | |||||
| WxMassSendResult massResult = wxService.massOpenIdsMessageSend(massMessage); | |||||
| ``` | |||||
| #### 图文消息 | |||||
| ```java | |||||
| // 先上传图文消息里需要的图片 | |||||
| WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream); | |||||
| WxMassNews news = new WxMassNews(); | |||||
| WxMassNewsArticle article1 = new WxMassNewsArticle(); | |||||
| article1.setTitle("标题1"); | |||||
| article1.setContent("内容1"); | |||||
| article1.setThumb_media_id(uploadMediaRes.getMedia_id()); | |||||
| news.addArticle(article1); | |||||
| WxMassNewsArticle article2 = new WxMassNewsArticle(); | |||||
| article2.setTitle("标题2"); | |||||
| article2.setContent("内容2"); | |||||
| article2.setThumb_media_id(uploadMediaRes.getMedia_id()); | |||||
| article2.setShow_cover_pic(true); | |||||
| article2.setAuthor("作者2"); | |||||
| article2.setContent_source_url("www.baidu.com"); | |||||
| article2.setDigest("摘要2"); | |||||
| news.addArticle(article2); | |||||
| WxMassUploadResult massUploadResult = wxService.massNewsUpload(news); | |||||
| WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage(); | |||||
| massMessage.setMsgtype(WxConsts.MASS_MSG_NEWS); | |||||
| massMessage.setMedia_id(uploadResult.getMedia_id()); | |||||
| massMessage.getTouser().add(openid); | |||||
| WxMassSendResult massResult = wxService.massOpenIdsMessageSend(massMessage); | |||||
| ``` | |||||
| ### 自定义菜单 | |||||
| #### 创建自定义菜单 | |||||
| ```java | |||||
| WxMenu wxMenu = new WxMenu(); | |||||
| // 设置菜单 | |||||
| wxService.menuCreate(wxMenu); | |||||
| ``` | |||||
| #### 删除自定义菜单 | |||||
| ```java | |||||
| wxService.menuDelete(); | |||||
| ``` | |||||
| #### 获得自定义菜单 | |||||
| ```java | |||||
| WxMenu wxMenu = wxService.menuGet() | |||||
| ``` | |||||
| ### 二维码 | |||||
| #### 获得二维码ticket | |||||
| ```java | |||||
| // 临时ticket | |||||
| WxQrCodeTicket ticket = wxService.qrCodeCreateTmpTicket(scene, expire_seconds); | |||||
| // 永久ticket | |||||
| WxQrCodeTicket ticket = wxService.qrCodeCreateLastTicket(scene); | |||||
| ``` | |||||
| #### 换取二维码图片 | |||||
| ```java | |||||
| WxQrCodeTicket ticket = ...; | |||||
| // 获得一个在系统临时目录下的文件,是jpg格式的 | |||||
| File file = wxService.qrCodePicture(ticket); | |||||
| ``` | |||||
| ### 短链接 | |||||
| ```java | |||||
| String shortUrl = wxService.shortUrl("www.baidu.com"); | |||||
| ``` | |||||
| ## 如何执行单元测试 | |||||
| 将 ``src/test/resources/test-config.sample.xml`` 改成 ``test-config.xml`` 设置appId, secret, accessToken(可选), openId | |||||
| ```bash | |||||
| mvn clean test | |||||
| ``` | |||||