方式一:通过网页授权的方式获取,前提是公众号已获得网页授权
公众号获得网页授权后,配置回调域名:
当用户点击某个菜单事件时,调用项目中的xxx.jsp或xxx.html文件(http://www.xxx.com/web/wx1.jsp),内容如下:
appid:公众号的:appid
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ include file="/commViews/taglib.jsp"%> <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes" /> </head> <script type="text/javascript"> window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx59f756xxxxxxx &redirect_uri=http%3a%2f%2fwww.xxxx.com%2fweb%2fwx2.jsp /*(http://www.xxxx.com/web/wx2.jsp)*/ &response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect";
</script> <body> </body> </html>
http://www.xxxx.com/web/wx2.jsp 获取到code后调用后台接口,通过code获取openid
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <%@ include file="/commViews/taglib.jsp" %> <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes"/> <%@ include file="/commViews/head.jsp"%> </head> <script type="text/javascript"> var is_weixin = (function () { return navigator.userAgent.toLowerCase().indexOf(‘micromessenger‘) !== -1 })(); var code = getUrlParam("code"); console.log("code:" + code); $(function () { if (code != null) { $.ajax({ url: "${ctx}appsite/wx/getOpenid", type: "get", dataType: ‘text‘, data: {code: code}, success: function (openid) { // alert(openid) }, error: function (msg) { console.log(msg); } }); } }); </script> <body> </body> </html>
后台获取openid的接口:
import com.alibaba.fastjson.JSONObject; import com.xxx.xxx.wechat.util.HttpRequestUtil; import org.springframework.beans.factory.annotation.Autowired; 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 javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Date; import java.util.HashMap; import java.util.Map; @Controller @RequestMapping("/xxxx/wx") public class AppWxController { @Autowired StxcContestUserService<StxcContestUser> stxcContestUserService; /** * 1 第一步:用户同意授权,获取code * * 2 第二步:通过code换取网页授权access_token * * 3 第三步:刷新access_token(如果需要) * * 4 第四步:拉取用户信息(需scope为 snsapi_userinfo) * * 5 附:检验授权凭证(access_token)是否有效 * * code=CODE&state=STATE * https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code */ /** * 通过code换取网页授权access_token * @param request * @param response * @return access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 * expires_in access_token接口调用凭证超时时间,单位(秒) * refresh_token 用户刷新access_token * openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID * scope 用户授权的作用域,使用逗号(,)分隔 */ @RequestMapping(value = "/getOpenid",produces = "application/json; charset=utf-8") @ResponseBody public String getAccess_token(HttpServletRequest request, HttpServletResponse response,Map map){ String code = request.getParameter("code"); String url = "https://api.weixin.qq.com/sns/oauth2/access_token"; Map<String,String> params = new HashMap<String, String>(); params.put("appid","wx59f75xxxxxxxxxx"); // 此处图方便直接将 appid,secret写在这里 params.put("secret","a0ff75cf900489xxxxxxxxxxx"); params.put("code",code); params.put("grant_type","authorization_code"); String result = HttpRequestUtil.getInfoByNet(url,params,"POST","https",null); JSONObject json = JSONObject.parseObject(result); String openid = json.getString("openid"); return openid; } }
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Map; public class HttpRequestUtil { //请求地址,请求参数,请求方式,请求协议,携带参数 public static String getInfoByNet(String url, Map<String,String> params,String requestMethod,String requestProtocol,String outputStr){ StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(url+"?"); String result=""; for (Map.Entry<String,String> arg:params.entrySet()){ stringBuffer.append(arg.getKey()+"="+arg.getValue()+"&"); } stringBuffer.deleteCharAt(stringBuffer.length() - 1); //System.out.println(stringBuffer); if(requestProtocol.equals("https")){ result = httpsRequest(stringBuffer.toString(), requestMethod, outputStr); //System.out.println(result); return result; }else { result = httpRequest(stringBuffer.toString(), requestMethod, outputStr); //System.out.println(result); return result; } } }
方式二:公众号未获得网页授权
登录公众号后配置如下:(可参考开发文档的 “入门指南”) https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Getting_Started_Guide.html
上面填写的Url 是自己项目中的接口,填写好后提交时公众号会发送一个GET请求到接口进行token验证。
注意:验证的时候接口必须是GET请求方式,接口是POST请求token会验证失败;等token验证成功后想把接口改为post请求也可以,
刚开始没注接口用的是post请求,token验证一直失败package com.cen.appsite.KpzsContest.controllerimport com.alibaba.fastjson.JSONObject;
import com.cen.appsite.wechat.util.HttpRequestUtil; import org.aspectj.bridge.MessageUtil; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.springframework.beans.factory.annotation.Autowired; 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.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller @RequestMapping("/xxxxx/wx") public class KpzsWxController { /* 踩坑一:用post请求,token验证一直失败 */ //@RequestMapping(value = "/checkSignature", method = RequestMethod.POST) @RequestMapping(value = "/checkSignature", meghod = RequestMethod.GET) /* 踩坑二:请求参数用这个,验证一直不通过 public void checkSignature(@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr, HttpServletResponse response) { */ public void checkSignature(HttpServletRequest request, HttpServletResponse response) { // xml请求解析 Map<String, String> requestMap = null; try { requestMap = parseXml(request); } catch (Exception e) { e.printStackTrace(); } // 发送方帐号(open_id),formUserName 即为想要获取的用户的openid String fromUserName = requestMap.get("FromUserName"); // 公众帐号 String toUserName = requestMap.get("ToUserName"); // 消息类型 String msgType = requestMap.get("MsgType"); String Event = requestMap.get("Event"); String EventKey = requestMap.get("EventKey"); //回复用户消息 --图文消息 String img = "<xml>\n" + "<ToUserName><![CDATA["+fromUserName+"]]></ToUserName>\n" + "<FromUserName><![CDATA["+toUserName+"]]></FromUserName>\n" + "<CreateTime>"+new Date().getTime()+"</CreateTime>\n" + "<MsgType><![CDATA[news]]></MsgType>\n" + "<ArticleCount>1</ArticleCount>\n" + "<Articles>\n" + "<item>\n" + "<Title><![CDATA[2019“倡导绿色环保生活”科普知识挑战赛]]></Title>\n" + "<Description><![CDATA[快来参与吧!]]></Description>\n" + "<PicUrl><![CDATA[http://www.xxxx.com/resource/images/kpzs.png]]></PicUrl>\n" + //图片路径 "<Url><![CDATA[http://www.xxxx.com/web/kpzs_index.jsp?openid="+fromUserName+"]]></Url>\n" + // 当用户点击图文消息时想要跳转的链接 "</item>\n" + "</Articles>\n" + "</xml>\n"; //回复用户消息 --纯文本 String text = "<xml>\n" + " <ToUserName><![CDATA["+fromUserName+"]]></ToUserName>\n" + " <FromUserName><![CDATA["+toUserName+"]]></FromUserName>\n" + " <CreateTime>"+new Date().getTime()+"</CreateTime>\n" + " <MsgType><![CDATA[text]]></MsgType>\n" + " <Content><![CDATA[你好啊]]></Content>\n" + " <MsgId>1234567890123456</MsgId>\n" + "</xml>"; try { PrintWriter out = response.getWriter(); // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if (SignUtil.checkSignature(request.getParameter("signature"), request.getParameter("timestamp"), request.getParameter("nonce"))) { //用户的所有消息都必须响应,否则用户会收到 “公众号服务存在故障”提示 if(Event != null && Event.equals("CLICK")){ //用户点击(菜单)事件 out.print(img); }else{ out.print(text); } } out.close(); } catch (IOException e) { e.printStackTrace(); } } public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List<Element> elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) map.put(e.getName(), e.getText()); // 释放资源 inputStream.close(); inputStream = null; return map; } }
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Map; public class HttpRequestUtil { //请求地址,请求参数,请求方式,请求协议,携带参数 public static String getInfoByNet(String url, Map<String,String> params,String requestMethod,String requestProtocol,String outputStr){ StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(url+"?"); String result=""; for (Map.Entry<String,String> arg:params.entrySet()){ stringBuffer.append(arg.getKey()+"="+arg.getValue()+"&"); } stringBuffer.deleteCharAt(stringBuffer.length() - 1); //System.out.println(stringBuffer); if(requestProtocol.equals("https")){ result = httpsRequest(stringBuffer.toString(), requestMethod, outputStr); //System.out.println(result); return result; }else { result = httpRequest(stringBuffer.toString(), requestMethod, outputStr); //System.out.println(result); return result; } } }
原文地址:https://www.cnblogs.com/L237/p/12348268.html
时间: 2024-10-05 19:28:59