2015-08-26 13:06:22 oldinaction 阅读数 6920
  • 微信开发13-微信门店开发(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信公众平台开发之微信门店开发是子恒老师《微信公众平台开发》视频教程的第13部。详细讲解了用php进行微信门店的开发。内容包含新增微信门店,列表门店列表,获取和修改门店信息等等。欢迎反馈,微信号:QQ68183131

    11214 人正在学习 去看看 秦子恒

当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。服务器在解析此数据包,获取相关参数的值从而做出回复。接收普通消息主要包括:文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息。XML数据包结构和相关参数如下:

1、文本消息

 <xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>
参数				描述
ToUserName		开发者微信号
FromUserName	 发送方帐号(一个OpenID)
CreateTime	 	消息创建时间 (整型)
MsgType	 		text
Content	 		文本消息内容
MsgId	 		消息id,64位整型

那么这些参数该如何获取呢,示例代码如下:

index.php(完整代码下载

<?php
/**
  * 作者:smalle
  * 网址:http://blog.csdn.net/oldinaction
  * 微信公众号:smallelife
  */

//定义 token
define("TOKEN", "smalle");
//实例化对象
$wechatObj = new wechatCallbackapiTest();
//调用函数
if (isset($_GET['echostr'])) {
	$wechatObj->valid();
}else{
	$wechatObj->responseMsg();
}

class wechatCallbackapiTest
{
	public function valid()
	{
		$echoStr = $_GET["echostr"];
		if($this->checkSignature()){
			echo $echoStr;
			exit;
		}
	}

	public function responseMsg()
	{
		$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  

		if (!empty($postStr)){  
			libxml_disable_entity_loader(true);//安全防护  
			$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);  
			$fromUsername = $postObj->FromUserName;  
			$toUsername = $postObj->ToUserName;
			$createTime = $postObj->CreateTime;
			$msgType = $postObj->MsgType;
			$content = $postObj->Content;
			$msgId = $postObj->MsgId;
			if($msgType == 'text'){
				$textTpl = "<xml>  
						<ToUserName><![CDATA[%s]]></ToUserName>  
						<FromUserName><![CDATA[%s]]></FromUserName>  
						<CreateTime>%s</CreateTime>  
						<MsgType><![CDATA[text]]></MsgType>  
						<Content><![CDATA[%s]]></Content>  
						<FuncFlag>0</FuncFlag>  
						</xml>";
				$time = time();
				$contentStr = "您发的是消息包含以下信息:\n发信人OpenID:".$fromUsername."\n收信人微信号:".$toUsername."\n发信时间:".$createTime."\n消息类型:".$msgType."\n消息内容:".$content."\n消息ID:".$msgId;  
				$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);  
				echo $resultStr;  
			}else{
				$textTpl = "<xml>  
						<ToUserName><![CDATA[%s]]></ToUserName>  
						<FromUserName><![CDATA[%s]]></FromUserName>  
						<CreateTime>%s</CreateTime>  
						<MsgType><![CDATA[text]]></MsgType>  
						<Content><![CDATA[%s]]></Content>  
						<FuncFlag>0</FuncFlag>  
						</xml>";
				$time = time();
				$contentStr = "您发的消息类型不是文本。而是".$msgType;
				$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);  
				echo $resultStr;  
			}

		}
	}
		
	private function checkSignature()
	{
		if (!defined("TOKEN")) {
			throw new Exception('TOKEN is not defined!');
		}
		$signature = $_GET["signature"];
		$timestamp = $_GET["timestamp"];
		$nonce = $_GET["nonce"];
		$token = TOKEN;
		$tmpArr = array($token, $timestamp, $nonce);
		sort($tmpArr, SORT_STRING);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		
		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}
}

?>
效果预览:


代码分析:

  • 第32-42行【$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];......$msgId = $postObj->MsgId;】:实现获取用户发送过来的消息数据。
  • 第43-55行【if($msgType == 'text'){......echo $resultStr;】:实现的是被动回复文本消息给用户

2、图片消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

 <xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[http://blog.csdn.net/oldinaction]]></PicUrl>
 <MediaId><![CDATA[media_id]]></MediaId>
 <MsgId>1234567890123456</MsgId>
 </xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		image
PicUrl	 		图片链接
MediaId	 		图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId	 		消息id,64位整型

3、语音消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		语音为voice
MediaId	 		语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
Format	 		语音格式,如amr,speex等
MsgID	 		消息id,64位整型

请注意,开通语音识别后,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段(注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试)。开启语音识别后的语音XML数据包如下:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<Recognition><![CDATA[腾讯微信团队]]></Recognition>
<MsgId>1234567890123456</MsgId>
</xml>
多出的字段中,Format为语音格式,一般为amr,Recognition为语音识别结果,使用UTF8编码。

4、视频消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		视频为video
MediaId	 		视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId		视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId	 		消息id,64位整型

5、小视频消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[shortvideo]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		小视频为shortvideo
MediaId	 		视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId		视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId	 		消息id,64位整型

6、地理位置消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[位置信息]]></Label>
<MsgId>1234567890123456</MsgId>
</xml> 
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		location
Location_X		地理位置维度
Location_Y		地理位置经度
Scale	 		地图缩放大小
Label	 		地理位置信息
MsgId	 		消息id,64位整型

当用户给公众账号发送位置时,便可以获取相应的地理位置信息。部分示例代码如下:

index.php(完整代码下载

$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  

if (!empty($postStr)){  
	libxml_disable_entity_loader(true);//安全防护  
	$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);  
	$fromUsername = $postObj->FromUserName;  
	$toUsername = $postObj->ToUserName;
	$msgType = $postObj->MsgType;
	$j = $postObj->Location_Y;//经度
	$w = $postObj->Location_X;//纬度
	$label = $postObj->Label;//地理位置信息
	if($msgType == 'location'){
		$textTpl = "<xml>  
				<ToUserName><![CDATA[%s]]></ToUserName>  
				<FromUserName><![CDATA[%s]]></FromUserName>  
				<CreateTime>%s</CreateTime>  
				<MsgType><![CDATA[text]]></MsgType>  
				<Content><![CDATA[%s]]></Content>  
				<FuncFlag>0</FuncFlag>  
				</xml>";
		$time = time();
		$contentStr = "您的位置信息如下:\n经度:".$j."\n纬度:".$w."\n地理位置信息:".$label;
		$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);  
		echo $resultStr;  
	}else{
		echo '';
	}

}
效果展示:

现在你可能觉得这一小串数字没什么用,到后面我会分享一些关于位置信息的小案例,那个时候就起作用了。


7、链接消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[公众平台官网链接]]></Title>
<Description><![CDATA[公众平台官网链接]]></Description>
<Url><![CDATA[url]]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		接收方微信号
FromUserName	发送方微信号,若为普通用户,则是一个OpenID
CreateTime		消息创建时间
MsgType	 		消息类型,link
Title	 			消息标题
Description		消息描述
Url	 			消息链接
MsgId	 		消息id,64位整型




===================================微笑微笑微笑===================================

关注【Smalle】【微信公众号:smallelife】              微笑             捐赠【Smalle】【微信公众号:smallelife】

关注就有豪礼相送哦,羡慕源码、羡慕工具、羡慕文档应有尽有      微笑       你的扫码便是我前进的动力,羡慕扫码、羡慕扫码、羡慕扫码

===================================微笑微笑微笑===================================

                                     


2018-04-18 11:18:54 gougouge555 阅读数 743
  • 微信开发13-微信门店开发(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信公众平台开发之微信门店开发是子恒老师《微信公众平台开发》视频教程的第13部。详细讲解了用php进行微信门店的开发。内容包含新增微信门店,列表门店列表,获取和修改门店信息等等。欢迎反馈,微信号:QQ68183131

    11214 人正在学习 去看看 秦子恒

上篇文章我们提到了微信消息的接收

那么在开始开发之前,我们需要在微信配置一些参数


URL为我们用于接收微信消息的网络地址,微信出于安全性与保密性的考虑,设置了消息加密(可选)和配置口令效验,下面的Token便是效验口令,这个随意设置,只需要在程序里进行效验操作时一致即可(这里的配置需要公网ip或公网域名,没有的朋友们可以选择团购一个云服务器)

微信的口令效验官方文档里有,我这里就不一一阐述说明了

进行了一个简单的模板代码处理

import java.io.*;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.edt.service.RedisService;
import com.edt.wechat.WeChatMsgFactory;
import com.edt.wechat.bean.Msg;
import com.edt.wechat.bean.event.Event;
import com.edt.wechat.bean.event.LocationEvent;
import com.edt.wechat.bean.normalmsg.RecognitionMsg;
import com.iceutils.weixin.security.IceWeiXinTokenUtils;
import org.dom4j.DocumentException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import static com.edt.common.SysInit.DICTIONARY_CONFIG;

/**
 * 
 * 接收微信参数,分发转向
 * @author: 苟开唯
 * @date: 2017年12月12日 下午2:44:15 
 *
 */
@Controller
@RequestMapping("/WechatMsgReceive")
public class WechatMsgController {
	@Resource
	private RedisService redisService;
	
	/**
	 * 接收微信发送的消息,根据请求方式分发转向(保存信息)
	 * @param request, response
	 * @return java.lang.String
	 * @author 苟开唯
	 * @date 2018/1/10 13:46
	 */
	@RequestMapping("MsgReceive")
	@ResponseBody
	public String msgReceive(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
		String method = request.getMethod();
		response.setContentType("text/html; charset=UTF-8");
		request.setCharacterEncoding("utf-8");
		System.out.println("微信中转");
		/**
		 * ================================
		 * 判断消息传输方式,若是get  则进行微信口令验证
		 * 若是post,进行消息处理
		 * ================================
		 */
		PrintWriter out = null;
		try {
			out = response.getWriter();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if("get".equalsIgnoreCase(method)){
			System.out.println("微信效验");
			String signature = request.getParameter("signature");
			String timestamp = request.getParameter("timestamp");
			String nonce = request.getParameter("nonce");
			String echostr = request.getParameter("echostr");


			String weiXinTokenSign = IceWeiXinTokenUtils.getWeiXinTokenSign(DICTIONARY_CONFIG.get("wechat_token"), timestamp, nonce);
			if (signature.equals(weiXinTokenSign)) {
				out.write(echostr);
				System.out.println("效验成功");
			} else {
				System.out.println("效验失败");
			}
		}else{
			
			/**
			 * =============
			 * post,进行消息处理
			 * =============
			 */
			try {
				StringBuffer sb = new StringBuffer();
				BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream()));
				String inputLine;
				while ( (inputLine = in.readLine()) != null) {
					sb.append(inputLine);
				}
				System.out.println("接收微信消息:" + sb.toString());
				Msg msg = WeChatMsgFactory.msgHanding(sb.toString());//将数据封装为bean实体类
				//判断数据若不符合规范,则返回空数据 ,停止执行
				if(msg != null){

					String rec = msgController(msg);//执行业务逻辑Controller

					out.write(rec);//返回数据
				}
			} catch (DocumentException e ) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch (IOException e) {
				e.printStackTrace();
			}


		}
		return null;
	}

	/**
	 * 普通消息业务逻辑
	 * 根据消息类型分发转向
	 * @param msg msg
	 * @return java.lang.String
	 * @author 苟开唯
	 * @date 2018/1/10 9:01
	 */
	private String msgController(Msg msg){
		String rec = "success";
		if(msg instanceof Msg ){
			//判断消息类型
			switch (msg.getMsgType()) {
				case "text":
					//TODO 文本消息
					break;

				case "image":
					//TODO 图片消息
					break;

				case "voice":
					//判断是否开通语音转换功能
					if(msg instanceof RecognitionMsg){
						//TODO 开通了语音
					}else{
						//TODO 未开通语音转换
					}
					break;
				case "video":
					//TODO 视频消息
					break;

				case "shortvideo":
					//TODO 视频消息
					break;

				case "location":
					//TODO 地理消息
					break;

				case "link":
					//TODO 链接消息
					break;

				case "event":

					Event event = (Event)msg;
					//判断事件类型
					rec = eventController(event, rec);//不能确认事件消息是否有返回值

					break;


				default:
					//TODO 消息异常处理
					break;
			}
		}else{
			//TODO 不是一个消息类型
		}
		return rec ;
	}


	/**
	 * 事件消息类型业务逻辑
	 * 根据事件类型分发转向
	 * @param event, rec
	 * @return java.lang.String
	 * @author 苟开唯
	 * @date 2018/1/10 9:02
	 */
	private String eventController(Event event, String rec){

		switch (event.getEvent()) {

			case "LOCATION"://用户地理位置事件
				/* 用户上报地理位置事件
				 * 1.获取用户地理信息--封装
				 * 2.将信息储存起来
				 */
				LocationEvent location = (LocationEvent)event;
				redisService.opsValue_set("userLocation_"+location.getFromUserName(),location,1, TimeUnit.HOURS );
				break;

			case "subscribe"://用户关注事件

				break;

			case "unsubscribe"://用户取消关注事件

				break;

			case "SCAN"://用户扫描二维码事件

				break;

			case "CLICK"://用户点击自定义菜单事件(用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。)

				break;

			case "VIEW"://用户点击菜单跳转链接时的事件推送

				break;

			default:
				break;
		}
		return rec;
	}







}


这里  我进行了消息的封装


整理了一下实体类的继承关系的结构图,可以参考此图自行封装


这些基本的消息类型可以满足我们的日常的开发和使用。如果大家感兴趣,可以跳转到微信开发者文档进行了解。



经过分析,我们只需要在接收到的xml信息的MsgType字段进行判断,查看消息类型,若不是event,则进行普通信息封装,若是event,则进行时间消息处理(区别很小,只是字段与消息内容不一样)

package com.xwu.wechat.msg;

import com.xwu.wechat.msg.bean.Msg;
import com.xwu.wechat.msg.bean.event.Event;
import com.xwu.wechat.msg.bean.event.EventWithKey;
import com.xwu.wechat.msg.bean.event.LocationEvent;
import com.xwu.wechat.msg.bean.event.SubscribeEvent;
import com.xwu.wechat.msg.bean.normalmsg.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.Serializable;


/**
 * 
 * 微信消息工厂
 * @author: 爱尚实训
 * @date: 2017年12月12日 下午3:32:05 
 *
 */
public class WeChatMsgFactory implements Serializable {
	private static final long serialVersionUID = -4365145153558799142L;

	/**
	 * 根据消息类型(MsgType字段)进行分发转向
	 * @param xmlString
	 * @return com.edt.entity.wechat.Msg
	 * @author 爱尚实训
	 * @date 2018/1/9 17:36
	 */
	public static Msg msgHanding(String xmlString) throws DocumentException{
		if(xmlString == null || "".equals(xmlString.trim())){
			return null;
		}
		Document document = DocumentHelper.parseText(xmlString);
		Msg msg = null;
		Element root = document.getRootElement();
		String msgType = root.element("MsgType").getText();
		System.out.println("消息类型:" + msgType);
		switch (msgType) {
		case "text"://文本消息
			msg = textMsgParse(root);
			break;
		case "image"://图片消息
			msg = pictureMsgParse(root);
			break;
		case "voice"://语音消息
			//判断是否拥有语音转换功能
			if(root.element("Recognition") == null){
				msg = voiceMsgParse(root);
			}else{
				msg = recognitionMsgParse(root);
			}
			
			break;
		case "shortvideo"://小视频消息
			msg = videoMsgParse(root);
			break;
		case "video"://视频消息
			msg = videoMsgParse(root);
			break;
		case "location"://地理位置消息
			msg = locationMsgParse(root);
			break;
		case "link"://链接消息
			msg = linkMsgParse(root);
			break;
		case "event"://事件消息
			msg = getEvent(root);
		default:
			//TODO 消息异常处理
			break;
		}
		
		return msg;
	}
	
	
	
	
	
	
	/**
	 * 生成事件类型消息
	 * @param root
	 * @return com.edt.entity.wechat.event.Event
	 * @author 爱尚实训
	 * @date 2018/1/9 17:36
	 */
	private static Event getEvent(Element root){
		Event rec = null;
		Element event = root.element("Event");
		String eventType = event.getText();
		switch (eventType) {
		case "LOCATION"://地理位置事件
			System.out.println("LOCATION");
			rec = locationEventParse(root);
			break;
		case "subscribe"://订阅事件
			if(root.element("EventKey") == null){
				rec = eventParse(root);
			}else{
				rec = subscribeEventParse(root);
			}
			break;
		case "unsubscribe"://取消订阅事件
			rec = eventParse(root);
			break;
		case "SCAN"://扫描二维码事件
			rec = subscribeEventParse(root);
			break;
		case "CLICK"://自定义菜单事件
			rec = eventWithKeyParse(root);
			break;
		case "VIEW"://自定义菜单事件
			rec = eventWithKeyParse(root);
			break;
			
		default:
			//TODO 异常事件消息处理
			break;
		}
		
		return rec;
		
	}
	
	
	
	//-------------------------普通消息类型-----------------------
	/**
	 * 生成文本信息实体类
	 * @param root
	 * @return com.edt.entity.wechat.normalmsg.TextMsg
	 * @author 爱尚实训
	 * @date 2018/1/9 17:36
	 */
	private static TextMsg textMsgParse(Element root){
		TextMsg msg = new TextMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setContent(root.element("Content").getText());
		return msg;
	}
	/**
	 * 生成视频信息实体类
	 * @param root
	 * @return com.xwu.entity.wechat.normalmsg.VideoMsg
	 * @author 爱尚实训
	 * @date 2018/1/9 17:37
	 */
	private static VideoMsg videoMsgParse(Element root){
		VideoMsg msg = new VideoMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setMediaId(root.element("MediaId").getText());
		msg.setThumbMediaId(root.element("ThumbMediaId").getText());
		return msg;
	}
	/**
	 * 生成图片信息实体类
	 * @param root
	 * @return com.xwu.entity.wechat.normalmsg.PictureMsg
	 * @author 爱尚实训
	 * @date 2018/1/9 17:38
	 */
	private static PictureMsg pictureMsgParse(Element root){
		PictureMsg msg = new PictureMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setMediaId(root.element("MediaId").getText());
		msg.setPicUrl(root.element("PicUrl").getText());
		return msg;
	}
	/**
	 * 生成声音信息实体类
	 * @param:WeChatMsgFactory
	 * @return:VoiceMsg
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:34:01 
	 *
	 */
	private static VoiceMsg voiceMsgParse(Element root){
		
		VoiceMsg msg = new VoiceMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setMediaId(root.element("MediaId").getText());
		msg.setFormat(root.element("Format").getText());
		return msg;
	} 	
	/**
	 * 生成地理信息实体类
	 * @param:WeChatMsgFactory
	 * @return:LocationMsg
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:34:20 
	 *
	 */
	private static LocationMsg locationMsgParse(Element root){
		LocationMsg msg = new LocationMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setLocation_X(Float.parseFloat(root.element("Location_X").getText()));
		msg.setLocation_Y(Float.parseFloat(root.element("Location_Y").getText()));
		msg.setScale(Integer.parseInt(root.element("Scale").getText()));
		msg.setLabel(root.element("Label").getText());
		return msg;
	} 
	
	
	/**
	 * 生成链接信息实体类
	 * @param:WeChatMsgFactory
	 * @return:LinkMsg
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:34:42 
	 *
	 */
	private static LinkMsg linkMsgParse(Element root){
		LinkMsg msg = new LinkMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setTitle(root.element("Title").getText());
		msg.setDescription(root.element("Description").getText());
		msg.setUrl(root.element("Url").getText());
		return msg;
	}
	
	/**
	 * 生成语音识别信息实体类
	 * @param:WeChatMsgFactory
	 * @return:VoiceMsg
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:34:01 
	 *
	 */
	private static RecognitionMsg recognitionMsgParse(Element root){
		RecognitionMsg msg = new RecognitionMsg();
		msg.setToUserName(root.element("ToUserName").getText()); 
		msg.setFromUserName(root.element("FromUserName").getText());
		msg.setCreateTime(root.element("CreateTime").getText());
		msg.setMsgType(root.element("MsgType").getText());
		msg.setMsgId(Long.parseLong(root.element("MsgId").getText()));
		msg.setMediaId(root.element("MediaId").getText());
		msg.setFormat(root.element("Format").getText());
		msg.setRecognition(root.element("Recognition").getText());
		
		return msg;
	}
	
	//--------------------------------------------------------
	
	//-------------------------事件消息类型-----------------------
	
	/**
	 * 生成地理信息实体类
	 * @param: xml根节点
	 * @return:LocationEvent
	 * @author: 爱尚实训
	 * @date: 2017年12月12日 下午3:58:21 
	 *
	 */
	private static LocationEvent locationEventParse(Element root){
		LocationEvent locationEvent = new LocationEvent();
		locationEvent.setToUserName(root.element("ToUserName").getText()); 
		locationEvent.setFromUserName(root.element("FromUserName").getText());
		locationEvent.setCreateTime(root.element("CreateTime").getText());
		locationEvent.setMsgType(root.element("MsgType").getText());
		locationEvent.setEvent(root.element("Event").getText());
		locationEvent.setLatitude(root.element("Latitude").getText());
		locationEvent.setLongitude(root.element("Longitude").getText());
		locationEvent.setPrecision(root.element("Precision").getText());
		return locationEvent;
	}
	/**
	 * 生成Event实体类
	 * @param:WeChatMsgFactory
	 * @return:Event
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:12:53 
	 *
	 */
	private static Event eventParse(Element root){
		Event event = new Event();
		event.setToUserName(root.element("ToUserName").getText()); 
		event.setFromUserName(root.element("FromUserName").getText());
		event.setCreateTime(root.element("CreateTime").getText());
		event.setMsgType(root.element("MsgType").getText());
		event.setEvent(root.element("Event").getText());
		return event;
	}
	/**
	 * 
	 * 生成EventWithKey实体类
	 * @param:WeChatMsgFactory
	 * @return:EventWithKey
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:13:39 
	 *
	 */
	private static EventWithKey eventWithKeyParse(Element root){
		EventWithKey event = new EventWithKey();
		event.setToUserName(root.element("ToUserName").getText()); 
		event.setFromUserName(root.element("FromUserName").getText());
		event.setCreateTime(root.element("CreateTime").getText());
		event.setMsgType(root.element("MsgType").getText());
		event.setEvent(root.element("Event").getText());
		event.setEventKey(root.element("EventKey").getText());
		return event;
	}
	
	/**
	 * 生成SubscribeEvent实体类
	 * @param:WeChatMsgFactory
	 * @return:SubscribeEvent
	 * @author: 爱尚实训
	 * @date: 2018年1月8日 上午9:14:06 
	 *
	 */
	private static SubscribeEvent subscribeEventParse(Element root){
		SubscribeEvent event = new SubscribeEvent();
		event.setToUserName(root.element("ToUserName").getText()); 
		event.setFromUserName(root.element("FromUserName").getText());
		event.setCreateTime(root.element("CreateTime").getText());
		event.setMsgType(root.element("MsgType").getText());
		event.setEvent(root.element("Event").getText());
		String text = root.element("EventKey").getText();
		//判断是否为扫描事件还是扫描关注事件
		if(text.indexOf("qrscene_") != -1){
			text = text.substring(8, text.length());
		}
		
		event.setEventKey(text);
		//event.setTicket(root.element("Ticket").getText());
		return event;
	}

	//--------------------------------------------------------

}

代码逻辑:将微信发送的数据进行工厂解析,会返回给我们一个msg类型的对象,可能也都有想到了,它是一个抽象父类,从工厂取出消息对象后,再次进行消息类型判断,根据不同的业务逻辑类型,去做相应的业务逻辑。

整体来说,接收微信消息,完全可以理解为带着参数来访问我们的controller。而最繁琐的地方,只是对微信的消息类型稍微混乱了一些,如果看不懂我的代码,首先把微信说明文档中的消息类型进行整理,查找公共字段,进行优化封装。其次统一管理,进行业务逻辑判断,并返回给微信“success”即可,即代表接收成功,否则微信则认为发送失败,5秒为一次请求,超过5秒将会再次发出请求,最多尝试请求三次,将停止发送(为了防止微信与我们的程序浪费性能,所以最好在这里进行回复处理)


微信消息的处理到此告一段落,这里可以进行被动回复消息(后续会说到),有兴趣的小伙伴可以先尝试一下!














2017-04-22 11:47:35 hq0556 阅读数 1660
  • 微信开发13-微信门店开发(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信公众平台开发之微信门店开发是子恒老师《微信公众平台开发》视频教程的第13部。详细讲解了用php进行微信门店的开发。内容包含新增微信门店,列表门店列表,获取和修改门店信息等等。欢迎反馈,微信号:QQ68183131

    11214 人正在学习 去看看 秦子恒

本例中有些引用的类与方法不做过多介绍,之后会提供完整源码下载,请自行查看。

本篇根据开发者文档-接收事件推送编写。请对照查看,一些传入与返回参数就不过多介绍。地址为:https://mp.weixin.qq.com/wiki/14/f79bdec63116f376113937e173652ba2.html


​在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式通知到开发者在开发者中心处设置的服务器地址,从而开发者可以获取到该信息。其中,某些事件推送在发生后,是允许开发者回复用户的,某些则不允许

关注/取消关注事件

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

/*
 * 接收事件推送消息
 * http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html
 */
@XmlRootElement
public class MsgBaseEvent {

    @XmlElement(name = "ToUserName")  
    private String ToUserName;      //开发者微信号

    @XmlElement(name = "FromUserName")  
    private String FromUserName;    //发送方帐号(一个OpenID)

    @XmlElement(name = "CreateTime")  
    private long CreateTime;        //消息创建时间 (整型)

    @XmlElement(name = "MsgType")  
    private String MsgType;         //消息类型,event

    @XmlElement(name = "Event")  
    private String Event;           //事件类型
}

扫描带参数二维码事件

用户扫描带场景值二维码时,可能推送以下两种事件:

  • 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
  • 如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。
    /*
     * 用户未关注时,进行关注后的事件推送
     * Event    事件类型,subscribe
     * EventKey 事件KEY值,qrscene_为前缀,后面为二维码的参数值
     * 
     * 用户已关注时的事件推送
     * Event    事件类型,SCAN
     * EventKey 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
     */
    @XmlRootElement
    public class MsgScanCodeEvent extends MsgBaseEvent {
    
        @XmlElement(name = "EventKey")
        private String EventKey;    //事件KEY值,qrscene_为前缀,后面为二维码的参数值 
    
        @XmlElement(name = "Ticket")
        private String Ticket;      //二维码的ticket,可用来换取二维码图片
    
        public String getEventKey() {
            return EventKey;
        }
        public void setEventKey(String eventKey) {
            EventKey = eventKey;
        }
    
        public String getTicket() {
            return Ticket;
        }
        public void setTicket(String ticket) {
            Ticket = ticket;
        }
    
        /*
         * 接收到的文本示例
         * <xml>
         *  <ToUserName><![CDATA[toUser]]></ToUserName>
         *  <FromUserName><![CDATA[FromUser]]></FromUserName>
         *  <CreateTime>123456789</CreateTime>
         *  <MsgType><![CDATA[event]]></MsgType>
         *  <Event><![CDATA[subscribe|SCAN]]></Event>
         *  <EventKey><![CDATA[qrscene_123123|SCENE_VALUE]]></EventKey>
         *  <Ticket><![CDATA[TICKET]]></Ticket>
         * </xml>
         */
        public static MsgScanCodeEvent requestMessage(String xmlStr) throws JAXBException {
            xmlStr = xmlStr.replace("xml", "msgScanCodeEvent");
            JAXBContext context = JAXBContext.newInstance(MsgScanCodeEvent.class);  
            Unmarshaller unmarshaller = context.createUnmarshaller();  
            return (MsgScanCodeEvent)unmarshaller.unmarshal(new StringReader(xmlStr));
        }
    }

上报地理位置事件

用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。

/*
 * Event--->
 * LOCATION
 */
@XmlRootElement
public class MsgLocationEvent extends MsgBaseEvent {

    @XmlElement(name = "Latitude") 
    private float Latitude;     //地理位置纬度

    @XmlElement(name = "Longitude") 
    private float Longitude;    //地理位置经度

    @XmlElement(name = "Precision") 
    private float Precision;    //地理位置精度

    public float getLatitude() {
        return Latitude;
    }
    public void setLatitude(float latitude) {
        Latitude = latitude;
    }

    public float getLongitude() {
        return Longitude;
    }
    public void setLongitude(float longitude) {
        Longitude = longitude;
    }

    public float getPrecision() {
        return Precision;
    }
    public void setPrecision(float precision) {
        Precision = precision;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *   <ToUserName><![CDATA[toUser]]></ToUserName>
     *   <FromUserName><![CDATA[fromUser]]></FromUserName>
     *   <CreateTime>1348831860</CreateTime>
     *   <MsgType><![CDATA[event]]></MsgType>
     *   <Event><![CDATA[LOCATION]]></Event>
     *   <Latitude>23.137466</Latitude>
     *   <Longitude>113.352425</Longitude>
     *   <Precision>119.385040</Precision>
     * </xml>
     */
    public static MsgLocationEvent requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "msgLocationEvent");
        JAXBContext context = JAXBContext.newInstance(MsgLocationEvent.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (MsgLocationEvent)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

自定义菜单事件

用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。

点击菜单拉取消息时的事件推送

/*
 * Event--->
 * click:点击菜单拉取消息时的事件推送
 */
@XmlRootElement
public class MenuClickEvent extends MenuBaseEvent {

    /*
     * 接收到的文本示例
     * <xml>
     *  <ToUserName><![CDATA[toUser]]></ToUserName>
     *  <FromUserName><![CDATA[FromUser]]></FromUserName>
     *  <CreateTime>123456789</CreateTime>
     *  <MsgType><![CDATA[event]]></MsgType>
     *  <Event><![CDATA[CLICK]]></Event>
     *  <EventKey><![CDATA[EVENTKEY]]></EventKey>
     * </xml>
     */
    public static MenuClickEvent requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "menuClickEvent");
        JAXBContext context = JAXBContext.newInstance(MenuClickEvent.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (MenuClickEvent)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

点击菜单跳转链接时的事件推送

/*
 * Event--->
 * view:点击菜单跳转链接时的事件推送
 */
@XmlRootElement
public class MenuViewEvent extends MenuBaseEvent {

    @XmlElement(name = "MenuId")  
    private String MenuId ;         //指菜单ID,如果是个性化菜单,则可以通过这个字段,知道是哪个规则的菜单被点击了。

    public String getMenuId() {
        return MenuId;
    }
    public void setMenuId(String menuId) {
        MenuId = menuId;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *  <ToUserName><![CDATA[toUser]]></ToUserName>
     *  <FromUserName><![CDATA[FromUser]]></FromUserName>
     *  <CreateTime>123456789</CreateTime>
     *  <MsgType><![CDATA[event]]></MsgType>
     *  <Event><![CDATA[VIEW]]></Event>
     *  <EventKey><![CDATA[www.qq.com]]></EventKey>
     *  <MenuId>MENUID</MenuId>
     * </xml>
     */
    public static MenuViewEvent requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "menuViewEvent");
        JAXBContext context = JAXBContext.newInstance(MenuViewEvent.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (MenuViewEvent)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}
2017-04-22 10:18:33 hq0556 阅读数 219
  • 微信开发13-微信门店开发(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信公众平台开发之微信门店开发是子恒老师《微信公众平台开发》视频教程的第13部。详细讲解了用php进行微信门店的开发。内容包含新增微信门店,列表门店列表,获取和修改门店信息等等。欢迎反馈,微信号:QQ68183131

    11214 人正在学习 去看看 秦子恒

本例中有些引用的类与方法不做过多介绍,之后会提供完整源码下载,请自行查看。

本篇根据开发者文档-接收普通消息编写。请对照查看,一些传入与返回参数就不过多介绍。地址为:https://mp.weixin.qq.com/wiki/14/f79bdec63116f376113937e173652ba2.html


当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。请注意:

  • 关于重试的消息排重,推荐使用msgid排重。
  • 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。详情请见“发送消息-被动回复消息”。
  • 为了保证更高的安全保障,开发者可以在公众平台官网的开发者中心处设置消息加密。开启加密后,用户发来的消息会被加密,公众号被动回复用户的消息也需要加密(但开发者通过客服接口等API调用形式向用户发送消息,则不受影响)。

消息类型有:

  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_SHORTVIDEO      = "shortvideo"; //请求消息类型:小视频
    public static final String REQ_MESSAGE_TYPE_LINK            = "link";                   //请求消息类型:链接
    public static final String REQ_MESSAGE_TYPE_LOCATION        = "location";           //请求消息类型:地理位置
    public static final String REQ_MESSAGE_TYPE_EVENT           = "event";              //请求消息类型:推送
/*
 * 接收普通消息
 * http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
 */
@XmlRootElement
public class BaseReqMsg {

    @XmlElement(name = "ToUserName")  
    private String ToUserName;          // 开发者微信号

    @XmlElement(name = "FromUserName")  
    private String FromUserName;        // 发送方帐号(一个OpenID)

    @XmlElement(name = "CreateTime")  
    private long CreateTime;            // 消息创建时间 (整型)

    @XmlElement(name = "MsgType")  
    private String MsgType;             // 消息类型(text/image/location/link)

    @XmlElement(name = "MsgId")  
    private long MsgId;                 // 消息id,64位整型
}

文本消息

/*
 * MsgType--->
 * text:文本消息
 */
@XmlRootElement
public class TextReqMsg extends BaseReqMsg {

    @XmlElement(name = "Content") 
    private String Content;     //文本消息内容

    public String getContent() {
        return Content;
    }
    public void setContent(String content) {
        Content = content;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *   <ToUserName><![CDATA[toUser]]></ToUserName>
     *   <FromUserName><![CDATA[fromUser]]></FromUserName>
     *   <CreateTime>1348831860</CreateTime>
     *   <MsgType><![CDATA[text]]></MsgType>
     *   <Content><![CDATA[this is a test]]></Content>
     *   <MsgId>1234567890123456</MsgId>
     * </xml>
     */
    public static TextReqMsg requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "textReqMsg");
        JAXBContext context = JAXBContext.newInstance(TextReqMsg.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (TextReqMsg)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

图片消息

/*
 * MsgType--->
 * image:图片消息
 */
@XmlRootElement
public class ImageReqMsg extends BaseReqMsg {

    @XmlElement(name = "PicUrl")  
    private String PicUrl ;     //图片链接(由系统生成)

    @XmlElement(name = "MediaId")  
    private String MediaId ;    //  图片消息媒体id,可以调用多媒体文件下载接口拉取数据。

    public String getPicUrl() {
        return PicUrl;
    }
    public void setPicUrl(String picUrl) {
        PicUrl = picUrl;
    }

    public String getMediaId() {
        return MediaId;
    }
    public void setMediaId(String mediaId) {
        MediaId = mediaId;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *   <ToUserName><![CDATA[toUser]]></ToUserName>
     *   <FromUserName><![CDATA[fromUser]]></FromUserName>
     *   <CreateTime>1348831860</CreateTime>
     *   <MsgType><![CDATA[image]]></MsgType>
     *   <PicUrl><![CDATA[this is a url]]></PicUrl>
     *   <MediaId><![CDATA[media_id]]></MediaId>
     *   <MsgId>1234567890123456</MsgId>
     * </xml>
     */
    public static ImageReqMsg requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "imageReqMsg");
        JAXBContext context = JAXBContext.newInstance(ImageReqMsg.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (ImageReqMsg)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

语音消息

/*
 * MsgType--->
 * voice:语音消息
 */
@XmlRootElement
public class VoiceReqMsg extends BaseReqMsg {

    @XmlElement(name = "MediaId")
    private String MediaId;     //语音消息媒体id,可以调用多媒体文件下载接口拉取该媒体

    @XmlElement(name = "Format")
    private String Format;      //  语音格式:amr

    @XmlElement(name = "Recognition")
    private String Recognition; //  语音识别结果,UTF8编码.需开通开通语音识别

    public String getMediaID() {
        return MediaId;
    }
    public void setMediaID(String mediaID) {
        MediaId = mediaID;
    }

    public String getFormat() {
        return Format;
    }
    public void setFormat(String format) {
        Format = format;
    }

    public String getRecognition() {
        return Recognition;
    }
    public void setRecognition(String recognition) {
        Recognition = recognition;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *  <ToUserName><![CDATA[toUser]]></ToUserName>
     *  <FromUserName><![CDATA[fromUser]]></FromUserName>
     *  <CreateTime>1357290913</CreateTime>
     *  <MsgType><![CDATA[voice]]></MsgType>
     *  <MediaId><![CDATA[media_id]]></MediaId>
     *  <Format><![CDATA[Format]]></Format>
     *  <Recognition><![CDATA[腾讯微信团队]]></Recognition>
     *  <MsgId>1234567890123456</MsgId>
     * </xml>
     */
    public static VoiceReqMsg requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "voiceReqMsg");
        JAXBContext context = JAXBContext.newInstance(VoiceReqMsg.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (VoiceReqMsg)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

视频消息/小视频消息

/*
 * MsgType--->
 * shortvideo:小视频消息
 * video:视频消息
 */
@XmlRootElement
public class VideoReqMsg extends BaseReqMsg {

    @XmlElement(name = "MediaId") 
    private String MediaId;     //视频消息媒体id,可以调用多媒体文件下载接口拉取数据。

    @XmlElement(name = "ThumbMediaId") 
    private String ThumbMediaId;//视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。

    public String getMediaId() {
        return MediaId;
    }
    public void setMediaId(String mediaId) {
        MediaId = mediaId;
    }

    public String getThumbMediaId() {
        return ThumbMediaId;
    }
    public void setThumbMediaId(String thumbMediaId) {
        ThumbMediaId = thumbMediaId;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *  <ToUserName><![CDATA[toUser]]></ToUserName>
     *  <FromUserName><![CDATA[fromUser]]></FromUserName>
     *  <CreateTime>1357290913</CreateTime>
     *  <MsgType><![CDATA[video|shortvideo ]]></MsgType>
     *  <MediaId><![CDATA[media_id]]></MediaId>
     *  <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
     *  <MsgId>1234567890123456</MsgId>
     * </xml>
     */
    public static VideoReqMsg requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "videoReqMsg");
        JAXBContext context = JAXBContext.newInstance(VideoReqMsg.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (VideoReqMsg)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

地理位置消息

/*
 * MsgType--->
 * location:地理位置消息
 */
@XmlRootElement
public class LocationReqMsg extends BaseReqMsg {

    @XmlElement(name = "Location_X") 
    private float Location_X;       //地理位置维度

    @XmlElement(name = "Location_Y") 
    private float Location_Y;       //地理位置经度

    @XmlElement(name = "Scale") 
    private float Scale;            //地图缩放大小

    @XmlElement(name = "Label") 
    private String Label;           //地理位置信息

    public float getLocation_X() {
        return Location_X;
    }
    public void setLocation_X(float location_X) {
        Location_X = location_X;
    }

    public float getLocation_Y() {
        return Location_Y;
    }
    public void setLocation_Y(float location_Y) {
        Location_Y = location_Y;
    }

    public float getScale() {
        return Scale;
    }
    public void setScale(float scale) {
        Scale = scale;
    }

    public String getLabel() {
        return Label;
    }
    public void setLabel(String label) {
        Label = label;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *  <ToUserName><![CDATA[toUser]]></ToUserName>
     *  <FromUserName><![CDATA[fromUser]]></FromUserName>
     *  <CreateTime>1351776360</CreateTime>
     *  <MsgType><![CDATA[location]]></MsgType>
     *  <Location_X>23.134521</Location_X>
     *  <Location_Y>113.358803</Location_Y>
     *  <Scale>20</Scale>
     *  <Label><![CDATA[位置信息]]></Label>
     *  <MsgId>1234567890123456</MsgId>
     * </xml>
     */
    public static LocationReqMsg requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "locationReqMsg");
        JAXBContext context = JAXBContext.newInstance(LocationReqMsg.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (LocationReqMsg)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}

链接消息

/*
 * MsgType--->
 * link:链接消息
 */
@XmlRootElement
public class LinkReqMsg extends BaseReqMsg {

    @XmlElement(name = "Title") 
    private String Title;       //消息标题

    @XmlElement(name = "Description") 
    private String Description; //消息描述

    @XmlElement(name = "Url") 
    private String Url;         //消息链接

    public String getTitle() {
        return Title;
    }
    public void setTitle(String title) {
        Title = title;
    }

    public String getDescription() {
        return Description;
    }
    public void setDescription(String description) {
        Description = description;
    }

    public String getUrl() {
        return Url;
    }
    public void setUrl(String url) {
        Url = url;
    }

    /*
     * 接收到的文本示例
     * <xml>
     *  <ToUserName><![CDATA[toUser]]></ToUserName>
     *  <FromUserName><![CDATA[fromUser]]></FromUserName>
     *  <CreateTime>1351776360</CreateTime>
     *  <MsgType><![CDATA[link]]></MsgType>
     *  <Title><![CDATA[公众平台官网链接]]></Title>
     *  <Description><![CDATA[公众平台官网链接]]></Description>
     *  <Url><![CDATA[url]]></Url>
     *  <MsgId>1234567890123456</MsgId>
     * </xml>
     */
    public static LinkReqMsg requestMessage(String xmlStr) throws JAXBException {
        xmlStr = xmlStr.replace("xml", "linkReqMsg");
        JAXBContext context = JAXBContext.newInstance(LinkReqMsg.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (LinkReqMsg)unmarshaller.unmarshal(new StringReader(xmlStr));
    }
}
2018-01-15 22:14:46 MYTLJP 阅读数 4952
  • 微信开发13-微信门店开发(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信公众平台开发之微信门店开发是子恒老师《微信公众平台开发》视频教程的第13部。详细讲解了用php进行微信门店的开发。内容包含新增微信门店,列表门店列表,获取和修改门店信息等等。欢迎反馈,微信号:QQ68183131

    11214 人正在学习 去看看 秦子恒

用了好几个小时的时间,整理了一下关于公众号的思维导图,由于CSDN不能上传相对应的文件,所以萍子一一的分解开的截图附上来,希望对大家有所帮助哦~
因为是电脑设备自动截图,又鉴于内容比较多,可能不是太清楚,需要的小伙伴们,可以联系我,我可以随时发给你。

学习微信公众号需要的配置

这里写图片描述


微信开发的主体、请求方式、数据类型和环境

主体

这里写图片描述

请求方式

这里写图片描述
这里写图片描述

数据类型和环境

这里写图片描述


开始开发

获取access_token值并存储

这里写图片描述
这里写图片描述


账号管理

生成带参数的二维码

这里写图片描述

长链接转短链接

这里写图片描述


消息管理

获取微信服务器的IP地址

接收普通消息

接收事件推送

被动回复用户消息

这里写图片描述


微信网页授权

微信网页授权步骤

第一步:跳转页面,用户同意授权,获取code

这里写图片描述

第二步:通过code换取网页授权access_token(与普通的access_token不一样,具体见下方)
第三步:如果需要,刷新access_token值

这里写图片描述

第四步:拉取用户信息(需要scope为snsapi_userinfo)
第五步:附,检验授权凭证access_token是否有效,一般用不到

这里写图片描述


微信JS-SDK

说明

这里写图片描述

JS-SDK使用步骤

这里写图片描述

上传图片素材

这里写图片描述


微信公众号

握手协议

这里写图片描述

自定义菜单

自定义菜单类型

这里写图片描述

自定义菜单的设置

这里写图片描述

自定义菜单参数说明

这里写图片描述

获取自定义菜单

这里写图片描述


自定义菜单事件推送/被动回复用户信息

自定义事件推送

这里写图片描述

被动回复用户信息

这里写图片描述

根据菜单类型的点击,被动回复

点击按钮事件

这里写图片描述

公众号首次被某个用户关注的推送

这里写图片描述

微信扫一扫,并展示扫的内容

这里写图片描述

推送图文消息

这里写图片描述

回复图片消息
没有点击按钮

这里写图片描述

微信开发

阅读数 176

没有更多推荐了,返回首页