Wechattty Project est un cadre de développement basé sur JAVA pour les comptes publics WeChat (y compris les comptes de service et les comptes d'abonnement) et les comptes d'entreprise WeChat. L'API bien encapsulée permet aux développeurs de se concentrer sur le développement de la logique métier et d'améliorer l'efficacité du développement.
Maven est utilisé ici pour introduire des dépendances.
<dependency>
<groupId>space.chensheng.wechatty</groupId>
<artifactId>wechatty-mp</artifactId>
<version>2.0.0</version>
</dependency>
MpAppContext
est l'entrée d'appel unifiée de l'API du compte public, qui est initialisée à l'aide de WechatMpBootstrap
.
WechatMpBootstrap bootstrap = new WechatMpBootstrap();
bootstrap.addMsgListener(new TextMessageListener());
MpAppContext mpAppContext = bootstrap.build();
Si le projet est géré à l'aide de Spring, un FactoryBean
peut être implémenté pour initialiser MpAppContext
pour référence ultérieure.
@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;
}
}
Il existe deux méthodes de configuration, l'une est配置文件
et l'autre est JAVA代码配置
. La priorité de JAVA代码配置
est supérieure à celle配置文件
.
Créez un nouveau fichier de configuration wechat-mp.properties et placez le fichier dans le chemin de classe du projet. Par exemple, dans un projet maven, ce fichier peut être placé dans le répertoire src/main/resources
. La configuration générale est la suivante :
token=thisIsToken
aesKey=thisIsAesKey
appId=thisIsYourAppId
appSecret=thisIsAppSecret
Lorsque MpAppConetxt
est initialisé, appelez la méthode customizeWechatContext
de WechatMpBootstrap
pour la 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");
}
});
Paramètres requis | illustrer |
---|---|
jeton | Le jeton du compte officiel peut être consulté en arrière-plan du compte officiel. |
aesClé | La clé utilisée pour le cryptage peut être consultée dans le backend du compte officiel. |
identifiant d'application | L'appId du compte officiel peut être consulté en arrière-plan du compte officiel. |
applicationSecret | L'appSecret du compte officiel peut être consulté en arrière-plan du compte officiel. |
Paramètres facultatifs | illustrer |
---|---|
activerCryptedMode | S'il faut activer le mode de cryptage de rappel, vrai par défaut. S'il est activé, vous devez télécharger le fichier de stratégie d'autorisations illimitées JCE pour couvrir les fichiers pertinents dans le jdk. Pour plus de détails, consultez des exemples d'erreurs courantes dans WeChat. |
autoUpdateAccessToken | S'il faut mettre à jour automatiquement le access_token lorsqu'une erreur liée à access_token se produit. La valeur par défaut est false. L'application peut le mettre à jour via des tâches planifiées, qui seront présentées en détail plus tard. |
accessTokenStrategyClass | La stratégie d'accès access_token, la valeur par défaut est space.chensheng.wechatty.common.http.MemoryAccessTokenStrategy, stocke le access_token dans la mémoire et l'application peut implémenter sa propre stratégie d'accès, comme le stocker dans la base de données, qui sera introduite dans détail plus tard. |
clé de paiement | Clé de paiement WeChat |
payCertFichier | Chemin du fichier du certificat de paiement WeChat |
payCertMot de passe | Mot de passe du certificat de paiement WeChat |
payMchId | Identifiant du marchand de paiement WeChat |
payClientIp | Appelez l'adresse IP de la machine pour le paiement |
poolingHttpProxyEnable | S'il faut demander le serveur WeChat via un serveur proxy, la valeur par défaut est false |
poolingHttpProxyHostname | Le nom d'hôte du serveur proxy, tel que www.chensheng.space |
poolingHttpProxyPort | Port du serveur proxy |
poolingHttpProxyNom d'utilisateur | Nom d'utilisateur du serveur proxy |
poolingHttpProxyMot de passe | Mot de passe du serveur proxy |
poolingHttpMaxPerRoute | Le nombre maximum de connexions simultanées par lien dans le pool de connexions http, la valeur par défaut est 50 |
poolingHttpMaxTotal | Le nombre maximum de connexions simultanées dans le pool de connexions http, par défaut 200 |
poolingHttpSocketTimeoutMillis | Nombre de millisecondes pour le délai d'expiration du socket, par défaut 10 000 |
poolingHttpConnectTimeoutMillis | Nombre de millisecondes pour se connecter au délai d'expiration du serveur WeChat, par défaut 10 000 |
poolingHttpConnectionRequestTimeoutMillis | Obtenez le délai d'expiration de la connexion en millisecondes à partir du pool de connexions http, par défaut 10 000 |
poolingHttpTcpNoDelay | S'il faut activer tpcNoDelay, vrai par défaut |
mpAppContext.getAccessTokenFetcher().updateAccessToken()
, généralement une fois toutes les 1,5 heures, car le délai d'expiration de access_token est de 2 heures.accessTokenStrategyClass=your.package.name.YourAccessTokenStrategy
dans wechat-mp.properties. Voici une stratégie pour accéder à la base de données accesss_token : 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 ();
}
}
Lorsque MpAppContext
est initialisé, ajoutez un écouteur de messages via WechatMpBootstrap
pour recevoir des messages (l'écouteur de messages sera présenté plus tard) :
WechatMpBootstrap bootstrap = new WechatMpBootstrap();
bootstrap.addMsgListener(new TextMessageListener());
bootstrap.addMsgListener(new SubscribeEventListener());
bootstrap.addMsgListener(new UnsubscribeEventListener());
Si vous avez défini une URL de rappel en arrière-plan du compte officiel WeChat, le serveur WeChat enverra une requête GET à cette URL pour vérification. Le développeur doit gérer cette requête dans l'application Web. Voici un exemple de vérification SpringMVC :
@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;
}
}
Après vérification de la demande de rappel, le mode de rappel est effectivement activé. Si l'utilisateur envoie un message au compte officiel, le serveur WeChat enverra une requête POST à l'URL de rappel et transmettra le message à cette URL. Le développeur doit gérer cette demande dans l'application Web. Voici un exemple de SpringMVC. (et l'exemple de vérification précédent d'activation du rappel dans un contrôleur) :
@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;
}
}
Les développeurs peuvent écouter des types spécifiques de messages en héritant space.chensheng.wechatty.common.message.MessageListener
. Voici un exemple d’écoute des SMS envoyés par les utilisateurs :
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 | illustrer |
---|---|
TexteMessage entrant | SMS |
ImageMessage entrant | Message photo |
LienMessage entrant | Aller au message graphique |
EmplacementMessage entrant | Partager des informations de localisation |
ShortVideoInboundMessage | Petit message vidéo |
VidéoMessage entrant | message vidéo |
Message entrant vocal | message vocal |
Message d'événement de clic | Cliquez sur le message du menu normal |
Afficher le message d'événement | Cliquez pour accéder au message du menu de liens |
LocalisationEventMessage | Messages d'événement de localisation |
Abonnez-vous à un message d'événement | Les utilisateurs suivent l'actualité du compte public |
DésabonnementEventMessage | N'oubliez pas de ne plus suivre les messages du compte public |
ScanEventMessage | L'utilisateur scanne le message du code QR |
MassSendJobFinishEventMessage | Rapport de fin d'envoi de message groupé |
information | illustrer |
---|---|
Message de réponse texte | réponse par SMS |
ImageRéponseMessage | Réponse en image |
MusiqueRéponseMessage | réponse musicale |
ActualitésRéponseMessage | Réponse graphique |
Message de réponse vidéo | réponse vidéo |
Message de réponse vocale | Réponse vocale |
Les comptes officiels peuvent envoyer de manière proactive des messages aux utilisateurs, notamment des messages de groupe et des messages du service client. Tous les messages sont envoyés uniformément en utilisant space.chensheng.wechatty.mp.message.MpMessageSender
.
TextMassMessage message = new TextMassMessage();
message.setIsToAll(true);
message.setContent("群发消息测试");
mpAppContext.getMpMessageSender().send(message, 3);
Type de message de groupe | illustrer |
---|---|
Message de masse texte | Texte en masse |
ImageMassMessage | Envoi de groupe d'images |
MpnewsMassMessage | Envoi groupé d'images et de textes dans WeChat |
MpvideoMassMessage | Envoi groupé de vidéos |
Message de masse vocale | Envoi de groupe vocal |
WxcardMassMessage | Distribution massive de cartes et de coupons WeChat |
TextCsMessage message = new TextCsMessage();
message.setToUser("thisIsUserOpenId");
message.setContent("客服消息测试 n 212");
mpAppContext.getMpMessageSender().send(message, 3);
Type de message du service client | illustrer |
---|---|
TexteCsMessage | Service client par SMS |
ImageCsMessage | Service client photo |
MpnewsCsMessage | Service client graphique dans WeChat |
ActualitésCsMessage | Service client graphique externe |
VidéoCsMessage | Service client vidéo |
Message VoixCs | Service client vocal |
WxcardCsMessage | Service client des cartes et bons WeChat |
La gestion du matériel implique principalement le téléchargement, l'interrogation, la modification et la suppression de matériel. Les types de matériel incluent des images, des vidéos, des voix et des graphiques.
Le téléchargement de matériaux s'effectue en exploitant la classe de téléchargement de matériel correspondante. Voici un exemple de téléchargement d'images :
File image = new File("/this/is/image/path.jpg");
ImagePermanentMedia material = new ImagePermanentMedia(mpAppContext, image);
UploadResponse resp = material.upload();
Classe de téléchargement de matériel | illustrer |
---|---|
ImagePermanentMedia | image permanente |
ThumbPermanentMedia | Miniature permanente |
VidéoPermanentMedia | vidéo permanente |
VoixPermanentMedia | voix permanente |
PermanentActualités | Images et textes permanents |
PermanentActualitésImg | Images dans des graphiques permanents |
ImageTemporaryMedia | Photo temporaire |
ThumbTemporaryMedia | Miniature temporaire |
VidéoTemporaireMédias | vidéo temporaire |
VoixTemporaireMedia | Voix temporaire |
L'opération de requête matérielle est effectuée via les classes d'outils space.chensheng.wechatty.mp.material.MaterialQuery
et 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)
L'opération de suppression de matériel est effectuée via la classe d'outils space.chensheng.wechatty.mp.material.MaterialDeleter
.
mpAppContext.getMaterialDeleter().delete(String mediaId)
La génération de codes QR avec des paramètres s'effectue via la classe d'outils space.chensheng.wechatty.mp.account.QRCodeCreator
.
mpAppContext.getQRCodeCreator().createTemporary(int expireSeconds, int sceneId)
mpAppContext.getQRCodeCreator().createPermanent(int sceneId)
mpAppContext.getQRCodeCreator().createPermanent(String sceneStr)
L'interrogation des informations utilisateur est implémentée via UserInfoQuery
.
mpAppConext.getUserInfoQuery().get(String openId)
mpAppContext.getUserInfoQuery().batchGet(List<String> openIds)
L'autorisation des utilisateurs est implémentée via AuthHelper
.
auth access token
via le code du lien d'autorisation : mpAppContext.getAuthHelper().fetchAuthAccessToken(String code)
auth access token
: mpAppContext.getAuthHelper().refreshAuthAccessToken(String refreshAccessToken)
auth access token
: mpAppContext.getAuthHelper().fetchAuthUserInfo(String authAccessToken, String openId)
Ce qui suit est un pseudocode pour l'autorisation de l'utilisateur :
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");
}
L'autorisation jsapi est implémentée via JsapiHelper
.
jsapi ticket
(vous pouvez utiliser des tâches planifiées pour obtenir régulièrement des tickets et les stocker dans la base de données) : mpAppContext.getJsapiHelper().fetchTicket()
mpAppContext.getJsapiHelper().generateSignature(String jsapiTicket, String nonceStr, long timestamp, String url)
Lors de l'initialisation MpAppContext
, appelez enablePayCert()
de WechatMpBootstrap
pour activer le paiement WeChat et configurer les paramètres associés. (Voir le module de configuration pour les paramètres spécifiques)
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)