进这个页面,https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
登陆下,然后获取appid和skey
去 【1】 里面的url,里面有个接口请求,这个时候需要内网穿透!!!
然后写个action,我这里用Servlet,可以用mvc
@WebServlet("/wx")
public class WxServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp 时间戳
nonce 随机数
echostr 随机字符串
*/
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
//校验证签名
if(WxService.check(timestamp,nonce,signature)) {
System.out.println("接入成功");
PrintWriter out = response.getWriter();
//原样返回echostr参数
out.print(echostr);
out.flush();
out.close();
}else {
System.out.println("接入失败");
}
}
}
检查token是否正确,注意 token可以随便写,但要和公众平台上的token一致
private static final String TOKEN = "cxl";
private static final String APPKEY="1fec136dbd19f44743803f89bd55ca62";
private static final String GET_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//微信公众号
private static final String APPID="wxb86ee2a85e10f543";
private static final String APPSECRET="2944570351da086aad7958fc9b04c8ba";
public static boolean check(String timestamp, String nonce, String signature) {
//1)将token、timestamp、nonce三个参数进行字典序排序
String[] strs = new String[] {TOKEN,timestamp,nonce};
Arrays.sort(strs);
//2)将三个参数字符串拼接成一个字符串进行sha1加密
String str = strs[0]+strs[1]+strs[2];
String mysig = sha1(str);
//3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
return mysig.equalsIgnoreCase(signature);
}
自己去微信公众平台上添加一下,注意 cc 为后缀名的域名无法被解析
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
/**
* 接收消息和事件推送
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf8");
response.setCharacterEncoding("utf8");
//处理消息和事件推送
Map<String, String> requestMap = WxService.parseRequest(request.getInputStream());
System.out.println(requestMap);
//准备回复的数据包
String respXml = WxService.getRespose(requestMap);
System.out.println(respXml);
PrintWriter out = response.getWriter();
out.print(respXml);
out.flush();
out.close();
}
package service;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.baidu.aip.ocr.AipOcr;
import com.thoughtworks.xstream.XStream;
import entity.AccessToken;
import entity.Article;
import entity.BaseMessage;
import entity.ImageMessage;
import entity.MusicMessage;
import entity.NewsMessage;
import entity.TextMessage;
import entity.VideoMessage;
import entity.VoiceMessage;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import sun.misc.Signal;
import util.Util;
public class WxService {
private static final String TOKEN = "cxl";
private static final String APPKEY="1fec136dbd19f44743803f89bd55ca62";
private static final String GET_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//微信公众号
private static final String APPID="wxb86ee2a85e10f543";
private static final String APPSECRET="2944570351da086aad7958fc9b04c8ba";
//百度AI
public static final String APP_ID = "11519092";
public static final String API_KEY = "q3TlGWWqEBG9uGvlFIBtpvY5";
public static final String SECRET_KEY = "A14W5VRNG8my1GXYYAyNND0RjzBwxI8A";
//用于存储token
private static AccessToken at;
/**
* 获取token
*/
private static void getToken() {
String url = GET_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
String tokenStr = Util.get(url);
JSONObject jsonObject = JSONObject.fromObject(tokenStr);
String token = jsonObject.getString("access_token");
String expireIn = jsonObject.getString("expires_in");
//创建token对象,并存起来。
at = new AccessToken(token, expireIn);
}
/**
* 向处暴露的获取token的方法
* @return
*/
public static String getAccessToken() {
if(at==null||at.isExpired()) {
getToken();
}
return at.getAccessToken();
}
/**
* 验证签名
* @param timestamp
* @param nonce
* @param signature
* @return
*/
public static boolean check(String timestamp, String nonce, String signature) {
//1)将token、timestamp、nonce三个参数进行字典序排序
String[] strs = new String[] {TOKEN,timestamp,nonce};
Arrays.sort(strs);
//2)将三个参数字符串拼接成一个字符串进行sha1加密
String str = strs[0]+strs[1]+strs[2];
String mysig = sha1(str);
//3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
return mysig.equalsIgnoreCase(signature);
}
/**
* 进行sha1加密
* @param str
* @return
*/
private static String sha1(String src) {
try {
//获取一个加密对象
MessageDigest md = MessageDigest.getInstance("sha1");
//加密
byte[] digest = md.digest(src.getBytes());
char[] chars= {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
StringBuilder sb = new StringBuilder();
//处理加密结果
for(byte b:digest) {
sb.append(chars[(b>>4)&15]);
sb.append(chars[b&15]);
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* 解析xml数据包
* @param is
* @return
*/
public static Map<String, String> parseRequest(InputStream is) {
Map<String, String> map = new HashMap<>();
SAXReader reader = new SAXReader();
try {
//读取输入流,获取文档对象
Document document = reader.read(is);
//根据文档对象获取根节点
Element root = document.getRootElement();
//获取根节点的所有的子节点
List<Element> elements = root.elements();
for(Element e:elements) {
map.put(e.getName(), e.getStringValue());
}
} catch (DocumentException e) {
e.printStackTrace();
}
return map;
}
/**
* 用于处理所有的事件和消息的回复
* @param requestMap
* @return 返回的是xml数据包
*/
public static String getRespose(Map<String, String> requestMap) {
BaseMessage msg=null;
String msgType = requestMap.get("MsgType");
switch (msgType) {
//处理文本消息
case "text":
msg=dealTextMessage(requestMap);
break;
case "image":
msg=dealImage(requestMap);
break;
case "voice":
break;
case "video":
break;
case "shortvideo":
break;
case "location":
break;
case "link":
break;
case "event":
msg = dealEvent(requestMap);
break;
default:
break;
}
//把消息对象处理为xml数据包
if(msg!=null) {
return beanToXml(msg);
}
return null;
}
/**
* 进行图片识别
* @param requestMap
* @return
*/
private static BaseMessage dealImage(Map<String, String> requestMap) {
// 初始化一个AipOcr
AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);
// 可选:设置网络连接参数
client.setConnectionTimeoutInMillis(2000);
client.setSocketTimeoutInMillis(60000);
// 调用接口
String path = requestMap.get("PicUrl");
//进行网络图片的识别
org.json.JSONObject res = client.generalUrl(path, new HashMap<String,String>());
String json = res.toString();
//转为jsonObject
JSONObject jsonObject = JSONObject.fromObject(json);
JSONArray jsonArray = jsonObject.getJSONArray("words_result");
Iterator<JSONObject> it = jsonArray.iterator();
StringBuilder sb = new StringBuilder();
while(it.hasNext()) {
JSONObject next = it.next();
sb.append(next.getString("words"));
}
return new TextMessage(requestMap, sb.toString());
}
/**
* 处理事件推送
* @param requestMap
* @return
*/
private static BaseMessage dealEvent(Map<String, String> requestMap) {
String event = requestMap.get("Event");
switch (event) {
case "CLICK":
return dealClick(requestMap);
case "VIEW":
return dealView(requestMap);
default:
break;
}
return null;
}
/**
* @param requestMap
* @return
*/
private static BaseMessage dealView(Map<String, String> requestMap) {
return null;
}
/**
* 处理click菜单
* @param requestMap
* @return
*/
private static BaseMessage dealClick(Map<String, String> requestMap) {
String key = requestMap.get("EventKey");
switch (key) {
//点击一菜单点
case "1":
//处理点击了第一个一级菜单
return new TextMessage(requestMap, "你点了一点第一个一级菜单");
case "32":
//处理点击了第三个一级菜单的第二个子菜单
break;
default:
break;
}
return null;
}
/**
* 把消息对象处理为xml数据包
* @param msg
* @return
*/
private static String beanToXml(BaseMessage msg) {
XStream stream = new XStream();
//设置需要处理XStreamAlias("xml")注释的类
stream.processAnnotations(TextMessage.class);
stream.processAnnotations(ImageMessage.class);
stream.processAnnotations(MusicMessage.class);
stream.processAnnotations(NewsMessage.class);
stream.processAnnotations(VideoMessage.class);
stream.processAnnotations(VoiceMessage.class);
String xml = stream.toXML(msg);
return xml;
}
/**
* 处理文本消息
* @param requestMap
* @return
*/
private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
//用户发来的内容
String msg = requestMap.get("Content");
if(msg.equals("图文")) {
List<Article> articles = new ArrayList<>();
articles.add(new Article("这是图文消息的标题", "这是图文消息的详细介绍", "https://img01.sogoucdn.com/app/a/100520093/137f7d5bc12ad4fc-9bf5547e8cef1005-5e008c268f9a5d5a6d49eceb3d171b27.jpg", "http://www.baidu.com"));
// articles.add(new Article("这是图文消息的标题2", "这是图文消息的详细介绍2", "https://img01.sogoucdn.com/app/a/100520093/137f7d5bc12ad4fc-9bf5547e8cef1005-5e008c268f9a5d5a6d49eceb3d171b27.jpg", "http://www.baidu.com"));
NewsMessage nm = new NewsMessage(requestMap, articles);
return nm;
}
if(msg.equals("登录")) {
String url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxb6777fffdf5b64a4&redirect_uri=http://www.6sdd.com/weixin/GetUserInfo&response_type=code&scope=snsapi_userinfo#wechat_redirect";
TextMessage tm = new TextMessage(requestMap, "点击+url+"\">这里登录");
return tm;
}
return null;
}
/**
* 上传临时素材
* @param path 上传的文件的路径
* @param type 上传的文件类型
* @return
*/
public static String upload(String path,String type) {
File file = new File(path);
//地址
String url="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("TYPE", type);
try {
URL urlObj = new URL(url);
//强转为案例连接
HttpsURLConnection conn = (HttpsURLConnection) urlObj.openConnection();
//设置连接的信息
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
//设置请求头信息
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Charset", "utf8");
//数据的边界
String boundary = "-----"+System.currentTimeMillis();
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
//获取输出流
OutputStream out = conn.getOutputStream();
//创建文件的输入流
InputStream is = new FileInputStream(file);
//第一部分:头部信息
//准备头部信息
StringBuilder sb = new StringBuilder();
sb.append("--");
sb.append(boundary);
sb.append("\r\n");
sb.append("Content-Disposition:form-data;name=\"media\";filename=\""+file.getName()+"\"\r\n");
sb.append("Content-Type:application/octet-stream\r\n\r\n");
out.write(sb.toString().getBytes());
System.out.println(sb.toString());
//第二部分:文件内容
byte[] b = new byte[1024];
int len;
while((len=is.read(b))!=-1) {
out.write(b, 0, len);
}
is.close();
//第三部分:尾部信息
String foot = "\r\n--"+boundary+"--\r\n";
out.write(foot.getBytes());
out.flush();
out.close();
//读取数据
InputStream is2 = conn.getInputStream();
StringBuilder resp = new StringBuilder();
while((len=is2.read(b))!=-1) {
resp.append(new String(b,0,len));
}
return resp.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取带参数二维码的ticket
* @return
*/
public static String getQrCodeTicket() {
String at = getAccessToken();
String url="https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+at;
//生成临时字符二维码
String data="{\"expire_seconds\": 600, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"llzs\"}}}";
String result = Util.post(url, data);
String ticket = JSONObject.fromObject(result).getString("ticket");
return ticket;
}
/**
* 获取用户的基本信息
* @return
*/
public static String getUserInfo(String openid) {
String url="https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("OPENID", openid);
String result = Util.get(url);
return result;
}
}
把这个工具类引进去,然后启动项目即可!
回复图文,会回复个图文消息,用户输入的发送之后,后台也可以进行文字的回复和图文的回复。
请求的工具类
package util;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import net.sf.json.JSONObject;
import service.WxService;
public class Util {
public static final String DEF_CHATSET = "UTF-8";
public static final int DEF_CONN_TIMEOUT = 30000;
public static final int DEF_READ_TIMEOUT = 30000;
public static String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";
// 配置您申请的KEY
public static final String APPKEY = "*************************";
/**
* 向指定的地址发送一个post请求,带着data数据
*
* @param url
* @param data
*/
public static String post(String url, String data) {
try {
URL urlObj = new URL(url);
URLConnection connection = urlObj.openConnection();
// 要发送数据出去,必须要设置为可发送数据状态
connection.setDoOutput(true);
// 获取输出流
OutputStream os = connection.getOutputStream();
// 写出数据
os.write(data.getBytes());
os.close();
// 获取输入流
InputStream is = connection.getInputStream();
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 向指定的地址发送get请求
*
* @param url
*/
public static String get(String url) {
try {
URL urlObj = new URL(url);
// 开连接
URLConnection connection = urlObj.openConnection();
InputStream is = connection.getInputStream();
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
*
* @param strUrl
* 请求地址
* @param params
* 请求参数
* @param method
* 请求方法
* @return 网络请求字符串
* @throws Exception
*/
public static String net(String strUrl, Map params, String method) throws Exception {
HttpURLConnection conn = null;
BufferedReader reader = null;
String rs = null;
try {
StringBuffer sb = new StringBuffer();
if (method == null || method.equals("GET")) {
strUrl = strUrl + "?" + urlencode(params);
}
URL url = new URL(strUrl);
conn = (HttpURLConnection) url.openConnection();
if (method == null || method.equals("GET")) {
conn.setRequestMethod("GET");
} else {
conn.setRequestMethod("POST");
conn.setDoOutput(true);
}
conn.setRequestProperty("User-agent", userAgent);
conn.setUseCaches(false);
conn.setConnectTimeout(DEF_CONN_TIMEOUT);
conn.setReadTimeout(DEF_READ_TIMEOUT);
conn.setInstanceFollowRedirects(false);
conn.connect();
if (params != null && method.equals("POST")) {
try {
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes(urlencode(params));
} catch (Exception e) {
// TODO: handle exception
}
}
InputStream is = conn.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, DEF_CHATSET));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sb.append(strRead);
}
rs = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
if (conn != null) {
conn.disconnect();
}
}
return rs;
}
// 将map型转为请求参数型
public static String urlencode(Map<String, Object> data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}