Wechattty Project是一个基于JAVA的微信公众号(包括服务号和订阅号)和微信企业号的开发框架,封装良好的API让开发者可以专注于业务逻辑的开发,提高开发效率。

简单使用教程

引入依赖

这里使用maven来引入依赖。

<dependency>  <groupId>space.chensheng.wechatty</groupId>  <artifactId>wechatty-mp</artifactId>  <version>2.0.0</version></dependency>

初始化

MpAppContext是公众号API的统一调用入口,使用WechatMpBootstrap对其进行初始化。

WechatMpBootstrap bootstrap = new WechatMpBootstrap();bootstrap.addMsgListener(new TextMessageListener());MpAppContext mpAppContext = bootstrap.build();

如果项目使用spring来管理,可实现一个FactoryBean来初始化MpAppContext,以便后续引用。

@Componentpublic class MpAppContextFactoryBean implements FactoryBean<MpAppContext> {    @Override    public MpAppContext get () throws Exception {        WechatMpBootstrap bootstrap = new WechatMpBootstrap();        bootstrap.addMsgListener(new TextMessageListener());        return bootstrap.build();    }    @Override    public Class<?> get Type() {        return MpAppContext.class;    }    @Override    public boolean isSingleton() {        return true;    }}

配置

配置方式有两种,一种是配置文件,另一种是 JAVA代码配置。其中JAVA代码配置的优先级高于配置文件

配置文件

新建配置文件wechat-mp.properties, 将该文件放在项目类路径下。比如maven项目,可将该文件放在src/main/resources目录下。一般的配置如下:

token=thisIsTokenaesKey=thisIsAesKeyappId=thisIsYourAppIdappSecret=thisIsAppSecret
JAVA代码配置

MpAppConetxt初始化时,调用WechatMpBootstrapcustomizeWechatContext方法来进行配置。

WechatMpBootstrap bootstrap = new WechatMpBootstrap();bootstrap.customizeWechatContext(new MpWechatContextCustomizer() {    @Override    public void customize(MpWechatContext wechatContext) {    wechatContext.setToken("thisIsToken");    wechatContext.setAesKey("thisIsAeskey");    wechatContext.setAppId("thisIsAppId");    wechatContext.setAppSecret("thisIsAppSecret");    }});
配置参数说明
必填参数说明
token公众号的token,可在公众号后台查看.
aesKey加密用的key, 可在公众号后台查看.
appId公众号appId,可在公众号后台查看。
appSecret公众号的appSecret,可在公众号后台查看。
可选参数说明
enableCryptedMode是否开启回调加密模式,默认true。如果开启则要下载JCE无限制权限策略文件,覆盖jdk中的相关文件,具体可查看微信常见错误举例
autoUpdateAccessToken出现access_token相关错误时是否自动更新access_token,默认false,应用可自己通过定时任务来更新,后面将详细介绍。
accessTokenStrategyClassaccess_token存取策略,默认是space.chensheng.wechatty.common.http.MemoryAccessTokenStrategy,将access_token存在内存中,应用可实现自己的存取策略,比如存在数据库中,后面将详细介绍。
payKey微信支付key
payCertFile微信支付证书文件路径
payCertPassword微信支付证书密码
payMchId微信支付商户id
payClientIp调用支付的机器ip
poolingHttpProxyEnable是否通过代理服务器给微信服务器必请求,默认false
poolingHttpProxyHostname代理服务器的hostname,比如www.chensheng.space
poolingHttpProxyPort代理服务器端口
poolingHttpProxyUsername代理服务器用户名
poolingHttpProxyPassword代理服务器密码
poolingHttpMaxPerRoutehttp连接池每条链路最大并发连接数,默认为50
poolingHttpMaxTotalhttp连接池最大并发连接数,默认200
poolingHttpSocketTimeoutMillissocket超时毫秒数,默认10000
poolingHttpConnectTimeoutMillis连接到微信服务器超时毫秒数,默认10000
poolingHttpConnectionRequestTimeoutMillis从htttp连接池获取连接超时毫秒数,默认10000
poolingHttpTcpNoDelay是否开启tpcNoDelay,默认true
access_token更新问题
  • 自动更新:如果开启了自动更新,则在因为access_token错误而导致请求微信接口失败的情况下,框架会自动更新access_token。
  • 定时更新:在应用中使用定时任务(比如quartz)来定时执行mpAppContext.getAccessTokenFetcher().updateAccessToken(),一般每1.5小时执行一次,因为access_token的过期时间为2小时。
  • 自动更新和定时更新可共存,如果多个线程并发执行更新access_token,只有一个线程会去请求微信服务器来更新access_token,其他线程会立即返回,不执行任何操作。
access_token存取策略问题
  • Web应用单机部署:如果您的应用是单机部署,则可直接使用默认的策略,将access_token存储在内存中。
  • Web应用集群部署:如果您的应用是集群部署,则要实现自己的access_token存取策略,将access_token存放在集群共享的媒介(比如数据库)来达到access_token中控管理的目的。实现完自己的策略类后,要在wechat-mp.properties中添加配置accessTokenStrategyClass=your.package.name.YourAccessTokenStrategy。以下是一个accesss_token数据库存取的策略:
import space.chensheng.wechatty.common.http.AccessTokenStrategy;//因为这个策略类的实例化不是通过Spring来管理的,所以在这个类中不能使用Autowired来注入bean,//要通过ApplicationContext#getBean方法来获取。public class Data AccessTokenStrategy implements AccessTokenStrategy{        //将access_token存到数据库中去    @Override    public void doSave(String accessToken) {        TokenService tokenService = ApplicationContextUtil        .getApplicationContext().getBean(TokenService.class);    tokenService.doSave(accessToken);    }        //从数据库中取出access_token    @Override    public String doQuery() {        TokenService tokenService = ApplicationContextUtil        .getApplicationContext().getBean(TokenService.class);    return tokenService.doQuery();    }}

接收消息

MpAppContext初始化时,通过WechatMpBootstrap添加消息监听器来接收消息(关于message listener会在后面介绍):

WechatMpBootstrap bootstrap = new WechatMpBootstrap();bootstrap.addMsgListener(new TextMessageListener());bootstrap.addMsgListener(new SubscribeEventListener());bootstrap.addMsgListener(new UnsubscribeEventListener());
验证微信服务器的开启回调请求

如果你已经在微信公众号后台设置了回调URL,微信服务器会向这个URL发送一个GET请求来验证,开发者需要在Web应用中处理这个请求。以下是一个SpringMVC的验证例子:

@RestController@RequestMapping(value = "/wechat-mp")public class CallbackController extends  Controller{    @Autowired    private MpAppContext mpAppContext;        //验证请求,并回复字符串    @RequestMapping(value = "/callback", method = RequestMethod.GET)    public String verify(String msg_signature, String timestamp, String nonce, String echostr) {        String reply = mpAppContext.getCallbackModeVerifier().verify(msg_signature, timestamp, nonce, echostr);    return reply;    }    }
消息回调请求处理

验证完开启回调请求后,回调模式就真正开启了。如果用户发了个消息给公众号,微信服务器会向回调URL发送一个POST请求,将消息转发到这个URL上,开发者需要在Web应用中处理这个请求,以下是一个SpringMVC的例子(和前面验证开启回调的例子在一个controller中):

@RestController@RequestMapping(value = "/wechat-mp")public class CallbackController extends  Controller{    @Autowired    private MpAppContext mpAppContext;        //接收回调消息,并回复相应 消息    @RequestMapping(value = "/callback", method = RequestMethod.POST)    public String verify(String msg_signature, String timestamp, String nonce) {        //postBody是请求体内容,String格式,开发者可以通过HttpServletRequest来解析        String reply  = mpAppContext.getMpMessageDispatcher().dispatch(msg_signature(), timestamp, nonce, postBody);    return reply ;    }}
回调消息的监听

开发者可以通过继承space.chensheng.wechatty.common.message.MessageListener来监听特定类型的消息。以下是一个监听用户发送的文本消息的例子:

public class TextMessageListener extends MessageListener<TextInboundMessage> {    @Override    protected ReplyMessage onMessage(TextInboundMessage message) {        String content = message.getContent();        //根据消息内容来回复用户    if ("1".equals(content)) {        TextReplyMessage replyMsg = new TextReplyMessage();        replyMsg.setContent("this is reply message content");        replyMsg.setFromUserName(message.getToUserName());        replyMsg.setToUserName(message.getFromUserName());        replyMsg.setCreateTime(System.currentTimeMillis());        return replyMsg;    }        //返回null表示不回复用户    return null;    }}
可监听的消息类型
消息说明
TextInboundMessage文本消息
ImageInboundMessage图片消息
InboundMessage跳转图文消息
LocationInboundMessage共享位置消息
ShortVideoInboundMessage小视频消息
VideoInboundMessage视频消息
VoiceInboundMessage语音消息
ClickEventMessage点击普通菜单消息
ViewEventMessage点击跳转链接菜单消息
LocationEventMessage位置事件消息
SubscribeEventMessage用户关注公众号消息
UnsubscribeEventMessage用记取消关注公众号消息
ScanEventMessage用户扫描二维码消息
MassSendJobFinishEventMessage群发消息发送完成报告
可回复的消息类型
消息说明
TextReplyMessage文本回复
ImageReplyMessage图片回复
MusicReplyMessage音乐回复
NewsReplyMessage图文回复
VideoReplyMessage视频回复
VoiceReplyMessage语音回复

发送消息

公众号可以主动发送消息给用户,包括群发消息和客服消息两大类型消息。所有消息统一使用space.chensheng.wechatty.mp.message.MpMessageSender来发送。

群发消息
TextMassMessage message = new TextMassMessage();message.setIsToAll(true);message.setContent("群发消息测试");mpAppContext.getMpMessageSender().send(message, 3);
群发消息类型说明
TextMassMessage文本群发
ImageMassMessage图片群发
MpnewsMassMessage微信内图文群发
MpvideoMassMessage视频群发
VoiceMassMessage语音群发
WxcardMassMessage微信卡券群发
客服消息
TextCsMessage message = new TextCsMessage();message.setToUser("thisIsUserOpenId");message.setContent("客服消息测试 
 212");mpAppContext.getMpMessageSender().send(message, 3);
客服消息类型说明
TextCsMessage文本客服
ImageCsMessage图片客服
MpnewsCsMessage微信内图文客服
NewsCsMessage外部图文客服
VideoCsMessage视频客服
VoiceCsMessage语音客服
WxcardCsMessage微信卡券客服

素材管理

素材管理主要是进行素材的上传、查询、修改、删除,素材类型包括图片、视频、语音、图文。

上传素材

上传素材通过操作对应的素材上传类来完成,下面是一个上传图片的例子:

File image = new File("/this/is/image/path.jpg");ImagePermanentMedia material = new ImagePermanentMedia(mpAppContext, image);UploadResponse resp = material.upload();
素材上传类说明
ImagePermanentMedia永久图片
ThumbPermanentMedia永久缩略图
VideoPermanentMedia永久视频
VoicePermanentMedia永久语音
PermanentNews永久图文
PermanentNewsImg永久图文中的图片
ImageTemporaryMedia临时图片
ThumbTemporaryMedia临时缩略图
VideoTemporaryMedia临时视频
VoiceTemporaryMedia临时语音
查询素材

查询素材操作通过工具类space.chensheng.wechatty.mp.material.MaterialQueryspace.chensheng.wechatty.mp.material.MaterialFinder完成。

  • 查询素材的数量信息:mpAppContext.getMaterialQuery().count()
  • 查询图文素材:mpAppContext.getMaterialQuery().listNews(int offset, int count)
  • 查询其他素材:mpAppContext.getMaterialQuery().listMedia(MediaType mediaType, int offset, int count)
  • 根据mediaId查找图文:mpAppContext.getMaterialFinder().findNews(String mediaId)
  • 根据mediaId查找永久视频:mpAppContext.getMaterialFinder().findPermanentVideo(String mediaId)
  • 根据mediaId查找临时视频:mpAppContext.getMaterialFinder().findTemporaryVideo(String mediaId)
  • 根据mediaId下载永久素材:mpAppContext.getMaterialFinder().downloadPermanentMedia(String mediaId, String saveDir, String fileName)
  • 根据mediaId下载临时素材:mpAppContext.getMaterialFinder().downloadTemporaryMedia(String mediaId, String saveDir, String fileName)
删除素材

删除素材操作通过工具类space.chensheng.wechatty.mp.material.MaterialDeleter完成。

  • 根据mediaId删除素材:mpAppContext.getMaterialDeleter().delete(String mediaId)

帐号管理

生成带参数二维码

生成带参数二维码通过工具类space.chensheng.wechatty.mp.account.QRCodeCreator完成。

  • 生成带参数临时二维码:mpAppContext.getQRCodeCreator().createTemporary(int expireSeconds, int sceneId)
  • 生成带整型参数永久二维码:mpAppContext.getQRCodeCreator().createPermanent(int sceneId)
  • 生成带字符串参数永久二维码:mpAppContext.getQRCodeCreator().createPermanent(String sceneStr)
查询用户信息

查询用户信息通过UserInfoQuery实现。

  • 查询单个用户信息: mpAppConext.getUserInfoQuery().get(String openId)
  • 批量查询用户信息:mpAppContext.getUserInfoQuery().batchGet(List<String> openIds)

微信授权

用户授权

用户授权通过AuthHelper实现。

  • 通过授权链接的code获取auth access token: mpAppContext.getAuthHelper().fetchAuthAccessToken(String code)
  • 刷新auth access token: mpAppContext.getAuthHelper().refreshAuthAccessToken(String refreshAccessToken)
  • 通过auth access token获取用户信息: mpAppContext.getAuthHelper().fetchAuthUserInfo(String authAccessToken, String openId)

以下是一段用户授权的伪代码:

public WxAuthLoginDto authAndLogin(String code) {    AuthAccessTokenResponse authResp = mpAppContext.getAuthHelper().fetchAuthAccessToken(code);    if (authResp == null || !authResp.isOk()) {        //授权失败,执行相应业务逻辑        return new WxAuthLoginDto("fail");    }            String openId = authResp.getOpenId();    AuthUserInfoResponse wxUserInfo = mpAppContext.getAuthHelper().fetchAuthUserInfo(authResp.getAccessToken(), authResp.getOpenId())    //根据微信用户信息在数据库里查找系统对应的用户,或新建一个用户        //进行登录相关业务逻辑处理    return new WxAuthLoginDto("success");}
jsapi授权

jsapi授权通过JsapiHelper实现。

  • 获取jsapi ticket(可使用定时任务来定时获取ticket并存于数据库中): mpAppContext.getJsapiHelper().fetchTicket()
  • 生成jsapi签名信息: mpAppContext.getJsapiHelper().generateSignature(String jsapiTicket, String nonceStr, long timestamp, String url)

微信支付

初始化MpAppContext时,调用WechatMpBootstrapenablePayCert()方法来启用微信支付,并配置相关参数。(具体参数查看配置模块)

WechatMpBootstrap bootstrap = new WechatMpBootstrap();bootstrap.enablePayCert();
  • 发送普通红包: mpAppContext.getPayHelper().sendRedPack(RedPackRequest request)
  • 发送群红包: mpAppContext.getPayHelper().sendGroupRedPack(GroupRedPackRequest request)
  • 转账: mpAppContext.getPayHelper().transfers(TransfersRequest request)
  • 生成预付款订单: mpAppContext.getPayHelper().unifiedOrder(UnifiedOrderRequest request)
  • 解析支付回调: mpAppContext.getPayHelper().parsePayNotify(String notifyContent)
  • 校验支付回调: mpAppContext.getPayHelper().validatePayNotify(PayNotifyResponse response)
  • 支付订单查询: mpAppContext.getPayHelper().orderQuery(OrderQueryRequest request)
  • 关闭支付订单: mpAppContext.getPayHelper().closeOrder(CloseOrderRequest request)
  • 生成短链接: mpAppContext.getPayHelper().shortUrl(String longUrl)
  • 生成js支付参数: mpAppContext.getPayHelper().generateJsapiPayParams(String prepayId, PaySignType signType)
  • 发起退款: mpAppContext.getPayHelper().refund(RefundRequest request)
  • 解析退款回调: mpAppContext.getPayHelper().parseRefundNotify(String notifyContent)
收藏 打印