| @@ -12,304 +12,43 @@ weixin-java-tools | |||
| 5. 微信服务端繁忙自动重试的功能 | |||
| 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 | |||
| WxConfigStorage config = new WxInMemoryConfigStorage(); | |||
| config.setAppId(...); | |||
| config.setSecret(...); | |||
| config.setToken(...); | |||
| config.setAppId(...); // 设置微信公众号的appid | |||
| config.setSecret(...); // 设置微信公众号的app secret | |||
| config.setToken(...); // 设置微信公众号的token | |||
| WxServiceImpl wxService = new WxServiceImpl(); | |||
| 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); | |||
| ``` | |||
| ### 群发消息 | |||
| 下面用用户列表群发(``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 | |||
| ``` | |||