微信公众平台与手机的交互

一,用户与服务器间消息交互流程

用户在手机端向公众账号发送一条消息,并收到回复的消息,这个动作的处理过程是怎样的?

接收消息:用户向公众账号发送消息,此时微信服务器接收到消息,并将消息的xml数据包发送到开发者填写的接口配置URL上;

发送消息:对于每一个POST请求,开发者在响应包(Get)中返回特定XML结构,对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。

交互流程:

(1)用户通过微信客户端向公众账号发送消息,消息首先会被微信服务器接收到;

(2)微信服务器接收到消息后,会根据开发者在接口配置信息中填写的URL,将信息通过HTTP
POST方式传递到公众账号服务器;

(3)公众账号服务器接收到消息后,会按照业务逻辑进行相应的处理;

(4)处理完成后,公众账号服务器会将处理结果返回给微信服务器;

(5)微信服务器将公众账号服务器返回的消息通过公众账号发送给用户;

注:在真个消息交互过程中,公众账号服务器需要做:(1)接收微信服务器器发送来的消息;(2)根据指定的业务逻辑对消息进行处理;(3)将处理结果返回给微信服务器。

二,消息的分类

微信服务器与公众账号服务器交互的消息分2类:

(1)接收消息:指用户发送给公众账号的消息

a:接收普通消息:有6种类型:文本消息、图片消息、语音消息、视频消息、地理位置消息、链接消息;

b:接收事件推送:

(2)事件:指用户对公众账号做出某种操作时,微信服务器会将对应的事件推送给公众账号服务器。有6种类型:关注/取消关注事件、扫描带参数二维码事件、上报地理位置事件、自定义菜单事件、点击菜单拉取消息时的事件推送、点击菜单跳转链接时的事件推送;

(3)发送消息:指公众账号回复给用户的消息。有6种类型:文本消息、图片消息、语音消息、视频消息、音乐消息、图文消息;

三,实例

 package org.liufeng.course.service;

import javax.servlet.http.HttpServlet;

/**
 * 请求处理的核心类 
 * 
 * @author liufeng
 * @date 2013-09-29
 */
public class CoreServlet extends HttpServlet {
   /**
   * 请求校验与处理
   */
   public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

/*********************企业号。。。。Start。。。。*********************************************************************************/                
     // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
      request.setCharacterEncoding("UTF-8");
      response.setCharacterEncoding("UTF-8");

       // 微信加密签名 
        String msg_signature =request.getParameter("msg_signature"); 
        // 时间戳 
        String timestamp =request.getParameter("timestamp"); 
        // 随机数 
        String nonce =request.getParameter("nonce");
 
        //从请求中读取整个post数据  
        InputStream inputStream =request.getInputStream(); 
        String postData =IOUtils.toString(inputStream, "UTF-8"); 
        System.out.println(postData); 
       
        String msg = ""; 
        WXBizMsgCrypt wxcpt = null; 
        try { 
            wxcpt = new WXBizMsgCrypt(sToken ,sEncodingAESKey , sCorpID ); 
            //解密消息 
            msg =wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData); 
        } catch (AesException e) { 
            e.printStackTrace();  
        } 
        System.out.println("msg=" +msg);  
        //调用核心服务类接收处理请求
        String respXml = CoreService.processRequest(msg);//调用核心业务类
       // 响应消息  
       PrintWriter out = response.getWriter(); 
       out.print(encryptMsg);  
       out.close(); 
    } 
}
public class CoreService {
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> *处理微信发来的请求——企业号 韩学敏
<span style="white-space:pre">	</span> *
<span style="white-space:pre">	</span> * @param request
<span style="white-space:pre">	</span> * @return xml
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>public static String processRequest(String msg) {
<span style="white-space:pre">	</span>//xml格式的消息数据
<span style="white-space:pre">	</span>StringrespXml = null;
<span style="white-space:pre">	</span>//默认返回的文本消息内容
<span style="white-space:pre">	</span>String respContent = "";
<span style="white-space:pre">	</span>try{
<span style="white-space:pre">	</span>// 调用parseXml方法解析请求消息
<span style="white-space:pre">	</span>Map<String,String> requestMap = MessageUtil.parseXml(msg);
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>// 发送方帐号
<span style="white-space:pre">	</span>String fromUserId = requestMap.get("FromUserName");
<span style="white-space:pre">	</span>// 公众帐号 
<span style="white-space:pre">	</span>String toUserName = requestMap.get("ToUserName");
<span style="white-space:pre">	</span>// 消息类型
<span style="white-space:pre">	</span>String msgType = requestMap.get("MsgType");
<span style="white-space:pre">	</span>//获取企业应用Id
<span style="white-space:pre">	</span>String agentId = requestMap.get("AgentID");
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>// 获取接口访问凭证
<span style="white-space:pre">	</span>String accessToken =CommonUtil.getAccessToken(toUserName, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getAccessToken();
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>// 回复文本消息
<span style="white-space:pre">	</span>TextMessagetextMessage = new TextMessage();
<span style="white-space:pre">	</span>textMessage.setToUserName(fromUserName);
<span style="white-space:pre">	</span>textMessage.setFromUserName(toUserName);
<span style="white-space:pre">	</span>textMessage.setCreateTime(newDate().getTime());
<span style="white-space:pre">	</span>textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span> //判断消息类型
<span style="white-space:pre">	</span>if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {// 文本消息
<span style="white-space:pre">	</span>   respContent = "您发送的是文本消息";
<span style="white-space:pre">	</span>}elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)){//图片
<span style="white-space:pre">	</span>   respContent = "您发送的是文本图片消息";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)){//语音
<span style="white-space:pre">	</span>   respContent = "您发送的是语音消息";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)){//地理位置
<span style="white-space:pre">	</span>   respContent ="您发送的是地理位置消息";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)){//事件推送
<span style="white-space:pre">	</span>   respContent = "您发送的是事件推送消息";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)){//视频
<span style="white-space:pre">	</span>   respContent ="您发送的是视频消息";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)){//链接
<span style="white-space:pre">	</span>   respContent = "您发送的是链接消息";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>textMessage.setContent(respContent);
<span style="white-space:pre">	</span>// 将文本消息对象转换成xml
<span style="white-space:pre">	</span>respXml= MessageUtil.messageToXml(textMessage);
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>}catch (Exception e) {
<span style="white-space:pre">	</span>e.printStackTrace();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>returnrespXml ;
<span style="white-space:pre">	</span>}
}
 
/**
 * 通用工具类
 */
public class CommonUtil {
<span style="white-space:pre">	</span>private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>       //获取AccessToken的Http请求  韩学敏 2015-2-25 10:58:36
<span style="white-space:pre">	</span>public final static Stringaccesstoken_url="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid =CORPID&corpsecret=CORPSECRET";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> *获取接口访问凭证 企业号 ——韩学敏 2015-2-25 10:59:57
<span style="white-space:pre">	</span> *
<span style="white-space:pre">	</span> *@param corpid 企业Id
<span style="white-space:pre">	</span> *@param corpsecret 凭证密钥
<span style="white-space:pre">	</span> * @return
<span style="white-space:pre">	</span> */ 
<span style="white-space:pre">	</span>public static Token getAccessToken(String corpid, String corpsecret) {
<span style="white-space:pre">		</span>Token token = null;
<span style="white-space:pre">		</span>String requestUrl = accesstoken_url.replace("CORPID",corpid).replace("CORPSECRET", corpsecret);
<span style="white-space:pre">		</span>// 发起GET请求获取凭证
<span style="white-space:pre">		</span>JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span>if(null != jsonObject) {
<span style="white-space:pre">		</span>try{
<span style="white-space:pre">			</span>token= new Token();
<span style="white-space:pre">			</span>token.setAccessToken(jsonObject.getString("access_token"));
<span style="white-space:pre">			</span>token.setExpiresIn(jsonObject.getInt("expires_in"));
<span style="white-space:pre">		</span>}catch (JSONException e) {
<span style="white-space:pre">			</span>token= null;
<span style="white-space:pre">			</span>// 获取token失败
<span style="white-space:pre">			</span>log.error("获取token失败 errcode:{} errmsg:{}",jsonObject.getInt("errcode"),jsonObject.getString("errmsg"));
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>returntoken;
<span style="white-space:pre">	</span>}
}
/**
 * 消息处理工具类
 */
public classMessageUtil {
<span style="white-space:pre">	</span>// 请求消息类型:文本
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_TEXT = "text";
<span style="white-space:pre">	</span>// 请求消息类型:图片
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
<span style="white-space:pre">	</span>// 请求消息类型:语音
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
<span style="white-space:pre">	</span>// 请求消息类型:视频
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_VIDEO = "video";
<span style="white-space:pre">	</span>// 请求消息类型:地理位置
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
<span style="white-space:pre">	</span>// 请求消息类型:链接
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_LINK = "link";
<span style="white-space:pre">	</span>// 请求消息类型:事件推送
<span style="white-space:pre">	</span>public static final String REQ_MESSAGE_TYPE_EVENT = "event";
<span style="white-space:pre">	</span>// 事件类型:subscribe(订阅)
<span style="white-space:pre">	</span>public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
<span style="white-space:pre">	</span>// 事件类型:unsubscribe(取消订阅)
<span style="white-space:pre">	</span>public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
<span style="white-space:pre">	</span>// 事件类型:scan(用户已关注时的扫描带参数二维码)
<span style="white-space:pre">	</span>public static final String EVENT_TYPE_SCAN = "scan";
<span style="white-space:pre">	</span>// 事件类型:LOCATION(上报地理位置)
<span style="white-space:pre">	</span>public static final String EVENT_TYPE_LOCATION = "LOCATION";
<span style="white-space:pre">	</span>// 事件类型:CLICK(自定义菜单)
<span style="white-space:pre">	</span>public static final String EVENT_TYPE_CLICK = "CLICK";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>// 响应消息类型:文本
<span style="white-space:pre">	</span>public static final String RESP_MESSAGE_TYPE_TEXT = "text";
<span style="white-space:pre">	</span>// 响应消息类型:图片
<span style="white-space:pre">	</span>public static final String RESP_MESSAGE_TYPE_IMAGE = "image";
<span style="white-space:pre">	</span>// 响应消息类型:语音
<span style="white-space:pre">	</span>public static final String RESP_MESSAGE_TYPE_VOICE = "voice";
<span style="white-space:pre">	</span>// 响应消息类型:视频
<span style="white-space:pre">	</span>public static final String RESP_MESSAGE_TYPE_VIDEO = "video";
<span style="white-space:pre">	</span>// 响应消息类型:音乐
<span style="white-space:pre">	</span>public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
<span style="white-space:pre">	</span>// 响应消息类型:图文
<span style="white-space:pre">	</span>public static final String RESP_MESSAGE_TYPE_NEWS = "news";
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 扩展xstream使其支持CDATA
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private static XStream xstream = new XStream(new XppDriver() {
<span style="white-space:pre">	</span>public HierarchicalStreamWriter createWriter(Writer out) {
<span style="white-space:pre">	</span>   return new PrettyPrintWriter(out) {
<span style="white-space:pre">	</span>   // 对所有xml节点的转换都增加CDATA标记
<span style="white-space:pre">	</span>    boolean cdata = true;
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>@SuppressWarnings("unchecked")
<span style="white-space:pre">	</span>public void startNode(String name, Class clazz) {
<span style="white-space:pre">	</span>   super.startNode(name,clazz);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>protected void writeText(QuickWriter writer, String text) {
<span style="white-space:pre">	</span>if(cdata) {
<span style="white-space:pre">	</span>   writer.write("<![CDATA[");
<span style="white-space:pre">	</span>   writer.write(text);
<span style="white-space:pre">	</span>   writer.write("]]>");
<span style="white-space:pre">	</span>}else {
<span style="white-space:pre">	</span>   writer.write(text);
<span style="white-space:pre">	</span>  }
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>};
<span style="white-space:pre">	</span>}
});
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> *文本消息对象转换成xml
<span style="white-space:pre">	</span> *
<span style="white-space:pre">	</span> * @paramtextMessage 文本消息对象
<span style="white-space:pre">	</span> * @return xml
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>public static String messageToXml(TextMessage textMessage) {
<span style="white-space:pre">		</span>xstream.alias("xml",textMessage.getClass());
<span style="white-space:pre">		</span>return xstream.toXML(textMessage);
<span style="white-space:pre">	</span>}
}
 
/**
 * 凭证 实体
  */
public class Token {
<span style="white-space:pre">	</span>// 接口访问凭证
<span style="white-space:pre">	</span>private String accessToken;
<span style="white-space:pre">	</span>// 凭证有效期,单位:秒
<span style="white-space:pre">	</span>private int expiresIn;
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>public String getAccessToken() {
<span style="white-space:pre">	</span>return accessToken;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>public void setAccessToken(String accessToken) {
<span style="white-space:pre">	</span>this.accessToken= accessToken;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>public int getExpiresIn() {
<span style="white-space:pre">	</span>return expiresIn;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>public void setExpiresIn(int expiresIn) {
<span style="white-space:pre">	</span>this.expiresIn= expiresIn;
<span style="white-space:pre">	</span>}
}
时间: 2024-10-07 04:15:07

微信公众平台与手机的交互的相关文章

微信公众平台开发最佳实践(第2版)

<微信公众平台开发最佳实践 第2版>微信公众平台开发经典之作全新改版,精心挑选最经典的商业项目开发,成千上万人次微信公众平台开发者从中受益 前言 出版说明 自从方倍工作室在博客园推出微信公众平台开发系列教程后,受到广大微信开发人员及爱好者的热情关注,相关文章的日访问量高达2万人次,而<微信公众平台开发入门教程>的阅读量超过50万,博客访问量总计超过500万,成为微信公众平台开发更新最快,传播最广.受众最多.资料最全的博客,很多博文被许多有影响力的网站转载,并被各大搜索引擎收录且排名

微信公众平台网页开发实战--2.从手机相册中选照片然后分享

通过对需求的了解,可以将其分解为: (1)微信端手机用户,可以使用微信的JSSDK. (2)选取图片,使用JSSDK的“chooseImage”,由于分享图片时本地地址无法分享,因此还需要JSSDK的“uploadImage”. (3)分享到朋友圈,需要JSSDK的“onMenuShareTimeline”. 综合起来,业务逻辑如图4.5所示. 图4.5  业务逻辑结构图 首先将JSSDK的环境复制一份到本节目录下,创建index.html文件.imageSharing.js文件,目录结构如图4

微信公众平台开发(35)(天气预报、股票查询、手机归属查询、在线听音乐、翻译、成绩查询功能)代码分享

微信公众平台开发应用(天气预报.股票查询.手机归属查询.在线听音乐.翻译.成绩查询功能) 原文: http://www.cnblogs.com/imaker/p/5491433.html 1.xml(信息返回用扩展语言XML来传递值) $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //extract post data if (!empty($postStr)){ $postObj = simplexml_load_string($postStr

政府部门没组织机构代码、法人证书,怎么开通认证微信公众平台?

政府机关微信公众号认证流程:1.确定需要认证的名字:如xx大队.xx局:2.准备资料:单位证件.运营人身份证.联系手机.登陆邮箱:3.确定类型:订阅号or服务号:资料准备好后,可直接联系公众平台服务商"杰客科技"的客服人员,2天内便可完成认证. 注意事项:1.政府机关认证时需要盖章,没有公章将无法认证:2.公众号认证后,排名将更靠前并显示v标志. 政府微信公众平台开通及认证:http://www.jcjclu.com/apply/201603149.html客服QQ:180805782

网络架构、云平台和微信公众平台开发接入

版权声明:本文为博主原创文章,未经博主允许不得转载. 云与后端相关的技术似乎并不属于嵌入式和物联智能硬件开发工程师的范畴,但是嵌入式开发工程师有必要认识成熟的网络架构和相关的云技术,以拓展自己在系统架构方面的视野.大数据分析是物联网背后的核心价值,物联智能硬件是物联大系统的终端,开发工程师不仅要深入精通物联技术,也应该去理解大系统,甚至整个生态领域的相关技术. 作为嵌入式开发工程师,也许并不需要熟悉云和后端的技术开发,但至少要对其中用到的技术和接口有一定的认识. 一.网络架构 常见的网络架构分为

微信公众平台开发基础知识38问

最近接触微信公众号后台的开发,看了一些资料基本可以满足简单的需求开发.笔者将这些问题及解答整理出来,以帮助更多初学者少走弯路. 1.订阅号与服务号的主要区别是什么? 订阅号每天能群发一条消息,没有自定义菜单及高级接口权限(目前 个人.企业订阅号关联腾讯微博认证之后才有自定义菜单):服务号有自定义菜单微信认证之后有高级接口权限,但每月只能群发一条消息. 2.到底该申请订阅号还是服务号? 申请哪种类型的公众账号,主要取决于账号的用途.服务号主要面向企业和组织,旨在为用户提供服务:订阅号主要面向媒体和

[转]微信公众平台(测试接口)开发前的准备工作(转载自walkingmanc的专栏)

本文转自:http://blog.csdn.net/jiangweicpu/article/details/21228949 http://blog.csdn.net/walkingmanc/article/details/21457097第二讲 探秘微信公众号 1.   申请微信公众号 我们要进行微信公众平台的开发,第一步当然是要有公众号了.什么?不知道什么是微信公众号,看来你还要先回炉炼炼了,呵呵.通俗的说,我们微信平台就好像是一个大社会,里面有个体人,也有各种组织机构.你自己使用的普通微信

微信公众平台开发教程新手解惑40则

[编者按]由CSDN和<程序员>杂志联合主办的 2014年微信开发者大会 将于8月23日在北京举行,邀请了来自于一线的微信开发商技术负责人或资深工程师从企业应用开发高级篇.智能客服与LBS.微信支付.微信上的HTML5社交应用.微信小店开发等角度为与会者带来实战分享( 议程 ).目前报名处于优惠票价阶段,通过申请加入CSDN CTO俱乐部即可享受8折购票价格(票款中均含午餐),在8月1日前完成付款的同学还将免费获赠微信开发图书一本(两选一,活动现场发放).  值得一提的是,CSDN优秀博主.畅

《微信公众平台入门到精通》Vol.2

<微信公众平台入门到精通>Vol.2 2017-05-28 连着两天没有更新公众平台的教程了,估计不少朋友在嘀咕了,非常抱歉,这些天疲倦的奔波在外,朋友们的消息还是及时在回复的,只是没有精力写东西.今天猛睡一天补交,接下来会空一些,会正常更新! 第二章    微信公众平台后台介绍 一.微信公众平台后台欢迎页面 登陆公众平台后首先进入的就是欢迎页,跟大部分CMS后台一样,这里会提供的是公众账号的一些运营数据,如下图: 在上次点击用户管理和实时消息两个导航选项后新增加的用户数和消息数,这话有点拗口