一文搞定web微信第三方登录

一文搞定web微信第三方登录

今天给大家分享一下微信pc第三方登录:

一、提前工作(提前工作省略,腾讯要你提供什么,你就提供什么就好了。):

1.1、申请微信开放平台账号(https://open.weixin.qq.com/):

1.2、企业开发平台认证

1.3、创建网站应用,注意网站名称、网站logo这个会给用户直观显示的。

1.4、完成1.3需要等待审核1-7天,审核成功腾讯会给你提供AppID和AppSecret

1.4、配置回调地址(为了方便本地调试用的花生壳地址,也可以采用其他内网映射外网工具例如:ngrok):

二、查看微信开放文档pc网站登录流程:

微信文档登录流程:

第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;通过code参数加上AppID和AppSecret等,通过API换取access_token;通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。腾讯官方提供的流程图:

三、微信提供两种二维码模式(我们来一一叙述):

第一种(跳转腾讯扫码页面):

3.1、第一步请求code:

封装获取code访问URL:

代码语言:javascript复制https://open.weixin.qq.com/connect/qrconnect?appid=wxea3axxxxx41a91a&redirect_uri=http://20y85987b7.51mypc.cn/&response_type=code&scope=snsapi_login&state=gd5q4tcr#wechat_redirect3.2、代码演示:

service层拼接url参数:

postman访问获取用户点击codeURl前端也可以写死,不过不能防止csrf攻击,主要是存放一下state参数:

访问获取code地址:

扫码登录:

重定向到我们提供给腾讯回调地址并且给我们带过来code以及state参数:

我们拿着临时凭证(code)去获取accessToken以及用户信息:

controller层:

service层:

postman请求获取用户信息:

以上就是第一种第三方登录方式。

第二种(网站内嵌微信登录二维码)

第一步:查阅官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

第二步:写前端代码:

后续步骤和方案1一致:

登录:

跳转页面获取临时凭证code(第二种方法:state目前没存放session,大家有兴趣可以补一下)

拿着code获取用户信息:

四、分享代码:

4.1、pom文件:

代码语言:javascript复制

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.3.2.RELEASE

cn.cnbuilder.wechat

pc-login

0.0.1-SNAPSHOT

pc-login

Demo project for Spring Boot

1.8

3.3.5.B

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter

mysql

mysql-connector-java

5.1.46

com.baomidou

mybatis-plus-boot-starter

3.0.7.1

org.projectlombok

lombok

true

cn.hutool

hutool-all

4.1.21

com.alibaba

fastjson

1.2.28

org.springframework.boot

spring-boot-starter-data-jpa

org.apache.commons

commons-lang3

3.8

org.springframework.boot

spring-boot-maven-plugin

4.2、controller:

代码语言:javascript复制index controller

package cn.cnbuilder.wechat.webLogin.controller;

import cn.cnbuilder.wechat.webLogin.entity.R;

import cn.cnbuilder.wechat.webLogin.service.WechatWebLoginService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**

* 首页

* create on 2020/08/07 by kingyifan

*/

@RestController

public class IndexController {

@GetMapping(value = "/")

public String getCreatCodeUrl() {

return "wechat之web第三方登录工程";

}

}

WechatWebLoginController:

package cn.cnbuilder.wechat.webLogin.controller;

import cn.cnbuilder.wechat.webLogin.service.WechatWebLoginService;

import cn.cnbuilder.wechat.webLogin.entity.R;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**

* wechat之web端第三方登录

* create on 2020/08/07 by kingyifan

*/

@RestController

@RequestMapping("/wechat")

public class WechatWebLoginController {

@Autowired

private WechatWebLoginService wechatWebLoginService;

/**

* 获取生成用户点击之后能获取code的接口

* 第一步:请求CODE

*

* 第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),

* 则可以通过在PC端打开以下链接:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

* 若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。

* 以上摘自-腾讯官方文档 :https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

*

* @param request 获取HttpServletRequest中session存放STATE

* STATE 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

* @return URL 微信登录请求地址

*/

@GetMapping(value = "/getCreatCodeUrl")

@ResponseBody

public R getCreatCodeUrl(HttpServletRequest request) {

String getCodeUrl = wechatWebLoginService.getCreatCodeUrl(request);

return R.ok().data(getCodeUrl);

}

/**

* 通过getCreatCodeUrl方法并且用户授权之后前端页面会拿到code参数,参数会直接拼接在回调地址后面

*

* 通过code获取access_token、openid、unionid(当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。)

*

* @param request

* @return

*/

@GetMapping(value = "/getUserInfoByCode")

@ResponseBody

public R getUserInfoByCode(HttpServletRequest request) {

//true:state是否存放session

return wechatWebLoginService.getInfoByCode(request);

}

}4.3、service:

代码语言:javascript复制service接口:

package cn.cnbuilder.wechat.webLogin.service;

import cn.cnbuilder.wechat.webLogin.entity.R;

import javax.servlet.http.HttpServletRequest;

import java.util.Map;

public interface WechatWebLoginService {

String getCreatCodeUrl(HttpServletRequest request);

R getInfoByCode(HttpServletRequest request );

}

serviceImpl:

package cn.cnbuilder.wechat.webLogin.service.impl;

import cn.cnbuilder.wechat.webLogin.entity.R;

import cn.cnbuilder.wechat.webLogin.entity.WeChatUserInfo;

import cn.cnbuilder.wechat.webLogin.entity.WechatBaseInfo;

import cn.cnbuilder.wechat.webLogin.mapper.WechatUserInfoMapper;

import cn.cnbuilder.wechat.webLogin.service.WechatWebLoginService;

import cn.cnbuilder.wechat.webLogin.utils.WechatWebLoginUtil;

import cn.hutool.core.util.RandomUtil;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@Service

public class WechatWebLoginServiceImpl implements WechatWebLoginService {

@Autowired

private WechatUserInfoMapper wechatUserInfoMapper;

@Override

public String getCreatCodeUrl(HttpServletRequest request) {

//state参数:用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

//第一步生成随机的state参数 该参数可用于防止csrf攻击(跨站请求伪造攻击)

String state = RandomUtil.randomString(8);

//第二步存放session

request.getSession().setAttribute("state", state);

//获取用户点击url可以生成code的链接

String getCodeUrl = WechatWebLoginUtil.getCodeUrl(state);

return getCodeUrl;

}

/**

* 根据code获取信息

* 第一步:判断state是否和我们存放的state一致

*
不一致,则直接返回这是一次非腾讯官方的回调请求。

* 第二步:判断用户是否同意登录(查看是否有code)

*
不同意:则直接返回登录失败

* 第三步:判断code是否有效,是否是腾讯返回的

*
是:获取信息

*
否:这是一次无效的登录请求

*

* @param request

*/

@Override

public R getInfoByCode(HttpServletRequest request) {

String isSetState = request.getParameter("state");

//是否存放State

if (isSetState != null && StringUtils.isNotEmpty(isSetState)) {

/**

* 第一步

* 查看state是否和我们存放的一致;

*/

//微信给的state

String wstate = request.getParameter("state");

//session中的state

Object sstate = request.getSession().getAttribute("state");

if (StringUtils.isEmpty(sstate.toString()) || !sstate.equals(wstate)) {

return R.error(500, "恶意请求");

}

}

/**

* 第二步查看用户是否授权:

* 用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数

* redirect_uri ? code = CODE & state = STATE

* 若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数

以上摘自微信官方文檔:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

*/

//获取腾讯给的code

String code = request.getParameter("code");

//判断是否是空的。

if (StringUtils.isBlank(code) || StringUtils.isEmpty(code)) {

return R.error(500, "code为空!");

}

//调用微信通过code获取access_token接口

WechatBaseInfo wechatBaseInfo = WechatWebLoginUtil.getBaseInfoByCode(code);

if (wechatBaseInfo.getErrcode() != null) {

return R.error(500, wechatBaseInfo.getErrmsg());

}

//获取到基础开发信息之后,判断用户信息在db是否完整

QueryWrapper queryWrapper = new QueryWrapper<>();

queryWrapper.eq("openid", wechatBaseInfo.getOpenid());

WeChatUserInfo dWeChatUserInfo = wechatUserInfoMapper.selectOne(queryWrapper);

//用户信息不存在

if (dWeChatUserInfo != null) {

//如果db存在则直接返回,如果怕用户更改了资料也可以重新走一下获取用户信息接口

return R.ok().data(dWeChatUserInfo);

}

//获取基础信息获取用户信息

WeChatUserInfo wechatUserInfo = WechatWebLoginUtil.getUserInfoByOpenid(wechatBaseInfo);

if (wechatUserInfo == null) {

return R.error(500, "用户信息获取失败!");

}

wechatUserInfoMapper.insert(wechatUserInfo);

return R.ok().data(wechatUserInfo);

}

}4.4、工具类:

代码语言:javascript复制package cn.cnbuilder.wechat.webLogin.utils;

import cn.cnbuilder.wechat.webLogin.entity.WeChatUserInfo;

import cn.cnbuilder.wechat.webLogin.entity.WechatBaseInfo;

import cn.hutool.http.HttpUtil;

import cn.hutool.json.JSONObject;

import cn.hutool.json.JSONUtil;

import org.apache.commons.lang3.StringUtils;

/**

* 微信第三方web登录工具类

* create on 2020.08.07 by kingyifan

*/

public class WechatWebLoginUtil {

//微信开放平台申请pc应用开发密钥 可以后期弄到配置文件动态获取

public static String APPID = "xxxxxxxxx";

public static String APPSECRET = "xxxxxxxxx";

//-------------------------------------微信第三方登录信息------------------------------------------------//

//获取codeurl下面是固定的

public static String GETCODEURL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";

//微信回调地址(这个地址可以说是前端页面,这个地址腾讯回调过来会在后面拼code参数)

public static String REDIRECTURI = "http://20y85987b7.51mypc.cn/";

//应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login

public static String SCOPE = "snsapi_login";

// 获取access_token 通过code获取access_token

public static String ACCESSTOKENURL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

//根据openid获取用户信息接口地址

public static String USERINFOURL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";

/**

* 拼接获取code的:接口地址

*

* @param state 随机数 防止csrf攻击(跨站请求伪造攻击)

* @return

*/

public static String getCodeUrl(String state) {

//替换appId、回调url 以及state参数

return GETCODEURL.replace("APPID", APPID).replace("REDIRECT_URI", REDIRECTURI).replace("SCOPE", SCOPE).replace("STATE", state);

}

/**

* 根据code获取用户基础开发信息、AccessToken、openId、unionId、refreshToken

*

* @param code 临时授权凭证

* @return

*/

public static WechatBaseInfo getBaseInfoByCode(String code) {

//基础信息实体类

WechatBaseInfo wechatBaseInfo = new WechatBaseInfo();

//拼接获取access_token的请求地址

String accessTokenUrl = ACCESSTOKENURL.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code);

//發送请求获取基础开发信息

String getResponseInfo = HttpUtil.get(accessTokenUrl);

if (StringUtils.isEmpty(getResponseInfo)) {

wechatBaseInfo.setErrcode(-1);

wechatBaseInfo.setErrmsg("错误请求");

return wechatBaseInfo;

}

//把请求结果转成json对象

JSONObject reObject = JSONUtil.parseObj(getResponseInfo);

//判断是否有异常 比如code失效。。。。

if (reObject.getInt("errcode") != null) {

/**

* 错误返回样例:

* {

* "errcode":40029,

* "errmsg":"invalid code"

* }

*/

wechatBaseInfo.setErrcode(reObject.getInt("errcode"));

wechatBaseInfo.setErrmsg(reObject.getStr("errmsg"));

return wechatBaseInfo;

} else {

/**

*正确的返回:

* {

* "access_token":"ACCESS_TOKEN",

* "expires_in":7200,

* "refresh_token":"REFRESH_TOKEN",

* "openid":"OPENID",

* "scope":"SCOPE",

* "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"

* }

*/

//接口调用凭证

wechatBaseInfo.setAccess_token(reObject.getStr("access_token"));

//access_token接口调用凭证超时时间,单位(秒)

wechatBaseInfo.setExpires_in(reObject.getStr("expires_in"));

//用户刷新access_token

wechatBaseInfo.setRefresh_token(reObject.getStr("refresh_token"));

// 授权用户唯一标识

wechatBaseInfo.setOpenid(reObject.getStr("openid"));

//用户授权的作用域,使用逗号(,)分隔

wechatBaseInfo.setScope(reObject.getStr("scope"));

// unionid 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。

wechatBaseInfo.setUnionid(reObject.getStr("unionid"));

return wechatBaseInfo;

}

}

/**

* 根据基础开发信息获取用户信息

*

* @param wechatBaseInfo

* @return

*/

public static WeChatUserInfo getUserInfoByOpenid(WechatBaseInfo wechatBaseInfo) {

WeChatUserInfo weChatUserInfo = new WeChatUserInfo();

//拼接获取userinfo的请求地址

String userInfoUrl = USERINFOURL.replace("ACCESS_TOKEN", wechatBaseInfo.getAccess_token()).replace("OPENID", wechatBaseInfo.getOpenid());

//發送请求获取用户信息

String getResponseInfo = HttpUtil.get(userInfoUrl);

if (StringUtils.isEmpty(getResponseInfo)) {

weChatUserInfo.setErrcode(-1);

weChatUserInfo.setErrmsg("错误请求");

return weChatUserInfo;

}

//把请求结果转成json对象

JSONObject reObject = JSONUtil.parseObj(getResponseInfo);

//判断是否有异常 比如无效的openId

if (reObject.getInt("errcode") != null) {

/**

* 错误的Json返回示例:

* {

* "errcode":40003,

* "errmsg":"invalid openid"

* }

*/

weChatUserInfo.setErrcode(reObject.getInt("errcode"));

weChatUserInfo.setErrmsg(reObject.getStr("errmsg"));

return weChatUserInfo;

} else {

//普通用户的标识,对当前开发者帐号唯一

weChatUserInfo.setOpenid(reObject.getStr("openid"));

//普通用户昵称

weChatUserInfo.setNickname(reObject.getStr("nickname"));

//普通用户性别,1为男性,2为女性

weChatUserInfo.setSex(reObject.getInt("sex"));

// 普通用户个人资料填写的省份

weChatUserInfo.setProvince(reObject.getStr("province"));

//普通用户个人资料填写的城市

weChatUserInfo.setCity(reObject.getStr("city"));

//国家,如中国为CN

weChatUserInfo.setCountry(reObject.getStr("country"));

//TODO 请注意,在用户修改微信头像后,旧的微信头像URL将会失效,因此开发者应该自己在获取用户信息后,将头像图片保存下来,避免微信头像URL失效后的异常情况。 这里需要下载用户头像然后保存到自己的服务器 这一步省略。。。

//用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空

weChatUserInfo.setHeadimgurl(reObject.getStr("headimgurl"));

// 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)

weChatUserInfo.setPrivilege(reObject.getJSONArray("privilege").toString());

//用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。

weChatUserInfo.setUnionid(reObject.getStr("unionid"));

return weChatUserInfo;

}

}

}4.5、实体类:

代码语言:javascript复制R:统一返回实体:

package cn.cnbuilder.wechat.webLogin.entity;

import java.util.HashMap;

import java.util.Map;

public class R extends HashMap {

private static final long serialVersionUID = -8713837118340960775L;

public R() {

put("code", 200);

put("msg", "success");

}

public static R error() {

return error(500, "未知异常,请联系管理员");

}

public static R error(String msg) {

return error(500, msg);

}

public static R error(int code, String msg) {

R r = new R();

r.put("code", code);

r.put("msg", msg);

return r;

}

public static R ok(String msg) {

R r = new R();

r.put("msg", msg);

return r;

}

public static R ok(Map map) {

R r = new R();

r.putAll(map);

return r;

}

public static R ok() {

return new R();

}

public R message(String message) {

this.put("message", message);

return this;

}

public R data(Object data) {

this.put("data", data);

return this;

}

@Override

public R put(String key, Object value) {

super.put(key, value);

return this;

}

public String getMessage() {

return String.valueOf(get("message"));

}

public Object getData() {

return get("data");

}

public Integer getCode() {

return (Integer) get("code");

}

}

微信第三方登录基础开发信息:

package cn.cnbuilder.wechat.webLogin.entity;

import lombok.Data;

/**

* 微信web登录基础开发信息

* 文档地址:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

*/

@Data

public class WechatBaseInfo {

/**

* 接口调用凭证

*/

private String access_token;

/**

* access_token接口调用凭证超时时间,单位(秒)

*/

private String expires_in;

/**

* 用户刷新access_token

*/

private String refresh_token;

/**

* 授权用户唯一标识

*/

private String openid;

/**

* 用户授权的作用域,使用逗号(,)分隔

*/

private String scope;

/**

* 当且仅当该移动应用已获得该用户的userinfo授权时,才会出现该字段

*/

private String unionid;

/**

* 错误编码

*/

private Integer errcode;

/**

* 错误信息

*/

private String errmsg;

}

用户信息实体:

package cn.cnbuilder.wechat.webLogin.entity;

import com.baomidou.mybatisplus.annotation.TableField;

import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;

import javax.persistence.Table;

import javax.persistence.Transient;

import javax.persistence.criteria.CriteriaBuilder;

@Data

@TableName("wechat_userinfo")

public class WeChatUserInfo {

/**

* 普通用户的标识,对当前开发者帐号唯一

*/

private String openid;

/**

* 普通用户昵称

*/

private String nickname;

/**

* 普通用户性别,1为男性,2为女性

*/

private Integer sex;

/**

* 普通用户个人资料填写的省份

*/

private String province;

/**

* 普通用户个人资料填写的城市

*/

private String city;

/**

* 国家,如中国为CN

*/

private String country;

/**

* 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空

*/

private String headimgurl;

/**

* 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)

*/

private String privilege;

/**

* 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。

*/

private String unionid;

/**

* 错误编码

*/

@TableField(exist = false)

private Integer errcode;

/**

* 错误信息

*/

@TableField(exist = false)

private String errmsg;

}mapper文件:

代码语言:javascript复制package cn.cnbuilder.wechat.webLogin.mapper;

import cn.cnbuilder.wechat.webLogin.entity.WeChatUserInfo;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import org.apache.ibatis.annotations.Mapper;

@Mapper

public interface WechatUserInfoMapper extends BaseMapper {

}

xml文件:

4.6、启动类:

代码语言:javascript复制package cn.cnbuilder.wechat.webLogin;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class PcLoginApplication {

public static void main(String[] args) {

SpringApplication.run(PcLoginApplication.class, args);

}

}4.7、配置文件:

代码语言:javascript复制application.yml文件:

spring:

profiles:

active: dev #选择要用那个配置文件

application-dev.yml文件:

#端口号访问路径

server:

port: 12008

servlet:

context-path: /

#spring

spring:

devtools:

restart:

enabled: true

# mysql 配置

datasource:

driver-class-name: com.mysql.jdbc.Driver

type: com.zaxxer.hikari.HikariDataSource

url: jdbc:mysql://127.0.0.1/wechat_weblogin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8

username: root

password: root

hikari:

## 最小空闲连接数量

minimum-idle: 5

## 空闲连接存活最大时间,默认600000(10分钟)

idle-timeout: 180000

## 连接池最大连接数,默认是10

maximum-pool-size: 10

## 此属性控制从池返回的连接的默认自动提交行为,默认值:true

auto-commit: true

## 连接池名称

pool-name: MyHikariCP

## 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟

max-lifetime: 1800000

## 数据库连接超时时间,默认30秒,即30000

connection-timeout: 30000

## 监听是否存活

connection-test-query: SELECT 1

servlet:

multipart:

enabled: true

max-file-size: -1

#mybatis

mybatis-plus:

mapper-locations: classpath:/mapper/*Mapper.xml

#实体扫描,多个package用逗号或者分号分隔

typeAliasesPackage: cn.cnbuilder.wechat.webLogin.entity

global-config:

# 数据库相关配置

db-config:

#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";

id-type: id_worker

#字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"

field-strategy: not_empty

#驼峰下划线转换

column-underline: true

#数据库大写下划线转换

# capital-mode: true

#逻辑删除配置

logic-delete-value: 0

logic-not-delete-value: 1

#刷新mapper 调试神器

refresh: true

# 原生配置

configuration:

map-underscore-to-camel-case: true

cache-enabled: false4.8、sql:

代码语言:javascript复制CREATE TABLE `wechat_userinfo` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

`openid` varchar(32) DEFAULT '' COMMENT '普通用户的标识,对当前开发者帐号唯一',

`nickname` varchar(50) DEFAULT '' COMMENT '普通用户昵称',

`sex` int(2) DEFAULT '0' COMMENT '普通用户性别,1为男性,2为女性',

`province` varchar(30) DEFAULT '' COMMENT ' 普通用户个人资料填写的省份',

`city` varchar(30) DEFAULT '' COMMENT '普通用户个人资料填写的城市',

`country` varchar(30) DEFAULT '' COMMENT '国家,如中国为CN',

`headimgurl` varchar(200) DEFAULT '' COMMENT '用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空',

`privilege` varchar(20) DEFAULT '' COMMENT '用户特权信息,json数组,如微信沃卡用户为(chinaunicom)',

`unionid` varchar(32) DEFAULT '' COMMENT '用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。',

PRIMARY KEY (`id`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;4.9、前端代码:

代码语言:javascript复制

KingYiFan微信第三方登录测试之内嵌二维码

css样式:

.impowerBox .qrcode {width: 200px;}

.impowerBox .title {display: none;}

.impowerBox .info {width: 200px;}

.impowerBox .status {text-align: center;} 终、、以上就是web微信第三方登录

网站名称:猿码优创

网站地址:http://blog.cnbuilder.cn

网站描述:年少是你未醒的梦话,风华是燃烬的彼岸花。

网站Logo/头像: [头像地址](https://blog.cnbuilder.cn/upload/2018/7/avatar20180720144536200.jpg)

欢迎关注猿码优创(联系小优优进内部群哦,新鲜技术优先更新):

📌 相关推荐

总愿别愿
365足球平台是合法的吗

总愿别愿

📅 01-03 👁️ 7956