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

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

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

接收消息:用户向公众账号发送消息,此时微信服务器接收到消息,并将消息的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 {
     /**
     *处理微信发来的请求——企业号 韩学敏
     *
     * @param request
     * @return xml
     */
     public static String processRequest(String msg) {
        //xml格式的消息数据
        String respXml = null;
       //默认返回的文本消息内容
       String respContent = "";
       try{
            // 调用parseXml方法解析请求消息
            Map<String,String> requestMap = MessageUtil.parseXml(msg);

            // 发送方帐号
            String fromUserId = requestMap.get("FromUserName");
            // 公众帐号 
            String toUserName = requestMap.get("ToUserName");
            // 消息类型
            String msgType = requestMap.get("MsgType");
           //获取企业应用Id
            String agentId = requestMap.get("AgentID");

           // 获取接口访问凭证
            String accessToken =CommonUtil.getAccessToken(toUserName, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getAccessToken();

           // 回复文本消息
          TextMessagetextMessage = new TextMessage();
          textMessage.setToUserName(fromUserName);
          textMessage.setFromUserName(toUserName);
          textMessage.setCreateTime(newDate().getTime());
          textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

          //判断消息类型
          if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {// 文本消息
               respContent = "您发送的是文本消息";
          }elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)){//图片
              respContent = "您发送的是文本图片消息";
  
          }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)){//语音
               respContent = "您发送的是语音消息";
 
          }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)){//地理位置
               respContent ="您发送的是地理位置消息";

          }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)){//事件推送
                respContent = "您发送的是事件推送消息";

          }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)){//视频
                 respContent ="您发送的是视频消息";

          }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)){//链接
                respContent = "您发送的是链接消息";

          }
           textMessage.setContent(respContent);
          // 将文本消息对象转换成xml
          respXml= MessageUtil.messageToXml(textMessage);

        }catch (Exception e) {
              e.printStackTrace();
        }
          returnrespXml ;
     }
}
 
/**
 * 通用工具类
 */
public class CommonUtil {
        private static Logger log = LoggerFactory.getLogger(CommonUtil.class);

       //获取AccessToken的Http请求  韩学敏 2015-2-25 10:58:36
       public final static Stringaccesstoken_url="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid =CORPID&corpsecret=CORPSECRET";

       /**
         *获取接口访问凭证 企业号 ——韩学敏 2015-2-25 10:59:57
         *
         *@param corpid 企业Id
         *@param corpsecret 凭证密钥
         * @return
          */ 
        public static Token getAccessToken(String corpid, String corpsecret) {
	      Token token = null;
              String requestUrl = accesstoken_url.replace("CORPID",corpid).replace("CORPSECRET", corpsecret);
	      // 发起GET请求获取凭证
		JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
		
		if(null != jsonObject) {
		try{
			token= new Token();
			token.setAccessToken(jsonObject.getString("access_token"));
			token.setExpiresIn(jsonObject.getInt("expires_in"));
		}catch (JSONException e) {
			token= null;
			// 获取token失败
			log.error("获取token失败 errcode:{} errmsg:{}",jsonObject.getInt("errcode"),jsonObject.getString("errmsg"));
		}
		}
		returntoken;
	}
}
/**
 * 消息处理工具类
 */
public class MessageUtil {
     // 请求消息类型:文本
     public static final String REQ_MESSAGE_TYPE_TEXT = "text";
     // 请求消息类型:图片
     public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
     // 请求消息类型:语音
     public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
     // 请求消息类型:视频
     public static final String REQ_MESSAGE_TYPE_VIDEO = "video";
     // 请求消息类型:地理位置
     public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
     // 请求消息类型:链接
     public static final String REQ_MESSAGE_TYPE_LINK = "link";
     // 请求消息类型:事件推送
     public static final String REQ_MESSAGE_TYPE_EVENT = "event";
     // 事件类型:subscribe(订阅)
     public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
     // 事件类型:unsubscribe(取消订阅)
     public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
     // 事件类型:scan(用户已关注时的扫描带参数二维码)
     public static final String EVENT_TYPE_SCAN = "scan";
     // 事件类型:LOCATION(上报地理位置)
     public static final String EVENT_TYPE_LOCATION = "LOCATION";
     // 事件类型:CLICK(自定义菜单)
     public static final String EVENT_TYPE_CLICK = "CLICK";

    // 响应消息类型:文本
     public static final String RESP_MESSAGE_TYPE_TEXT = "text";
    // 响应消息类型:图片
     public static final String RESP_MESSAGE_TYPE_IMAGE = "image";
    // 响应消息类型:语音
    public static final String RESP_MESSAGE_TYPE_VOICE = "voice";
    // 响应消息类型:视频
    public static final String RESP_MESSAGE_TYPE_VIDEO = "video";
    // 响应消息类型:音乐
    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
    // 响应消息类型:图文
    public static final String RESP_MESSAGE_TYPE_NEWS = "news";

    /**
      * 扩展xstream使其支持CDATA
     */
     private static XStream xstream = new XStream(new XppDriver() {
     public HierarchicalStreamWriter createWriter(Writer out) {
         return new PrettyPrintWriter(out) {
        // 对所有xml节点的转换都增加CDATA标记
         boolean cdata = true;
 
        @SuppressWarnings("unchecked")
        public void startNode(String name, Class clazz) {
           super.startNode(name,clazz);
      }
 
    protected void writeText(QuickWriter writer, String text) {
         if(cdata) {
            writer.write("<![CDATA[");
            writer.write(text);
            writer.write("]]>");
         }else {
            writer.write(text);
     }
   }
  };
 }
 });
 
      /**
      *文本消息对象转换成xml
      *
      * @paramtextMessage 文本消息对象
      * @return xml
      */
     public static String messageToXml(TextMessage textMessage) {
	 xstream.alias("xml",textMessage.getClass());
		return xstream.toXML(textMessage);
	}
     }
 }
/**
 * 凭证 实体
  */
public class Token {
     // 接口访问凭证
     private String accessToken;
     // 凭证有效期,单位:秒
      private int expiresIn;

     public String getAccessToken() {
        return accessToken;
     }
 
     public void setAccessToken(String accessToken) {
         this.accessToken= accessToken;
      }

     public int getExpiresIn() {
         return expiresIn;
      }
 
    public void setExpiresIn(int expiresIn) {
       this.expiresIn= expiresIn;
    }
}











评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值