Wechattty Project is a JAVA-based development framework for WeChat public accounts (including service accounts and subscription accounts) and WeChat enterprise accounts. The well-encapsulated API allows developers to focus on the development of business logic and improve development efficiency.
Maven is used here to introduce dependencies.
<dependency>
<groupId>space.chensheng.wechatty</groupId>
<artifactId>wechatty-mp</artifactId>
<version>2.0.0</version>
</dependency>
MpAppContext
is the unified calling entrance for the public account API, which is initialized using WechatMpBootstrap
.
WechatMpBootstrap bootstrap = new WechatMpBootstrap();
bootstrap.addMsgListener(new TextMessageListener());
MpAppContext mpAppContext = bootstrap.build();
If the project is managed using spring, a FactoryBean
can be implemented to initialize MpAppContext
for subsequent reference.
@Component
public class MpAppContextFactoryBean implements FactoryBean<MpAppContext> {
@Override
public MpAppContext getObject() throws Exception {
WechatMpBootstrap bootstrap = new WechatMpBootstrap();
bootstrap.addMsgListener(new TextMessageListener());
return bootstrap.build();
}
@Override
public Class<?> getObjectType() {
return MpAppContext.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
There are two configuration methods, one is配置文件
and the other is JAVA代码配置
. The priority of JAVA代码配置
is higher than that配置文件
.
Create a new configuration file wechat-mp.properties and place the file in the project class path. For example, in a maven project, this file can be placed in the src/main/resources
directory. The general configuration is as follows:
token=thisIsToken
aesKey=thisIsAesKey
appId=thisIsYourAppId
appSecret=thisIsAppSecret
When MpAppConetxt
is initialized, call the customizeWechatContext
method of WechatMpBootstrap
for configuration.
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");
}
});
Required parameters | illustrate |
---|---|
token | The token of the official account can be viewed in the background of the official account. |
aesKey | The key used for encryption can be viewed in the background of the official account. |
appId | The appId of the official account can be viewed in the background of the official account. |
appSecret | The appSecret of the official account can be viewed in the background of the official account. |
Optional parameters | illustrate |
---|---|
enableCryptedMode | Whether to enable callback encryption mode, default true. If it is turned on, you need to download the JCE unrestricted permissions policy file to cover the relevant files in the jdk. For details, see examples of common errors in WeChat. |
autoUpdateAccessToken | Whether to automatically update the access_token when an access_token-related error occurs. The default is false. The application can update it through scheduled tasks, which will be introduced in detail later. |
accessTokenStrategyClass | The access_token access strategy, the default is space.chensheng.wechatty.common.http.MemoryAccessTokenStrategy, stores the access_token in the memory, and the application can implement its own access strategy, such as storing it in the database, which will be introduced in detail later. |
payKey | WeChat payment key |
payCertFile | WeChat payment certificate file path |
payCertPassword | WeChat payment certificate password |
payMchId | WeChat payment merchant ID |
payClientIp | Call the machine IP for payment |
poolingHttpProxyEnable | Whether to request the WeChat server through a proxy server, the default is false |
poolingHttpProxyHostname | The hostname of the proxy server, such as www.chensheng.space |
poolingHttpProxyPort | Proxy server port |
poolingHttpProxyUsername | Proxy server username |
poolingHttpProxyPassword | Proxy server password |
poolingHttpMaxPerRoute | The maximum number of concurrent connections per link in the http connection pool, the default is 50 |
poolingHttpMaxTotal | The maximum number of concurrent connections in the http connection pool, default 200 |
poolingHttpSocketTimeoutMillis | Number of milliseconds for socket timeout, default 10000 |
poolingHttpConnectTimeoutMillis | Number of milliseconds to connect to the WeChat server timeout, default 10000 |
poolingHttpConnectionRequestTimeoutMillis | Get the connection timeout milliseconds from the http connection pool, default 10000 |
poolingHttpTcpNoDelay | Whether to enable tpcNoDelay, default true |
mpAppContext.getAccessTokenFetcher().updateAccessToken()
regularly, usually once every 1.5 hours, because the expiration time of access_token is 2 hours.accessTokenStrategyClass=your.package.name.YourAccessTokenStrategy
in wechat-mp.properties. The following is a strategy for accessing the accesss_token database: import space . chensheng . wechatty . common . http . AccessTokenStrategy ;
//因为这个策略类的实例化不是通过Spring来管理的,所以在这个类中不能使用Autowired来注入bean,
//要通过ApplicationContext#getBean方法来获取。
public class DatabaseAccessTokenStrategy 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 ();
}
}
When MpAppContext
is initialized, add a message listener through WechatMpBootstrap
to receive messages (the message listener will be introduced later):
WechatMpBootstrap bootstrap = new WechatMpBootstrap();
bootstrap.addMsgListener(new TextMessageListener());
bootstrap.addMsgListener(new SubscribeEventListener());
bootstrap.addMsgListener(new UnsubscribeEventListener());
If you have set a callback URL in the WeChat official account background, the WeChat server will send a GET request to this URL for verification. The developer needs to handle this request in the web application. The following is a SpringMVC verification example:
@RestController
@RequestMapping(value = "/wechat-mp")
public class CallbackController extends BaseController{
@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;
}
}
After verifying the callback request, the callback mode is actually enabled. If the user sends a message to the official account, the WeChat server will send a POST request to the callback URL and forward the message to this URL. The developer needs to handle this request in the web application. The following is an example of SpringMVC (and the previous verification Example of enabling callback in a controller):
@RestController
@RequestMapping(value = "/wechat-mp")
public class CallbackController extends BaseController{
@Autowired
private MpAppContext mpAppContext;
//接收回调消息,并回复相应xml消息
@RequestMapping(value = "/callback", method = RequestMethod.POST)
public String verify(String msg_signature, String timestamp, String nonce) {
//postBody是请求体内容,String格式,开发者可以通过HttpServletRequest来解析
String replyXml = mpAppContext.getMpMessageDispatcher().dispatch(msg_signature(), timestamp, nonce, postBody);
return replyXml;
}
}
Developers can listen to specific types of messages by inheriting space.chensheng.wechatty.common.message.MessageListener
. Here is an example of listening to text messages sent by users:
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;
}
}
information | illustrate |
---|---|
TextInboundMessage | text message |
ImageInboundMessage | Picture message |
LinkInboundMessage | Jump to graphic message |
LocationInboundMessage | Share location information |
ShortVideoInboundMessage | Small video message |
VideoInboundMessage | video message |
VoiceInboundMessage | voice message |
ClickEventMessage | Click on the normal menu message |
ViewEventMessage | Click to jump to link menu message |
LocationEventMessage | Location event messages |
SubscribeEventMessage | Users follow public account news |
UnsubscribeEventMessage | Remember to unfollow public account messages |
ScanEventMessage | User scans QR code message |
MassSendJobFinishEventMessage | Group message sending completion report |
information | illustrate |
---|---|
TextReplyMessage | text reply |
ImageReplyMessage | Picture reply |
MusicReplyMessage | music reply |
NewsReplyMessage | Graphic reply |
VideoReplyMessage | video reply |
VoiceReplyMessage | Voice reply |
Official accounts can proactively send messages to users, including group messages and customer service messages. All messages are sent uniformly using space.chensheng.wechatty.mp.message.MpMessageSender
.
TextMassMessage message = new TextMassMessage();
message.setIsToAll(true);
message.setContent("群发消息测试");
mpAppContext.getMpMessageSender().send(message, 3);
Group message type | illustrate |
---|---|
TextMassMessage | Bulk text |
ImageMassMessage | Picture group sending |
MpnewsMassMessage | Group sending of pictures and text within WeChat |
MpvideoMassMessage | Video group sending |
VoiceMassMessage | Voice group sending |
WxcardMassMessage | WeChat card and coupon mass distribution |
TextCsMessage message = new TextCsMessage();
message.setToUser("thisIsUserOpenId");
message.setContent("客服消息测试 n 212");
mpAppContext.getMpMessageSender().send(message, 3);
Customer service message type | illustrate |
---|---|
TextCsMessage | Text customer service |
ImageCsMessage | Picture customer service |
MpnewsCsMessage | Graphic customer service within WeChat |
NewsCsMessage | External graphic customer service |
VideoCsMessage | Video customer service |
VoiceCsMessage | Voice customer service |
WxcardCsMessage | WeChat Card and Voucher Customer Service |
Material management mainly involves uploading, querying, modifying, and deleting materials. Material types include pictures, videos, voices, and graphics.
Uploading materials is completed by operating the corresponding material upload class. The following is an example of uploading images:
File image = new File("/this/is/image/path.jpg");
ImagePermanentMedia material = new ImagePermanentMedia(mpAppContext, image);
UploadResponse resp = material.upload();
Material upload class | illustrate |
---|---|
ImagePermanentMedia | permanent picture |
ThumbPermanentMedia | Permanent thumbnail |
VideoPermanentMedia | permanent video |
VoicePermanentMedia | permanent voice |
PermanentNews | Permanent pictures and texts |
PermanentNewsImg | Pictures in Permanent Graphics |
ImageTemporaryMedia | Temporary picture |
ThumbTemporaryMedia | Temporary thumbnail |
VideoTemporaryMedia | temporary video |
VoiceTemporaryMedia | Temporary voice |
The material query operation is completed through the tool classes space.chensheng.wechatty.mp.material.MaterialQuery
and space.chensheng.wechatty.mp.material.MaterialFinder
.
mpAppContext.getMaterialQuery().count()
mpAppContext.getMaterialQuery().listNews(int offset, int count)
mpAppContext.getMaterialQuery().listMedia(MediaType mediaType, int offset, int count)
mpAppContext.getMaterialFinder().findNews(String mediaId)
mpAppContext.getMaterialFinder().findPermanentVideo(String mediaId)
mpAppContext.getMaterialFinder().findTemporaryVideo(String mediaId)
mpAppContext.getMaterialFinder().downloadPermanentMedia(String mediaId, String saveDir, String fileName)
mpAppContext.getMaterialFinder().downloadTemporaryMedia(String mediaId, String saveDir, String fileName)
The material deletion operation is completed through the tool class space.chensheng.wechatty.mp.material.MaterialDeleter
.
mpAppContext.getMaterialDeleter().delete(String mediaId)
Generating QR codes with parameters is completed through the tool class space.chensheng.wechatty.mp.account.QRCodeCreator
.
mpAppContext.getQRCodeCreator().createTemporary(int expireSeconds, int sceneId)
mpAppContext.getQRCodeCreator().createPermanent(int sceneId)
mpAppContext.getQRCodeCreator().createPermanent(String sceneStr)
Querying user information is implemented through UserInfoQuery
.
mpAppConext.getUserInfoQuery().get(String openId)
mpAppContext.getUserInfoQuery().batchGet(List<String> openIds)
User authorization is implemented through AuthHelper
.
auth access token
through the authorization link code: mpAppContext.getAuthHelper().fetchAuthAccessToken(String code)
auth access token
: mpAppContext.getAuthHelper().refreshAuthAccessToken(String refreshAccessToken)
auth access token
: mpAppContext.getAuthHelper().fetchAuthUserInfo(String authAccessToken, String openId)
The following is a pseudocode for user authorization:
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 authorization is implemented through JsapiHelper
.
jsapi ticket
(you can use scheduled tasks to get tickets regularly and store them in the database): mpAppContext.getJsapiHelper().fetchTicket()
mpAppContext.getJsapiHelper().generateSignature(String jsapiTicket, String nonceStr, long timestamp, String url)
When initializing MpAppContext
, call enablePayCert()
method of WechatMpBootstrap
to enable WeChat payment and configure relevant parameters. (See the configuration module for specific parameters)
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)
mpAppContext.getPayHelper().generateJsapiPayParams(String prepayId, PaySignType signType)
mpAppContext.getPayHelper().refund(RefundRequest request)
mpAppContext.getPayHelper().parseRefundNotify(String notifyContent)