微信公众号开发学习

来源:互联网 发布:ubuntu嵌入式工控机 编辑:程序博客网 时间:2024/05/17 01:06

微信公众号开发学习

1、Readme说明:微信公众号平台开发最好用PHP,但Java也是可以实现的,下面代码用Java语言演示了HttpURLConnection的使用,成为公众号开发者,接收微信公众号信息,响应文本消息,发布菜单,获取用户基本信息等操作。

下面会给出供参考的程序源代码。

 

2、XStream简单介绍:

1XStream可以将Java对象和xml文档之间相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换。

2Javaxml,用toXML()方法。

XmlJava,用fromXML()方法。

(3)在没有任何设置默认情况下,Javaxml的映射,是Java成员名对应xml的元素名,Java类的全名对应xml根元素的名字。而实际中,往往是xmljava类都有了,需要相互转换,必须进行别名映射。

(4)别名配置包括三种情况:

①类别名,用aliasString nameClass type

②类成员别名,用aliasFieldString aliasClass definedInString fieldName

③类成员作为属性别名,用aliasAttributeClass definedInString attributeNameString alias),单独命名没有意义,还要通过useAttributeForClass definedInString fieldName)应用到某个类上。


3、下面是包及类的关系图:



4、源代码:

(1)action包

****action

********MainAction.java

********TestAction.java

①MainAction.java

package com.remoa.action;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.ServletOutputStream;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.remoa.common.util.ConfigureUtil;import com.remoa.common.util.MessageUtil;import com.remoa.common.util.SignUtil;import com.remoa.domain.message.TextResponse;import com.remoa.domain.message.WeixinRequest;/** * 处理事务逻辑的主类(验证登录,接收消息及回复消息等) * @author Remoa * */@WebServlet("/MainAction")public class MainAction extends HttpServlet {private static final long serialVersionUID = 1L;    private static final String charset = ConfigureUtil.getValue("charset");           public MainAction() {        super();    }protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("MainAction.doGet():start!");response.setCharacterEncoding(charset);request.setCharacterEncoding(charset);//获取必要的参数,验证服务器地址的有效性String token = request.getParameter("token");//密码String signature = request.getParameter("signature");//微信加密签名String timestamp = request.getParameter("timestamp");//时间戳String nonce = request.getParameter("nonce");//随机数String echostr = request.getParameter("echostr");//随机字符串System.out.println(signature + " " + echostr);//调用登录工具类进行验证boolean sign = SignUtil.validSign(signature, token, timestamp, nonce);ServletOutputStream outputStream = response.getOutputStream();//验证成功则返回随机字符串内容,否则验证失败if(sign){outputStream.write(echostr.getBytes());outputStream.flush();}else{outputStream.write("验证失败".getBytes());outputStream.flush();}}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("MainAction.doPost():start!");request.setCharacterEncoding(charset);response.setCharacterEncoding(charset);ServletInputStream inputStream = request.getInputStream();//获取微信请求消息WeixinRequest xinReq = MessageUtil.fromXmlToWeixinReq(inputStream);//将xml字符串转换为WeixinRequest对象TextResponse textResponse = new TextResponse();textResponse.setToUserName(xinReq.getFromUserName());//实现响应的开发者微信号textResponse.setFromUserName(xinReq.getToUserName());//响应传达的接收方账号textResponse.setCreateTime(System.currentTimeMillis());//返回系统当前时间textResponse.setMsgType("text");//响应文本消息textResponse.setContent("小编已收到您的消息");//回复的消息内容String respStr = MessageUtil.toXmlFromResp(textResponse);response.getOutputStream().write(respStr.getBytes());}}

②TestAction.java

package com.remoa.action;import java.io.IOException;import java.util.Scanner;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 此类用于测试连接成功后接收消息是否成功 * @author Remoa * */@WebServlet("/TestAction")public class TestAction extends HttpServlet {private static final long serialVersionUID = 1L;           public TestAction() {        super();    }protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.getWriter().append("Served at: ").append(request.getContextPath());}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ServletInputStream inputStream = request.getInputStream();Scanner scanner = new Scanner(inputStream, "UTF-8");while(scanner.hasNextLine()){System.out.println(scanner.nextLine());}scanner.close();}}

(2)common包

****common

********util

************ConfigureUtil.java

************HttpUtil.java

************MessageUtil.java

************SignUtil.java

ConfigureUtil.java

package com.remoa.common.util;import java.io.IOException;import java.io.InputStream;import java.util.Properties;/** * 获取配置信息工具类 * @author Remoa * */public class ConfigureUtil {private static Properties pro;static{InputStream is = ConfigureUtil.class.getClassLoader().getResourceAsStream("conf.properties");//通过类加载器返回作为输入流读取配置文件pro = new Properties();try {pro.load(is);//从输入流中读取属性列表is.close();} catch (IOException e) {e.printStackTrace();System.out.println("发生了I/O异常错误");}}/** * 从配置文件中获得属性值 * @param key 键 * @return value 返回键对应的值 */public static String getValue(String key){return pro.getProperty(key);}/** * 仅用于测试该配置信息工具类是否能获取到配置文件中的值 * @param args */public static void main(String[] args){String value = ConfigureUtil.getValue("charset");System.out.println(value);}}

HttpUtil.java

package com.remoa.common.util;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.Reader;import java.io.UnsupportedEncodingException;import java.net.MalformedURLException;import java.net.ProtocolException;import java.net.URL;import sun.net.www.protocol.http.HttpURLConnection;/** * Http连接工具类 * @author Remoa * */public class HttpUtil {/** * 发送http请求 * @param url 请求地址 * @param method 请求方法 * @param param 请求参数 * @param charset 字符集 * @return 返回请求结果 */public static String sendHttpReq(String url, String method, String param, String charset){HttpURLConnection httpURLConnection = null;//生成请求连接到Http服务器BufferedOutputStream bufferedOutputStream = null;// 缓冲输出流BufferedReader bufferedReader = null;//读取字符输入流URL urlObj;try {urlObj = new URL(url);httpURLConnection = (HttpURLConnection)urlObj.openConnection();//连接url所引用的远程对象} catch (MalformedURLException e) {e.printStackTrace();System.out.println("出现了使用未知协议错误");} catch (IOException e) {e.printStackTrace();System.out.println("出现了I/O异常错误");}httpURLConnection.setDoInput(true);//读取指定url服务器的资源if(param != null){httpURLConnection.setDoOutput(true);//写入数据到指定url服务器}httpURLConnection.setUseCaches(false);//不允许连接使用缓存httpURLConnection.setReadTimeout(1000 * 60);//设置读超时,此处设置为1分钟,单位为毫秒httpURLConnection.setConnectTimeout(1000 * 60);//设置建立连接超时,此处设置为1分钟,单位为毫秒try {httpURLConnection.setRequestMethod(method);} catch (ProtocolException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("无法重置方法或者请求的方法对 HTTP 无效");}//设置请求方法try {if(param != null){bufferedOutputStream = new BufferedOutputStream(httpURLConnection.getOutputStream());bufferedOutputStream.write(param.getBytes());bufferedOutputStream.flush();bufferedOutputStream.close();}} catch (IOException e) {e.printStackTrace();System.out.println("缓冲输出流出现了I/O异常错误");}try {bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), charset));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("读取字符输入流出现了I/O异常错误");}StringBuilder stringBuilder = new StringBuilder();//提供了与StringBuffer兼容的api,当字符缓冲区被单个线程所使用时,优先使用此类,因为其比StringBuffer要快String line = null;//读取一个文本行操作try {if((line = bufferedReader.readLine()) != null){stringBuilder.append(line).append("\n");}bufferedReader.close();} catch (IOException e) {e.printStackTrace();System.out.println("读取字符输入流出现了I/O异常错误");}httpURLConnection.disconnect();//指示近期服务器不太可能有其他请求return stringBuilder.toString();}/** * 实现关闭流、关闭连接的功能 * @param reader 关闭字符读取流 * @param inputStream 关闭输入流 * @param outputStream 关闭输出流 * @param httpURLConnection 关闭http服务器连接 */public static void closeAll(Reader reader, InputStream inputStream, OutputStream outputStream, HttpURLConnection httpURLConnection) {//关闭字符流if(reader != null){try {reader.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("发生I/O错误");}}if(inputStream != null){try {inputStream.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("发生I/O错误");}}if(outputStream != null){try {outputStream.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("发生I/O错误");}}if(httpURLConnection != null){httpURLConnection.disconnect();}}/** * 实现上传素材的功能 * @param url 请求地址 * @param filePath 文件路径 * @param charset 字符编码方式 * @return String 表单地址 */public static String upload(String url, String filePath, String charset) {HttpURLConnection httpURLConnection = null;//生成请求连接到Http服务器BufferedOutputStream bufferedOutputStream = null;// 缓冲输出流BufferedReader bufferedReader = null;//读取字符输入流BufferedInputStream fileInput = null;URL urlObj;try {urlObj = new URL(url);httpURLConnection = (HttpURLConnection)urlObj.openConnection();//连接url所引用的远程对象} catch (MalformedURLException e) {e.printStackTrace();System.out.println("出现了使用未知协议错误");} catch (IOException e) {e.printStackTrace();System.out.println("出现了I/O异常错误");}httpURLConnection.setDoInput(true);//允许读取指定url服务器的资源httpURLConnection.setDoOutput(true);//允许写入数据到指定url服务器httpURLConnection.setUseCaches(false);//不允许连接使用缓存httpURLConnection.setReadTimeout(1000 * 60);//设置读超时,此处设置为1分钟,单位为毫秒httpURLConnection.setConnectTimeout(1000 * 60);//设置建立连接超时,此处设置为1分钟,单位为毫秒try {httpURLConnection.setRequestMethod("POST");//设置请求方法} catch (ProtocolException e) {e.printStackTrace();System.out.println("无法重置方法或者请求的方法对 HTTP 无效");}String boundary = String.valueOf(System.currentTimeMillis());httpURLConnection.addRequestProperty("Content-Type", "multipart/form-data:boundary=" + boundary);//设置请求头StringBuilder headstr = new StringBuilder("----");headstr.append(boundary).append("\r\n").append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(filePath).append("\"").append("\r\n").append("Content-Type: application/octet-stream\r\n\r\n");//设置附件表单信息try {bufferedOutputStream = new BufferedOutputStream(httpURLConnection.getOutputStream());} catch (IOException e) {e.printStackTrace();System.out.println("创建输出流时发生 I/O 错误");}try {bufferedOutputStream.write(headstr.toString().getBytes());//写入表单信息} catch (IOException e) {e.printStackTrace();System.out.println("写入时发生I/O错误");}try {bufferedOutputStream.flush();} catch (IOException e) {e.printStackTrace();System.out.println("刷新缓冲输出流时发生I/O错误");}//写入附件try {fileInput = new BufferedInputStream(new FileInputStream(filePath));} catch (FileNotFoundException e) {e.printStackTrace();System.out.println("没有找到文件");}byte[] bytebuf = new byte[1024];int len = 0;try {while((len = fileInput.read(bytebuf)) != -1){bufferedOutputStream.write(bytebuf, 0, len);bufferedOutputStream.write(("\r\n--" + boundary + "--\r\n").getBytes(charset));bufferedOutputStream.flush();bufferedOutputStream.close();fileInput.close();}} catch (IOException e) {e.printStackTrace();System.out.println("发生I/O异常");}try {bufferedOutputStream.write(("\r\n--" + boundary + "--\r\n").getBytes(charset));} catch (UnsupportedEncodingException e) {e.printStackTrace();System.out.println("不支持该字符编码");} catch (IOException e) {e.printStackTrace();System.out.println("发生I/O异常");}try {bufferedOutputStream.flush();bufferedOutputStream.close();fileInput.close();} catch (IOException e) {e.printStackTrace();System.out.println("发生I/O异常");}StringBuilder stringBuilder = null;try {bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), charset));String line = null;stringBuilder = new StringBuilder();//提供了与StringBuffer兼容的api,当字符缓冲区被单个线程所使用时,优先使用此类,因为其比StringBuffer要快while((line = bufferedReader.readLine()) != null){stringBuilder.append(line).append("\n");}bufferedReader.close();} catch (UnsupportedEncodingException e) {e.printStackTrace();System.out.println("不支持该字符编码");} catch (IOException e) {e.printStackTrace();System.out.println("发生I/O异常");}httpURLConnection.disconnect();return stringBuilder.toString();}}

③MessageUtil.java

package com.remoa.common.util;import java.io.InputStream;import java.util.Scanner;import com.remoa.domain.message.TextResponse;import com.remoa.domain.message.WeixinRequest;import com.thoughtworks.xstream.XStream;/** * 消息处理工具类,包括接收消息及发送消息的处理 * @author Remoa * */public class MessageUtil {public static final String charset = ConfigureUtil.getValue("charset");/** * 将微信请求接收到的xml字符串转换为Java处理微信消息请求的类WeixinRequest对象 * @param in ServletInputStream输入流 * @return fromXML 返回WeixinRequest对象 */public static WeixinRequest fromXmlToWeixinReq(InputStream in){Scanner scan = new Scanner(in, charset);//从指定流中构造一个新的扫描器StringBuffer str = new StringBuffer();while(scan.hasNextLine()){str.append(scan.nextLine()).append("\r\n");}scan.close();System.out.println(str.toString());XStream xStream = new XStream();xStream.alias("xml", WeixinRequest.class);WeixinRequest fromXML = (WeixinRequest)xStream.fromXML(str.toString());System.out.println(fromXML);return fromXML;}/** * 将文本消息响应结果转换为xml字符串 * @param textResponse 文本消息响应对象 * @return toxml 返回xml字符串 */public static String toXmlFromResp(TextResponse textResponse){XStream xStream = new XStream();xStream.alias("xml", TextResponse.class);String toXml = xStream.toXML(textResponse);System.out.println(toXml.toString());return toXml;}}

④SignUtil.java

package com.remoa.common.util;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;/** * 登录工具类 * @author Remoa * */public class SignUtil {//开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:/** * 判断登录的有效性 * @param signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 * @param token 密码 * @param timestamp 时间戳 * @param nonce 随机数 * @return boolean 返回判断值true或false */public static boolean validSign(String signature, String token, String timestamp, String nonce){String[] paramArr = new String[]{token, timestamp, nonce};Arrays.sort(paramArr);//Arrays类用来操作数组(比如排序和搜索)的各种方法。sort对数组按数字升序进行排序。StringBuilder sb = new StringBuilder(paramArr[0]);sb.append(paramArr[1]).append(paramArr[2]);String ciphertext = null;try {MessageDigest md = MessageDigest.getInstance("SHA-1");//为应用程序提供信息摘要算法的功能byte[] digest = md.digest(sb.toString().getBytes());ciphertext = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;}private static String byteToStr(byte[] byteArray) {String rst = "";for (int i = 0; i < byteArray.length; i++) {rst += byteToHex(byteArray[i]);}return rst;}private static String byteToHex(byte b) {char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };char[] tempArr = new char[2];tempArr[0] = Digit[(b >>> 4) & 0X0F];tempArr[1] = Digit[b & 0X0F];String s = new String(tempArr);return s;}}

(3)domain包

****domain

********AccessToken

************AccessToken.java

********menu

************Menu.java

************MyButton.java

********message

************BaseMessageResponse.java

************ErrorMessage.java

************ImageResponseMessage.java

************TextResponse.java

************WeixinRequest.java

********user

************UserInfo.java

①AccessToken.java

package com.remoa.domain.AccessToken;/** * 接口调用凭据获取类 * @author Remoa * */public class AccessToken {private String access_token;//获取到的凭证private long expires_in;//凭证有效时间(单位:秒)public String getAccess_token() {return access_token;}public void setAccess_token(String access_token) {this.access_token = access_token;}public long getExpires_in() {return expires_in;}public void setExpires_in(long expires_in) {this.expires_in = expires_in;}}

②Menu.java

package com.remoa.domain.menu;import java.util.ArrayList;import java.util.List;import com.alibaba.fastjson.JSON;/** * 菜单实体类 * @author Remoa * */public class Menu {private List<MyButton> button = new ArrayList<MyButton>();public List<MyButton> getButton() {return button;}public void setButton(List<MyButton> button) {this.button = button;}public void addButton(MyButton button){this.getButton().add(button);}public static Menu getDefaultMenu(){Menu menu = new Menu();MyButton button1 = new MyButton();button1.setName("五绝风采");button1.setType("click");button1.setKey("Superman");MyButton button1_1 = new MyButton();button1_1.setName("黄药师");button1_1.setType("click");button1_1.setKey("Doctor Huang");MyButton button1_2 = new MyButton();button1_2.setName("欧阳锋");button1_2.setType("click");button1_2.setKey("Feng Ouyang");button1.addSub_button(button1_1);button1.addSub_button(button1_2);MyButton button2 = new MyButton();button2.setName("百度一下");button2.setType("view");button2.setUrl("http://www.baidu.com");menu.addButton(button1);menu.addButton(button2);return menu;}public static void main(String[] args){Menu menu = Menu.getDefaultMenu();System.out.println(JSON.toJSONString(menu, true));}}

③MyButton.java

package com.remoa.domain.menu;import java.util.ArrayList;import java.util.List;/** * 菜单上的按钮实体类定义 * @author Remoa * */public class MyButton {private List<MyButton> sub_button = new ArrayList<MyButton>();//二级菜单数组,个数应为1~5个private String type;//菜单的响应动作类型private String name;//菜单标题,不超过16个字节,子菜单不超过40个字节private String key;//菜单KEY值,用于消息接口推送,不超过128字节,click等点击类型必须private String url;//网页链接,用户点击菜单可打开链接,不超过1024字节,view类型必须private String media_id;//调用新增永久素材接口返回的合法media_id,media_id类型和view_limited类型必须public void addSub_button(MyButton button){this.sub_button.add(button);}public List<MyButton> getSub_button() {return sub_button;}public void setSub_button(List<MyButton> sub_button) {this.sub_button = sub_button;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMedia_id() {return media_id;}public void setMedia_id(String media_id) {this.media_id = media_id;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Button [sub_button=" + sub_button + ",type=" + type + ",name=" + name + "]";}}

④BaseMessageResponse.java

package com.remoa.domain.message;/** * 回复各类信息其所含参数构成的基础类 * @author Remoa * */public class BaseMessageResponse {private String ToUserName;//开发者微信号private String FromUserName;//发送方账号,一个openIDprivate long CreateTime;//消息创建时间 (整型)private String MsgType;//消息类型public String getToUserName() {return ToUserName;}public void setToUserName(String toUserName) {ToUserName = toUserName;}public String getFromUserName() {return FromUserName;}public void setFromUserName(String fromUserName) {FromUserName = fromUserName;}public long getCreateTime() {return CreateTime;}public void setCreateTime(long createTime) {CreateTime = createTime;}public String getMsgType() {return MsgType;}public void setMsgType(String msgType) {MsgType = msgType;}}

⑤ErrorMessage.java

package com.remoa.domain.message;/** * 出现错误时信息类 * @author Remoa * */public class ErrorMessage {private long errcode;//错误码private String errmsg;//错误信息public long getErrcode() {return errcode;}public void setErrcode(long errcode) {this.errcode = errcode;}public String getErrmsg() {return errmsg;}public void setErrmsg(String errmsg) {this.errmsg = errmsg;}}

⑥ImageResponseMessage.java

package com.remoa.domain.message;/** * 回复图片消息 * @author Remoa * */public class ImageResponseMessage extends BaseMessageResponse{private Image image = new Image();public String getMediaId() {return image.getMediaId();}public void setMediaId(String mediaId) {image.setMediaId(mediaId);}public Image getImage() {return image;}public void setImage(Image image) {this.image = image;}}/** * 图片类 * @author Remoa * */class Image{private String MediaId;//图片消息媒体id,可以调用多媒体文件下载接口拉取数据。public String getMediaId() {return MediaId;}public void setMediaId(String mediaId) {MediaId = mediaId;}}

⑦TextResponse.java

package com.remoa.domain.message;/** * 回复文本消息 * @author Remoa * */public class TextResponse extends BaseMessageResponse{private String Content;//文本消息内容public String getContent() {return Content;}public void setContent(String content) {Content = content;}}

⑧WeixinRequest.java

package com.remoa.domain.message;/** * 处理公众号请求类 * @author Remoa * */public class WeixinRequest {private String ToUserName;//接收方帐号(收到的OpenID)private String FromUserName;//开发者微信号private long CreateTime;//消息创建时间 (整型)private String MsgType;//消息类型private String Content;//回复文本消息特有,回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)//用户未关注时,进行关注后的事件推送的特有参数private String MsgId;//回复图片消息,通过素材管理接口上传多媒体文件,得到的id。private String Event;//事件类型,subscribeprivate String EventKey;//事件KEY值,qrscene_为前缀,后面为二维码的参数值private String Ticket;//二维码的ticket,可用来换取二维码图片public String getToUserName() {return ToUserName;}public void setToUserName(String toUserName) {ToUserName = toUserName;}public String getFromUserName() {return FromUserName;}public void setFromUserName(String fromUserName) {FromUserName = fromUserName;}public long getCreateTime() {return CreateTime;}public void setCreateTime(int createTime) {CreateTime = createTime;}public String getMsgType() {return MsgType;}public void setMsgType(String msgType) {MsgType = msgType;}public String getContent() {return Content;}public void setContent(String content) {Content = content;}public String getMsgId() {return MsgId;}public void setMsgId(String msgId) {MsgId = msgId;}public String getEvent() {return Event;}public void setEvent(String event) {Event = event;}public String getEventKey() {return EventKey;}public void setEventKey(String eventKey) {EventKey = eventKey;}public String getTicket() {return Ticket;}public void setTicket(String ticket) {Ticket = ticket;}@Overridepublic String toString() {return "WeiXinReq [ToUserName=" + ToUserName + ", FromUserName=" + FromUserName + ", CreateTime=" + CreateTime + ", MsgType=" + MsgType + ", Content=" + Content + ", MsgId=" + MsgId + ", Event=" + Event + ", EventKey=" + EventKey + ", Ticket=" + Ticket + "]";}}


⑨UserInfo.java

package com.remoa.domain.user; /* 获取用户基本信息(UnionID机制)在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID * (加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。 * 公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。 * @author Remoa * */public class UserInfo {private int subscribe;//用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。private String openid;//用户的标识,对当前公众号唯一private int sex;//用户的性别,值为1时是男性,值为2时是女性,值为0时是未知private String city;//用户所在城市private String country;//用户所在国家private String province;//用户所在省份private String language;//用户的语言,简体中文为zh_CNprivate String headimgurl;//用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。private String subscribe_time;//用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间private String unionid;//只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。private String remark;//公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注private String groupid;//用户所在的分组IDpublic int getSubscribe() {return subscribe;}public void setSubscribe(int subscribe) {this.subscribe = subscribe;}public String getOpenid() {return openid;}public void setOpenid(String openid) {this.openid = openid;}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getLanguage() {return language;}public void setLanguage(String language) {this.language = language;}public String getHeadimgurl() {return headimgurl;}public void setHeadimgurl(String headimgurl) {this.headimgurl = headimgurl;}public String getSubscribe_time() {return subscribe_time;}public void setSubscribe_time(String subscribe_time) {this.subscribe_time = subscribe_time;}public String getUnionid() {return unionid;}public void setUnionid(String unionid) {this.unionid = unionid;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}public String getGroupid() {return groupid;}public void setGroupid(String groupid) {this.groupid = groupid;}}

6 0