java开发微信公众号

时间:2022-12-22 23:05:58

1.接入微信公众号

java开发微信公众号java开发微信公众号
    public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.
out.println("接口测试开始!!!");
//微信加密签名
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;
// response.encodeRedirectURL("success.jsp");


}
/**
* 处理微信服务器发来的消息
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//消息的接受、处理、响应
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding(
"utf-8");
//调用核心业务类型接受消息、处理消息
String respMessage = EastnetService.processRequest(request);

//响应消息
PrintWriter out = response.getWriter();
out.print(respMessage);
out.close();


}
确认请求来自于微信服务器
java开发微信公众号java开发微信公众号
 1 import java.security.MessageDigest;
2 import java.security.NoSuchAlgorithmException;
3 import java.util.Arrays;
4 import java.util.Iterator;
5 import java.util.Map;
6 import java.util.Set;
7 import java.util.concurrent.ConcurrentHashMap;
8
9 /**
10 * 请求校验工具类
11 * @author pengsong
12 * @date 2016.01.19
13 */
14 public class SignUtil {
15 //与微信配置中的的Token一致
16 private static String token = "你的token";
17
18 public static boolean checkSignature(String signature, String timestamp,
19 String nonce) {
20 String[] arra = new String[]{token,timestamp,nonce};
21 //将signature,timestamp,nonce组成数组进行字典排序
22 Arrays.sort(arra);
23 StringBuilder sb = new StringBuilder();
24 for(int i=0;i<arra.length;i++){
25 sb.append(arra[i]);
26 }
27 MessageDigest md = null;
28 String stnStr = null;
29 try {
30 md = MessageDigest.getInstance("SHA-1");
31 byte[] digest = md.digest(sb.toString().getBytes());
32 stnStr = byteToStr(digest);
33 } catch (NoSuchAlgorithmException e) {
34 // TODO Auto-generated catch block
35 e.printStackTrace();
36 }
37 //释放内存
38 sb = null;
39 //将sha1加密后的字符串与signature对比,标识该请求来源于微信
40 return stnStr!=null?stnStr.equals(signature.toUpperCase()):false;
41 }
42 /**
43 * 将字节数组转换成十六进制字符串
44 * @param digestArra
45 * @return
46 */
47 private static String byteToStr(byte[] digestArra) {
48 // TODO Auto-generated method stub
49 String digestStr = "";
50 for(int i=0;i<digestArra.length;i++){
51 digestStr += byteToHexStr(digestArra[i]);
52 }
53 return digestStr;
54 }
55 /**
56 * 将字节转换成为十六进制字符串
57 */
58 private static String byteToHexStr(byte dByte) {
59 // TODO Auto-generated method stub
60 char[] Digit = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
61 char[] tmpArr = new char[2];
62 tmpArr[0] = Digit[(dByte>>>4)&0X0F];
63 tmpArr[1] = Digit[dByte&0X0F];
64 String s = new String(tmpArr);
65 return s;
66 }
67
68 public static void main(String[] args) {
69 /*byte dByte = 'A';
70 System.out.println(byteToHexStr(dByte));*/
71 Map<String,String> map = new ConcurrentHashMap<String, String>();
72 map.put("4", "zhangsan");
73 map.put("100", "lisi");
74 Set set = map.keySet();
75 Iterator iter = set.iterator();
76 while(iter.hasNext()){
77 // String keyV = (String) iter.next();
78 String key =(String)iter.next();
79 System.out.println(map.get(key));
80 // System.out.println(map.get(iter.next()));
81 }
82 /*for(int i=0;i<map.size();i++){
83
84 }*/
85 }
效验signature SignUtil

 

2.创建菜单

      2.1获取Access_Token

java开发微信公众号java开发微信公众号
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.eastnet.wechat.pojo.AccessToken;
import com.eastnet.wechat.pojo.Menu;

import net.sf.json.JSONObject;
public class WeixinUtil {
// private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
// 获取access_token的接口地址(GET) 限200(次/天)
public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
// 菜单创建(POST) 限100(次/天)
public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
/**
* 发起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();
System.
out.println(buffer.toString());
jsonObject
= JSONObject.fromObject(buffer.toString());
}
catch (ConnectException ce) {
System.
out.println("Weixin server connection timed out.");
}
catch (Exception e) {
System.err.println(
"https request error:{}");
// log.error("https request error:{}", e);
}
return jsonObject;
}
/**
* 获取access_token
*
* @param appid 凭证
* @param appsecret 密钥
* @return
*/
public static AccessToken getAccessToken(String appid, String appsecret) {
AccessToken accessToken
= null;

String requestUrl
= access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject
= httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken
= new AccessToken();
accessToken.setToken(jsonObject.getString(
"access_token"));
accessToken.setExpiresIn(jsonObject.getInt(
"expires_in"));
}
catch (Exception e) {
accessToken
= null;
// 获取token失败
System.out.println("获取token失败 errcode:"+jsonObject.getInt("errcode")+"errmsg:"+jsonObject.getString("errmsg"));
// log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
}
}
return accessToken;
}
/**
* 创建菜单
*
* @param menu 菜单实例
* @param accessToken 有效的access_token
* @return 0表示成功,其他值表示失败
*/
public static int createMenu(Menu menu, String accessToken) {
int result = 0;

// 拼装创建菜单的url
String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
// 将菜单对象转换成json字符串
String jsonMenu = JSONObject.fromObject(menu).toString();
// 调用接口创建菜单
JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);

if (null != jsonObject) {
if (0 != jsonObject.getInt("errcode")) {
result
= jsonObject.getInt("errcode");
System.
out.println("创建菜单失败errcode:"+jsonObject.getInt("errcode")+"errmsg:"+jsonObject.getString("errmsg"));
// log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
}
}

return result;
}
}
WeixinUtil
java开发微信公众号java开发微信公众号
public class AccessToken {
// 获取到的凭证
private String token;
// 凭证有效时间,单位:秒
private int expiresIn;

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}

public int getExpiresIn() {
return expiresIn;
}

public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}
AccessToken类
java开发微信公众号java开发微信公众号
import javax.net.ssl.X509TrustManager;  

/**
* 证书信任管理器(用于https请求)
*
* @author steve
* @date 2013-08-08
*/
public class MyX509TrustManager implements X509TrustManager{
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
证书信任管理器(用于https请求) MyX509TrustManager

 

java开发微信公众号java开发微信公众号
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;

import com.eastnet.wechat.pojo.AccessToken;
import com.eastnet.wechat.pojo.Button;
import com.eastnet.wechat.pojo.CommonButton;
import com.eastnet.wechat.pojo.ComplexButton;
import com.eastnet.wechat.pojo.Menu;
import com.eastnet.wechat.pojo.ViewButton;
import com.eastnet.wechat.utils.WeixinUtil;

public class CreateMenuServlet extends HttpServlet {

/**
* Constructor of the object.
*/
public CreateMenuServlet() {
super();
}

/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy();
// Just puts "destroy" string in log
// Put your code here
}

/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

// 第三方用户唯一凭证
String appId = "你的appId";
// 第三方用户唯一凭证密钥
String appSecret = "你的appSecret";

// 调用接口获取access_token
AccessToken at = WeixinUtil.getAccessToken(appId, appSecret);

if (null != at) {
// 调用接口创建菜单
int result = WeixinUtil.createMenu(getMenu(), at.getToken());

// 判断菜单创建结果
if (0 == result){
response.setContentType(
"text/html;charset=UTF-8");
PrintWriter pw
= response.getWriter();
pw.println(
"菜单创建成功!");
pw.flush();
}
else{
response.setContentType(
"text/html;charset=UTF-8");
PrintWriter pw
= response.getWriter();
pw.println(
"菜单创建失败,错误码:" + result);
pw.flush();
}
}
}

/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

doGet(request, response);
}

/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
/**
* 组装菜单数据
*
* @return
*/
private static Menu getMenu() {
CommonButton btn11
= new CommonButton();
btn11.setName(
"个人信息查看");
btn11.setType(
"click");
btn11.setKey(
"stuInfoView");

CommonButton btn12
= new CommonButton();
btn12.setName(
"个人信息修改");
btn12.setType(
"click");
btn12.setKey(
"stuInfoEdit");

CommonButton btn21
= new CommonButton();
btn21.setName(
"行程查看");
btn21.setType(
"click");
btn21.setKey(
"stuTravelView");

CommonButton btn22
= new CommonButton();
btn22.setName(
"行程添加");
btn22.setType(
"click");
btn22.setKey(
"stuTravelAdd");

CommonButton btn23
= new CommonButton();
btn23.setName(
"行程修改");
btn23.setType(
"click");
btn23.setKey(
"stuTravelEdit");

CommonButton btn31
= new CommonButton();
btn31.setName(
"操作说明");
btn31.setType(
"click");
btn31.setKey(
"help");

CommonButton btn32
= new CommonButton();
btn32.setName(
"呼叫管理员");
btn32.setType(
"click");
btn32.setKey(
"callAdmin");

CommonButton btn33
= new CommonButton();
btn33.setName(
"意见反馈");
btn33.setType(
"click");
btn33.setKey(
"suggestions");

ComplexButton mainBtn1
= new ComplexButton();
mainBtn1.setName(
"个人信息");
mainBtn1.setSub_button(
new Button[] { btn11, btn12});

ComplexButton mainBtn2
= new ComplexButton();
mainBtn2.setName(
"行程");
mainBtn2.setSub_button(
new Button[] { btn21, btn22, btn23});

ComplexButton mainBtn3
= new ComplexButton();
mainBtn3.setName(
"帮助");
mainBtn3.setSub_button(
new Button[] { btn31, btn32, btn33 });

/**
* 这是公众号xiaoqrobot目前的菜单结构,每个一级菜单都有二级菜单项<br>
*
* 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br>
* 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:<br>
* menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 });
*/
Menu menu
= new Menu();
menu.setButton(
new Button[] { mainBtn1, mainBtn2, mainBtn3 });

return menu;
}
CreateMenuServlet
java开发微信公众号java开发微信公众号
public class CommonButton extends Button {
private String type;
private String key;

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}
}
CommonButton
public class ComplexButton extends Button {  
private Button[] sub_button;

public Button[] getSub_button() {
return sub_button;
}

public void setSub_button(Button[] sub_button) {
this.sub_button = sub_button;
}
}
java开发微信公众号java开发微信公众号
public class Menu {
private Button[] button;

public Button[] getButton() {
return button;
}

public void setButton(Button[] button) {
this.button = button;
}
}
Menu