网站应用实现微信登录完整示例

220 阅读1分钟

网站应用实现微信登录完整示例

阅读文档

https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

微信参数配置

wx:
  open:
    app_id: wxedaaaaaaaa89b47
    app_secret: 23wxedaaaaaaaa89b475155
    redirect_url: http://localhost:8888/api/wx/callback
@Component
public class WxConfig implements InitializingBean {

    @Value("${wx.open.app_id}")
    private String appId;

    @Value("${wx.open.app_secret}")
    private String appSecret;

    @Value("${wx.open.redirect_url}")
    private String redirectUrl;

    public static String WX_OPEN_APP_ID;
    public static String WX_OPEN_APP_SECRET;
    public static String WX_OPEN_REDIRECT_URL;

    @Override
    public void afterPropertiesSet() {
        WX_OPEN_APP_ID = appId;
        WX_OPEN_APP_SECRET = appSecret;
        WX_OPEN_REDIRECT_URL = redirectUrl;
    }
}

生成二维码

1.跳转新窗口二维码登录

通过网站点击事件跳转新窗口二维码登录

https://open.weixin.qq.com/connect/qrconnect?appid=xxxxxx&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fapi%2Fwx%2Fcallback&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect

2.网站内嵌二维码微信登录

<template>
  <div>
    <el-button @click="login">登录</el-button>

    <div id="weixinLogin" style="width: 200px;height: 200px"></div>
  </div>
</template>

<script>
import demoApi from "@/api/demodemoApi";

export default {
  data() {
    return {}
  },
  mounted() {
    const script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = 'http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js'
    document.body.appendChild(script)
  },
  methods: {
    login() {
      demoApi.getLoginParam().then(response => {
        var obj = new WxLogin({
          self_redirect: true,
          id: 'weixinLogin',
          appid: response.data.appid,
          scope: response.data.scope,
          redirect_uri: response.data.redirect_uri,
          state: response.data.state,
          style: 'black',
          href: ''
        })
        console.log(obj)
      })
    }
  }
}
</script>

<style scoped>

</style>

demoApi.js

import request from '@/utils/request'
export default {
   getLoginParam() {
    return request({
      url: 'http://localhost:8888/api/wx/getLoginParam',
      method: 'get'
    })
  }
}

封装二维码参数接口

    @GetMapping("getLoginParam")
    @ResponseBody
    public Map<String, Object> genQrConnect() {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("appid", WxConfig.WX_OPEN_APP_ID);
            map.put("scope","snsapi_login");
            String wxOpenRedirectUrl = WxConfig.WX_OPEN_REDIRECT_URL;
            wxOpenRedirectUrl = URLEncoder.encode(wxOpenRedirectUrl, "utf-8");
            map.put("redirect_uri",wxOpenRedirectUrl);
            map.put("state",System.currentTimeMillis()+"");
            return map;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

微信回调接口

    @GetMapping("callback")
    public String callback(String code, String state) {
        //获取临时票据 code
        log.info("code:{}", code);

        // 组装获取accessToken的url
        String accessTokenUrl = getAccessTokenUrl(code);

        // httpclient请求获取accesstokenInfo
        try {
            String accesstokenInfo = HttpClientUtils.get(accessTokenUrl);
            log.info("accesstokenInfo:{}", accesstokenInfo);

            //从返回字符串获取两个值 openid和access_token
            JSONObject jsonObject = JSONObject.parseObject(accesstokenInfo);
            String access_token = jsonObject.getString("access_token");
            String openid = jsonObject.getString("openid");

            // TODO 根据openid判断数据库是否存在微信用户信息
            UserInfo userInfo = null;
            if (userInfo == null) {
                // httpclient请求获取用户信息
                String userInfoUrl = getUserInfoUrl(access_token, openid);
                String resultInfo = HttpClientUtils.get(userInfoUrl);
                log.info("resultInfo:{}", resultInfo);

                //解析用户信息
                JSONObject resultUserInfoJson = JSONObject.parseObject(resultInfo);
                //用户昵称
                String nickname = resultUserInfoJson.getString("nickname");
                //用户头像
                String headimgurl = resultUserInfoJson.getString("headimgurl");

                // TODO 微信用户信息保存数据库
            }

            // 数据库存在微信用户信息,生产Token信息后直接返回
            Map<String, String> map = new HashMap<>();
            map.put("name", "userName");
            map.put("token", "createTwtToken");

            //跳转前端页面
            return "redirect:" + "http://localhost:9528" + "/weixin/callback?token=" + map.get("token") + "&name=" + URLEncoder.encode(map.get("name"), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("httpclient请求出现异常。。。");
            return null;
        }
    }

    /**
     * 使用code、appid、appscrect换取access_token
     *
     * @param code
     * @return
     */
    private String getAccessTokenUrl(String code) {
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                WxConfig.WX_OPEN_APP_ID,
                WxConfig.WX_OPEN_APP_SECRET,
                code);
        return accessTokenUrl;
    }

    /**
     * 通过openid和access_token得到用户信息
     *
     * @param access_token
     * @param openid
     * @return
     */
    private String getUserInfoUrl(String access_token, String openid) {
        String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                "?access_token=%s" +
                "&openid=%s";
        String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);
        return userInfoUrl;
    }

回调返回页面

<template>
  <div>

  </div>
</template>

<script>

export default {
  data() {
    return {}
  },
  mounted() {
    let token = this.$route.query.token
    let name = this.$route.query.name
    this.loginCallback(token,name);
  },
  methods: { 	
    loginCallback(name, token) {
      console.log(name,token)
    },

  }
}
</script>

<style scoped>

</style>