├── .gitignore ├── .travis.yml ├── README.MD ├── commit.sh ├── pom.xml └── src └── main ├── java └── com │ └── github │ └── binarywang │ └── demo │ └── wx │ └── open │ ├── WxOpenApplication.java │ ├── config │ ├── RedisProperies.java │ └── WechatOpenProperties.java │ ├── controller │ ├── WechatApiController.java │ └── WechatNotifyController.java │ └── service │ └── WxOpenServiceDemo.java └── resources └── application.yml /.gitignore: -------------------------------------------------------------------------------- 1 | #mac 2 | .DS_Store 3 | # https://github.com/github/gitignore/blob/master/Java.gitignore 4 | 5 | *.class 6 | 7 | # Mobile Tools for Java (J2ME) 8 | .mtj.tmp/ 9 | 10 | # Package Files # 11 | *.jar 12 | *.war 13 | *.ear 14 | 15 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 16 | hs_err_pid* 17 | 18 | /.project 19 | 20 | 21 | # https://github.com/github/gitignore/blob/master/Maven.gitignore 22 | target/ 23 | pom.xml.tag 24 | pom.xml.releaseBackup 25 | pom.xml.versionsBackup 26 | pom.xml.next 27 | release.properties 28 | dependency-reduced-pom.xml 29 | buildNumber.properties 30 | .mvn/timing.properties 31 | 32 | 33 | # https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore 34 | 35 | .metadata 36 | bin/ 37 | tmp/ 38 | *.tmp 39 | *.bak 40 | *.swp 41 | *~.nib 42 | local.properties 43 | .settings/ 44 | .loadpath 45 | .recommenders 46 | 47 | # Eclipse Core 48 | .project 49 | 50 | # External tool builders 51 | .externalToolBuilders/ 52 | 53 | # Locally stored "Eclipse launch configurations" 54 | *.launch 55 | 56 | # PyDev specific (Python IDE for Eclipse) 57 | *.pydevproject 58 | 59 | # CDT-specific (C/C++ Development Tooling) 60 | .cproject 61 | 62 | # JDT-specific (Eclipse Java Development Tools) 63 | .classpath 64 | 65 | # Java annotation processor (APT) 66 | .factorypath 67 | 68 | # PDT-specific (PHP Development Tools) 69 | .buildpath 70 | 71 | # sbteclipse plugin 72 | .target 73 | 74 | # Tern plugin 75 | .tern-project 76 | 77 | # TeXlipse plugin 78 | .texlipse 79 | 80 | # STS (Spring Tool Suite) 81 | .springBeans 82 | 83 | # Code Recommenders 84 | .recommenders/ 85 | 86 | 87 | # https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore 88 | 89 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 90 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 91 | 92 | # User-specific stuff: 93 | .idea/workspace.xml 94 | .idea/tasks.xml 95 | .idea/dictionaries 96 | .idea/vcs.xml 97 | .idea/jsLibraryMappings.xml 98 | 99 | # Sensitive or high-churn files: 100 | .idea/dataSources.ids 101 | .idea/dataSources.xml 102 | .idea/dataSources.local.xml 103 | .idea/sqlDataSources.xml 104 | .idea/dynamic.xml 105 | .idea/uiDesigner.xml 106 | 107 | # Gradle: 108 | .idea/gradle.xml 109 | .idea/libraries 110 | 111 | # Mongo Explorer plugin: 112 | .idea/mongoSettings.xml 113 | 114 | ## File-based project format: 115 | *.iws 116 | 117 | ## Plugin-specific files: 118 | 119 | # IntelliJ 120 | /out/ 121 | 122 | # mpeltonen/sbt-idea plugin 123 | .idea_modules/ 124 | 125 | # JIRA plugin 126 | atlassian-ide-plugin.xml 127 | 128 | # Crashlytics plugin (for Android Studio and IntelliJ) 129 | com_crashlytics_export_strings.xml 130 | crashlytics.properties 131 | crashlytics-build.properties 132 | fabric.properties 133 | 134 | 135 | # zeroturnaround 136 | rebel.xml 137 | 138 | 139 | # log 140 | log/ 141 | logs/ 142 | 143 | 144 | # IntelliJ IDEA 145 | *.iml 146 | .idea/ 147 | 148 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk8 4 | 5 | script: "mvn clean package -Dmaven.test.skip=true" 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | notifications: 12 | email: 13 | - binarywang@vip.qq.com 14 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | ### 本Demo基于Spring Boot构建,实现微信第三方平台开发功能。 2 | 3 | #### 本项目为WxJava的Demo演示程序,更多信息请查阅:https://github.com/Wechat-Group/WxJava 4 | 5 | [![码云Gitee](https://gitee.com/binary/weixin-java-open-demo/badge/star.svg?theme=blue)](https://gitee.com/binary/weixin-java-open-demo) 6 | [![Github](http://github-svg-buttons.herokuapp.com/star.svg?user=Wechat-Group&repo=weixin-java-open-demo&style=flat&background=1081C1)](https://github.com/Wechat-Group/weixin-java-open-demo) 7 | [![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-open-demo.svg?branch=master)](https://travis-ci.org/Wechat-Group/weixin-java-open-demo) 8 | ----------------------- 9 | 10 | ## 使用步骤: 11 | 1. 新手遇到问题,请务必先阅读[【开发文档首页】](https://github.com/Wechat-Group/WxJava/wiki)的常见问题部分,可以少走很多弯路,节省不少时间。如还有其他问题请[【在此提问】](https://github.com/Wechat-Group/weixin-java-open-demo/issues),谢谢配合。 12 | 1. 配置:修改`/src/main/resources/application.yml` ,根据自己需要填写相关配置(需要注意的是:yml文件内的属性冒号后面的文字之前需要加空格,可参考已有配置,否则属性会设置不成功); 13 | 1. 运行Java程序:`com.github.binarywang.demo.wechat.WxOpenDemoApplication`; 14 | 1. 配置微信第三方平台中的授权事件接收URL:http://my-domain/notify/receive_ticket 15 | 1. 配置微信第三方平台中的公众号消息与事件接收URL http://my-domain/notify/$APPID$/callback 16 | 1. 首次启动后需要 等待收到 微信推送的 component_verify_ticket 后才可以使用接口 (在第三方平台创建审核通过后,微信服务器每隔10分钟会向第三方的消息接收地址推送一次component_verify_ticket,用于获取第三方平台接口调用凭据) 17 | 1. 浏览器访问:http://my-domain/api/auth/goto_auth_url_show 点击 go 跳转到微信授权页面 扫码授权 18 | -------------------------------------------------------------------------------- /commit.sh: -------------------------------------------------------------------------------- 1 | git commit -a -m ":arrow_up: 升级sdk版本为4.7.0" 2 | git pull --rebase 3 | 4 | git push origin master 5 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.3.3.RELEASE 10 | 11 | com.github.binarywang 12 | weixin-java-open-demo 13 | 1.0-SNAPSHOT 14 | jar 15 | 16 | spring-boot-demo-for-wechat-open 17 | Spring Boot Demo with wechat Open 18 | 19 | 20 | 4.7.0 21 | 22 | 1.8 23 | 1.8 24 | UTF-8 25 | UTF-8 26 | zh_CN 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | com.fasterxml.jackson.core 35 | jackson-databind 36 | 37 | 38 | 39 | 40 | 41 | com.github.binarywang 42 | weixin-java-open 43 | ${weixin-java-open.version} 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | redis.clients 55 | jedis 56 | 3.3.0 57 | 58 | 59 | com.github.jedis-lock 60 | jedis-lock 61 | 1.0.0 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-maven-plugin 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/demo/wx/open/WxOpenApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.demo.wx.open; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | /** 6 | * @author 007 7 | */ 8 | @SpringBootApplication 9 | public class WxOpenApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(WxOpenApplication.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/demo/wx/open/config/RedisProperies.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.demo.wx.open.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import redis.clients.jedis.JedisPoolConfig; 5 | import redis.clients.jedis.Protocol; 6 | 7 | import javax.net.ssl.HostnameVerifier; 8 | import javax.net.ssl.SSLParameters; 9 | import javax.net.ssl.SSLSocketFactory; 10 | /** 11 | * @author 007 12 | */ 13 | @ConfigurationProperties(prefix = "wechat.redis") 14 | public class RedisProperies extends JedisPoolConfig { 15 | private String host = Protocol.DEFAULT_HOST; 16 | private int port = Protocol.DEFAULT_PORT; 17 | private String password; 18 | private int database = 1; 19 | private int connectionTimeout = Protocol.DEFAULT_TIMEOUT; 20 | private int soTimeout = Protocol.DEFAULT_TIMEOUT; 21 | private String clientName; 22 | private boolean ssl; 23 | private SSLSocketFactory sslSocketFactory; 24 | private SSLParameters sslParameters; 25 | private HostnameVerifier hostnameVerifier; 26 | 27 | public boolean isSsl() { 28 | return ssl; 29 | } 30 | 31 | public void setSsl(boolean ssl) { 32 | this.ssl = ssl; 33 | } 34 | 35 | public SSLSocketFactory getSslSocketFactory() { 36 | return sslSocketFactory; 37 | } 38 | 39 | public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) { 40 | this.sslSocketFactory = sslSocketFactory; 41 | } 42 | 43 | public SSLParameters getSslParameters() { 44 | return sslParameters; 45 | } 46 | 47 | public void setSslParameters(SSLParameters sslParameters) { 48 | this.sslParameters = sslParameters; 49 | } 50 | 51 | public HostnameVerifier getHostnameVerifier() { 52 | return hostnameVerifier; 53 | } 54 | 55 | public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { 56 | this.hostnameVerifier = hostnameVerifier; 57 | } 58 | 59 | public String getHost() { 60 | return host; 61 | } 62 | 63 | public void setHost(String host) { 64 | if (host == null || "".equals(host)) { 65 | host = Protocol.DEFAULT_HOST; 66 | } 67 | this.host = host; 68 | } 69 | 70 | public int getPort() { 71 | return port; 72 | } 73 | 74 | public void setPort(int port) { 75 | this.port = port; 76 | } 77 | 78 | public String getPassword() { 79 | return password; 80 | } 81 | 82 | public void setPassword(String password) { 83 | if ("".equals(password)) { 84 | password = null; 85 | } 86 | this.password = password; 87 | } 88 | 89 | public int getDatabase() { 90 | return database; 91 | } 92 | 93 | public void setDatabase(int database) { 94 | this.database = database; 95 | } 96 | 97 | public String getClientName() { 98 | return clientName; 99 | } 100 | 101 | public void setClientName(String clientName) { 102 | if ("".equals(clientName)) { 103 | clientName = null; 104 | } 105 | this.clientName = clientName; 106 | } 107 | 108 | public int getConnectionTimeout() { 109 | return connectionTimeout; 110 | } 111 | 112 | public void setConnectionTimeout(int connectionTimeout) { 113 | this.connectionTimeout = connectionTimeout; 114 | } 115 | 116 | public int getSoTimeout() { 117 | return soTimeout; 118 | } 119 | 120 | public void setSoTimeout(int soTimeout) { 121 | this.soTimeout = soTimeout; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/demo/wx/open/config/WechatOpenProperties.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.demo.wx.open.config; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | import org.apache.commons.lang3.builder.ToStringStyle; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | /** 7 | * @author 007 8 | */ 9 | @ConfigurationProperties(prefix = "wechat.open") 10 | public class WechatOpenProperties { 11 | /** 12 | * 设置微信三方平台的appid 13 | */ 14 | private String componentAppId; 15 | 16 | /** 17 | * 设置微信三方平台的app secret 18 | */ 19 | private String componentSecret; 20 | 21 | /** 22 | * 设置微信三方平台的token 23 | */ 24 | private String componentToken; 25 | 26 | /** 27 | * 设置微信三方平台的EncodingAESKey 28 | */ 29 | private String componentAesKey; 30 | 31 | public String getComponentAppId() { 32 | return componentAppId; 33 | } 34 | 35 | public void setComponentAppId(String componentAppId) { 36 | this.componentAppId = componentAppId; 37 | } 38 | 39 | public String getComponentSecret() { 40 | return componentSecret; 41 | } 42 | 43 | public void setComponentSecret(String componentSecret) { 44 | this.componentSecret = componentSecret; 45 | } 46 | 47 | public String getComponentToken() { 48 | return componentToken; 49 | } 50 | 51 | public void setComponentToken(String componentToken) { 52 | this.componentToken = componentToken; 53 | } 54 | 55 | public String getComponentAesKey() { 56 | return componentAesKey; 57 | } 58 | 59 | public void setComponentAesKey(String componentAesKey) { 60 | this.componentAesKey = componentAesKey; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return ToStringBuilder.reflectionToString(this, 66 | ToStringStyle.MULTI_LINE_STYLE); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/demo/wx/open/controller/WechatApiController.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.demo.wx.open.controller; 2 | 3 | import com.github.binarywang.demo.wx.open.service.WxOpenServiceDemo; 4 | import me.chanjar.weixin.common.error.WxErrorException; 5 | import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult; 6 | import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | import org.springframework.web.bind.annotation.ResponseBody; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | /** 20 | * @author 007 21 | */ 22 | @Controller 23 | @RequestMapping("/api") 24 | public class WechatApiController { 25 | private final Logger logger = LoggerFactory.getLogger(getClass()); 26 | @Autowired 27 | private WxOpenServiceDemo wxOpenServiceDemo; 28 | @GetMapping("/auth/goto_auth_url_show") 29 | @ResponseBody 30 | public String gotoPreAuthUrlShow(){ 31 | return "go"; 32 | } 33 | @GetMapping("/auth/goto_auth_url") 34 | public void gotoPreAuthUrl(HttpServletRequest request, HttpServletResponse response){ 35 | String host = request.getHeader("host"); 36 | String url = "http://"+host+"/api/auth/jump"; 37 | try { 38 | url = wxOpenServiceDemo.getWxOpenComponentService().getPreAuthUrl(url); 39 | // 添加来源,解决302跳转来源丢失的问题 40 | response.addHeader("Referer", "http://"+host); 41 | response.sendRedirect(url); 42 | } catch (WxErrorException | IOException e) { 43 | logger.error("gotoPreAuthUrl", e); 44 | throw new RuntimeException(e); 45 | } 46 | } 47 | @GetMapping("/auth/jump") 48 | @ResponseBody 49 | public WxOpenQueryAuthResult jump(@RequestParam("auth_code") String authorizationCode){ 50 | try { 51 | WxOpenQueryAuthResult queryAuthResult = wxOpenServiceDemo.getWxOpenComponentService().getQueryAuth(authorizationCode); 52 | logger.info("getQueryAuth", queryAuthResult); 53 | return queryAuthResult; 54 | } catch (WxErrorException e) { 55 | logger.error("gotoPreAuthUrl", e); 56 | throw new RuntimeException(e); 57 | } 58 | } 59 | @GetMapping("/get_authorizer_info") 60 | @ResponseBody 61 | public WxOpenAuthorizerInfoResult getAuthorizerInfo(@RequestParam String appId){ 62 | try { 63 | return wxOpenServiceDemo.getWxOpenComponentService().getAuthorizerInfo(appId); 64 | } catch (WxErrorException e) { 65 | logger.error("getAuthorizerInfo", e); 66 | throw new RuntimeException(e); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/demo/wx/open/controller/WechatNotifyController.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.demo.wx.open.controller; 2 | 3 | import com.github.binarywang.demo.wx.open.service.WxOpenServiceDemo; 4 | import me.chanjar.weixin.common.error.WxErrorException; 5 | import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 7 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 8 | import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | /** 16 | * @author 007 17 | */ 18 | @RestController 19 | @RequestMapping("/notify") 20 | public class WechatNotifyController { 21 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 22 | @Autowired 23 | protected WxOpenServiceDemo wxOpenService; 24 | 25 | @RequestMapping("/receive_ticket") 26 | public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp, 27 | @RequestParam("nonce") String nonce, @RequestParam("signature") String signature, 28 | @RequestParam(name = "encrypt_type", required = false) String encType, 29 | @RequestParam(name = "msg_signature", required = false) String msgSignature) { 30 | log.info( 31 | "\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}]," 32 | + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", 33 | signature, encType, msgSignature, timestamp, nonce, requestBody); 34 | 35 | if (!StringUtils.equalsIgnoreCase("aes", encType) 36 | || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) { 37 | throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); 38 | } 39 | 40 | // aes加密的消息 41 | WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody, 42 | wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); 43 | log.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); 44 | try { 45 | String out = wxOpenService.getWxOpenComponentService().route(inMessage); 46 | log.debug("\n组装回复信息:{}", out); 47 | } catch (WxErrorException e) { 48 | log.error("receive_ticket", e); 49 | } 50 | 51 | 52 | return "success"; 53 | } 54 | 55 | @RequestMapping("{appId}/callback") 56 | public Object callback(@RequestBody(required = false) String requestBody, 57 | @PathVariable("appId") String appId, 58 | @RequestParam("signature") String signature, 59 | @RequestParam("timestamp") String timestamp, 60 | @RequestParam("nonce") String nonce, 61 | @RequestParam("openid") String openid, 62 | @RequestParam("encrypt_type") String encType, 63 | @RequestParam("msg_signature") String msgSignature) { 64 | log.info( 65 | "\n接收微信请求:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}]," 66 | + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", 67 | appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody); 68 | if (!StringUtils.equalsIgnoreCase("aes", encType) 69 | || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) { 70 | throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); 71 | } 72 | 73 | String out = ""; 74 | // aes加密的消息 75 | WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody, 76 | wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); 77 | log.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); 78 | // 全网发布测试用例 79 | if (StringUtils.equalsAnyIgnoreCase(appId, "wxd101a85aa106f53e", "wx570bc396a51b8ff8")) { 80 | try { 81 | if (StringUtils.equals(inMessage.getMsgType(), "text")) { 82 | if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) { 83 | out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml( 84 | WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback") 85 | .fromUser(inMessage.getToUser()) 86 | .toUser(inMessage.getFromUser()) 87 | .build(), 88 | wxOpenService.getWxOpenConfigStorage() 89 | ); 90 | } else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) { 91 | String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api"; 92 | WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build(); 93 | wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage); 94 | } 95 | } else if (StringUtils.equals(inMessage.getMsgType(), "event")) { 96 | WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build(); 97 | wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage); 98 | } 99 | } catch (WxErrorException e) { 100 | logger.error("callback", e); 101 | } 102 | }else{ 103 | WxMpXmlOutMessage outMessage = wxOpenService.getWxOpenMessageRouter().route(inMessage, appId); 104 | if(outMessage != null){ 105 | out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, wxOpenService.getWxOpenConfigStorage()); 106 | } 107 | } 108 | return out; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/demo/wx/open/service/WxOpenServiceDemo.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.demo.wx.open.service; 2 | 3 | import com.github.binarywang.demo.wx.open.config.RedisProperies; 4 | import com.github.binarywang.demo.wx.open.config.WechatOpenProperties; 5 | import me.chanjar.weixin.open.api.impl.WxOpenInRedisConfigStorage; 6 | import me.chanjar.weixin.open.api.impl.WxOpenMessageRouter; 7 | import me.chanjar.weixin.open.api.impl.WxOpenServiceImpl; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 12 | import org.springframework.stereotype.Service; 13 | import redis.clients.jedis.JedisPool; 14 | 15 | import javax.annotation.PostConstruct; 16 | 17 | /** 18 | * @author 007 19 | */ 20 | @Service 21 | @EnableConfigurationProperties({WechatOpenProperties.class, RedisProperies.class}) 22 | public class WxOpenServiceDemo extends WxOpenServiceImpl { 23 | private Logger logger = LoggerFactory.getLogger(getClass()); 24 | @Autowired 25 | private WechatOpenProperties wechatOpenProperties; 26 | @Autowired 27 | private RedisProperies redisProperies; 28 | private volatile static JedisPool pool; 29 | private WxOpenMessageRouter wxOpenMessageRouter; 30 | 31 | @PostConstruct 32 | public void init() { 33 | WxOpenInRedisConfigStorage inRedisConfigStorage = new WxOpenInRedisConfigStorage(getJedisPool()); 34 | inRedisConfigStorage.setComponentAppId(wechatOpenProperties.getComponentAppId()); 35 | inRedisConfigStorage.setComponentAppSecret(wechatOpenProperties.getComponentSecret()); 36 | inRedisConfigStorage.setComponentToken(wechatOpenProperties.getComponentToken()); 37 | inRedisConfigStorage.setComponentAesKey(wechatOpenProperties.getComponentAesKey()); 38 | setWxOpenConfigStorage(inRedisConfigStorage); 39 | wxOpenMessageRouter = new WxOpenMessageRouter(this); 40 | wxOpenMessageRouter.rule().handler((wxMpXmlMessage, map, wxMpService, wxSessionManager) -> { 41 | logger.info("\n接收到 {} 公众号请求消息,内容:{}", wxMpService.getWxMpConfigStorage().getAppId(), wxMpXmlMessage); 42 | return null; 43 | }).next(); 44 | } 45 | public WxOpenMessageRouter getWxOpenMessageRouter(){ 46 | return wxOpenMessageRouter; 47 | } 48 | 49 | private JedisPool getJedisPool() { 50 | if (pool == null) { 51 | synchronized (WxOpenServiceDemo.class) { 52 | if (pool == null) { 53 | pool = new JedisPool(redisProperies, redisProperies.getHost(), 54 | redisProperies.getPort(), redisProperies.getConnectionTimeout(), 55 | redisProperies.getSoTimeout(), redisProperies.getPassword(), 56 | redisProperies.getDatabase(), redisProperies.getClientName(), 57 | redisProperies.isSsl(), redisProperies.getSslSocketFactory(), 58 | redisProperies.getSslParameters(), redisProperies.getHostnameVerifier()); 59 | } 60 | } 61 | } 62 | return pool; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | org.springframework.web: DEBUG 4 | com.github.binarywang.demo.wx.open: DEBUG 5 | 6 | wechat: 7 | open: 8 | componentAppId: "" 9 | componentSecret: "" 10 | componentToken: "" 11 | componentAesKey: "" 12 | redis: 13 | host: "127.0.0.1" 14 | server: 15 | port: 80 16 | 17 | 18 | --------------------------------------------------------------------------------