微信扫码登录

1. 逻辑说明

1.java拼接生成一个二维码的访问地址;(包含回调地址)

2.扫码,微信平台获取到用户信息,然后回调java,平台把结果返回给前端(可以返回openid或者用户信息之类的,逻辑自己定)

2. 正式使用

2.1 微信开放平台申请

2.1.1 网站应用申请

需要有自己的网站(备过案的)才可申请;(反正挺麻烦的)

2.1.2 账号密码

需要微信开放平台网站应用的(appid和appsecret)

2.2 代码

2.2.1 具体实现
package com.init.employee.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.init.common.result.*;
import com.init.employee.dto.TokenDTO;
import com.init.mbg.mapper.EmployeeMapper;
import com.init.employee.service.IEmployeeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.init.mbg.model.Employee;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
    //调接口
    @Autowired
    private RestTemplate restTemplate;

    @Value("${wx.qr.appId}")
    private String appId;//在配置文件里写,或者用的时候直接定义

    @Value("${wx.qr.secret}")
    private String secret;

    @Override
    public String getLoginQr() {
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        String redirectUrl = "http://www.xxxx.cn/employee/open/login/back";//这里的地址需要在开放平台设置回调域名,测试的时候项目需要是80端口
        //在hosts文件里添加域名解析
        //# 将www.txjava.cn 解析成127.0.0.1
        //127.0.0.1 www.txjava.cn
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        String state = "xxxx";
        log.info("state = {}", state);
        String qrCodeUrl = String.format(baseUrl, appId, redirectUrl, state);
        log.info("生成微信扫描二维码重定向地址为:{}", qrCodeUrl);
        return "redirect:" + qrCodeUrl;
    }

    @Override
    public Result loginBack(String code, String state) {
        TokenDTO dto = new TokenDTO();
        log.info("当前code:{},当前state:{}", code, state);
        if (code == null) {
            return new Result("操作失败");
        }
        OpenTokenResult openToken = getOpenToken(code, state);
        if (openToken == null) {
            return new Result("操作失败");
        }
        String accessToken = openToken.getAccess_token();
        String openId = openToken.getOpenid();
        if (StringUtils.isAnyBlank(accessToken, openId)) {
            return new Result("操作失败");
        }
        dto.setOpenId(openId);
        OpenUserResult openUserInfo = getOpenUserInfo(accessToken, openId);
        return new Result(openUserInfo);
    }

    @Override
    public String getOpenIdQr() {
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        String redirectUrl = "http://www.xxxx.cn/employee/open/openid/back";//这里的地址需要在开放平台设置回调域名,测试的时候项目需要是80端口。
        //在hosts文件里添加域名解析
        //# 将www.txjava.cn 解析成127.0.0.1
        //127.0.0.1 www.txjava.cn
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        String state = "xxxx";
        log.info("state = {}", state);
        String qrCodeUrl = String.format(baseUrl, appId, redirectUrl, state);
        log.info("生成微信扫描二维码重定向地址为:{}", qrCodeUrl);
        return "redirect:" + qrCodeUrl;
    }

    @Override
    public Result openIdBack(String code, String state) {
        log.info("当前code:{},当前state:{}", code, state);
        if (code == null) {
            return new Result(ResultCode.USER_CODE_LESS);
        }
        OpenTokenResult openToken = getOpenToken(code, state);
        if (openToken == null) {
            return new Result(ResultCode.USER_TOKEN_FAILED);
        }
        return new Result(openToken.getOpenid());
    }
	
    //回调方法里的第一个请求,获取用户openid和accesstoken
    private OpenTokenResult getOpenToken(String code, String state) {
        String token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
        Map<String, Object> param = new HashMap<>();
        HttpHeaders headers = new HttpHeaders();
        ResponseEntity<String> entity = null;
        try {
            entity = restTemplate.exchange(
                    token_url,
                    HttpMethod.GET,
                    new HttpEntity<String>(headers),
                    String.class,
                    param);
        } catch (RestClientException e) {
            log.info("请求生成token失败");
            return null;
        }
        if (entity == null) {
            return null;
        }
        String response = JSONObject.toJSONString(entity);
        ResponseResult resultTemp = JSONObject.parseObject(response, ResponseResult.class);
        String body = resultTemp.getBody();
        OpenTokenResult openTokenResult = JSONObject.parseObject(body, OpenTokenResult.class);
        return openTokenResult;
    }
    //回调方法里的第二个请求,获取用户info
    private OpenUserResult getOpenUserInfo(String accessToken, String openId) {
        String getInfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId;
        Map<String, Object> infoParam = new HashMap<>();
        HttpHeaders infoHeader = new HttpHeaders();
        ResponseEntity<String> infoEntity = null;
        try {
            infoEntity = restTemplate.exchange(
                    getInfo_url,
                    HttpMethod.GET,
                    new HttpEntity<String>(infoHeader),
                    String.class,
                    infoParam);
        } catch (RestClientException e) {
            log.info("请求用户信息失败");
            return null;
        }
        if (infoEntity == null) {
            return null;
        }
        String infoResponse = JSONObject.toJSONString(infoEntity);
        ResponseResult infoResult = JSONObject.parseObject(infoResponse, ResponseResult.class);
        String infoBody = infoResult.getBody();
        OpenUserResult openUserResult = JSONObject.parseObject(infoBody, OpenUserResult.class);
        return openUserResult;
    }
}
2.2.2 封装类
  • OpenTokenResult
package com.init.common.result;

import lombok.Data;

import java.io.Serializable;

@Data
public class OpenTokenResult implements Serializable {
    private String access_token;
    private Integer expires_in;
    private String refresh_token;
    private String openid;
    private String scope;
    private Integer errcode;
    private String errmsg;
}
  • OpenUserResult
package com.init.common.result;

import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class OpenUserResult implements Serializable {
    private String openid;
    private String nickname;
    private String sex;
    private String province;
    private String city;
    private String country;
    private String headimgurl;
    private List privilege;
    private String unionid;
    private Integer errcode;
    private String errmsg;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值