uniappH5+springboot微信授权登录获取用户数据(非静默授权)

uniappH5+springboot微信授权登录获取用户数据(非静默授权)

微信网页授权开发文档

准备工作

微信公众号appid和appSecret及配置相关的ip白名单

uniappH5+springboot微信授权登录获取用户数据(非静默授权)_第1张图片

配置网页授权域名,具体操作看里面的提示

uniappH5+springboot微信授权登录获取用户数据(非静默授权)_第2张图片

一. 前端发送请求微信接口获取code

  1. html页面代码
<template>
	<view class="main">
		

		<view class="title-bg">
			
			<view class="containers" v-if="isLogin">
				<button>
					<image :src="headimgurl" mode="aspectFill">image> 
					<view>{{nickname}}view>
				button>
			view>
			
			<view class="containers" v-else>
				<button @click="login()">
					<image src="/static/images/login.png" mode="aspectFill">image> 
					<view>点击授权登录view>
				button>
			view>
			
		view>

		
		<view class="menu-bottom">
			<view class="menu menu-border-bottom" @click="exitLogin()" v-if="isLogin">
				<view class="menul">
					<image src="/static/images/exit.png" mode="aspectFill">image>
				view>
				<view class="menur">
					<view class="menur-text">退出登录view>
					<view class="menur-img"><image src="/static/images/right.png" mode="aspectFill">image>view>
				view>
			view>
			
		view>
		
	view>


template>

<script>
	export default {

		data() {
			return {
				isLogin: false,
				nickname: "", //用户名
				headimgurl: "", //头像
				openid: "", //openid
			}
		},
		onLoad() {
			//强制刷新页面,当从pageB返回到pageA时,刷新页面
			window.onpageshow = function (evt) {
			
				setTimeout(function(){
					if(evt.persisted){
						location.reload(true);
					}
				});
			
			}

			var res_openid = uni.getStorageSync("openid")
			
			if (res_openid  != "") {
				this.nickname = uni.getStorageSync("nickname");
				this.headimgurl = uni.getStorageSync("headimgurl");
				this.openid = uni.getStorageSync("openid");
				this.isLogin = true
			}
			
		},
		onShow() {
			this.checkWeChatCode()
			
			
		},

		
		methods: {
			//方法:用来提取code
			getUrlCode(name) {
				return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ''])[1]
					.replace(/\+/g, '%20')) || null
			},
			//检查浏览器地址栏中微信接口返回的code
			checkWeChatCode() {
				var that = this
				
				let code = that.getUrlCode('code')
				let	res_code = uni.getStorageSync("hccode")
				
				if(that.openid == "" || that.openid == undefined || that.openid == null){//未登陆
					
					if(code != "" && code != undefined && code != null){
						if(res_code != code){
							
							let res =  that.$myRequest({
								url: 'wechat/apiBaseController/getOpenId',
								method:'get',
								data: {
									code:code
								}
							})
							.then(res =>{
								
								if(res.data.errcode == 0){
									//.then是接收正确返回的信息
									that.openid = res.data.data.openid
									uni.setStorageSync("code",code)
									uni.setStorageSync("nickname",res.data.data.nickname)//用户名
									uni.setStorageSync("headimgurl",res.data.data.headimgurl)//头像
									uni.setStorageSync("openid",res.data.data.openid)//openid
									
									window.history.back()
									uni.switchTab({
										url:'./my'
									})
								}else{
									window.history.back()
									uni.showToast({
										title: '登录失败'+err.data.data,
										icon:'none',
										duration: 1000
									})
								}
								
							})
							.catch(err =>{
								window.history.back()
								// .catch 返回报错信息
								uni.showToast({
									title: '请求异常' + err.errMsg,
									icon: 'none',
									duration: 1500
								})
							})
							
						}else{
							uni.showToast({
								title: '已处于登录状态',
								icon: 'none',
								duration: 1500
							})
						}
					}
					
				
				}
				
			},
			login() {
				//请求微信接口,用来获取code
				let local = encodeURIComponent(window.location.href); //获取当前页面地址作为回调地址
				
				//通过微信官方接口获取code之后,会重新刷新设置的回调地址【redirect_uri】,之后会继续进入到onload()方法
				var appid = "";//你的appid
				location.href =
					"https://open.weixin.qq.com/connect/oauth2/authorize?appid="+
					appid +
					"&redirect_uri="+local+"&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect"
				
				
			},
			
			exitLogin() {
				var that = this
				uni.showModal({
					title: "温馨提示",
					content: "你确定退出登录吗?",
					cancelColor:'#999494',
					confirmColor: '#203c42',//确定文字的颜色
					success(res) {
						if (res.confirm) {
							that.isLogin = false
							uni.removeStorageSync("nickname");
							uni.removeStorageSync("headimgurl");
							uni.removeStorageSync("openid");
							uni.removeStorageSync("code");
							// uni.removeStorageSync("qzstaffLogin");//职工登录
							uni.showToast({
								title: '退出成功',
								icon: 'none',
								duration: 1000
							})
							setTimeout(()=>{
								uni.switchTab({
									url:'../index/anotherIndex'
								})
							},1000)
						}
					}
				})
			},
		}

	}
script>
<style>
	page{
		background: #f7f7f7;
	}
	
	.title-bg{
		height: 380rpx;
		background-image: url(../../static/images/my_bg.png);
		background-size: 100% 100%;
	}
	.title-bg .containers {
		margin: auto;
		text-align: center;
		padding-top: 80rpx;
		height: 300rpx;
		backdrop-filter: blur(4rpx);
	}
	.title-bg .containers button{
		display: block;
		background: none;
		padding: 0;
		border: 0;
		line-height: 0;
		width: 300rpx;	
	}
	.title-bg .containers button::after { 
		border: none 
	}
	
	.title-bg .containers button image{
		width: 170rpx;
		height: 170rpx;
		border-radius: 50%;
	}
	.title-bg .containers button view{
		margin-top: 10rpx;
		height: 80rpx;
		line-height: 80rpx; 
		font-size: 38rpx;
		color: #222222;
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 1;
		-webkit-box-orient: vertical;
		word-break: break-all;
	}
	
	.menu-border-bottom{
		border-bottom: 1px solid #f2f2f2;
	}
	.main .menu-bottom{
		margin-top: 20rpx;
	}
	.main .menu-bottom:last-child{
		padding-bottom: 150rpx;
	}
	.main .quit {
		text-align: center;
		padding: 40rpx 0px;
		color: #90948d;
		margin-top: 20px;
	} 
style>

  1. myRequest 请求工具类

创建request.js写入如下代码

// 定一个常量 存储请求地址
export const BASE_URL = 'hhttp://localhost:8901/'//springboot接口路径,上线这里配置成域名就好
export const myRequest = (options)=>{
	return new Promise((resolve, reject)=>{
		// 封装主体:网络请求
		uni.request({
			url: BASE_URL + options.url,
			header: {},
			data: options.data || {},		
			method: options.method || 'GET',// 默认值GET,如果有需要改动,在options中设定其他的method值
			success: (res) => {
				// console.log(res.data);		// 控制台显示数据信息
				resolve(res)
			},
			fail: (err) =>{
				// 页面中弹框显示失败
				uni.showToast({
					title: '请求接口失败',
					icon:'none',
					duration: 2000

				})
				// 返回错误消息
				reject(err)
			}
		})
	}
	)
}

3.全局挂载requests.js中的myRequest方法

main.js中写入如下代码

import App from './App'
import Vue from 'vue'
import store from './store/index.js'
import uView from 'uview-ui'

import { myRequest } from './utils/request.js';//自己创建的request.js路径
Vue.config.productionTip = false
// vuex
Vue.prototype.$store = store
// 引用uView
Vue.use(uView)

// 挂载到全局,让所有的页面都能调用myRequest方法
Vue.prototype.$myRequest = myRequest
App.mpType = 'app'
const app = new Vue({
    ...App,
	store
})
app.$mount()

二. 通过code获取相关的微信用户头像等数据

import cc.jinjun.febs.common.controller.BaseController;
import cc.jinjun.febs.common.utils.HttpUtil;
import cc.jinjun.febs.pay.wechat.WechatEnum;
import cc.jinjun.febs.wechat.entity.ResultData;
import cc.jinjun.febs.wechat.entity.WxUserInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;

//获取微信用户openid唯一标识
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/wechat/apiLoginController")
@CrossOrigin
public class ApiLoginController extends BaseController {

    

	@ResponseBody
    @GetMapping("/getOpenId")
    public ResultData getOpenId(String code) throws IOException {
        try {
            //        String result = new GetOpenid().getResult(code);
//        JSONObject jsonObject = JSON.parseObject(result);
//        System.out.println(jsonObject);
//        System.out.println("---------------------"+jsonObject.getString("openid"));

            String url = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                    "?appid=" + WechatEnum.appId +//WechatEnum.appId更换成自己的appid
                    "&secret=" + WechatEnum.appSecret +//WechatEnum.appSecret 更换成自己的appSecret
                    "&code=" + code +
                    "&grant_type=authorization_code";
            String result_url = HttpUtil.doPost(url);
            log.info("请求获取access_token:" + result_url);
            //返回结果的json对象
            JSONObject resultObject = JSON.parseObject(result_url);
            //请求获取userInfo
            String infoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=" + resultObject.getString("access_token") +
                    "&openid=" + resultObject.getString("openid") +
                    "&lang=zh_CN";
            String infoUrl_url = HttpUtil.doPost(infoUrl);
            log.info("请求获取access_token:" + infoUrl_url);
            JSONObject userJsonObject = JSON.parseObject(infoUrl_url);
            WxUserInfo wxUserInfo = new WxUserInfo(userJsonObject.getString("nickname"), userJsonObject.getString("headimgurl"), userJsonObject.getString("openid"));

            if (wxUserInfo.getOpenid() == null) {
                return new ResultData(201, "授权登录失败", wxUserInfo);
            }
            return new ResultData(0, "登录成功", wxUserInfo);
        } catch (Exception e) {
            return new ResultData(501, "登录失败", e.getMessage());
        }
    }
}

WxUserInfo 类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WxUserInfo {

    private String nickname;//用户名
    private String headimgurl;//头像
    private String openid;//openid

}

ResultData 类

public class ResultData<T> {
    //返回状态码,为0表示结果正确,不为0表示结果异常
    private Integer errcode;
    //结果描述
    private String errmsg;
    //返回数据
    private T data;

    public ResultData() {
    }

    public ResultData(Integer errcode, String errmsg, T data) {
        this.errcode = errcode;
        this.errmsg = errmsg;
        this.data = data;
    }

    public Integer getErrcode() {
        return errcode;
    }

    public void setErrcode(Integer errcode) {
        this.errcode = errcode;
    }

    public String getErrmsg() {
        return errmsg;
    }

    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResultData{" +
                "errcode=" + errcode +
                ", errmsg='" + errmsg + '\'' +
                ", data=" + data +
                '}';
    }
}

HttpUtil 类

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpStatus;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName: HttpUtil
 * @USER: Administrator
 * @DATE: 2020/4/21
 * @TODO:
 **/
public class HttpUtil {
    public static String doGet(String urlPath, HashMap<String, Object> params)
            throws Exception {
        StringBuilder sb = new StringBuilder(urlPath);
        if (params != null && !params.isEmpty()) { // 说明有参数
            sb.append("?");

            Set<Map.Entry<String, Object>> set = params.entrySet();
            for (Map.Entry<String, Object> entry : set) { // 遍历map里面的参数
                String key = entry.getKey();
                String value = "";
                if (null != entry.getValue()) {
                    value = entry.getValue().toString();
                    // 转码
                    value = URLEncoder.encode(value, "UTF-8");
                }
                sb.append(key).append("=").append(value).append("&");
            }

            sb.deleteCharAt(sb.length() - 1); // 删除最后一个&
        }
        URL url = new URL(sb.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000); // 5s超时
        conn.setRequestMethod("GET");

        if (conn.getResponseCode() == HttpStatus.OK.value()) {// HttpStatus.SC_OK ==
            // 200
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            StringBuilder sbs = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sbs.append(line);
            }
            return sbs.toString();
        }

        return null;
    }

    public static String doPost(String url, Map<String, Object> param) {

        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key).toString());
                }
            }
            URI uri = builder.build();

            // 创建http Post请求
            HttpPost httpPost = new HttpPost(uri);

            // 执行请求
            response = httpclient.execute(httpPost);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }


    public static String doGet(String url) throws Exception {
        return doGet(url, null);
    }


    public static String doPost(String url) {
        return doPost(url, null);
    }





}

maven


 <dependency>
      <groupId>org.apache.httpcomponentsgroupId>
      <artifactId>httpclientartifactId>
      <version>4.5.3version>
  dependency>
  
 <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>

 <dependency>
      <groupId>com.alibabagroupId>
      <artifactId>fastjsonartifactId>
      <version>1.2.83version>
      <scope>compilescope>
  dependency>

<dependency>
    <groupId>org.apache.commonsgroupId>
    <artifactId>commons-lang3artifactId>
dependency>
<dependency>
    <groupId>commons-iogroupId>
    <artifactId>commons-ioartifactId>
    <version>2.8.0version>
dependency>

注意
完成代码后将后端项目部署到微信公众号IP白名单对应的服务器运行,不然获取不到access_token

前端部署后要分配域名,域名跟网页授权域名对应,后端项目也可以分配域名

多多指教,共同进步丫

你可能感兴趣的:(uniapp,java,前端,java,spring,boot,前端,uni-app)