微信开放平台全网发布

来源:互联网 发布:重装系统无法安装软件 编辑:程序博客网 时间:2024/05/15 07:15

最近刚做了微信开放平台全网发布的开发,整理一下贴出来


前置条件 已经做好了相关的开发工作(比如扫码授权之类的),项目导入了微信SDK(最后会附上我自己用的SDK jar包)


sdk jar 地址: https://github.com/liyiorg/weixin-popular   

BUG :weixin.popular.bean.message.EventMessage 内的@XmlElement(name = "MsgID") private String msgId; // 消息ID号 红色处原来D是小写,应该是大写,不知道现在改了没有,自己注意


 platformToken:你要全网发布的开放平台填写的token,  platformAESKey:你要全网发布的开放平台填写的加密秘钥,  platformAppId:你要全网发布的开放平台的appId


/** * 功能描述:扫码授权,第三方开放平台每10分钟推送一次component_verify_ticket接受处理方法,这是controller * @author yanfei.li * @date 2017年9月26日 下午3:42:24   * @param request * @param response * @return "success" * @throws BusinessException */@RequestMapping(value = "/platform/event/receive")@ResponseBodypublic String receiver(HttpServletRequest request, HttpServletResponse response) throws BusinessException{  try {ServletInputStream inputStream = request.getInputStream();if (inputStream != null) {String xmlData = StreamUtils.copyToString(inputStream,Charset.forName("utf-8"));String timestamp = request.getParameter("timestamp");String nonce = request.getParameter("nonce");String msgSignature = request.getParameter("msg_signature");//解密,platformToken:你要全网发布的开放平台填写的token,  platformAESKey:你要全网发布的开放平台填写的加密秘钥,  platformAppId:你要全网发布的开放平台的appIdWXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(platformToken, platformAESKey, platformAppId);xmlData = wxBizMsgCrypt.decryptMsg(msgSignature, timestamp, nonce, xmlData);//下面是将component_verify_ticket 信息保存到自己的数据库,这一块应该是调用service再调用dao的,为了方便整合到一起了,自己拆分。//转换成map,XMLConverUtil是微信SDK的工具Map<String,String> xmlMap=XMLConverUtil.convertToMap(xmlData);String appId = xmlMap.get("AppId");String componentVerifyTicket = xmlMap.get("ComponentVerifyTicket");Date createTime = new Date(Long.parseLong(xmlMap.get("CreateTime"))*1000);String infoType = xmlMap.get("InfoType");String authorizerAppid = xmlMap.get("AuthorizerAppid");String authCode = xmlMap.get("AuthorizationCode");String authCodeExpiredTime = xmlMap.get("AuthorizationCodeExpiredTime");//数据库表实体初始化WechatVerifyTicketEntity verifyticket = null;verifyticket = verifyticketDao.findOne(appId, infoType);if(verifyticket == null ) {verifyticket = new WechatVerifyTicketEntity();}verifyticket.setAppId(appId);verifyticket.setCreateTime(createTime);verifyticket.setInfoType(infoType);verifyticket.setAuthorizerAppid(authorizerAppid);verifyticket.setAuthCode(authCode);verifyticket.setAuthCodeExpiredTime(authCodeExpiredTime);verifyticket.setVerifyTicket(componentVerifyTicket);//保存到数据库this.verifyticketDao.saveOrUpdate(verifyticket);}} catch (IOException | AesException e) {logger.error("/wxopen/platform/event/receive error: ", e);} //不管出没出错,都返回了success,出错信息自己查自己的日志return "success";}


消息与事件推送受理入口


/** * 功能描述:微信消息与事件推送 接受处理方法入口 * @author yanfei.li * @date 2017年9月26日 下午3:44:29   * @param appid 公众号appid * @param request * @param response * @throws BusinessException */@RequestMapping(value = "/platform/callback/{appid}")@ResponseBodypublic void callback(@PathVariable("appid") String appid, HttpServletRequest request, HttpServletResponse response) throws BusinessException{  try{ServletInputStream inputStream = request.getInputStream();if (inputStream != null) {//StreamUtils 微信SDK的工具类String xmlData = StreamUtils.copyToString(inputStream,Charset.forName("utf-8"));inputStream.close();String timestamp = request.getParameter("timestamp");String nonce = request.getParameter("nonce");String msgSignature = request.getParameter("msg_signature");//解密WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(platformToken, platformAESKey, platformAppId);xmlData = wxBizMsgCrypt.decryptMsg(msgSignature, timestamp, nonce, xmlData);logger.info("==>receiveData=" + xmlData );EventMessage eventMessage = null;eventMessage = XMLConverUtil.convertToObject(EventMessage.class, xmlData);if("wx570bc396a51b8ff8".equals(appid)){//全网发布,wx570bc396a51b8ff8是固定的微信全网发布测试公众号appidpublishThirdPlatform(eventMessage, request, response);}else {//正常业务处理normalBusiness(appid, eventMessage, request, response);}}else {responseReplyMessage(response,"success");}}catch(Exception e){logger.error("/wxopen/platform/callback/" + appid + " error: ", e);if(!(e instanceof IOException)){try {responseReplyMessage(response,"success");} catch (IOException e1) {logger.error("/wxopen/platform/callback/" + appid + " return error: ", e1);}}else {logger.error("IOException");}}}


全网发布相关处理函数


/** * 功能描述:全网发布主函数处理入口 * @author yanfei.li * @date 2017年9月26日 下午3:41:22   * @param eventMessage * @param request * @param response * @throws IOException * @throws AesException  */private void publishThirdPlatform(EventMessage eventMessage,HttpServletRequest request, HttpServletResponse response) throws IOException, AesException{String event = eventMessage.getMsgType();if("event".equals(event)){replyEventMessage(request, response,eventMessage);}else if ("text".equals(eventMessage.getMsgType())) {replyTextMessage(request, response, eventMessage);}}/** * 功能描述:全网发布,步骤二、三 回复文本消息 * @author yanfei.li * @date 2017年9月26日 下午4:10:56   * @param request * @param response * @param eventMessage * @throws BusinessException  * @throws IOException  */private void replyTextMessage(HttpServletRequest request, HttpServletResponse response, EventMessage eventMessage) throws BusinessException, IOException{if(eventMessage == null){throw new BusinessException(BusinessException.ERROR_INTERNAL_SERVER_ERROR, "==>replyTextMessage,eventMessage is null");}String content = eventMessage.getContent();if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){//步骤二,回复文本消息content = content + "_callback";StringBuffer sb = new StringBuffer();          sb.append("<xml>");          sb.append("<ToUserName><![CDATA["+eventMessage.getFromUserName()+"]]></ToUserName>");          sb.append("<FromUserName><![CDATA["+eventMessage.getToUserName()+"]]></FromUserName>");          sb.append("<CreateTime>"+eventMessage.getCreateTime()+"</CreateTime>");          sb.append("<MsgType><![CDATA[text]]></MsgType>");          sb.append("<Content><![CDATA["+content+"]]></Content>");        sb.append("</xml>");          String replyMsg = sb.toString();        String returnValue = "";WXBizMsgCrypt pc;try {//platformToken:你要全网发布的开放平台填写的token,  platformAESKey:你要全网发布的开放平台填写的加密秘钥,  platformAppId:你要全网发布的开放平台的appIdpc = new WXBizMsgCrypt(platformToken, platformAESKey, platformAppId);returnValue = pc.encryptMsg(replyMsg, eventMessage.getCreateTime().toString(), request.getParameter("nonce"));        responseReplyMessage(response,returnValue);} catch (AesException e) {throw new BusinessException(BusinessException.ERROR_INTERNAL_SERVER_ERROR, "replyTextMessage",e);}        }else {//步骤三,回复空字符串,然后调用客服接口发送消息String touser = eventMessage.getFromUserName();//因为是往回发,所有接收人是消息发送人,容易写错String authCode = content.replaceAll("QUERY_AUTH_CODE:", "");//authcode 用于“使用授权码换取公众号的授权信息”API,将$query_auth_code$的值赋值给API所需的参数authorization_code获取接口调用凭证。try {//直接回复""字符串responseReplyMessage(response,"");} catch (IOException e) {throw new BusinessException(BusinessException.ERROR_INTERNAL_SERVER_ERROR, "replyTextMessage",e);}//调用客服接口发送消息//获取测试公众号接口调用凭证,接口方法实现 见最后同名方法String authorizerAccessToken = this.wechatTokenService.publishGetToken(authCode);if(authorizerAccessToken == null){throw new BusinessException(BusinessException.ERROR_INTERNAL_SERVER_ERROR, "==>get authorizer access token failure,value is null");}//Message TextMessage是微信SDK的Message message = new TextMessage(touser,authCode+"_from_api");//发送客服消息weixin.popular.api.MessageAPI.messageCustomSend(token,JSON.toJSONString(message));}}/** * 功能描述:全网发布,步骤一回复事件消息 * @author yanfei.li * @date 2017年9月26日 下午4:34:14   * @param request * @param response * @param eventMessage * @throws IOException * @throws AesException  */private void replyEventMessage(HttpServletRequest request, HttpServletResponse response, EventMessage eventMessage) throws BusinessException, IOException{if(eventMessage == null){throw new BusinessException(BusinessException.ERROR_INTERNAL_SERVER_ERROR, "==>replyEvetMessage,eventMessage is null");}String content = eventMessage.getEvent() + "from_callback";StringBuffer sb = new StringBuffer();        sb.append("<xml>");          sb.append("<ToUserName><![CDATA["+eventMessage.getFromUserName()+"]]></ToUserName>");          sb.append("<FromUserName><![CDATA["+eventMessage.getToUserName()+"]]></FromUserName>");          sb.append("<CreateTime>"+eventMessage.getCreateTime()+"</CreateTime>");          sb.append("<MsgType><![CDATA[text]]></MsgType>");          sb.append("<Content><![CDATA["+content+"]]></Content>");          sb.append("</xml>");          String replyMsg = sb.toString(); String returnValue = "";WXBizMsgCrypt pc;try {//platformToken:你要全网发布的开放平台填写的token,  platformAESKey:你要全网发布的开放平台填写的加密秘钥,  platformAppId:你要全网发布的开放平台的appIdpc = new WXBizMsgCrypt(platformToken, platformAESKey, platformAppId);returnValue = pc.encryptMsg(replyMsg, eventMessage.getCreateTime().toString(), request.getParameter("nonce"));        responseReplyMessage(response,returnValue);} catch (AesException e) {throw new BusinessException(BusinessException.ERROR_INTERNAL_SERVER_ERROR, "replyEventMessage",e);}}    /**     * 统一回复微信服务器          * @param response     * @param content     * @throws IOException     */    public void responseReplyMessage(HttpServletResponse response,String content) throws IOException{        PrintWriter pw = response.getWriter();        pw.write(content);        pw.flush();        pw.close();    } /** * 功能描述:获取access_token * @author yanfei.li * @date 2017年9月27日 下午2:18:24   * @param authCode * @return */    public String publishGetToken(String authCode) {if(authCode == null){logger.error("================>publishGetToken,authCode is null");return null;}//获取每十分钟推送一次的那个ticket, platformAppId:你要全网发布的开放平台的appIdString verifyTicket = this.verifyticketDao.getRecentTicket(platformAppId);if(verifyTicket == null){logger.error("================>publishGetToken,verifyTicket is null");return null;}//获取开放平台access_token,appSecret:你要全网发布的开放平台的appsecret,  appId:你要全网发布的开放平台的appIdComponentAccessToken accessToken = weixin.popular.api.ComponentAPI.api_component_token(appId, appSecret, verifyTicket);if(accessToken == null){logger.error("================>publishGetToken,accessToken is null");return null;}String accessTokenStr = accessToken.getComponent_access_token();ApiQueryAuthResult queryAuth = weixin.popular.api.ComponentAPI.api_query_auth(accessToken, appId, authCode);if(queryAuth == null){logger.error("================>publishGetToken,queryAuth is null");return null;}return queryAuth.getAuthorization_info().getAuthorizer_access_token();}


结合微信SDK工具包  实现的。请忽略日志打印,不能直接复制使用,另外正常的业务处理分支没有贴出来,只贴了全网发布的。消息推送入口对全网发布和正常业务处理做了分流处理,不影响原本的项目


全网发布,开放平台注意事项

1.公众号的IP白名单只针对通过公众号的appid和secret获取access_token时有效(直接通过api接口调用https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxx&secret=xxx),如果是通过扫码授权即微信开放平台则IP白名单无效(个人推测微信开放平台在所有微信公众号的默认白名单内),最好配置IP白名单,这样在appid和secret泄露后还有一层保护,因为IP白名单的修改需要管理员扫码确认,不能直接通过这俩值获取token


2.微信开放平台全网发布前,只接受授权测试公众号列表内的授权,一旦全网发布后会支持所有微信公众的授权。IP白名单配置的是访问开放平台的服务器的IP地址,发布不发布都需要,否则会报错


3.开放平台IP白名单的修改没有在发布的范畴内,可随时更改


4.调用开放平台接口所需要的appId和secret是对应开放平台应用的,跟公众号没有关系


5.授权事件接受URL主要是每十分钟推送一次component_verify_ticket,该值用户获取开放平台的接口调用凭证的参数之一


6.开放平台的公众号消息校验Token和加解密Key可以自己定义,但一定要和我们开发配置中保持对应一致


7.公众号消息与事件接受URL会将粉丝跟公众号的互动推送到该URL,%APPID%是当前公众号的APPID


8.已经发布的开放平台内容可以更改,更改完了还需要进行一次全网发布,会有一个覆盖现有发布,需要审核,审核完成之前将继续使用上次发布的内容









阅读全文
0 0
原创粉丝点击