[置顶] 微信开放平台的第三方平台、全网发布流程、组件API、返回普通文本消息
2015-09-07 16:05
831 查看
微信开放平台的第三方平台全网发布流程
1、在这里先吐槽一下微信的开放平台的全网发布流程文档。说实话:这个文档写的是真的不咋地!
(1)、公众号消息校验Token、公众号消息加解密Key、公众号消息与事件接收URL、网页开发域名.
这些信息都需要在微信开放平台设置
(2) 、 加密、解密的 代码在微信开放平台文档里面都有,自己下载即可.
2、啥也不说了,直接上代码:
3、容易出错的点:
(1)、组件API: 记住这地方,要去重新获取authorizer_access_token值,发送消息的人,必须是自己,别弄错了,不然返回错误码4***3
(2)、返回普通文本消息的时候,千万别加密那个XML的字符串,加密就报错.
(3)、还有一个就是,全网发布的时候,要将自己的外网IP填写在 白名单里面,不然获取token会失败报错 61004
(4)、如果几次的测试都通过的情况下,突然有一天或者一段时间 客服发送接口返回值 出现48001,提示api没有权限,那估计就是腾讯的服务器八成挂了,耐心的等待吧!
4、本文档截稿日期为
2015-09-07, 请距此时间过久的朋友阅读时,具体以微信开放平台官方文档为主! 此处仅供参考
1、在这里先吐槽一下微信的开放平台的全网发布流程文档。说实话:这个文档写的是真的不咋地!
(1)、公众号消息校验Token、公众号消息加解密Key、公众号消息与事件接收URL、网页开发域名.
这些信息都需要在微信开放平台设置
(2) 、 加密、解密的 代码在微信开放平台文档里面都有,自己下载即可.
2、啥也不说了,直接上代码:
import java.io.BufferedReader; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.rubyeye.xmemcached.MemcachedClient; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.map.ObjectMapper; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.weixin.core.aes.AesException; import com.weixin.core.aes.WXBizMsgCrypt; import com.weixin.scm.auth.model.PlatformParam; import com.weixin.scm.auth.service.PlatformParamService; import com.weixin.support.api.ProxyInterfaceApi; import com.weixin.support.model.component.AuthorizationInfo; import com.weixin.support.model.component.MpAuthorization; import com.weixin.support.service.WxConfigStorageService; import com.weixin.util.HttpClientCommonSSL; /** * <p>ClassName: 测试微信 全网检测 </p> * <p>Description: 检测通过后 才能进行全网发布 </p> * @author Andy 2015年8月31日 */ @Controller @RequestMapping(value = "/weixinOpenCheck") public class WeixinOpenCheckController { private static final Log log = LogFactory.getLog(WeixinOpenCheckController.class); @Autowired private WxConfigStorageService wxConfigStorageService; @Autowired private PlatformParamService platformParamService; @Autowired private MemcachedClient memcachedClient; @ResponseBody @RequestMapping(value = "{appid}/callback", method = RequestMethod.POST) public void acceptMessageAndEvent(HttpServletRequest request, HttpServletResponse response ,@PathVariable(value = "appid") String appId)//springMVC 获取地址里面的参数信息 throws IOException, AesException, DocumentException { log.info("进入全网发布流程================================================================================="); String nonce = request.getParameter("nonce"); String timestamp = request.getParameter("timestamp"); String msgSignature = request.getParameter("msg_signature"); log.info("读取数据为:"+"msg_signature="+msgSignature+", timestamp="+timestamp+", nonce="+nonce+", appid="+appId); if (!StringUtils.isNotBlank(msgSignature)) return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息 StringBuilder sb = new StringBuilder(); BufferedReader in = request.getReader(); String line; while ((line = in.readLine()) != null) { sb.append(line); } in.close(); String xml = sb.toString(); //将xml变成字符串 log.info("读取的XML为:"+xml); if (appId.equals("wx570bc396a51b8ff8")){// 微信自动化测试的专用测试公众账号 PlatformParam component = platformParamService.selectPlatformParam();//获取 平台ID WXBizMsgCrypt pc = new WXBizMsgCrypt(component.getToken(),component.getSymmetricKey(), component.getComponentAppId()); log.info("加解密======================================"); try { xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml);//将xml进行加密后,和sign签名码进行对比,如果正确则返回xml log.info("解密后:"+xml); Document doc = DocumentHelper.parseText(xml); Element rootElt = doc.getRootElement(); String msgType = rootElt.elementText("MsgType"); String toUserName = rootElt.elementText("ToUserName"); String fromUserName = rootElt.elementText("FromUserName"); if(msgType.equals("event")){// 返回类型值,做一下区分 String event = rootElt.elementText("Event"); //返回时, 将发送人和接收人 调换一下即可 replyEventMessage(request,response,event,fromUserName,toUserName); } if(msgType.equals("text")){ //标示文本消息, String content = rootElt.elementText("Content"); //返回时, 将发送人和接收人 调换一下即可 processTextMessage(request,response,content,fromUserName,toUserName);//用文本消息去拼接字符串。微信规定 } } catch (AesException e) { log.error("错误码为: "+e.getCode()); log.error("错误信息为: "+e.getMessage()); //应该做容错处理 } }else{ log.info("appid="+appId+",正确的值为:wx570bc396a51b8ff8"); log.info("检测不是微信开放平台测试账号,发布程序终止."); } } /** * 方法描述: 类型为enevt的时候,拼接 * @param request * @param response * @param event * @param toUserName 发送接收人 * @param fromUserName 发送人 * @author Andy 2015年9月1日 下午2:16:26 */ public void replyEventMessage(HttpServletRequest request, HttpServletResponse response, String event, String toUserName, String fromUserName) throws DocumentException, IOException { String content = event + "from_callback"; replyTextMessage(request,response,content,toUserName,fromUserName); } /** * 方法描述: 立马回应文本消息并最终触达粉丝 * @param content 文本 * @param toUserName 发送接收人 * @param fromUserName 发送人 * @author Andy 2015年8月31日 下午6:24:38 */ public void processTextMessage(HttpServletRequest request, HttpServletResponse response, String content,String toUserName, String fromUserName) throws IOException, DocumentException{ if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){ String returnContent = content+"_callback"; replyTextMessage(request,response,returnContent,toUserName,fromUserName); }else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){ response.getWriter().print("");//需在5秒内返回空串表明暂时不回复,然后再立即使用客服消息接口发送消息回复粉丝 log.info("content:"+content+" content[1]:"+content.split(":")[1]+" fromUserName:"+fromUserName+" toUserName:"+toUserName); //接下来客服API再回复一次消息 //此时 content字符的内容为是 QUERY_AUTH_CODE:adsg5qe4q35 replyApiTextMessage(content.split(":")[1],toUserName); } } /** * 方法描述: 直接返回给微信开放平台 * @param request * @param response * @param content 文本 * @param toUserName 发送接收人 * @param fromUserName 发送人 * @author Andy 2015年9月1日 下午2:15:40 */ 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(); log.info("确定发送的XML为:"+replyMsg);//千万别加密 returnJSON(replyMsg,response); } /** * 方法描述: 调用客服回复消息给粉丝 * @param auth_code * @param fromUserName * @throws DocumentException * @throws IOException * @return void * @author Andy 2015年9月7日 上午9:48:01 */ public void replyApiTextMessage(String auth_code, String fromUserName) throws DocumentException, IOException { // 得到微信授权成功的消息后,应该立刻进行处理!!相关信息只会在首次授权的时候推送过来 String componentAccessToken= wxConfigStorageService.getComponentAccessToken();//本人平台缓存的token PlatformParam component = platformParamService.selectPlatformParam();//获取 平台ID //https://api.weixin.qq.com/cgi-bin/component/api_query_auth 到这个微信的接口去获取数据 MpAuthorization m=ProxyInterfaceApi.getInstance().mpAuthorization(componentAccessToken, component.getComponentAppId(),auth_code); AuthorizationInfo info=m.getAuthorization_info(); String authorizer_access_token = info.getAuthorizer_access_token(); String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+authorizer_access_token; JSONObject json = new JSONObject(); json.put("touser",fromUserName); json.put("msgtype", "text"); json.put("text", "{\"content\":\""+auth_code+"_from_api"+"\"}"); String result = HttpClientCommonSSL.commonPostStream(url, json.toString()); log.info("客服发送接口返回值:"+result); } /** * 方法描述: 返回数据到请求方 * @param data 数据 * @param response * @author Andy 2015年9月1日 下午1:06:54 */ public void returnJSON(Object data,HttpServletResponse response) { try { ObjectMapper objectMapper = new ObjectMapper(); JsonEncoding encoding = JsonEncoding.UTF8; response.setContentType("application/json"); org.codehaus.jackson.JsonGenerator generator = objectMapper.getJsonFactory(). createJsonGenerator(response.getOutputStream(), encoding); objectMapper.writeValue(generator, data); } catch (IOException e) { e.printStackTrace(); } } /** * 方法描述: * @param args * @return void * @author Andy 2015年8月31日 下午5:31:07 */ public static void main(String[] args) { JSONObject j=new JSONObject(); j.put("content", "aaa"+"_from_api"); System.out.println(j.toString()); System.out.println("{\"content\":\"好的_from_api\"}"); } }
3、容易出错的点:
(1)、组件API: 记住这地方,要去重新获取authorizer_access_token值,发送消息的人,必须是自己,别弄错了,不然返回错误码4***3
(2)、返回普通文本消息的时候,千万别加密那个XML的字符串,加密就报错.
(3)、还有一个就是,全网发布的时候,要将自己的外网IP填写在 白名单里面,不然获取token会失败报错 61004
(4)、如果几次的测试都通过的情况下,突然有一天或者一段时间 客服发送接口返回值 出现48001,提示api没有权限,那估计就是腾讯的服务器八成挂了,耐心的等待吧!
4、本文档截稿日期为
2015-09-07, 请距此时间过久的朋友阅读时,具体以微信开放平台官方文档为主! 此处仅供参考
相关文章推荐
- 模仿QQ、微信表情输入框
- 支付宝支付与微信支付服务端回调notify_url数据的区别
- 微信开发之图灵机器人 e19a
- 微信公众号:搭建新浪SAE服务器,遇到token验证失败的问题
- 微信公众号支付(一):获取用户openId
- 微信常用JS接口调用指南
- 【chrome插件】web版微信接入图灵机器人API实现自动回复
- 微信降权微商刷屏,暴力刷屏的时代已经全面过去
- android 自定义相册 像微信相册一样的形式
- 微信客户端解决众包资料的收集和分发
- 微信公众平台的后台开发流程(一)
- 仿微信界面滑动(9.7)
- 微信分享
- 上线10天 来看看微信读书中的“匠心”
- 【技术】悬浮微信二维码微博分享置顶
- 微信公众平台所带来的互动式营销
- 零java基础搞定微信Server_4:写一个servlet的demo
- 如何判断不是微信内置浏览器
- Java内部类小程序(成员内部类,静态内部类,匿名内部类)
- 微信开发关闭当前网页跳到公众号主界面