众所周知,在微信开放平台申请第三方平台成功后,开发完成,需要全网发布,这样其他公众号才可以进行授权,不然只能使用申请第三方平台时自己填写的测试公众号
当需要全网发布的时,微信开放平台会自动化测试,验证通过后才可以发布成功。详见官方文档,会给配置的消息与事件通知的地址发送消息进行测试。
Controller
/**
* 消息与事件接收
* @author yupanpan
* @date 2020/1/10 13:32
* @param request
* @param appid
* @return void
*/
@RequestMapping("/component/{appid}/event")
@ApiOperation("消息与事件接收")
public void eventNotice(HttpServletRequest request, @PathVariable("appid") String appid, HttpServletResponse response) throws AesException, IOException {
boolean eventNotice = wechatOpenPlatformThirdPartyService.eventNotice(request, appid, response);
if(eventNotice){
WXBizMsgCrypt pc = new WXBizMsgCrypt(ApplicationPropertiesUtils.getWechatOpenThirdpartyVerifyToken(), ApplicationPropertiesUtils.getWechatOpenThirdpartyEncodingKey(),
ApplicationPropertiesUtils.getWechatOpenThirdpartyAppid());
String replyMsg = pc.encryptMsg("", System.currentTimeMillis() + "",
WxUtil.generateNonceStr());//加密回复
PrintWriter writer = response.getWriter();
writer.write(replyMsg);
writer.flush();
}
}
WXBizMsgCrypt由官方提供的,
ApplicationPropertiesUtils.getWechatOpenThirdpartyVerifyToken() 对应消息校验Token
ApplicationPropertiesUtils.getWechatOpenThirdpartyEncodingKey() 对应消息加解密Key
ApplicationPropertiesUtils.getWechatOpenThirdpartyAppid() 对应第三方平台的Appid,审核通过后会有
Service
@Override
@Transactional
public boolean eventNotice(HttpServletRequest request, String appid, HttpServletResponse response){
try {
Map<String, String> mapData = getMapData(request, verifyToken, encodingKey, appId);
return this.subscribeEvent(request,mapData,appid,response);
}catch (Exception e){
logger.error("第三方消息与事件推送异常",e);
return false;
}
}
@Override
@Transactional
public boolean subscribeEvent(HttpServletRequest request,Map<String, String> mapData,String appid,HttpServletResponse response) throws Exception {
synchronized(this){
logger.info("解密后内容====>>>>{}",mapData.toString());
String event = mapData.get(WxConstant.WX_CARD_EVENT);
String openId = mapData.get("fromUserName");
String devWechatNumber = mapData.get("toUserName");
logger.info("======>>>openId:{}", openId);
if(WechatConstants.Event.SUBSCRIBE.getCodeType().equals(event)||WechatConstants.Event.SCAN.getCodeType().equals(event)) {
//扫码关注
String eventKey = mapData.get("eventKey");
logger.info("eventKey:{}", eventKey);
if (StringUtils.isNotBlank(eventKey)) {
//第一次关注会有qrscene_前缀,已关注再扫码直接跳进公众号,没有qrscene_前缀
if(eventKey.contains("qrscene_")){
eventKey= eventKey.replace("qrscene_", "");
}
if(eventKey.contains("&")){
String[] scene_str = eventKey.split("&");
//解密扫码参数,证明是由自己第三方平台发出的二维码关注通知,非自己第三方平台的事件不做处理
if(WechatConstants.ARTSTEP.equals(AESUtils.AESDncode(null,scene_str[1]))){
Long studentId = Long.valueOf(scene_str[0]);
if(studentId!=null){
logger.info("======>>>studentId:{}", studentId);
//新增或更新微信相关信息
this.saveStudentWechatOpenInfo(studentId, openId, appid);
//禁用旧版本的微信绑定关系通知
this.inActiveParentWechat(studentId, openId, appid);
}
}
}
} else {
//非扫码关注
}
return true;
}
//取消关注,删除绑定者所有微信隐私信息
if(WechatConstants.Event.UN_SUBSCRIBE.getCodeType().equals(event)){
logger.info("openId[{}],appId[{}]解绑",openId,appid);
studentWechatOpenInfoDao.deleteByOpenIdAndAppId(openId,appid);
return true;
}
//全网发布自动化测试公众号
if(appid.equals("wx570bc396a51b8ff8")){
logger.info("第三方平台测试公众号接受event====>>>>{}",event);
if(WechatConstants.Event.TEXT.getCodeType().equals(event)){
String content = mapData.get("content");
processTextMessage(request, response, content, openId, devWechatNumber,appid);
}
if(WechatConstants.Event.EVENT.getCodeType().equals(event)){// 返回类型值,做一下区分
//返回时, 将发送人和接收人 调换一下即可
replyEventMessage(request,response,event,openId,devWechatNumber);
}
return false;
}
return true;
}
}
只需要关注全网发布自动化测试那里的代码即可
/**
* 方法描述: 直接返回给微信开放平台
* @param request
* @param response
* @param content 文本
* @param openId 发送接收人
* @param devWechatNumber 发送人
*/
private void replyTextMessage(HttpServletRequest request, HttpServletResponse response,
String content,String openId, String devWechatNumber) throws Exception {
Long createTime = System.currentTimeMillis() / 1000;
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
sb.append("<ToUserName><![CDATA[" + openId + "]]></ToUserName>");
sb.append("<FromUserName><![CDATA[" + devWechatNumber + "]]></FromUserName>");
sb.append("<CreateTime>" + createTime + "</CreateTime>");
sb.append("<MsgType><![CDATA[text]]></MsgType>");
sb.append("<Content><![CDATA[" + content + "]]></Content>");
sb.append("</xml>");
logger.info("发送的XML明文为====>>>>"+sb.toString());
WXBizMsgCrypt pc = new WXBizMsgCrypt(verifyToken, encodingKey,
appId);
String replyMsg = pc.encryptMsg(sb.toString(), System.currentTimeMillis() + "",
WxUtil.generateNonceStr());//加密回复
logger.info("确定发送的XML====>>>>"+replyMsg);
PrintWriter writer = response.getWriter();
writer.write(replyMsg);
writer.flush();
}
/**
* 方法描述: 类型为enevt的时候,拼接
* @param request
* @param response
* @param event
* @param openId 发送接收人
* @param devWechatNumber 发送人
*/
public void replyEventMessage(HttpServletRequest request, HttpServletResponse response,
String event, String openId, String devWechatNumber)
throws Exception {
String content = event + "from_callback";
replyTextMessage(request,response,content,openId,devWechatNumber);
}
/**
* 方法描述: 立马回应文本消息并最终触达粉丝
* @param content 文本
* @param openId 发送接收人
* @param devWechatNumber 发送人
*/
public void processTextMessage(HttpServletRequest request, HttpServletResponse response,
String content,String openId, String devWechatNumber,String appid)
throws Exception{
if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){
String returnContent = content+"_callback";
replyTextMessage(request,response,returnContent,openId,devWechatNumber);
}else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){
response.getWriter().print("");//需在5秒内返回空串表明暂时不回复,然后再立即使用客服消息接口发送消息回复粉丝
logger.info("content:"+content+" content[1]:"+content.split(":")[1]+" fromUserName:"+devWechatNumber+" toUserName:"+openId);
//接下来客服API再回复一次消息
//此时 content字符的内容为是 QUERY_AUTH_CODE:adsg5qe4q35
replyApiTextMessage(content.split(":")[1],openId,appid);
}
}
/**
* 方法描述: 直接返回给微信开放平台
* @param request
* @param response
* @param content 文本
* @param toUserName 发送接收人
* @param fromUserName 发送人
public void replyTextMessage(HttpServletRequest request, HttpServletResponse response,
String content,String toUserName, String fromUserName)
throws DocumentException, IOException {
Long createTime = System.currentTimeMillis() / 1000;
StringBuffer sb = new StringBuffer(512);
sb.append("<xml>");
sb.append("<ToUserName><![CDATA["+toUserName+"]]></ToUserName>");
sb.append("<FromUserName><![CDATA["+fromUserName+"]]></FromUserName>");
sb.append("<CreateTime>"+createTime.toString()+"</CreateTime>");
sb.append("<MsgType><![CDATA[text]]></MsgType>");
sb.append("<Content><![CDATA["+content+"]]></Content>");
sb.append("</xml>");
String replyMsg = sb.toString();
logger.info("确定发送的XML为:"+replyMsg);
returnJSON(replyMsg,response);
}
*/
/**
* 方法描述: 调用客服回复消息给粉丝
* @param auth_code
* @param openId
* @throws DocumentException
* @throws IOException
* @return void
*/
public void replyApiTextMessage(String auth_code, String openId,String appid) throws Exception {
// 得到微信授权成功的消息后,应该立刻进行处理!!相关信息只会在首次授权的时候推送过来
String componentAccessToken= WechatCache.getThirdPartyAuthorizerAccessToken();//本人平台缓存的token
//https://api.weixin.qq.com/cgi-bin/component/api_query_auth 到这个微信的接口去获取数据
ThirdPartyAuthInfo thirdPartyAuthInfo = thirdPartyAuthInfoDao.findBySchoolIdAndAppId(appid);
String authorizer_access_token = thirdPartyAuthInfo.getAuthorizerAccessToken();
String result = checkCustomMessage(authorizer_access_token, openId, auth_code);
if(result.contains("40001")){
String testAuthorizerAccessToken = getTestAuthorizerAccessToken(appid);
checkCustomMessage(testAuthorizerAccessToken, appid, auth_code);
}
}
private String checkCustomMessage(String authorizer_access_token,String openId,String auth_code) throws Exception{
String url = WechatConstants.MESSAGE_CUSTOM_SEND.replace("AUTHORIZER_ACCESS_TOKEN",authorizer_access_token);
JSONObject json = new JSONObject();
json.put("touser",openId);
json.put("msgtype", "text");
json.put("text", "{\"content\":\""+auth_code+"_from_api"+"\"}");
String result = HTTPUtils.sendPost(url, json.toJSONString());
logger.info("客服发送接口返回值:"+result);
return result;
}
来源:CSDN
作者:ypp91zr
链接:https://blog.csdn.net/ypp91zr/article/details/104052923