前言
微信掃碼登陸,前段時間寫完微信掃碼登入後,由於有多個專案都需要微信登入,而公眾號的數量有限。 所以需要研究一下多個專案使用同一個公眾號登入。
思路
原來的思路: 每個後臺與微信伺服器之間進行通訊, 需要多個公眾號
那麼,使用一個公眾號的話,建立一箇中間伺服器,與微信進行通訊就行了。
同時,與微信伺服器互動的程式碼不需要在專案1、2中寫, 省下了很多程式碼編寫
先說一下前提: 本專案是先登入,然後繫結微信使用者後, 後續才能使用微信登入。
有了思路之後流程大概如下:
假如在登入的系統是: 專案1, 而伺服器收到微信推送事件後需要做這幾件事
- 判斷該事件是否是向 專案1 推送
- 校驗該微信使用者是否與 專案1 繫結
- 伺服器 向 專案1 傳送 登入成功的請求。
- 專案1 向登入成功的客戶端,執行登入成功邏輯
- 伺服器向微信公眾號, 傳送登入成功的資訊。
如何判斷事件是否屬於專案1
解決:專案1向伺服器傳送請求的時候帶上專案關鍵字
例如: 專案的名稱為 schedule, 則請求的時候帶上引數為shcedule
例如第5行, 引數帶上專案的關鍵字
1 final Map<String, String> 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<String, String> 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 <T> void httpPost(String url , T entity, Map<String, String> variables) {
//建立請求頭
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 新增url引數格式
String requestUrl = CommonServiceImpl.addParam(url, variables);
HttpEntity<T> requestEntity = new HttpEntity<T>(entity, headers);
RestTemplate restTemplate = new RestTemplate();
// 傳送post請求
ResponseEntity<String> 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);
}