前言
微信扫码登陆,前段时间写完微信扫码登录后,由于有多个项目都需要微信登录,而公众号的数量有限。 所以需要研究一下多个项目使用同一个公众号登录。
思路
原来的思路: 每个后台与微信服务器之间进行通信, 需要多个公众号
那么,使用一个公众号的话,建立一个中间服务器,与微信进行通信就行了。
同时,与微信服务器交互的代码不需要在项目1、2中写, 省下了很多代码编写
先说一下前提: 本项目是先登录,然后绑定微信用户后, 后续才能使用微信登录。
有了思路之后流程大概如下:
假如在登录的系统是: 项目1, 而服务器收到微信推送事件后需要做这几件事
- 判断该事件是否是向 项目1 推送
- 校验该微信用户是否与 项目1 绑定
- 服务器 向 项目1 发送 登录成功的请求。
- 项目1 向登录成功的客户端,执行登录成功逻辑
- 服务器向微信公众号, 发送登录成功的信息。
如何判断事件是否属于项目1
解决:项目1向服务器发送请求的时候带上项目关键字
例如: 项目的名称为 schedule, 则请求的时候带上参数为shcedule
例如第5行, 参数带上项目的关键字
1 final Map variables = new HashMap<>();
2 variables.put("client", this.wxMpConfig.getClient());
3 variables.put("username", userDetails.getUsername());
4 variables.put("sessionId", sessionId);
5 String requestUrl = UserServiceImpl.addParam( this.wxMpConfig.getService() + "request/getBindQrCode", variables);
6 RestTemplate restTemplate = new RestTemplate();
7 String bindQrCode = restTemplate.getForObject(requestUrl, String.class, variables);
如何校验该微信用户是否与 项目1 绑定
方法1 :向项目1 发送请求, 让项目1来判断。
方法2: 绑定用户的时候,将微信用户和用户存到数据库中,并记录是哪一个项目
方法1
需要项目1
自己记录用户和微信用户的对应关系,方法2
自己记录了对应关系,项目1
可选择记录或不记录
服务器 向 项目1 发送 登录成功的请求。
需要我们根据项目关键字 client
,获取 项目1的地址
这时候我们可以写个前台, 记录该地址
final Map variables = new HashMap<>();
variables.put("wsLoginToken", wsLoginToken);
variables.put("username", user.getUsername());
String url = setting.getUrl() + "/api/wechat/login";
CommonServiceImpl.httpPost(url, weChatUser, variables);
post请求用到的包是 org.springframework.web.client.RestTemplate
然后简单封装了一下, 并加入了请求重试:
@Retryable(value = {RestClientException.class, EOFException.class}, maxAttempts = 3,
backoff = @Backoff(delay = 1000L,multiplier = 1))
static public void httpPost(String url , T entity, Map variables) {
//创建请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 添加url参数格式
String requestUrl = CommonServiceImpl.addParam(url, variables);
HttpEntity requestEntity = new HttpEntity(entity, headers);
RestTemplate restTemplate = new RestTemplate();
// 发送post请求
ResponseEntity response = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, String.class, variables);
// 判断请求是否发生异常
if(!response.getStatusCode().is2xxSuccessful()){
System.out.println("请求失败...");
// 抛出异常
throw new RestClientException(response.getBody());
}
}
项目1 向登录成功的客户端,执行登录成功逻辑
@Override
public void bindWsUuidToWeChatUser(String wsLoginToken, String username) {
// 登录凭证 前台凭该loginUid作为用户名和密码登录
String loginUid = UUID.randomUUID().toString();
this.map.put(loginUid, username);
simpMessagingTemplate.convertAndSendToUser(wsLoginToken,
"/stomp/scanLoginQrCode",
loginUid);
}