天天看點

java簡易微信掃碼登入

微信掃碼登入

    • 準備工作
    • 流程
    • 項目結構和代碼:
    • 最終效果
    • 注:

準備工作

1、微信測試賬号

2、外網能夠通路的位址,用于微信掃碼成功之後回調

流程

1、微信測試賬号添加網頁授權擷取使用者基本資訊,并修改回調位址(微信測試賬号頁面)

java簡易微信掃碼登入

2、掃碼的賬号需要關注測試公衆号(微信測試賬号頁面)

java簡易微信掃碼登入

3、生成二維碼,并掃碼登入(項目頁面),成功之後會将基本資料顯示出來

項目結構和代碼:

java簡易微信掃碼登入

1、WeCatController

package com.avie.ltd.controller;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.transform.Source;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.alibaba.fastjson.JSONObject;
import com.avie.ltd.entity.Constants;

/**
 * 微信登入
 * 
 * @author DH
 * @date 2019年6月18日 下午8:04:15
 */
@Controller
public class WeCatController {

	/**
	 * wx :讀取Appid相關配置資訊靜态類
	 */
	@Autowired
	private Constants constants;

	/**
	 * 使用者資訊臨時儲存處
	 */
	private static Object quert;

	/**
	 * 微信登入頁
	 */
	@GetMapping("/wxLogin")
	public String login() {
		return "wxlogin";
	}

	/**
	 * pc點選微信登入,生成登入二維碼
	 * 
	 * @author DH
	 * @date 2019年6月19日 下午5:58:56
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/wxLoginPage", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, String> wxLoginPage(HttpServletRequest request) throws Exception {

		String sessionId = request.getSession().getId();
		// 設定redirect_uri和state=sessionId以及測試号資訊,傳回授權url
		String uri = this.getAuthorizationUrl("pc", sessionId);
		Map<String, String> data = new HashMap<String, String>();
		data.put("sessionId", sessionId);
		// 用來前端生成二維碼
		data.put("uri", uri);
		// 生成二維碼清除上一個使用者的資料
		quert = null;
		return data;
	}

	/**
	 * 掃描二維碼授權成功,取到code,設定的回調方法
	 * 
	 * @author DH
	 * @date 2019年6月19日 下午5:58:36
	 * @param code
	 * @param state
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/pcAuth")
	@ResponseBody
	public String pcCallback(String code, String state, HttpServletRequest request, HttpServletResponse response,
			HttpSession session) throws Exception {
		// 根據code擷取access_token和openId,不懂看微信文檔
		String result = this.getAccessToken(code);
		JSONObject jsonObject = JSONObject.parseObject(result);
		// String refresh_token = jsonObject.getString("refresh_token");
		String access_token = jsonObject.getString("access_token");
		String openId = jsonObject.getString("openId");
		// 授權成功 --> 根據token和openId擷取微信使用者資訊,不懂看我上一篇文章開始分享的連結
		JSONObject infoJson = this.getUserInfo(access_token, openId);
		if (infoJson != null) {
			infoJson.put("openId", openId);
		}
		// 登入成功儲存使用者資料
		quert = infoJson;
		return "登入成功";
	}

	/**
	 * 檢測登入狀态(擷取使用者資訊) 每秒被調用一次,
	 * 
	 * @param 登入成功,立馬得到使用者資訊傳回前台,并取消監聽
	 * 
	 * @author DH
	 * @return
	 * @date 2019年6月19日 下午8:18:38
	 */
	@RequestMapping(value = "/getInfoJson")
	@ResponseBody
	public String getInfoJson(HttpSession session) {
		if (quert == null) {
			return "no";
		}
		return quert.toString();
	}

	/**
	 * 擷取生成的二維碼url連接配接
	 * 
	 * @author DH
	 * @date 
	 * @param appid:公衆号的唯一辨別
	 * @param redirect_uri:授權後重定向的回調連結位址
	 * @param response_type:傳回類型,填寫code
	 * @param scope:應用授權作用域,snsapi_base,snsapi_userinfo
	 * @param state:非必傳,重定向後會帶上state參數,開發者可以填寫a-zA-Z0-9的參數值,最多128位元組
	 * @param wechat_redirect:無論直接打開還是做頁面302重定向時候,必須帶此參數
	 * @return
	 */
	public String getAuthorizationUrl(String type, String state) {
		// url
		String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";
		String callbackUrl = "";
		Object urlState = "";
		try {
			if ("pc".equals(type)) {
				// pc端回調方法(沒處理,我這裡回調一緻)
				callbackUrl = URLEncoder.encode(constants.getWeCatRedirectUrl() + "/pcAuth", "utf-8");
				urlState = state;
			} else if ("mobile".equals(type)) {
				// pc端回調方法
				callbackUrl = URLEncoder.encode(constants.getWeCatRedirectUrl() + "/pcAuth", "utf-8");
				urlState = System.currentTimeMillis();
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 權限 snsapi_userinfo snsapi_base
		String scope = "snsapi_base";
		url = String.format(url, constants.getWeCatAppId(), callbackUrl, scope, urlState);
		return url;
	}

	/**
	 * 擷取 token, openId(token有效期2小時)
	 * 
	 * @author DH
	 * @date 
	 * @param code
	 * @return
	 */
	public String getAccessToken(String code) {
		System.out.println(code);
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
		url = String.format(url, constants.getWeCatAppId(), constants.getWeCatAppSecret(), code);
		UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
		URI uri = builder.build().encode().toUri();

		String resp = getRestTemplate().getForObject(uri, String.class);
		if (resp.contains("openid")) {
			JSONObject jsonObject = JSONObject.parseObject(resp);
			String access_token = jsonObject.getString("access_token");
			String openId = jsonObject.getString("openid");
			JSONObject res = new JSONObject();
			res.put("access_token", access_token);
			res.put("openId", openId);
			res.put("refresh_token", jsonObject.getString("refresh_token"));
			return res.toJSONString();
		} else {
			return null;
		}
	}

	/**
	 * 微信接口中,token和openId是一起傳回,故此方法不需實作
	 * 
	 * @param accessToken
	 * @return
	 */
	public String getOpenId(String accessToken) {
		return null;
	}

	/**
	 * 擷取使用者資訊
	 * 
	 * @param accessToken
	 * @param openId
	 * @return
	 */
	public JSONObject getUserInfo(String accessToken, String openId) {
		String url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&;
		url = String.format(url, accessToken, openId);
		UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
		URI uri = builder.build().encode().toUri();
		String resp = getRestTemplate().getForObject(uri, String.class);
		if (resp.contains("errcode")) {
			return null;
		} else {
			JSONObject data = JSONObject.parseObject(resp);
			JSONObject result = new JSONObject();
			result.put("id", data.getString("unionid"));
			result.put("sex", data.getString("sex"));
			result.put("nickName", data.getString("nickname"));
			result.put("avatar", data.getString("headimgurl"));
			System.out.println(data.toString());
			return result;
		}
	}

	/**
	 * 微信的token隻有2小時的有效期,過時需要重新擷取,是以官方提供了,根據refresh_token
	 * 重新整理擷取token的方法,本項目僅僅是擷取使用者,資訊,并将資訊存入庫,是以兩個小時也已經足夠了
	 * 
	 * @author DH
	 * @date 
	 * @param refresh_token
	 * @return
	 */
	public String refreshToken(String refresh_token) {
		String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";
		url = String.format(url, constants.getWeCatAppId(), refresh_token);
		UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
		URI uri = builder.build().encode().toUri();
		ResponseEntity<JSONObject> resp = getRestTemplate().getForEntity(uri, JSONObject.class);
		JSONObject jsonObject = resp.getBody();
		String access_token = jsonObject.getString("access_token");
		return access_token;
	}

	/**
	 * 
	 * @author DH
	 * @date
	 * @return
	 */
	public static RestTemplate getRestTemplate() {// 手動添加
		SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
		requestFactory.setReadTimeout(120000);
		List<HttpMessageConverter<?>> messageConverters = new LinkedList<>();
		messageConverters.add(new ByteArrayHttpMessageConverter());
		messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
		messageConverters.add(new ResourceHttpMessageConverter());
		messageConverters.add(new SourceHttpMessageConverter<Source>());
		messageConverters.add(new AllEncompassingFormHttpMessageConverter());
		messageConverters.add(new MappingJackson2HttpMessageConverter());
		RestTemplate restTemplate = new RestTemplate(messageConverters);
		restTemplate.setRequestFactory(requestFactory);
		return restTemplate;
	}
}

           

2、Constants

package com.avie.ltd.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * qq ,wx 登陸常量配置類
 */
@Configuration
public class Constants {



	@Value("${constants.weCatAppId}")
	private String weCatAppId;

	@Value("${constants.weCatAppSecret}")
	private String weCatAppSecret;

	@Value("${constants.weCatRedirectUrl}")
	private String weCatRedirectUrl;

	

	public String getWeCatAppId() {
		return weCatAppId;
	}

	public void setWeCatAppId(String weCatAppId) {
		this.weCatAppId = weCatAppId;
	}

	public String getWeCatAppSecret() {
		return weCatAppSecret;
	}

	public void setWeCatAppSecret(String weCatAppSecret) {
		this.weCatAppSecret = weCatAppSecret;
	}

	public String getWeCatRedirectUrl() {
		return weCatRedirectUrl;
	}

	public void setWeCatRedirectUrl(String weCatRedirectUrl) {
		this.weCatRedirectUrl = weCatRedirectUrl;
	}

	
}

           

3、wxlogin.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>微信登入二維碼1</title>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script src="/js/qrcode.js"></script>
</head>

 <script type="text/javascript"  >
 

 var c = null;
 //監聽
 function getInfoJson(){
 	$.ajax({
         //url: "http://dhwxdl.free.idcfengye.com/getInfoJson",
         url: "http://127.0.0.1:8080/getInfoJson",
         type: "get",
         success: function (data) {
        	 if(data != "no"){
        		 $("#userinfo").html(data);
        		 //登入成功,取消監聽
        		 clearInterval(c);
             }
         }
 	});
 }
 
    function wechatLogin(){
    	$.ajax({
            //url: "http://dhwxdl.free.idcfengye.com/wxLoginPage",
            url: "http://127.0.0.1:8080/wxLoginPage",
            type: "POST",
            success: function (data) {
            	$("#sessionId").val(data.sessionId);
            	//生成二維碼
            	var qrcode = new QRCode(document.getElementById("code"), {
                    width : 200,
                    height : 200
                });
                qrcode.makeCode(data.uri);      
                //監聽是否成功登入(每秒執行一次 getInfoJson方法)
                c  = setInterval(getInfoJson,1000);
            }
    	});
    }
</script>
<body>
<input type="button" value="微信登入" onclick="wechatLogin()" /> 
<input type="hidden" id="sessionId"/>
<br/><br/><br/><br/>
<div id="code"></div> 
<div id="userinfo"></div> 
</body>
</html>

           

4、application.properties

server.port=8080
spring.application.name=compute-service
application.token = COMPUTE-SERVICE

#log
logging.config=classpath:logback.xml
logging.path=log


constants.weCatAppId=測試賬号的AppId
constants.weCatAppSecret=測試賬号的Secret
constants.weCatRedirectUrl=微信回調的位址
           

5、pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.avie.ltd</groupId>
	<artifactId>computeService</artifactId>
	<version>3001</version>
	<packaging>jar</packaging>
	<name>computeService</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
	</parent>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		
		 <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>
		<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.38</version>
        </dependency>

		 <!-- thymeleaf 模版   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        
		 <!-- web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<!-- 可執行jar配置 -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<configuration>
					<skipTests>true</skipTests>
				</configuration>
			</plugin>
		</plugins>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/**</include>
				</includes>
				<filtering>false</filtering>
			</resource>
			<!-- 打包XML檔案 -->
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.xml</include>
				</includes>
				<filtering>true</filtering>
			</resource>
		</resources>
		<finalName>computeService</finalName>
	</build>
</project>

           

最終效果

1、進入頁面點選微信登入之後會顯示二維碼

java簡易微信掃碼登入

2、掃碼成功之後會顯示基本資訊

java簡易微信掃碼登入

注:

1、項目參考了其他人的部落格

2、該項目隻是個簡單的測試項目

3、掃碼的微信号需關注測試賬号

4、項目完整代碼連結:download.csdn.net/download/qq_41833449/11998862