Spring Boot集成weixin4j
1.weixin4j官方网站
weixin4j入门视频传送门
weixin4j入门:https://v.qq.com/x/page/t0630doxoaz.html
weixin4j-spring-boot入门:https://v.qq.com/x/page/e0764lyx518.html
2.weixin4j
weixin4j是一个用Java编写针对微信开发的工具包,为Java微信开发爱好者提供的微信公众开发平台SDK.
项目地址:https://github.com/ansitech/weixin4j
3.weixin4j-spring
weixin4j-spring主要是针对Spring MVC项目,集成了weixin4j,支持xml配置和注解配置bean.
4.weixin4j-spring-boot-starter
这是为了集成spring boot而搭建的框架,所以针对weixin4j也做了一定的修改。
父项目名为weixin4j-spring-boot
其本身包含2个模块weixin4j-spring-boot-autoconfigure和weixin4j-spring-boot-starter。
5.添加maven依赖pom.xml
好消息:weixin4j、weixin4j-spring、weixin4j-spring-boot-starter三大组件终于全部上maven了,可以直接pom引用了。
Spring Boot用户,直接添加依赖:
<dependency> <groupId>org.weixin4j.spring.boot</groupId> <artifactId>weixin4j-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>
Spring MVC用户,直接添加依赖:
<dependency> <groupId>org.weixin4j</groupId> <artifactId>weixin4j-spring</artifactId> <version>1.0.0</version> </dependency>
独立使用:
<dependency> <groupId>org.weixin4j</groupId> <artifactId>weixin4j</artifactId> <version>0.1.3</version> </dependency>
6.创建weixin4j配置
weixin4j的配置有2种方式:
第一种:使用weixin4j.properties配置文件
将配置文件放在资源目录即classess下名称为weixin4j.properties。
配置参数:
#微信SDK配置文件 #读取规则:优先读取System.getProperty() #再从weixin4j.properties读取,key #如果System.getProperty()与weixin4j.properties都没设置,则默认未NULL #开发者调试设置 weixin4j.debug=true #公众号Token weixin4j.token=weixin4j #公众号原始ID weixin4j.oauth.originalid= #开发者第三方用户唯一凭证 weixin4j.oauth.appid= #开发者第三方用户唯一凭证密钥 weixin4j.oauth.secret= #消息加密方式 0:明文模式(默认), 1:兼容模式, 2:安全模式(推荐) weixin4j.oauth.encodingtype=0 #消息加密密钥(43位字符组成A-Za-z0-9) weixin4j.oauth.encodingaeskey=0123456789abcedfghijklmnopqrstuvwxyzZXCVBNM #网页安全授权URL weixin4j.oauth.url= #公众平台接口域名 #通用域名(api.weixin.qq.com),使用该域名将访问官方指定就近的接入点; #上海域名(sh.api.weixin.qq.com),使用该域名将访问上海的接入点; #深圳域名(sz.api.weixin.qq.com),使用该域名将访问深圳的接入点; #香港域名(hk.api.weixin.qq.com),使用该域名将访问香港的接入点。 weixin4j.api.domain=api.weixin.qq.com #微信支付_商户ID weixin4j.pay.partner.id= #微信支付_商户密钥 weixin4j.pay.partner.key= #微信支付_通知URL weixin4j.pay.notify_url= #连接超时设置 weixin4j.http.connectionTimeout=25000 #请求超时设置 weixin4j.http.readTimeout=25000 #证书路径 weixin4j.http.cert.path= weixin4j.http.cert.secret= #默认消息处理函数 weixin4j.handler=org.weixin4j.spi.DefaultMessageHandler weixin4j.message.handler.normal=org.weixin4j.spi.DefaultNormalMessageHandler weixin4j.message.handler.event=org.weixin4j.spi.DefaultEventMessageHandler
第二种:基于spring boot的配置文件,application.properties或application.yml
application.properties配置参数:
#微信开发配置 #开发者第三方用户唯一凭证 weixin4j.config.appid= #开发者第三方用户唯一凭证密钥 weixin4j.config.secret= #公众号原始ID weixin4j.config.originalid= #消息加密方式 0:明文模式(默认), 1:兼容模式, 2:安全模式(推荐) weixin4j.config.encodingtype=0 #消息加密密钥(43位字符组成A-Za-z0-9) weixin4j.config.encodingaeskey=0123456789abcedfghijklmnopqrstuvwxyzZXCVBNM #网页安全授权URL weixin4j.config.oauthUrl= #微信支付配置 #微信支付_商户ID,例如10000000001 weixin4j.pay.partnerId= #微信支付_商户密钥,由商户设置32位字符 weixin4j.pay.partnerKey= #微信支付_通知URL,异步接收微信支付结果的URL weixin4j.pay.notifyUrl= #证书路径(pk12格式),例如:/opt/cert/10000000001.pk12 weixin4j.pay.certPath= #证书密钥,默认为商户ID,例如:10000000001 weixin4j.pay.certSecret=
application.yml配置参数:
weixin4j: #微信开发配置 config: #开发者第三方用户唯一凭证 appid: #开发者第三方用户唯一凭证密钥 secret: #公众号原始ID originalid: #消息加密方式 0:明文模式(默认), 1:兼容模式, 2:安全模式(推荐) encodingtype: 0 #消息加密密钥(43位字符组成A-Za-z0-9) encodingaeskey: 0123456789abcedfghijklmnopqrstuvwxyzZXCVBNM #网页安全授权URL oauthUrl: #微信支付配置 pay: #微信支付_商户ID,例如10000000001 partnerId: #微信支付_商户密钥,由商户设置32位字符 partnerKey: #微信支付_通知URL,异步接收微信支付结果的URL notifyUrl: #证书路径(pk12格式),例如:/opt/cert/10000000001.pk12 certPath: #证书密钥,默认为商户ID,例如:10000000001 certSecret:
7.实现ITokenLoader,自主选择存储AccessToken方式
本例给大家演示了使用Redis缓存方式:
package com.ansitech.weixin4j; import com.alibaba.fastjson.JSON; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.weixin4j.loader.ITokenLoader; import org.weixin4j.model.base.Token; @Component public class RedisTokenLoader implements ITokenLoader { private static final Logger LOG = LoggerFactory.getLogger(RedisTokenLoader.class); private final String ACCESS_TOKEN_KEY = "ats_wx100000000001"; @Autowired private StringRedisTemplate stringRedisTemplate; public RedisTokenLoader(String appid) { this.appid = appid; } @Override public Token get() { String accessToken = stringRedisTemplate.opsForValue().get(ACCESS_TOKEN_KEY); LOG.info("wechat access_token:{}", accessToken); return JSON.parseObject(accessToken, Token.class); } @Override public void refresh(Token token) { LOG.info("refresh wechat access_token:{}", token.toString()); String accessToken = JSON.toJSONString(token); //ticket.getExpires_in() - 600L,是为了提前10分钟过期 stringRedisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, token.getExpires_in() - 600L, TimeUnit.SECONDS); } }
8.同理可以实现ITicketLoader
package com.ansitech.weixin4j.factory; import com.alibaba.fastjson.JSON; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.weixin4j.loader.ITicketLoader; import org.weixin4j.model.js.Ticket; import org.weixin4j.model.js.TicketType; @Component public class RedisTicketLoader implements ITicketLoader { private static final Logger LOG = LoggerFactory.getLogger(RedisTicketLoader.class); private final String ACCESS_TOKEN_KEY = "ats_wx100000000001"; @Autowired private StringRedisTemplate stringRedisTemplate; @Override public Ticket get(TicketType ticketType) { String key = ""; if (null != ticketType) { switch (ticketType) { case JSAPI: key = "wechat_ticket_jsapi"; break; case WX_CARD: key = "wechat_ticket_wxcard"; break; default: key = "wechat_ticket"; break; } } String ticket = stringRedisTemplate.opsForValue().get(key); LOG.info("wechat ticket:{}", ticket); return JSON.parseObject(ticket, Ticket.class); } @Override public void refresh(Ticket ticket) { String key = ""; if (null != ticket.getTicketType()) { switch (ticket.getTicketType()) { case JSAPI: key = "wechat_ticket_jsapi_" + appid; break; case WX_CARD: key = "wechat_ticket_wxcard_" + appid; break; default: key = "wechat_ticket_" + appid; break; } } LOG.info("refresh wechat ticket:{}", ticket.toString()); String ticketValue = JSON.toJSONString(ticket); //ticket.getExpires_in() - 600L,是为了提前10分钟过期 stringRedisTemplate.opsForValue().set(key, ticketValue, ticket.getExpires_in() - 600L, TimeUnit.SECONDS); } }
9.微信开发者接入
weixin4j-spring包内置了消息接入处理Controller,直接继承即可。
package com.ansitech.weixin4j.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.weixin4j.spring.web.WeixinJieruController; /** * 微信开发者接入 * * @author yangqisheng */ @Controller @RequestMapping("/weixin/jieru") public class JieruController extends WeixinJieruController { }
10.实现公众号普通消息处理
实现接口INormalMessageHandler即可
package com.ansitech.weixin4j.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.weixin4j.model.message.OutputMessage; import org.weixin4j.model.message.normal.ImageInputMessage; import org.weixin4j.model.message.normal.LinkInputMessage; import org.weixin4j.model.message.normal.LocationInputMessage; import org.weixin4j.model.message.normal.ShortVideoInputMessage; import org.weixin4j.model.message.normal.TextInputMessage; import org.weixin4j.model.message.normal.VideoInputMessage; import org.weixin4j.model.message.normal.VoiceInputMessage; import org.weixin4j.model.message.output.TextOutputMessage; import org.weixin4j.spi.INormalMessageHandler; /** * 公众号普通消息处理 * * @author yangqisheng */ @Component public class MyNormalMessageHandler implements INormalMessageHandler { @Override public OutputMessage textTypeMsg(TextInputMessage msg) { return new TextOutputMessage("你的消息已收到"); } @Override public OutputMessage imageTypeMsg(ImageInputMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage voiceTypeMsg(VoiceInputMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage videoTypeMsg(VideoInputMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage shortvideoTypeMsg(ShortVideoInputMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage locationTypeMsg(LocationInputMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage linkTypeMsg(LinkInputMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }
11.实现公众号事件消息处理
实现IEventMessageHandler接口即可实现事件消息的处理。package com.ansitech.weixin4j.service;
import org.weixin4j.model.message.OutputMessage; import org.weixin4j.model.message.event.ClickEventMessage; import org.weixin4j.model.message.event.LocationEventMessage; import org.weixin4j.model.message.event.LocationSelectEventMessage; import org.weixin4j.model.message.event.PicPhotoOrAlbumEventMessage; import org.weixin4j.model.message.event.PicSysPhotoEventMessage; import org.weixin4j.model.message.event.PicWeixinEventMessage; import org.weixin4j.model.message.event.QrsceneScanEventMessage; import org.weixin4j.model.message.event.QrsceneSubscribeEventMessage; import org.weixin4j.model.message.event.ScanCodePushEventMessage; import org.weixin4j.model.message.event.ScanCodeWaitMsgEventMessage; import org.weixin4j.model.message.event.SubscribeEventMessage; import org.weixin4j.model.message.event.UnSubscribeEventMessage; import org.weixin4j.model.message.event.ViewEventMessage; import org.weixin4j.model.message.output.TextOutputMessage; import org.weixin4j.spi.IEventMessageHandler; /** * 公众号事件消息处理 * * @author yangqisheng */
@Component
public class MyEventMessageHandler implements IEventMessageHandler{ @Override public OutputMessage subscribe(SubscribeEventMessage msg) { return new TextOutputMessage("感谢你的关注"); } @Override public OutputMessage unSubscribe(UnSubscribeEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage qrsceneSubscribe(QrsceneSubscribeEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage qrsceneScan(QrsceneScanEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage location(LocationEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage click(ClickEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage view(ViewEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage scanCodePush(ScanCodePushEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage scanCodeWaitMsg(ScanCodeWaitMsgEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage picSysPhoto(PicSysPhotoEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage picPhotoOrAlbum(PicPhotoOrAlbumEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage picWeixin(PicWeixinEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public OutputMessage locationSelect(LocationSelectEventMessage msg) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }