├── .editorconfig
├── .gitignore
├── .travis.yml
├── README.md
├── build
├── check-style-suppression.xml
├── check-style.xml
├── find-bugs-exclude-filter.xml
└── pmd.xml
├── commit.sh
├── pom.xml
└── src
└── main
├── java
└── com
│ └── github
│ └── weixin
│ └── demo
│ ├── config
│ ├── MainConfiguration.java
│ ├── MenuConfig.java
│ └── WxPayConfiguration.java
│ ├── controller
│ ├── CoreController.java
│ ├── GenericController.java
│ ├── PaymentController.java
│ └── TemplateMessageController.java
│ ├── handler
│ ├── AbstractHandler.java
│ ├── LogHandler.java
│ ├── MsgHandler.java
│ └── SubscribeHandler.java
│ ├── service
│ ├── CoreService.java
│ └── impl
│ │ └── CoreServiceImpl.java
│ └── util
│ ├── GenericReturnModel.java
│ ├── MD5Util.java
│ ├── ReturnModel.java
│ ├── Sha1Util.java
│ ├── XMLUtil.java
│ └── package-info.java
├── resources
├── applicationContext.xml
├── log4j.properties
├── spring-mvc.xml
├── wx.properties
└── wxPay.properties
└── webapp
└── WEB-INF
├── views
└── index.html
└── web.xml
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig: http://editorconfig.org/
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = space
7 | indent_size = 4
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 |
13 | [*.md]
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Java template
3 | *.class
4 |
5 | # Mobile Tools for Java (J2ME)
6 | .mtj.tmp/
7 |
8 | # Package Files #
9 | *.jar
10 | *.war
11 | *.ear
12 |
13 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
14 | hs_err_pid*
15 |
16 | /.settings
17 | /.classpath
18 | /.project
19 | /.tomcatplugin
20 | /target
21 | /work
22 | /src/main/webapp/.#webclasspath
23 |
24 | .idea/
25 | *.iml
26 |
--------------------------------------------------------------------------------
/.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 | - binaryw@qq.com
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | ----
5 | [](https://gitee.com/binary/weixin-java-tools-springmvc)
6 | [](https://github.com/Wechat-Group/weixin-java-demo-springmvc)
7 | [](https://travis-ci.org/Wechat-Group/weixin-java-demo-springmvc)
8 |
9 | This repository is a wechat springmvc demo based on **WxJava**
10 |
11 | 本仓库的项目是一个基 于**[WxJava](https://github.com/wechat-group/WxJava)** 的springmvc Demo.
12 |
13 | 新手遇到问题,请务必先阅读[【开发文档首页】](https://github.com/Wechat-Group/WxJava/wiki)的常见问题部分,可以少走很多弯路,节省不少时间。
14 |
15 |
16 | ## 本项目目前实现了如下功能:
17 |
18 | * 与微信服务器的AES加密通信
19 | * 微信支付
20 | * 商户号向个人用户转账
21 | * 自定义菜单
22 | * 关注公众号、客服消息路由处理
23 | * 模版消息
24 | * 通过openid获取用户基本信息
25 | * 通过code获得基本用户信息
26 |
27 |
28 | Welcome to Pull Requests!
29 |
30 | 欢迎大家积极Pull Requests来丰富此Demo的功能!
31 |
32 | ## 快速使用:
33 |
34 | **将项目下载到本地**
35 | ```shell
36 | git clone https://github.com/wechat-group/weixin-java-demo-springmvc
37 | ```
38 |
39 | **配置公众号信息**
40 |
41 | 打开`src/main/resources/wx.properties`文件,配置公众号相关信息。
42 |
43 | **Maven打包**
44 | ```shell
45 | mvn war:war
46 | ```
47 |
48 | **上传至服务器**
49 |
50 | 必须使用服务器的80端口才能与微信服务器进行交互。
51 |
52 | **微信公众平台服务器配置**
53 |
54 | 进入到**微信公众平台**的`开发/基本配置`页面,配置`URL(服务器地址)`、`Token(令牌)`、`EncodingAESKey(消息加解密密钥)`。
55 | ```shell
56 | URL(服务器地址):http://192.168.1.1/wechatTestService/core
57 | ```
58 |
59 | ## License
60 | - 本项目的所有代码除另有说明外,均按照 [MIT License](https://github.com/racaljk/hosts/blob/master/LICENSE) 发布。
61 | - 本项目的.java,README.MD,wiki等资源基于[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)
62 | 这意味着你可以拷贝、并再发行本项目的内容,但是你将必须同样**提供原作者信息以及协议声明**。同时你也**不能将本项目用于商业用途**,
63 | 按照我们狭义的理解(增加附属条款),凡是**任何盈利的活动皆属于商业用途**。
64 | - 请在遵守当地相关法律法规的前提下使用本项目。
65 |
66 | 
67 |
--------------------------------------------------------------------------------
/build/check-style-suppression.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 | * Created by bjliumingbo on 2017/5/12. 15 | * 16 | * @author FirenzesEagle 17 | * @author BinaryWang 18 | */ 19 | @Configuration 20 | public class MainConfiguration { 21 | @Value("#{wxProperties.appId}") 22 | private String appId; 23 | 24 | @Value("#{wxProperties.appSecret}") 25 | private String appSecret; 26 | 27 | @Value("#{wxProperties.token}") 28 | private String token; 29 | 30 | @Value("#{wxProperties.aesKey}") 31 | private String aesKey; 32 | 33 | @Bean 34 | public WxMpConfigStorage wxMpConfigStorage() { 35 | WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl(); 36 | configStorage.setAppId(this.appId); 37 | configStorage.setSecret(this.appSecret); 38 | configStorage.setToken(this.token); 39 | configStorage.setAesKey(this.aesKey); 40 | return configStorage; 41 | } 42 | 43 | @Bean 44 | public WxMpService wxMpService() { 45 | WxMpService wxMpService = new WxMpServiceImpl(); 46 | wxMpService.setWxMpConfigStorage(wxMpConfigStorage()); 47 | return wxMpService; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/github/weixin/demo/config/MenuConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.weixin.demo.config; 2 | 3 | import me.chanjar.weixin.common.bean.menu.WxMenu; 4 | import me.chanjar.weixin.common.bean.menu.WxMenuButton; 5 | import me.chanjar.weixin.common.error.WxErrorException; 6 | import me.chanjar.weixin.mp.api.WxMpService; 7 | import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; 8 | import me.chanjar.weixin.mp.config.WxMpConfigStorage; 9 | import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; 10 | 11 | import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; 12 | 13 | /** 14 | * Created by FirenzesEagle on 2016/6/1 0001. 15 | * Email:liumingbo2008@gmail.com 16 | */ 17 | public class MenuConfig { 18 | 19 | /** 20 | * 定义菜单结构 21 | * 22 | * @return 23 | */ 24 | protected static WxMenu getMenu() { 25 | 26 | MainConfig mainConfig = new MainConfig("appid", "appsecret", "token", "aesKey"); 27 | WxMpService wxMpService = mainConfig.wxMpService(); 28 | 29 | WxMenu menu = new WxMenu(); 30 | WxMenuButton button1 = new WxMenuButton(); 31 | button1.setType(MenuButtonType.VIEW); 32 | button1.setName("买家订单"); 33 | button1.setUrl(wxMpService.getOAuth2Service().buildAuthorizationUrl("", "snsapi_base", "")); 34 | 35 | WxMenuButton button2 = new WxMenuButton(); 36 | button2.setName("我是卖家"); 37 | 38 | WxMenuButton button21 = new WxMenuButton(); 39 | button21.setType(MenuButtonType.VIEW); 40 | button21.setName("我的订单"); 41 | button21.setUrl(wxMpService.getOAuth2Service().buildAuthorizationUrl("", "snsapi_base", "")); 42 | 43 | WxMenuButton button22 = new WxMenuButton(); 44 | button22.setType(MenuButtonType.VIEW); 45 | button22.setName("收入统计"); 46 | button22.setUrl(wxMpService.getOAuth2Service().buildAuthorizationUrl("", "snsapi_base", "")); 47 | 48 | WxMenuButton button23 = new WxMenuButton(); 49 | button23.setType(MenuButtonType.VIEW); 50 | button23.setName("发布商品"); 51 | button23.setUrl(wxMpService.getOAuth2Service().buildAuthorizationUrl("", "snsapi_base", "")); 52 | 53 | WxMenuButton button24 = new WxMenuButton(); 54 | button24.setType(MenuButtonType.VIEW); 55 | button24.setName("商品管理"); 56 | button24.setUrl(wxMpService.getOAuth2Service().buildAuthorizationUrl("", "snsapi_base", "")); 57 | 58 | button2.getSubButtons().add(button21); 59 | button2.getSubButtons().add(button22); 60 | button2.getSubButtons().add(button23); 61 | button2.getSubButtons().add(button24); 62 | 63 | WxMenuButton button3 = new WxMenuButton(); 64 | button3.setType(MenuButtonType.CLICK); 65 | button3.setName("使用帮助"); 66 | button3.setKey("help"); 67 | 68 | menu.getButtons().add(button1); 69 | menu.getButtons().add(button2); 70 | menu.getButtons().add(button3); 71 | 72 | return menu; 73 | } 74 | 75 | 76 | public static class MainConfig { 77 | 78 | private String appId; 79 | private String appSecret; 80 | private String token; 81 | private String aesKey; 82 | 83 | /** 84 | * 为了生成自定义菜单使用的构造函数 85 | * 86 | * @param appId 87 | * @param appSecret 88 | * @param token 89 | * @param aesKey 90 | */ 91 | protected MainConfig(String appId, String appSecret, String token, String aesKey) { 92 | this.appId = appId; 93 | this.appSecret = appSecret; 94 | this.token = token; 95 | this.aesKey = aesKey; 96 | } 97 | 98 | public WxMpConfigStorage wxMpConfigStorage() { 99 | WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl(); 100 | configStorage.setAppId(this.appId); 101 | configStorage.setSecret(this.appSecret); 102 | configStorage.setToken(this.token); 103 | configStorage.setAesKey(this.aesKey); 104 | return configStorage; 105 | } 106 | 107 | public WxMpService wxMpService() { 108 | WxMpService wxMpService = new WxMpServiceImpl(); 109 | wxMpService.setWxMpConfigStorage(wxMpConfigStorage()); 110 | return wxMpService; 111 | } 112 | 113 | } 114 | 115 | /** 116 | * 运行此main函数即可生成公众号自定义菜单,注意要修改MainConfig构造方法行代码的对应四个参数为实际值 117 | * 118 | * @param args 119 | */ 120 | public static void main(String[] args) { 121 | MainConfig mainConfig = new MainConfig("appid", "appsecret", "token", "aesKey"); 122 | WxMpService wxMpService = mainConfig.wxMpService(); 123 | try { 124 | wxMpService.getMenuService().menuCreate(getMenu()); 125 | } catch (WxErrorException e) { 126 | e.printStackTrace(); 127 | } 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/github/weixin/demo/config/WxPayConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.weixin.demo.config; 2 | 3 | import com.github.binarywang.wxpay.config.WxPayConfig; 4 | import com.github.binarywang.wxpay.service.WxPayService; 5 | import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 微信支付相关配置 12 | *
13 | * Created by bjliumingbo on 2017/5/12. 14 | */ 15 | @Configuration 16 | public class WxPayConfiguration { 17 | @Value("#{wxPayProperties.appId}") 18 | private String appId; 19 | 20 | @Value("#{wxPayProperties.mchId}") 21 | private String mchId; 22 | 23 | @Value("#{wxPayProperties.mchKey}") 24 | private String mchKey; 25 | 26 | @Value("#{wxPayProperties.subAppId}") 27 | private String subAppId; 28 | 29 | @Value("#{wxPayProperties.subMchId}") 30 | private String subMchId; 31 | 32 | @Value("#{wxPayProperties.keyPath}") 33 | private String keyPath; 34 | 35 | @Bean 36 | public WxPayConfig payConfig() { 37 | WxPayConfig payConfig = new WxPayConfig(); 38 | payConfig.setAppId(this.appId); 39 | payConfig.setMchId(this.mchId); 40 | payConfig.setMchKey(this.mchKey); 41 | payConfig.setSubAppId(this.subAppId); 42 | payConfig.setSubMchId(this.subMchId); 43 | payConfig.setKeyPath(this.keyPath); 44 | 45 | return payConfig; 46 | } 47 | 48 | @Bean 49 | public WxPayService payService() { 50 | WxPayService payService = new WxPayServiceImpl(); 51 | payService.setConfig(payConfig()); 52 | return payService; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/github/weixin/demo/controller/CoreController.java: -------------------------------------------------------------------------------- 1 | package com.github.weixin.demo.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; 7 | import me.chanjar.weixin.common.error.WxErrorException; 8 | import me.chanjar.weixin.mp.config.WxMpConfigStorage; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | 15 | import com.github.weixin.demo.service.CoreService; 16 | import com.github.weixin.demo.util.ReturnModel; 17 | import me.chanjar.weixin.mp.api.WxMpService; 18 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 19 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 20 | import me.chanjar.weixin.mp.bean.result.WxMpUser; 21 | 22 | /** 23 | * Created by FirenzesEagle on 2016/5/30 0030. 24 | * Email:liumingbo2008@gmail.com 25 | */ 26 | @Controller 27 | public class CoreController extends GenericController { 28 | 29 | @Autowired 30 | protected WxMpConfigStorage configStorage; 31 | @Autowired 32 | protected WxMpService wxMpService; 33 | @Autowired 34 | protected CoreService coreService; 35 | 36 | @RequestMapping(value = "/index") 37 | public String index() { 38 | return "index"; 39 | } 40 | 41 | /** 42 | * 微信公众号webservice主服务接口,提供与微信服务器的信息交互 43 | */ 44 | @RequestMapping(value = "/core") 45 | public void wechatCore(HttpServletRequest request, HttpServletResponse response) throws Exception { 46 | response.setContentType("text/html;charset=utf-8"); 47 | response.setStatus(HttpServletResponse.SC_OK); 48 | 49 | String signature = request.getParameter("signature"); 50 | String nonce = request.getParameter("nonce"); 51 | String timestamp = request.getParameter("timestamp"); 52 | 53 | if (!this.wxMpService.checkSignature(timestamp, nonce, signature)) { 54 | // 消息签名不正确,说明不是公众平台发过来的消息 55 | response.getWriter().println("非法请求"); 56 | return; 57 | } 58 | 59 | String echoStr = request.getParameter("echostr"); 60 | if (StringUtils.isNotBlank(echoStr)) { 61 | // 说明是一个仅仅用来验证的请求,回显echostr 62 | String echoStrOut = String.copyValueOf(echoStr.toCharArray()); 63 | response.getWriter().println(echoStrOut); 64 | return; 65 | } 66 | 67 | String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) 68 | ? "raw" 69 | : request.getParameter("encrypt_type"); 70 | 71 | if ("raw".equals(encryptType)) { 72 | // 明文传输的消息 73 | WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream()); 74 | WxMpXmlOutMessage outMessage = this.coreService.route(inMessage); 75 | if (outMessage == null) { 76 | response.getWriter().write(""); 77 | } else { 78 | response.getWriter().write(outMessage.toXml()); 79 | } 80 | return; 81 | } 82 | 83 | if ("aes".equals(encryptType)) { 84 | // 是aes加密的消息 85 | String msgSignature = request.getParameter("msg_signature"); 86 | WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml( 87 | request.getInputStream(), this.configStorage, timestamp, nonce, 88 | msgSignature); 89 | log.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); 90 | WxMpXmlOutMessage outMessage = this.coreService.route(inMessage); 91 | if (outMessage == null) { 92 | response.getWriter().write(""); 93 | } else { 94 | response.getWriter().write(outMessage.toEncryptedXml(this.configStorage)); 95 | } 96 | 97 | return; 98 | } 99 | 100 | response.getWriter().println("不可识别的加密类型"); 101 | } 102 | 103 | /** 104 | * 通过openid获得基本用户信息 105 | * 详情请见: http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html 106 | * 107 | * @param openid openid 108 | * @param lang zh_CN, zh_TW, en 109 | */ 110 | @RequestMapping(value = "/getUserInfo") 111 | public WxMpUser getUserInfo(HttpServletResponse response, @RequestParam(value = "openid") String openid, 112 | @RequestParam(value = "lang") String lang) { 113 | ReturnModel returnModel = new ReturnModel(); 114 | WxMpUser wxMpUser = null; 115 | try { 116 | wxMpUser = this.wxMpService.getUserService().userInfo(openid, lang); 117 | returnModel.setResult(true); 118 | returnModel.setDatum(wxMpUser); 119 | renderString(response, returnModel); 120 | } catch (WxErrorException e) { 121 | returnModel.setResult(false); 122 | returnModel.setReason(e.getError().toString()); 123 | renderString(response, returnModel); 124 | log.error(e.getError().toString()); 125 | } 126 | return wxMpUser; 127 | } 128 | 129 | /** 130 | * 通过code获得基本用户信息 131 | * 详情请见: http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html 132 | * 133 | * @param code code 134 | * @param lang zh_CN, zh_TW, en 135 | */ 136 | @RequestMapping(value = "/getOAuth2UserInfo") 137 | public void getOAuth2UserInfo(HttpServletResponse response, @RequestParam(value = "code") String code, 138 | @RequestParam(value = "lang") String lang) { 139 | ReturnModel returnModel = new ReturnModel(); 140 | WxOAuth2AccessToken accessToken; 141 | WxMpUser wxMpUser; 142 | try { 143 | accessToken = this.wxMpService.getOAuth2Service().getAccessToken(code); 144 | wxMpUser = this.wxMpService.getUserService() 145 | .userInfo(accessToken.getOpenId(), lang); 146 | returnModel.setResult(true); 147 | returnModel.setDatum(wxMpUser); 148 | renderString(response, returnModel); 149 | } catch (WxErrorException e) { 150 | returnModel.setResult(false); 151 | returnModel.setReason(e.getError().toString()); 152 | renderString(response, returnModel); 153 | log.error(e.getError().toString()); 154 | } 155 | } 156 | 157 | /** 158 | * 用code换取oauth2的openid 159 | * 详情请见: http://mp.weixin.qq.com/wiki/1/8a5ce6257f1d3b2afb20f83e72b72ce9.html 160 | * 161 | * @param code code 162 | */ 163 | @RequestMapping(value = "/getOpenid") 164 | public void getOpenid(HttpServletResponse response, @RequestParam(value = "code") String code) { 165 | ReturnModel returnModel = new ReturnModel(); 166 | WxOAuth2AccessToken accessToken; 167 | try { 168 | accessToken = this.wxMpService.getOAuth2Service().getAccessToken(code); 169 | returnModel.setResult(true); 170 | returnModel.setDatum(accessToken.getOpenId()); 171 | renderString(response, returnModel); 172 | } catch (WxErrorException e) { 173 | returnModel.setResult(false); 174 | returnModel.setReason(e.getError().toString()); 175 | renderString(response, returnModel); 176 | log.error(e.getError().toString()); 177 | } 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/com/github/weixin/demo/controller/GenericController.java: -------------------------------------------------------------------------------- 1 | package com.github.weixin.demo.controller; 2 | 3 | import com.google.gson.Gson; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * 所有自定义Controller的顶级接口,封装常用的与session和response、request相关的操作 12 | *
13 | * Created by FirenzesEagle on 2016/4/19 0019. 14 | */ 15 | public abstract class GenericController { 16 | 17 | /** 18 | * 日志对象 19 | */ 20 | protected Logger logger = LoggerFactory.getLogger(getClass()); 21 | 22 | /** 23 | * 客户端返回JSON字符串 24 | * 25 | * @param response 26 | * @param object 27 | * @return 28 | */ 29 | protected String renderString(HttpServletResponse response, Object object) { 30 | return renderString(response, new Gson().toJson(object), "application/json"); 31 | } 32 | 33 | /** 34 | * 客户端返回字符串 35 | * 36 | * @param response 37 | * @param string 38 | * @return 39 | */ 40 | protected String renderString(HttpServletResponse response, String string, String type) { 41 | try { 42 | response.reset(); 43 | response.setContentType(type); 44 | response.setCharacterEncoding("utf-8"); 45 | //解决跨域问题 46 | response.setHeader("Access-Control-Allow-Origin", "*"); 47 | response.getWriter().print(string); 48 | return null; 49 | } catch (IOException e) { 50 | return null; 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/github/weixin/demo/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package com.github.weixin.demo.controller; 2 | 3 | import java.util.Map; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | 11 | import com.github.binarywang.wxpay.bean.entpay.EntPayRequest; 12 | import com.github.binarywang.wxpay.bean.entpay.EntPayResult; 13 | import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; 14 | import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; 15 | import com.github.binarywang.wxpay.config.WxPayConfig; 16 | import com.github.binarywang.wxpay.exception.WxPayException; 17 | import com.github.binarywang.wxpay.service.WxPayService; 18 | import com.github.binarywang.wxpay.util.SignUtils; 19 | import com.github.weixin.demo.util.ReturnModel; 20 | import com.github.weixin.demo.util.Sha1Util; 21 | import com.github.weixin.demo.util.XMLUtil; 22 | import com.google.gson.Gson; 23 | 24 | /** 25 | * 微信支付Controller 26 | *
27 | * Created by FirenzesEagle on 2016/6/20 0020.
28 | * Email:liumingbo2008@gmail.com
29 | */
30 | @Controller
31 | @RequestMapping(value = "wxPay")
32 | public class PaymentController extends GenericController {
33 |
34 | @Autowired
35 | private WxPayConfig payConfig;
36 | @Autowired
37 | private WxPayService payService;
38 |
39 | /**
40 | * 用于返回预支付的结果 WxMpPrepayIdResult,一般不需要使用此接口
41 | *
42 | * @param response
43 | * @param request
44 | */
45 | @RequestMapping(value = "getPrepayIdResult")
46 | public void getPrepayId(HttpServletResponse response,
47 | HttpServletRequest request) throws WxPayException {
48 | WxPayUnifiedOrderRequest payInfo = WxPayUnifiedOrderRequest.newBuilder()
49 | .openid(request.getParameter("openid"))
50 | .outTradeNo(request.getParameter("out_trade_no"))
51 | .totalFee(Integer.valueOf(request.getParameter("total_fee")))
52 | .body(request.getParameter("body"))
53 | .tradeType(request.getParameter("trade_type"))
54 | .spbillCreateIp(request.getParameter("spbill_create_ip"))
55 | .notifyUrl("")
56 | .build();
57 | log
58 | .info("PartnerKey is :" + this.payConfig.getMchKey());
59 | WxPayUnifiedOrderResult result = this.payService.unifiedOrder(payInfo);
60 | log.info(new Gson().toJson(result));
61 | renderString(response, result);
62 | }
63 |
64 | /**
65 | * 返回前台H5调用JS支付所需要的参数,公众号支付调用此接口
66 | *
67 | * @param response
68 | * @param request
69 | */
70 | @RequestMapping(value = "getJSSDKPayInfo")
71 | public void getJSSDKPayInfo(HttpServletResponse response,
72 | HttpServletRequest request) {
73 | ReturnModel returnModel = new ReturnModel();
74 | WxPayUnifiedOrderRequest prepayInfo = WxPayUnifiedOrderRequest.newBuilder()
75 | .openid(request.getParameter("openid"))
76 | .outTradeNo(request.getParameter("out_trade_no"))
77 | .totalFee(Integer.valueOf(request.getParameter("total_fee")))
78 | .body(request.getParameter("body"))
79 | .tradeType(request.getParameter("trade_type"))
80 | .spbillCreateIp(request.getParameter("spbill_create_ip"))
81 | .notifyUrl("// TODO 填写通知回调地址")
82 | .build();
83 |
84 | try {
85 | Map
19 | * Created by FirenzesEagle on 2016/7/11 0011.
20 | * Email:liumingbo2008@gmail.com
21 | */
22 | @Controller
23 | @RequestMapping(value = "templateMessage")
24 | public class TemplateMessageController extends GenericController {
25 |
26 | // 模板消息字体颜色
27 | private static final String TEMPLATE_FRONT_COLOR = "#32CD32";
28 | @Autowired
29 | protected WxMpConfigStorage configStorage;
30 | @Autowired
31 | protected WxMpService wxMpService;
32 |
33 | @RequestMapping(value = "notifyOrderPaySuccessTemplate")
34 | public void notifyOrderPaySuccessTemplate(HttpServletResponse response,
35 | HttpServletRequest request) {
36 | WxMpTemplateMessage orderPaySuccessTemplate = WxMpTemplateMessage.builder().build();
37 | orderPaySuccessTemplate.setToUser(request.getParameter("openid"));
38 | orderPaySuccessTemplate.setTemplateId("ENp7UwpOtlhvieebUvDm0mK4n0hTvbH0Me83HdBUvC0");
39 | orderPaySuccessTemplate.setUrl(request.getParameter("url"));
40 | WxMpTemplateData firstData = new WxMpTemplateData("first", "订单支付成功", TEMPLATE_FRONT_COLOR);
41 | WxMpTemplateData orderMoneySumData = new WxMpTemplateData("orderMoneySum", request.getParameter("orderMoneySum"), TEMPLATE_FRONT_COLOR);
42 | WxMpTemplateData orderProductNameData = new WxMpTemplateData("orderProductName", request.getParameter("orderProductName"), TEMPLATE_FRONT_COLOR);
43 | WxMpTemplateData remarkData = new WxMpTemplateData("Remark", request.getParameter("remark"), TEMPLATE_FRONT_COLOR);
44 | orderPaySuccessTemplate.addData(firstData)
45 | .addData(orderMoneySumData)
46 | .addData(orderProductNameData)
47 | .addData(remarkData);
48 | try {
49 | wxMpService.getTemplateMsgService()
50 | .sendTemplateMsg(orderPaySuccessTemplate);
51 | } catch (WxErrorException e) {
52 | logger.error(e.getMessage());
53 | }
54 | }
55 |
56 | @RequestMapping(value = "notifyOrderStatusUpdateTemplate")
57 | public void notifyOrderStatusUpdateTemplate(HttpServletResponse response,
58 | HttpServletRequest request) {
59 | WxMpTemplateMessage orderPaySuccessTemplate = WxMpTemplateMessage.builder().build();
60 | orderPaySuccessTemplate.setToUser(request.getParameter("openid"));
61 | orderPaySuccessTemplate.setTemplateId("X8ccwRF4EAx7VHFQGzi78Gl0C3GcpGpYgWk-HFFOWA0");
62 | orderPaySuccessTemplate.setUrl(request.getParameter("url"));
63 | WxMpTemplateData firstData = new WxMpTemplateData("first", "订单状态更新", TEMPLATE_FRONT_COLOR);
64 | WxMpTemplateData orderMoneySumData = new WxMpTemplateData("OrderSn", request.getParameter("OrderSn"), TEMPLATE_FRONT_COLOR);
65 | WxMpTemplateData orderProductNameData = new WxMpTemplateData("OrderStatus", request.getParameter("OrderStatus"), TEMPLATE_FRONT_COLOR);
66 | WxMpTemplateData remarkData = new WxMpTemplateData("remark", request.getParameter("remark"), TEMPLATE_FRONT_COLOR);
67 | orderPaySuccessTemplate.addData(firstData)
68 | .addData(orderMoneySumData)
69 | .addData(orderProductNameData)
70 | .addData(remarkData);
71 | try {
72 | wxMpService.getTemplateMsgService()
73 | .sendTemplateMsg(orderPaySuccessTemplate);
74 | } catch (WxErrorException e) {
75 | logger.error(e.getMessage());
76 | }
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/github/weixin/demo/handler/AbstractHandler.java:
--------------------------------------------------------------------------------
1 | package com.github.weixin.demo.handler;
2 |
3 | import com.google.gson.Gson;
4 | import me.chanjar.weixin.mp.api.WxMpMessageHandler;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | /**
9 | * 消息处理Handler的父类
10 | *
11 | * Created by FirenzesEagle on 2016/7/27 0027.
12 | * Email:liumingbo2008@gmail.com
13 | */
14 | public abstract class AbstractHandler implements WxMpMessageHandler {
15 | protected Logger logger = LoggerFactory.getLogger(getClass());
16 | protected final Gson gson = new Gson();
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/github/weixin/demo/handler/LogHandler.java:
--------------------------------------------------------------------------------
1 | package com.github.weixin.demo.handler;
2 |
3 | import java.util.Map;
4 |
5 | import org.springframework.stereotype.Component;
6 |
7 | import me.chanjar.weixin.common.session.WxSessionManager;
8 | import me.chanjar.weixin.mp.api.WxMpService;
9 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
10 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
11 |
12 | /**
13 | * 对所有接收到的消息输出日志,也可进行持久化处理
14 | *
15 | * Created by FirenzesEagle on 2016/7/27 0027.
16 | * Email:liumingbo2008@gmail.com
17 | */
18 | @Component
19 | public class LogHandler extends AbstractHandler {
20 | @Override
21 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
22 | Map
16 | * Created by FirenzesEagle on 2016/7/27 0027.
17 | * Email:liumingbo2008@gmail.com
18 | */
19 | @Component
20 | public class MsgHandler extends AbstractHandler {
21 | @Override
22 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map
20 | * Created by FirenzesEagle on 2016/7/27 0027.
21 | * Email:liumingbo2008@gmail.com
22 | */
23 | @Component
24 | public class SubscribeHandler extends AbstractHandler {
25 |
26 | @Autowired
27 | protected WxMpConfigStorage configStorage;
28 | @Autowired
29 | protected WxMpService wxMpService;
30 | @Autowired
31 | protected CoreService coreService;
32 |
33 |
34 | @Override
35 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map