扫码登录需要一个微信公众号,只有关注了这个公众号的微信,才有权限扫码登录。所以首先申请一个微信公众号。
1.公众号 - 打开下面网址申请一个测试公众号用作开发测试 ``` https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
扫码登录
申请一个公众号
扫码关注公众号
- 配置回调域名 找到网页账号
’
点击修改,配置你的域名,如果没有自己的域名建议下载一个花生壳,花生壳6块钱能买一个https的域名内网穿透‘
2.编码 下面代码以spring boot为例,这里引入了一个集成好的依赖,如果想自己开发对应方法,请参考[微信开发文档](https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html),很简单
- 引入pom依赖
```xml
<!-- wx -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.7.0</version>
</dependency>
<!-- tool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.20</version>
</dependency>
<!-- zxing -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.1</version>
</dependency>
```
- yml配置文件中加入以下配置
```
wx:
#公众号的appID
app-id: wxbe******d3b006f6
#公众号的appsecret
secret: f9ac33a******8aa2c17f3b70f921251
#公众号中配置的域名
domain: https://api.12121.com
#接口回调地址
redirect-url: /work/wx/user/info
```
- 编写配置类
```java
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "wx")
public class WeChatProperty {
private String appId;
private String secret;
private String domain;
private String redirectUrl;
}
```
- 注入Bean
```java
@Configuration
public class WeChatConfig {
@Resource
private WeChatProperty weChatProperty;
@Bean
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
@Bean
public WxMpConfigStorage wxMpConfigStorage() {
WxMpDefaultConfigImpl wxMpConfigStorage = new WxMpDefaultConfigImpl();
wxMpConfigStorage.setAppId(weChatProperty.getAppId());
wxMpConfigStorage.setSecret(weChatProperty.getSecret());
return wxMpConfigStorage;
}
}
```
- service接口
```java
public interface WeChatService {
/**
* 获取扫码登录二维码
*
* @param state state
*/
void getQr(String state);
/**
* 获取扫码登录二维码
*
* @param state state
* @return 二维码
*/
BaseResult<?> getQrData(String state);
/**
* 获取用户信息
*
* @param code code
* @param state state
* @return 用户信息
*/
BaseResult<?> userInfo(String code, String state);
}
```
- service接口实现类
```java
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public class WeChatServiceImpl implements WeChatService {
private final WxMpService wxMpService;
private final WeChatProperty weChatProperty;
@Override
public void getQr(String state) {
try {
ImgUtil.write(getQrImage(state), ImgUtil.IMAGE_TYPE_PNG, ServletUtil.getResponse().getOutputStream());
} catch (Exception e) {
log.info(ExceptionUtils.getStackTrace(e));
}
}
@Override
public BaseResult<?> getQrData(String state) {
return ResultUtil.buildResultSuccess(ImgUtil.toBase64DataUri(getQrImage(state), ImgUtil.IMAGE_TYPE_PNG));
}
@Override
public BaseResult<WxMpUser> userInfo(String code, String state) {
try {
WxMpOAuth2AccessToken token = getToken(code);
WxMpUser userInfo = wxMpService.oauth2getUserInfo(token, null);
return ResultUtil.buildResultSuccess(userInfo);
} catch (WxErrorException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
return ResultUtil.buildResultError(ResponseCodeEnum.WX_GET_USER_INFO_ERROR);
}
/**
* 获取token信息
*
* @param code code
* @return token信息
*/
private WxMpOAuth2AccessToken getToken(String code) {
try {
return wxMpService.oauth2getAccessToken(code);
} catch (WxErrorException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
return null;
}
/**
* 获取鉴权地址
*
* @param scope 鉴权类型
* @param state state
* @return 扫码鉴权地址
*/
private String getRedirectUrl(String scope, String state) {
return wxMpService.oauth2buildAuthorizationUrl(getCallbackUrl(), scope, state);
}
/**
* 获取回调地址
*
* @return 回调地址
*/
private String getCallbackUrl() {
return weChatProperty.getDomain() + weChatProperty.getRedirectUrl();
}
/**
* 获取验证二维码图片
*
* @param state state
* @return 图片
*/
private BufferedImage getQrImage(String state) {
return QrCodeUtil.generate(getRedirectUrl(WxConsts.OAuth2Scope.SNSAPI_USERINFO, state),
QrConfig.create()
.setWidth(300)
.setHeight(300));
}
}
```
- 编写Controller
```java
@Tag(name = "WX", description = "md相关接口")
@RestController
@RequestMapping("/wx")
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public class WeChatController {
private final WeChatService weChatService;
@Operation(tags = "WX", summary = "获取验证图片", method = "/userInfo", description = "获取验证图片")
@PassToken
@GetMapping("/qr")
public void getQr(@RequestParam("state") String state) {
weChatService.getQr(state);
}
@Operation(tags = "WX", summary = "获取验证链接", method = "/userInfo", description = "获取验证链接")
@PassToken
@GetMapping("/qr/data")
public BaseResult<?> getQrData(@RequestParam("state") String state) {
return weChatService.getQrData(state);
}
@Operation(tags = "WX", summary = "获取用户详情接口", method = "/userInfo", description = "获取用户详情接口")
@PassToken
@GetMapping("/user/info")
public BaseResult<?> userInfo(@RequestParam("code") String code, @RequestParam("state") String state) {
return weChatService.userInfo(code, state);
}
}
```
### 3.使用
- 访问/wx/qr接口
- 微信扫码
可以看到后端日志中已经获取到了用户的基本信息