JAVA微信公众号推送信息
package weixin.util;import java.io.Serializable;/*
*AccessToken 对象
*/public classAccessTokenimplementsSerializable{ //获取到的凭证 private String accessToken;
//凭证有效时间,单位:秒 private int expiresin;
/** * @returnthe accessToken */ public String getAccessToken() {
return accessToken;
}
/** * @paramaccessToken the accessToken to set */ public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
/** * @returnthe expiresin */ public int getExpiresin() {
return expiresin;
}
/** * @paramexpiresin the expiresin to set */ public void setExpiresin(int expiresin) {
this.expiresin = expiresin;
}
public AccessToken() {
// TODO Auto-generated constructor stub }
}
package weixin.util;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import javax.net.ssl.X509TrustManager;/**
* 微信请求 - 信任管理器
*/public classMyX509TrustManagerimplementsX509TrustManager{ public MyX509TrustManager() {
// TODO Auto-generated constructor stub }
@Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override public X509Certificate[] getAcceptedIssuers() {
// return new X509Certificate[0]; return null;
}
}
package weixin.util;/**
* 模板详细信息
* 根据需求自己更改
*/public classTemplateData{ private String value;
private String color;
public TemplateData(String value,String color){
this.value = value;
this.color = color;
}
/** * @returnthe value */
public String getValue() {
return value;
}
/** * @paramvalue the value to set */
public void setValue(String value) {
this.value = value;
}
/** * @returnthe color */
public String getColor() {
return color;
}
/** * @paramcolor the color to set */
public void setColor(String color) {
this.color = color;
}
}
package weixin.util;import java.util.Map;/**
* 注册成功,通知模板消息实体类
*/
public classTemplateMessage{
//用户OpenID
private String touser;
private String template_id; //模板消息ID
private String url; //URL置空,在发送后,点模板消息进入一个空白页面(ios),或无法点击(android)。
private String topcolor; //标题颜色
private Map templateData; //模板详细信息
public static TemplateMessage New() {
return new TemplateMessage();
}
/** * @returnthe touser */
public String getTouser() {
return touser;
}
/** * @paramtouser the touser to set */
public void setTouser(String touser) {
this.touser = touser;
}
/** * @returnthe template_id */
public String getTemplate_id() {
return template_id;
}
/** * @paramtemplate_id the template_id to set */
public void setTemplate_id(String template_id) {
this.template_id = template_id;
}
/** * @returnthe url */
public String getUrl() {
return url;
}
/** * @paramurl the url to set */
public void setUrl(String url) {
this.url = url;
}
/** * @returnthe topcolor */
public String getTopcolor() {
return topcolor;
}
/** * @paramtopcolor the topcolor to set */
public void setTopcolor(String topcolor) {
this.topcolor = topcolor;
}
/** * @returnthe templateData */
public Map getTemplateData() {
return templateData;
}
/** * @paramtemplateData the templateData to set */
public void setTemplateData(Map templateData) {
this.templateData = templateData;
}
}
package weixin.util;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
public classWX_HttpsUtil{
private static Logger log = LoggerFactory.getLogger(WX_HttpsUtil.class);
/** * 发送https请求 * @paramrequestUrl 请求地址 * @paramrequestMethod 请求方式(GET、POST) * @paramoutputStr 提交的数据 * @returnJSONObject(通过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.parseObject(buffer.toString());
} catch (ConnectException ce) {
log.error("连接超时:{}", ce);
} catch (Exception e) {
log.error("https请求异常:{}", e);
}
return jsonObject;
}
}
package weixin.util;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
public classWX_TemplateMsgUtil{
private static Logger log = LoggerFactory.getLogger(WX_TemplateMsgUtil.class);
/** * 封装模板详细信息 * @return*/ public static JSONObject packJsonmsg(Map param) {
JSONObject json = new JSONObject();
for (Map.Entry entry : param.entrySet()) {
JSONObject keyJson = new JSONObject();
TemplateData dta= entry.getValue();
keyJson.put("value",dta.getValue());
keyJson.put("color", dta.getColor());
json.put(entry.getKey(), keyJson);
}
return json;
}
/** * 根据模板的编号 新增并获取模板ID * @paramtemplateSerialNumber 模板库中模板的 "编号" * @return模板ID */ public static String getWXTemplateMsgId(String templateSerialNumber){
String tmpurl = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();
JSONObject json = new JSONObject();
json.put("template_id_short", templateSerialNumber);
JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "POST", json.toString());
JSONObject resultJson = new JSONObject(result);
String errmsg = (String) resultJson.get("errmsg");
log.info("获取模板编号返回信息:" + errmsg);
if(!"ok".equals(errmsg)){
return "error";
}
String templateId = (String) resultJson.get("template_id");
return templateId;
}
/** * 根据模板ID 删除模板消息 * @paramtemplateId 模板ID * @return*/ public static String deleteWXTemplateMsgById(String templateId){
String tmpurl = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();
JSONObject json = new JSONObject();
json.put("template_id", templateId);
try{
JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "POST", json.toString());
JSONObject resultJson = new JSONObject(result);
log.info("删除"+templateId+"模板消息,返回CODE:"+ resultJson.get("errcode"));
String errmsg = (String) resultJson.get("errmsg");
if(!"ok".equals(errmsg)){
return "error";
}
}catch(Exception e){
e.printStackTrace();
}
return "success";
}
/** * 发送微信消息(模板消息) * @paramtouser 用户 OpenID * @paramtemplatId 模板消息ID * @paramclickurl URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)。 * @paramtopcolor 标题颜色 * @paramdata 详细内容 * @return*/
public static String sendWechatMsgToUser(String touser, String templatId, String clickurl, String topcolor, JSONObject data) {
String tmpurl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();
JSONObject json = new JSONObject();
json.put("touser", touser);
json.put("template_id", templatId);
json.put("url", clickurl);
json.put("topcolor", topcolor);
json.put("data", data);
try{
JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "POST", json.toString());
JSONObject resultJson = new JSONObject(result);
log.info("发送微信消息返回信息:" + resultJson.get("errcode"));
String errmsg = (String) resultJson.get("errmsg");
if(!"ok".equals(errmsg)){ //如果为errmsg为ok,则代表发送成功,公众号推送信息给用户了。 return "error";
}
}catch(Exception e){
e.printStackTrace();
return "error";
}finally {
if(templatId!=null) {
//删除新增的 微信模板 deleteWXTemplateMsgById(templatId);
}
}
return "success";
}
}
package weixin.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
public classWX_TokenUtil{
private static Logger log = LoggerFactory.getLogger(WX_TokenUtil.class);
/**
* 获得微信 AccessToken
* access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。
* 开发者需要access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取
* 的access_token失效。
* (此处我是把token存在Redis里面了)
*/ public static AccessToken getWXToken() {
String appId="wxfb36eac9d8bwe23q";
String appSecret="bf1as96d3e5af6be50464fcd2eba1413";
String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId+"&secret="+ appSecret;
JSONObject jsonObject = WX_HttpsUtil.httpsRequest(tokenUrl, "GET", null);
System.out.println("jsonObject:"+jsonObject);
AccessToken access_token = new AccessToken();
if (null != jsonObject) {
try {
access_token.setAccessToken(jsonObject.getString("access_token"));
access_token.setExpiresin(jsonObject.getInteger("expires_in"));
} catch (JSONException e) {
access_token = null;
// 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
}
}
return access_token;
}
}
package weixin.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
public classWX_UserUtil{
private static Logger log = LoggerFactory.getLogger(WX_UserUtil.class);
/** * 根据微信openId 获取用户是否订阅 * @paramopenId 微信openId * @return是否订阅该公众号标识 */ public static Integer subscribeState(String openId){
String tmpurl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+WX_TokenUtil.getWXToken().getAccessToken() +"&openid="+openId;
JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "GET",null);
JSONObject resultJson = new JSONObject(result);
log.error("获取用户是否订阅 errcode:{} errmsg:{}", resultJson.getInteger("errcode"), resultJson.getString("errmsg"));
String errmsg = (String) resultJson.get("errmsg");
if(errmsg==null){
//用户是否订阅该公众号标识(0代表此用户没有关注该公众号 1表示关注了该公众号)。 Integer subscribe = (Integer) resultJson.get("subscribe");
return subscribe;
}
return -1;
}
}
package weixin.util;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class TestWX {
public static void main(String[] args) {
//新增用户成功 - 推送微信消息
senMsg("oYpZz1LHPO5qggb5tfiWdDDh7lCQ"); }
static void senMsg(String openId){
//用户是否订阅该公众号标识 (0代表此用户没有关注该公众号 1表示关注了该公众号)
Integer state= WX_UserUtil.subscribeState(openId); System.out.println("state:"+state); // 绑定了微信并且关注了服务号的用户 , 注册成功-推送注册短信
if(state==1){
Map param = new HashMap<>(); param.put("first",new TemplateData("恭喜其小林!","#696969")); param.put("keyword1",new TemplateData("12345345456","#696969")); param.put("keyword2",new TemplateData("2017年","#696969")); param.put("remark",new TemplateData("祝愉快!","#696969")); //注册的微信-模板Id
// String regTempId = WX_TemplateMsgUtil.getWXTemplateMsgId("ywBb70467vr18"); JSON.toJSONString(param); JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(param)); //调用发送微信消息给用户的接口
WX_TemplateMsgUtil.sendWechatMsgToUser(openId,"veNLgN8mi-L3Gn67PfkO6l-yS42CV7m8T0c4Pf-PjFw", "",
"#000000", jsonObject); //获取公众号的自动回复规则
String urlinfo="https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info?access_token="+WX_TokenUtil.getWXToken().getAccessToken(); JSONObject joinfo = WX_HttpsUtil.httpsRequest(urlinfo, "GET", null); Object o=joinfo.get("is_add_friend_reply_open"); // System.out.println("o:"+joinfo); String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}"; JSONObject Token = WX_HttpsUtil.httpsRequest(getTokenUrl, "GET", null); System.out.println("Token:"+Token); }
}
}
和微信交互servlet
package weixin.util.wxservlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public classWxServletextendsHttpServlet{
public WxServlet() {
// TODO Auto-generated constructor stub }
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 微信加密签名 String signature = request.getParameter("signature");
// 时间戳 String timestamp = request.getParameter("timestamp");
// 随机数 String nonce = request.getParameter("nonce");
// 随机字符串 String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
out.close();
out = null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub super.doPost(req, resp);
}
}
package weixin.util.wxservlet;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/** *
请求校验工具类
* @authorm * */public classSignUtil{ // 与接口配置信息中的Token要一致 private static String token = "weixin";
/** * 验证签名 * * @paramsignature * @paramtimestamp * @paramnonce * @return*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// 将token、timestamp、nonce三个参数进行字典序排序 Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
/** * 将字节数组转换为十六进制字符串 * * @parambyteArray * @return*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/** * 将字节转换为十六进制字符串 * * @parammByte * @return*/
private static String byteToHexStr(byte mByte) {
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[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}