微信授权登录获取用户信息有2种方式:
1.静默授权获取用户信息、
2.非静默授权弹出授权界面,用户确认之后获取用户信息(这种方法能够获取到更多信息)。
开发前准备:
1.获取到AppID
2.AppSecret
3.设置IP白名单
4.添加网页授权域名
公众号设置->功能设置
前端获取code:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
通过code换取网页授权access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
拉取用户信息
https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN
<dependency>
<groupId>com.github.kevinsawicki</groupId>
<artifactId>http-request</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
package com.pica.cloud.patient.resident.server.util;
import com.alibaba.fastjson.JSON;
import com.github.kevinsawicki.http.HttpRequest;
import com.pica.cloud.patient.resident.common.constants.CommonCons;
import com.pica.cloud.patient.resident.server.configuration.BeanConfiguration;
import com.pica.cloud.patient.resident.server.vo.AccessTokenVo;
import com.pica.cloud.patient.resident.server.vo.WechatUserInfoVo;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @ClassName WechatUtil
* @Description
* @Author Jun.li0101
* @Date 2019/3/19 16:43
* @ModifyDate 2019/3/19 16:43
* @Version 1.0
*/
@Component
@Slf4j
public class WechatUtil {
private static BeanConfiguration configuration;
private final static Integer SUCCESS = 0;
@Autowired
public WechatUtil(BeanConfiguration config) {
WechatUtil.configuration = config;
}
public static AccessTokenVo getWechatAccessToken(String code) {
if (code == null) {
return null;
}
String url = String.format(CommonCons.Wechat.LOGIN_ACCESS_TOKEN_URL, configuration.getAppId(), configuration.getAppSecret(), code);
try {
String result = HttpRequest.get(url).body();
log.info("getWechatAccessToken result:{}", result);
var token = JSON.parseObject(result, AccessTokenVo.class);
if (token.getErrCode() == null || SUCCESS.equals(token.getErrCode())) {
log.info("get wechat access token:{}", token);
return token;
} else {
log.warn("code {} request wechat api get access token error:{}", code, token);
}
} catch (Exception ex) {
log.error("getWechatAccessToken error", ex);
}
return null;
}
public static WechatUserInfoVo getWechatUserInfo(AccessTokenVo tokenVo) {
if (tokenVo == null) {
return null;
}
var url = String.format(CommonCons.Wechat.GET_USER_INFO_URL, tokenVo.getAccessToken(), tokenVo.getOpenId());
try {
String result = HttpRequest.get(url).body();
var info = JSON.parseObject(result, WechatUserInfoVo.class);
if (info.getErrCode() == null || SUCCESS.equals(info.getErrCode())) {
log.info("get wechat user info:{}", info);
return info;
} else {
log.warn("request wechat api get user information error:{}", info);
}
} catch (Exception ex) {
log.error("getWechatUserInfo error", ex);
}
return null;
}
}
package com.pica.cloud.patient.resident.server.vo;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* @ClassName AccessTokenVo
* @Description {@link} 参考 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=&lang=zh_CN
* @Author Jun.li0101
* @Date 2019/3/19 17:15
* @ModifyDate 2019/3/19 17:15
* @Version 1.0
*/
@Getter
@Setter
@ToString
public class AccessTokenVo extends WechatCommonVo {
@JSONField(format = "access_token")
private String accessToken;
@JSONField(format = "expires_in")
private Integer expiresIn;
@JSONField(format = "refresh_token")
private String refreshToken;
@JSONField(format = "openid")
private String openId;
@JSONField(format = "scope")
private String scope;
@JSONField(format = "unionid")
private String unionId;
}
//
package com.pica.cloud.patient.resident.server.vo;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* @ClassName WechatUserInfoVo
* @Description {@link} 参考 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317853&token=&lang=zh_CN
* @Author Jun.li0101
* @Date 2019/3/19 18:59
* @ModifyDate 2019/3/19 18:59
* @Version 1.0
*/
@Getter
@Setter
@ToString
public class WechatUserInfoVo extends WechatCommonVo {
@JSONField(format = "openid")
private String openid;
@JSONField(format = "nickname")
private String nickname;
@JSONField(format = "sex")
private Integer sex;
@JSONField(format = "province")
private String province;
@JSONField(format = "city")
private String city;
@JSONField(format = "country")
private String country;
@JSONField(format = "headimgurl")
private String headImgurl;
@JSONField(format = "unionid")
private String unionid;
@JSONField(format = "language")
private String language;
}
- 微信登录表情特殊符号处理
据库以及JDBC默认的字符集都是utf8,在存储emoji表情时会报错:
Incorrect string value: '\xF0\x9F\xA4\xA9' for column 'nickname'
原因是utf8不支持4字节的emoji表情。
具体如下:
utf8与utf8mb4具有相同存储特性:相同的代码值,相同的编码,相同的长度。不过utf8mb4扩展到一个字符最多可有4位元,所以能支持更多的位元集。utf8mb4不只兼容utf8,还能比utf8能展示更新的字符。将编码改为utf8mb4外不需要做其他转换。
为了要跟国际接轨,原本的utf8编码在存储某些国家的文字(或是罕见字)已经不敷使用,因此在mysql5.5.3版以上,可以开始使用4-Byte UTF-8 Unicode的编码方式。
Mysql查看版本方式:
select version();
Mysql在5.5.3版本之后增加了utf8mb4字符编码,mb4即most bytes 4。简单说utf8mb4是utf8的超集并完全兼容utf8,能够用四个字元存储更多的字符。
utf8mb4可以向下兼容utf8,而且比utf8可以表示更多的字符。此外,将编码改为utf8mb4不需 要其他转换。
解决办法:
1.修改mysql配置文件my.cnf,同时将库表的默认字符集都改为utf8mb4;
default-character-set=utf8mb4
同时修改项目的JDBC连接配置
spring.datasource.tomcat.init-s-q-l=SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci