微信公众平台官网 https://mp.weixin.qq.com/,点击注册
选择订阅号(本文章只介绍个人账号,公司账号没试过,下次试了再发),之后注册部分不一一赘述。实在不会,网上可以搜到注册教程,完成注册。
如果对公众号没特别要求直接操作公众平台就可以了,这里主要介绍java后台开发者调用微信接口的操作。
由于个人号不能操作模板,我们这里选择 “开发“->“开发者工具”->“公众平台测试账号”,点击进入
进入页面记住自己的appID和appsecret(很重要)
下面配置接口信息,这里我的理解是将我们的程序与微信服务器连接起来,让我的程序成为开发者方便开发。
下面进入eclipse编写java程序
我用的是maven项目来管理的
首先:
package com.dajingzhu.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
//工具类在后面我会发出来
import com.alibaba.fastjson.JSONArray;
import com.dajingzhu.bean.SHA1;
import com.dajingzhu.bean.Template;
import com.dajingzhu.bean.TemplateParam;
import com.dajingzhu.service.WechatService;
import com.dajingzhu.utils.CommonUtil;
import com.dajingzhu.utils.WeChatUtil;
import com.dajingzhu.utils.WeixinUtil;
import net.sf.json.JSONObject;
@Controller
//这个和之后要设置的url息息相关
@RequestMapping(value="/wx")
public class WeChatController {
private static int i=0;
//这里的token与之前说的接口配置的token要相同(注意,这个token与之后的accesstoken是不同的)
private String Token = "fjjjkl";
//主方法,接口配置的url也是定位到这个方法的
@RequestMapping(value = "/chat", method = { RequestMethod.GET, RequestMethod.POST })
@ResponseBody
public void liaotian( PrintWriter out,HttpServletRequest request, HttpServletResponse response) throws IOException {
//设置输入编码格式
request.setCharacterEncoding("UTF-8");
//设置输出编码格式
response.setCharacterEncoding("UTF-8");
System.out.println("进入chat");
//判断输入是否是get请求方式,个人理解:如果是get请求,说明在配置上图接口配置的请求是get方式,其他的不是get方式
boolean isGet = request.getMethod().toLowerCase().equals("get");
if (isGet) {
//如果是get请求得到微信加密签名等属性进行字典排序,access方法在下面
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
System.out.println(signature);
System.out.println(timestamp);
System.out.println(nonce);
System.out.println(echostr);
access(request, response);
} else {
// 进入POST聊天处理
i++;
System.out.println("enter post");
/* try {
// 接收消息并返回消息
acceptMessage(request, response);
} catch (IOException e) {
e.printStackTrace();
} */
if(request!=null) {
//如果请求头不为空,返回消息
WechatService ws= new WechatService();
String processRequest = ws.processRequest(request);
response.getWriter().write(processRequest);
processRequest=new String(processRequest.getBytes(), "Utf-8");
out.write(processRequest);
System.out.println("==============");
}
//i为计数,每次发送消息返回模板消息,五次之后不返回(为保障程序的纯洁性,这是单独的发送模板消息,之后我集成到其他程序上去了,如果逻辑啥的走不通不要惊讶,找找原因,这已经是大半完成品了),都在同一个页面,要理解微信的工作方式
//根据AppID和appsecret生成accesstoken;
String access_token=WeixinUtil.getAccessToken("让你记住的appid","让你记住的appsecret");
System.out.println(access_token);
//根据从工具类得到的accesstoken得到所有关注本公众号的用户数组
JSONArray openIdArray = WeChatUtil.getOpenIds(access_token);
//每个用户循环发送
for (Object openId : openIdArray) {
System.out.println(openId.toString());
//模板实体类
Template tem=new Template();
//模板id
tem.setTemplateId("模板id"); 】
//模板背景色
tem.setTopColor("#00DD00");
//要发送的用户的openid
tem.setToUser(openId.toString());
//点击模板可以跳转的url
tem.setUrl("");
//向模板id插入东西,可以是从另一个方法传来的对象哦,那样就可以实现模板的实时变动
里面的first等字段都是和市直模板内容对应的,微信模板不知道怎么创建百度一下就好了,当时我写程序可都是面向百度编程
List
paras.add(new TemplateParam("first","我们已收到您的货款,开始为您打包商品,请耐心等待: )","#FF3333"));
paras.add(new TemplateParam("keyword1","¥20.00","#0044BB"));
paras.add(new TemplateParam("keyword2","火烧牛干巴","#0044BB"));
// paras.add(new TemplateParam("alarm_type","火烧牛干巴","#0044BB"));
paras.add(new TemplateParam("keyword3","火烧牛干巴","#0044BB"));
paras.add(new TemplateParam("remark","感谢你对我们商城的支持!!!!","#AAAAAA"));
//利用方法发送模板
tem.setTemplateParamList(paras);
//System.out.println(tem);
//查看返回结果,返回的是状态码和json数据,状态码各代表不同意思,200是成功
boolean result=sendTemplateMsg(access_token,tem);
System.out.println(result);
}
}
}
}
//进行微信字典排序加密,防止数据泄露
private String access(HttpServletRequest request, HttpServletResponse response) {
// 验证URL真实性
System.out.println("进入验证access");
String signature = request.getParameter("signature");// 微信加密签名
String timestamp = request.getParameter("timestamp");// 时间戳
String nonce = request.getParameter("nonce");// 随机数
String echostr = request.getParameter("echostr");// 随机字符串
List
params.add(Token);
params.add(timestamp);
params.add(nonce);
// 1. 将token、timestamp、nonce三个参数进行字典序排序
Collections.sort(params, new Comparator
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
// 2. 将三个参数字符串拼接成一个字符串进行sha1加密
String temp = SHA1.encode(params.get(0) + params.get(1) + params.get(2));
if (temp.equals(signature)) {
try {
response.getWriter().write(echostr);
System.out.println("成功返回 echostr:" + echostr);
return echostr;
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("失败 认证");
return null;
}
//发送模板消息的方法
public static boolean sendTemplateMsg(String token,Template template){
boolean flag=false;
String requestUrl="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
requestUrl=requestUrl.replace("ACCESS_TOKEN", token);
JSONObject jsonResult=CommonUtil.httpsRequest(requestUrl, "POST", template.toJSON());
System.out.println(jsonResult);
if(jsonResult!=null){
System.out.println(jsonResult);
int errorCode=jsonResult.getInt("errcode");
String errorMessage=jsonResult.getString("errmsg");
if(errorCode==0){
flag=true;
}else{
System.out.println("模板消息发送失败:"+errorCode+","+errorMessage);
flag=false;
}
}
return flag;
}
}
(这里用了大量的工具类,我也是从网上找的,有的重复,有的有错 ,自求多福吧)
package com.dajingzhu.service;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.dajingzhu.bean.TextMessage;
import com.dajingzhu.utils.WechatMessageUtil;
public class WechatService {
public String processRequest(HttpServletRequest request) {
Map
// 发送方帐号(一个OpenID)
String fromUserName = map.get("FromUserName");
// 开发者微信号
String toUserName = map.get("ToUserName");
// 消息类型
String msgType = map.get("MsgType");
// 默认回复一个"success"
String responseMessage = "success";
// 对消息进行处理
if (WechatMessageUtil.MESSAGE_TEXT.equals(msgType)) {// 文本消息
System.out.println("传来的是text");
TextMessage textMessage = new TextMessage();
textMessage.setMsgType(WechatMessageUtil.MESSAGE_TEXT);
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(System.currentTimeMillis());
textMessage.setContent("我已经受到你发来的消息了");
System.out.println(textMessage);
responseMessage = WechatMessageUtil.textMessageToXml(textMessage);
System.out.println(responseMessage);
}
return responseMessage;
}
public void sendemplate() {
}
package com.dajingzhu.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import com.dajingzhu.bean.Token;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
/*
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;*/
/**
* 类名: CommonUtil
* 描述: 通用工具类
* 开发人员: souvc
* 创建时间: 2015-9-30
* 发布版本:V1.0
*/
public class CommonUtil {
//private static Logger log = LoggerFactory.makeNewLoggerInstance(CommonUtil.class);
// 凭证获取(GET)
public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/**
* 发送https请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
//log.error("连接超时:{}", ce);
ce.printStackTrace();
} catch (Exception e) {
/// log.error("https请求异常:{}", e);
e.printStackTrace();
}
return jsonObject;
}
/**
* 获取接口访问凭证
*
* @param appid 凭证
* @param appsecret 密钥
* @return
*/
public static Token getToken(String appid, String appsecret) {
Token token = null;
String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
// 发起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"));
e.printPartialStackTrace(null);
}
}
return token;
}
}
package com.dajingzhu.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class HttpUtil {
/*
* https请求
* requestUrl:请求地址
* requestMethod:GET / POST
* outputStr:POST请求数据,GET请传NULL
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
ce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
* http请求
* requestUrl:请求地址
* requestMethod:GET / POST
* outputStr:POST请求数据,GET请传NULL
*/
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
ce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
* http请求
* requestUrl:请求地址
*/
public static String httpRequest(String requestUrl) {
InputStream inputStream = null;
try {
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET");
httpUrlConn.connect();
// 获得返回的输入流
inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
return buffer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/*
* url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值,
*
URL字符转义
用其它字符替代吧,或用全角的。
+ URL 中+号表示空格 %2B
空格 URL中的空格可以用+号或者编码 %20
/ 分隔目录和子目录 %2F
? 分隔实际的URL和参数 %3F
% 指定特殊字符 %25
# 表示书签 %23
& URL 中指定的参数间的分隔符 %26
= URL 中指定参数的值 %3D
*/
public static String httpParameterFilter(String param){
String s = "";
if (param.length() == 0) return "";
s = param.replaceAll("+", "%2B");
s = s.replaceAll(" ", "%20");
s = s.replaceAll("/", "%2F");
s = s.replaceAll("?", "%3F");
s = s.replaceAll("%'", "%25");
s = s.replaceAll("#'", "%23");
s = s.replaceAll("&'", "%26");
s = s.replaceAll("=", "%3D");
return s;
}
}
package com.dajingzhu.utils;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 类名: MyX509TrustManager
* 描述: 信任管理器
* 开发人员: fj
* 创建时间: 2018-6-12
* 发布版本:V1.0
*/
public class MyX509TrustManager implements X509TrustManager {
// 检查客户端证书
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 检查服务器端证书
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509证书数组
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
package com.dajingzhu.utils;
import java.io.Writer;
import java.lang.reflect.Field;
import com.dajingzhu.bean.XStreamCDATA;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
* xml 转换工具类
*
* @author morning
* @date 2015年2月16日 下午2:42:50
*/
public class SerializeXmlUtil {
public static XStream createXstream() {
return new XStream(new XppDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
boolean cdata = false;
Class> targetClass = null;
@Override
public void startNode(String name, @SuppressWarnings("rawtypes") Class clazz) {
super.startNode(name, clazz);
// 业务处理,对于用XStreamCDATA标记的Field,需要加上CDATA标签
if (!name.equals("xml")) {
cdata = needCDATA(targetClass, name);
} else {
targetClass = clazz;
}
}
@Override
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write(" writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
}
private static boolean needCDATA(Class> targetClass, String fieldAlias) {
boolean cdata = false;
// first, scan self
cdata = existsCDATA(targetClass, fieldAlias);
if (cdata)
return cdata;
// if cdata is false, scan supperClass until java.lang.Object
Class> superClass = targetClass.getSuperclass();
while (!superClass.equals(Object.class)) {
cdata = existsCDATA(superClass, fieldAlias);
if (cdata)
return cdata;
superClass = superClass.getClass().getSuperclass();
}
return false;
}
private static boolean existsCDATA(Class> clazz, String fieldAlias) {
if ("MediaId".equals(fieldAlias)) {
return true; // 特例添加 morning99
}
// scan fields
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 1. exists XStreamCDATA
if (field.getAnnotation(XStreamCDATA.class) != null) {
XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);
// 2. exists XStreamAlias
if (null != xStreamAlias) {
if (fieldAlias.equals(xStreamAlias.value()))// matched
return true;
} else {// not exists XStreamAlias
if (fieldAlias.equals(field.getName()))
return true;
}
}
}
return false;
}
}
package com.dajingzhu.utils;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dajingzhu.bean.WeChatContext;
/**
* 微信工具
* @Author wuwz
* @TypeName WeChatUtil
*/
@SuppressWarnings("unchecked")
public abstract class WeChatUtil {
// access_token有效毫秒记录数
public static long ACCESS_TOKEN_TIME = 0;
// jsapi_ticket有效毫秒记录数
public static long JSAPI_TICKET_TIME = 0;
// jsapi_ticket有效毫秒记录数
public static Map
// 微信配置上下文
public static WeChatContext context = WeChatContext.getInstance();
// 获取关注用户
public static JSONObject getUsersJSON(String token) {
try {
//请求接口地址
String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN";
//请求参数
requestUrl=requestUrl.replace("ACCESS_TOKEN", token);
//发起请求
String result = HttpUtil.httpRequest(requestUrl, "GET", requestUrl);
if(result != null && !"".equals(result)) {
return JSON.parseObject(result);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 获取关注用户的OpenIds
public static JSONArray getOpenIds(String token) {
try {
JSONObject usersJsonObj = getUsersJSON(token);
return (usersJsonObj.getJSONObject("data")).getJSONArray("openid");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.dajingzhu.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.dajingzhu.bean.TextMessage;
import com.thoughtworks.xstream.XStream;
public class WechatMessageUtil {
// 各种消息类型,除了扫带二维码事件
/**
* 文本消息
*/
public static final String MESSAGE_TEXT = "text";
/**
* 图片消息
*/
public static final String MESSAtGE_IMAGE = "image";
/**
* 图文消息
*/
public static final String MESSAGE_NEWS = "news";
/**
* 语音消息
*/
public static final String MESSAGE_VOICE = "voice";
/**
* 视频消息
*/
public static final String MESSAGE_VIDEO = "video";
/**
* 小视频消息
*/
public static final String MESSAGE_SHORTVIDEO = "shortvideo";
/**
* 地理位置消息
*/
public static final String MESSAGE_LOCATION = "location";
/**
* 链接消息
*/
public static final String MESSAGE_LINK = "link";
/**
* 事件推送消息
*/
public static final String MESSAGE_EVENT = "event";
/**
* 事件推送消息中,事件类型,subscribe(订阅)
*/
public static final String MESSAGE_EVENT_SUBSCRIBE = "subscribe";
/**
* 事件推送消息中,事件类型,unsubscribe(取消订阅)
*/
public static final String MESSAGE_EVENT_UNSUBSCRIBE = "unsubscribe";
/**
* 事件推送消息中,上报地理位置事件
*/
public static final String MESSAGE_EVENT_LOCATION_UP = "LOCATION";
/**
* 事件推送消息中,自定义菜单事件,点击菜单拉取消息时的事件推送
*/
public static final String MESSAGE_EVENT_CLICK = "CLICK";
/**
* 事件推送消息中,自定义菜单事件,点击菜单跳转链接时的事件推送
*/
public static final String MESSAGE_EVENT_VIEW = "VIEW";
/**
* 将xml转化为Map集合
*
* @param request
* @return
*/
public static Map
Map
SAXReader reader = new SAXReader();
InputStream ins = null;
try {
ins = request.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
Document doc = null;
try {
doc = reader.read(ins);
} catch (DocumentException e1) {
e1.printStackTrace();
}
Element root = doc.getRootElement();
@SuppressWarnings("unchecked")
List
for (Element e : list) {
map.put(e.getName(), e.getText());
}
try {
ins.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return map;
}
/**
* 文本消息转化为xml
*
* @param textMessage
* @return
*/
public static String textMessageToXml(TextMessage textMessage) {
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
}
package com.dajingzhu.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
/**
* 公众平台通用接口工具类
*/
public class WeixinUtil {
/**
* 发起https请求并获取结果
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
ce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return jsonObject;
}
/**
* 获取access_token
*
* @param appid 凭证
* @param appsecret 密钥
* @return
*/
public static String getAccessToken(String appid, String appsecret) {
// 获取公众号access_token的链接
String access_token = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
String requestUrl = access_token.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
return jsonObject.getString("access_token");
} catch (JSONException e) {
}
}
return null;
}
/**
* 获取jsapi_ticket
*
* @param appid 凭证
* @param appsecret 密钥
* @return
*/
public static String getJsapiTicket(String accessToken) {
// 获取公众号jsapi_ticket的链接
String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
if (accessToken != null) {
String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
// String requestUrl = access_token_url.replace("APPID",
// appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
return jsonObject.getString("ticket");
} catch (JSONException e) {
}
}
} else {
System.out.println("*****token为空 获取ticket失败******");
}
return null;
}
}
package com.dajingzhu.bean;
/**
* @author gaowei.cheng
* 2016年1月19日
* 微信消息基类
*/
public class BaseWechatMessage {
/**
* 开发者微信号
*/
private String ToUserName;
/**
* 发送方帐号(一个OpenID)
*/
private String FromUserName;
/**
* 消息创建时间 (整型)
*/
private long CreateTime;
/**
* 消息类型
*/
private String MsgType;
/**
* 消息id,64位整型
*/
private String MsgId;
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;
}
public String getMsgId() {
return MsgId;
}
public void setMsgId(String msgId) {
MsgId = msgId;
}
}
package com.dajingzhu.bean;
import java.security.MessageDigest;
public final class SHA1 {
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* Takes the raw bytes from the digest and formats them correct.
*
* @param bytes
* the raw bytes from the digest.
* @return the formatted bytes.
*/
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
// 把密文转换成十六进制的字符串形式
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
public static String encode(String str) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(str.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package com.dajingzhu.bean;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* POST的XML数据包转换为消息接受对象
*
*
* 由于POST的是XML数据包,所以不确定为哪种接受消息,
* 所以直接将所有字段都进行转换,最后根据MsgType字段来判断取何种数据
*
package com.dajingzhu.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
public class MediaIdMessage {
@XStreamAlias("MediaId")
@XStreamCDATA
private String MediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
package com.dajingzhu.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
*
* @author morning
* @date 2015年2月16日 下午2:29:32
*/
@XStreamAlias("xml")
public class OutputMessage {
@XStreamAlias("ToUserName")
@XStreamCDATA
private String ToUserName;
@XStreamAlias("FromUserName")
@XStreamCDATA
private String FromUserName;
@XStreamAlias("CreateTime")
private Long CreateTime;
@XStreamAlias("MsgType")
@XStreamCDATA
private String MsgType = "text";
private ImageMessage Image;
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;
}
public ImageMessage getImage() {
return Image;
}
public void setImage(ImageMessage image) {
Image = image;
}
}
package com.dajingzhu.bean;
import java.util.List;
public class Template {
// 消息接收方
private String toUser;
// 模板id
private String templateId;
// 模板消息详情链接
private String url;
// 消息顶部的颜色
private String topColor;
// 参数列表
private List
public String getToUser() {
return toUser;
}
public void setToUser(String toUser) {
this.toUser = toUser;
}
public String getTemplateId() {
return templateId;
}
public void setTemplateId(String templateId) {
this.templateId = templateId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTopColor() {
return topColor;
}
public void setTopColor(String topColor) {
this.topColor = topColor;
}
public String toJSON() {
StringBuffer buffer = new StringBuffer();
buffer.append("{");
buffer.append(String.format("\"touser\":\"%s\"", this.toUser)).append(",");
buffer.append(String.format("\"template_id\":\"%s\"", this.templateId)).append(",");
buffer.append(String.format("\"url\":\"%s\"", this.url)).append(",");
buffer.append(String.format("\"topcolor\":\"%s\"", this.topColor)).append(",");
buffer.append("\"data\":{");
TemplateParam param = null;
for (int i = 0; i < this.templateParamList.size(); i++) {
param = templateParamList.get(i);
// 判断是否追加逗号
if (i < this.templateParamList.size() - 1){
buffer.append(String.format("\"%s\": {\"value\":\"%s\",\"color\":\"%s\"},", param.getName(), param.getValue(), param.getColor()));
}else{
buffer.append(String.format("\"%s\": {\"value\":\"%s\",\"color\":\"%s\"}", param.getName(), param.getValue(), param.getColor()));
}
}
buffer.append("}");
buffer.append("}");
return buffer.toString();
}
public List
return templateParamList;
}
public void setTemplateParamList(List
this.templateParamList = templateParamList;
}
}
package com.dajingzhu.bean;
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;
}
@Override
public String toString() {
return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn + "]";
}
}
package com.dajingzhu.bean;
/**
* 微信基础配置上下文
* @Author wuwz
* @TypeName WeChatContext
*/
public class WeChatContext {
private WeChatContext() {}
private static WeChatContext context;
private String appId;
private String appSecrct;
private String validateUrl;
private String token;
private String templateId;
public static WeChatContext getInstance() {
if(context == null) {
context = new WeChatContext();
}
return context;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getAppSecrct() {
return appSecrct;
}
public void setAppSecrct(String appSecrct) {
this.appSecrct = appSecrct;
}
public String getValidateUrl() {
return validateUrl;
}
public void setValidateUrl(String validateUrl) {
this.validateUrl = validateUrl;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getTemplateId() {
return templateId;
}
public void setTemplateId(String templateId) {
this.templateId = templateId;
}
}
将写好的程序发布到Tomcat上,而微信接口开发者配置只接受80端口,我的解决方案是Ngrok反向代理,模拟80端口(我前面的文章有写过怎么设置ngork反向代理),把地址填写到接口配置的url上,设置token,点击保存,保存成功就能调用接口,如果不能调用就是程序的问题,检测程序,排错。