WeChat public account development "One" OAuth2.0 web page authorization and authentication to obtain user's detailed information and realize automatic login

Original statement: This article belongs to another blog of mine [ http://blog.csdn.net/liaohaojian/article/details/70175835 ] Original work, not reprinted by others

From the contact with the official account to the present, we have developed and maintained two official accounts, and encountered many problems during the development process. Now I record some module functions here, and I hope to make a summary and help others.

If you want to do a good job, you must first sharpen your tools. First, let's see what you need to prepare or understand to develop a public account.

 

  1. Web development tools: official development tools, use your own WeChat account to debug the JS-SDK-related functions and permissions of WeChat webpage authorization, debugging, and inspection pages, and simulate the input and output of most SDKs. Download address: web development tools download
  2. Development documentation: https://mp.weixin.qq.com/wiki
  3.  Log in to the WeChat official account for testing and obtain the appID and appsecret of the official account. The login address is: http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login Take the official official account to test, because there are risks and you don’t have to worry about affecting the normal use of the official official account when debugging, and some interfaces are stricter on the official official account, but can be released on the test official account, such as template information)

Let’s go to the main topic, realize WeChat webpage authorization, and obtain WeChat information. It is mainly used to log in with WeChat account as a user. If you only need to bind WeChat, you can directly request to obtain WeChat OpenId (unique to the current public account) without authorization. User binding (in the code below, how to implement it), this function can be viewed in the development document: WeChat Web Development - "WeChat Web Authorization", and the official start below.

1. Fill in the domain name of the authorization callback page

Enter the test official account, find the webpage account in the experience interface permission table, and add your own domain name on the right side. You can fill in the local IP for the test official account. If you are an official official account, you can only fill in your own domain name. When calling, it will prompt: redirect_uri parameter error! If there are other configurations that you don't understand, you can check the details in the development documentation.

2. Code display

1). The parameters returned by calling the WeChat interface are in JSON format, encapsulating an Http request method
public class WeixinUtil {
       /**
	 * Initiate an https request and get the result
	 * @param requestUrl request address
	 * @param requestMethod request method (GET, POST)
	 * @param outputStr Submitted data
	 * @return JSONObject (get the attribute value of the json object by JSONObject.get(key))
	 */
   public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
	JSONObject jsonObject = null;
	StringBuffer buffer = new StringBuffer();
	try {
		// Create an SSLContext object and initialize it with our specified trust manager
		TrustManager[] tm = { new MyX509TrustManager() };
		SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
		sslContext.init(null, tm, new java.security.SecureRandom());
		// Get the SSLSocketFactory object from the above SSLContext object
		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);
		// Set the request method (GET/POST)
		httpUrlConn.setRequestMethod(requestMethod);
		if ("GET".equalsIgnoreCase(requestMethod))
			httpUrlConn.connect();
		// when there is data to submit
		if (null != outputStr) {
			OutputStream outputStream = httpUrlConn.getOutputStream();
			// Pay attention to the encoding format to prevent Chinese garbled characters
			outputStream.write(outputStr.getBytes("UTF-8"));
			outputStream.close();
		}
		// Convert the returned input stream to a string
		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();
		// release resources
		inputStream.close();
		inputStream = null;
		httpUrlConn.disconnect();
		jsonObject = JSONObject.fromObject(buffer.toString());
	} catch (ConnectException ce) {
		log.error("Weixin server connection timed out.");
	} catch (Exception e) {
		log.error("https request error:{}", e);
	}
	return jsonObject;
    }
}
2). The following shows the user authorization when accessing the personal center
/**
 * Personal Center
 * @param request
 * @param response
 * @return
 */
@RequestMapping("/gotoPeopleIndex")
public String gotoPeopleIndex(HttpServletRequest request,HttpServletResponse response){
	//Determine whether it has been authorized. When the authorization is passed, the session "WeixinUserInfo" will be saved, so that when the next visit, if WeixinUserInfo exists, it means that it has been authorized and the user information already exists.
	WeixinUserInfo WeixinUserInfo = (WeixinUserInfo) session.getAttribute("WeixinUserInfo");
	if(WeixinUserInfo==null){//No authorization, jump to the authorization page, if you do not need authorization, the scope is snsapi_base, which will not pop up the authorization page
		String url  = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+TimedTask.appid+"&redirect_uri="+TimedTask.websiteAndProject+"/weixinF/getOpenInfo/gotoPeopleIndex&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
		return "redirect:"+url;
	}else{
		return "weixin/customer/userInfo";
	}
}
/**
 * Wechat webpage authorized to obtain wechat details
 * @param code
 * @param state
 * @param view Adjusted view after authorization
 * @param request
 * @param appid public account appid
 * @param appsecret public account appsecret
 * @param websiteAndProject request address and project name, such as mine is http://192.168.2.113/seafood
 * @param response
 * @throws ServletException
 * @throws IOException
 */
@RequestMapping("/getOpenInfo/{view}")
public void getOpenInfo(@RequestParam("code") String code,@RequestParam("state") String state,@PathVariable("view") String view,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
	// User agrees to authorize
	if (!"authdeny".equals(code)) {
		//Get OpenId
		OpenIdResult open = WeixinUtil.getOpenId(request, code, TimedTask.appid, TimedTask.appsecret);
		//Check if the authorization credential (access_token) is valid
		int result = WeixinUtil.checkAccessToken(open.getAccess_token(), open.getOpenid());
		if(0 != result){
			open = WeixinUtil.getNewAccess_Token(open,open.getRefresh_token(),TimedTask.appid);
		}
		// Web page authorization interface access credentials
		String accessToken = open.getAccess_token();
		String openId = open.getOpenid();
		//Get the details of the WeChat user. If you do not need authorization, you can skip this step and directly use the OpenId of WeChat to find out whether it has been bound, without jumping to the binding interface
		WeixinUserInfo user = WeixinUtil.getWeixinUserInfo(accessToken, openId);
		Customer customer = weixinFirstServer.getCustomerDetailByOpenId(user.getOpenId());
		if(customer!=null){
			if(customer.getAccountStatus()==2){
				response.setContentType("text/html; charset=UTF-8");
				try {
					response.sendRedirect(TimedTask.websiteAndProject+"/weixin/customer/noAuthority.jsp");
				} catch (IOException e) {
					e.printStackTrace ();
				}
				return;
			}
			customer.setHeadPhoto(user.getHeadImgUrl());
		}else{
			Customer newuser = new Customer();
			newuser.setCustomerWeixinId(openId);
			newuser.setCustomerWNickname(user.getNickname());
			newuser.setSex(user.getSex());
			// bind
			result = weixinFirstServer.addCustomerInfo(newuser);
			if(result<=0){
				response.setContentType("text/html; charset=UTF-8");
				try {
					response.sendRedirect(TimedTask.websiteAndProject+"/weixin/customer/error.jsp");
				} catch (IOException e) {
					e.printStackTrace ();
				}
			}else{
				customer = weixinFirstServer.getCustomerDetailByOpenId(user.getOpenId());
				if(customer.getAccountStatus()==2){
					response.setContentType("text/html; charset=UTF-8");
					try {
						response.sendRedirect(TimedTask.websiteAndProject+"/weixin/customer/noAuthority.jsp");
					} catch (IOException e) {
						e.printStackTrace ();
					}
					return;
				}
			}
		}
		session.setAttribute("customerInfo", customer);
		session.setAttribute("WeixinUserInfo", user);
		request.setAttribute("state", state);
		response.setContentType("text/html; charset=UTF-8");
		try {
			response.sendRedirect(TimedTask.websiteAndProject+"/weixinF/"+view);
		} catch (IOException e) {
			e.printStackTrace ();
		}
	}else{
		response.setContentType("text/html; charset=UTF-8");
		try {
			response.sendRedirect(TimedTask.websiteAndProject+"/weixin/customer/error.jsp");
		} catch (IOException e) {
			e.printStackTrace ();
		}
	}
}
WeChat tool class code:
public class WeixinUtil {
	public final static String getOpen_id_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	/**
	 * Verify that the authorization credential (access_token) is valid
	 * @param accessToken credentials
	 * @param openid id
	 * @return
	 */
	public static int checkAccessToken(String accessToken, String openid) {
		String requestUrl = "https://api.weixin.qq.com/sns/auth?access_token="+accessToken+"&openid="+openid;
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		int result = 1;
		// if the request was successful
		if (null != jsonObject) {
			try {
				result = jsonObject.getInt("errcode");
			} catch (JSONException e) {
				accessToken = null;
				// Failed to get token
				log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return result;
	}
	/**
	 * User authorization, use refresh_token to refresh access_token
	 * @return
	 */
	public static OpenIdResult getNewAccess_Token(OpenIdResult open,String refresh_token,String openId) {
		String requestUrl = getNewAccess_token.replace("REFRESH_TOKEN", refresh_token).replace("APPID", openId);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		// if the request was successful
		if (null != jsonObject) {
			try {
				open.setAccess_token(jsonObject.getString("access_token"));
			} catch (JSONException e) {
				// Failed to get token
				log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return open;
	}
	/**
	 * Get basic user information
	 * @param request
	 * @param code
	 * @param appid
	 * @param appsecret
	 * @return
	 */
	public static OpenIdResult getOpenId(HttpServletRequest request, String code,String appid, String appsecret) {
		String requestURI = request.getRequestURI();
		String param = request.getQueryString();
		if(param!=null){
			requestURI = requestURI+"?"+param;
		}
		String url = getOpen_id_url.replace("APPID",appid).replace("SECRET",appsecret).replace("CODE",code);
		JSONObject jsonObject = httpRequest(url, "POST", null);
		OpenIdResult result = new OpenIdResult();
		if (null != jsonObject) {
			Object obj = jsonObject.get("errcode");
			if (obj == null) {
				result.setAccess_token(jsonObject.getString("access_token"));
				result.setExpires_in(jsonObject.getString("expires_in"));
				result.setOpenid(jsonObject.getString("openid"));
				result.setRefresh_token(jsonObject.getString("refresh_token"));
				result.setScope(jsonObject.getString("scope"));
			}else{
				System.out.println("Get openId receipt:"+jsonObject.toString()+"Access path:"+requestURI);
				log.error("Access path:"+requestURI);
				log.error("获取openId失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return result;
	}
	/**
	 * Obtain user information through webpage authorization
	 * @param accessToken Web page authorization API call credentials
	 * @param openId User ID
	 * @return WeixinUserInfo
	 */
	public static WeixinUserInfo getWeixinUserInfo(String accessToken, String openId) {
		WeixinUserInfo user = null;
		// splicing request address
		String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
		requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
		// Obtain user information through web page authorization
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		if (null != jsonObject) {
			try {
				user = new WeixinUserInfo();
				// user's ID
				user.setOpenId(jsonObject.getString("openid"));
				// Nick name
				user.setNickname(jsonObject.getString("nickname"));
				// gender (1 is male, 2 is female, 0 is unknown)
				user.setSex(jsonObject.getInt("sex"));
				// user's country
				user.setCountry(jsonObject.getString("country"));
				// user's province
				user.setProvince(jsonObject.getString("province"));
				// user's city
				user.setCity(jsonObject.getString("city"));
				// profile picture
				user.setHeadImgUrl(jsonObject.getString("headimgurl"));
				// user privilege information
				user.setPrivilegeList(JSONArray.toList(jsonObject.getJSONArray("privilege"), List.class));
			} catch (Exception e) {
				user = null;
				int errorCode = jsonObject.getInt("errcode");
				String errorMsg = jsonObject.getString("errmsg");
				log.error("Failed to get user information errcode:{} errmsg:{}, reqUrl{}", errorCode, errorMsg);
			}
		}
		return user;
	}
}
The following shows the code for automatic login when the user's session is invalid, and no authorization is required at this time.
@RequestMapping("/gotoGoodsView")
public String gotoGoodsView(@RequestParam(value="longitude",defaultValue="",required=false) String longitude,@RequestParam(value="latitude",defaultValue="",required=false) String latitude){
	String param = request.getQueryString();
	String url = request.getServletPath();
	if(param!=null){
		url = url+"?"+param.replaceAll("&","-");//If you don't replace & with something else, the parameters will be lost when you re-login successfully
	}
	Customer customerInfo = (Customer) session.getAttribute("customerInfo");
	if(customerInfo==null){//session is invalid, jump to get WeChat details page (authorization)
		return "redirect:/weixinF/getCode?view="+TimedTask.websiteAndProject+"/weixinF/autoLogin&view2="+TimedTask.websiteAndProject+url;
	}
	return "/weixin/customer/goodsList";
}
@RequestMapping("/getCode")
public void getCode(HttpServletResponse response){
	String view = request.getParameter("view");//Get the path of openId
	String view2 = request.getParameter("view2");//The path to jump after getting openId successfully
	String redirect_url = "";
	try {
		redirect_url = URLEncoder.encode(view,"UTF-8");
		if(view2!=null && !"".equals(view2)){
			view2 = view2.replaceAll("-","&");
			redirect_url = redirect_url +"?redirect_url="+ URLEncoder.encode(URLEncoder.encode(view2,"UTF-8"),"UTF-8");
		}
	} catch (UnsupportedEncodingException e1) {
		e1.printStackTrace();
	}
	String url = WeixinUtil.getCode_url.replace("APPID",TimedTask.appid).replace("REDIRECT_URI",redirect_url);
	response.setContentType("text/html; charset=UTF-8");
	try {
		response.sendRedirect(url);
	} catch (IOException e) {
		e.printStackTrace ();
	}
}
/**
 * Automatically log in and jump
 * @param code
 * @param appid public account appid
 * @param appsecret public account appsecret
 * @param websiteAndProject request address and project name, such as mine is http://192.168.2.113/seafood
 * @param url Jump path after automatic login
 * @return
 */
@RequestMapping("/autoLogin")
public String autoLogin(HttpServletResponse response,@RequestParam(value="code",defaultValue="") String code,@RequestParam(value="redirect_url",defaultValue="") String url){
	OpenIdResult open = WeixinUtil.getOpenId(request,code,TimedTask.appid,TimedTask.appsecret);//根据Code获取OpenId
	//Find whether there is the customer according to OpenId, without binding
	Customer customerInfo = weixinFirstServer.getCustomerDetailByOpenId(open.getOpenid());
	if(customerInfo!=null){
		if(customerInfo.getAccountStatus()==2){//Is the user account normal?
			return "redirect:"+TimedTask.websiteAndProject+"/weixin/customer/noAuthority.jsp";
		}
		session.setAttribute("customerInfo", customerInfo);//Save user information in session
		response.setContentType("text/html; charset=UTF-8");
		try {
			response.sendRedirect(url);
		} catch (IOException e) {
			e.printStackTrace ();
		}
		return null;
	}else{
		url= url.replaceAll("&","-");
		url = url.replace(TimedTask.websiteAndProject,"");
		String redirectUrl  = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+TimedTask.appid+"&redirect_uri="+TimedTask.websiteAndProject+"/weixinF/getOpenInfoRedirectAction?actionName="+url+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
		response.setContentType("text/html; charset=UTF-8");
		try {
			response.sendRedirect(redirectUrl);
		} catch (IOException e) {
			e.printStackTrace ();
		}
		return null;
	}
}
At this point, WeChat webpage authorization authentication, automatic login with session invalidation has been completed, if you have any questions, please point out in the comment area
 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326267246&siteId=291194637