Requirements: Login to the website using WeChat Official Account and retrieve user information.
Prerequisites#
- WeChat Official Account has been authenticated.
- Have a server that can receive callbacks from the WeChat server.
Steps#
1. Obtain the appid and appsecret of the WeChat Official Account.#
2. Connect to the server and receive callbacks from the WeChat server. You need a domain name, and you can use a tool like cpolar for intranet penetration.#
First, prepare the resources shown in the image#
Explanation:
-
The URL represents the verification of whether the WeChat server exists. It needs to be configured according to the requirements. For example, the address here is
https://13a34511.r1.cpolar.top/api/user/wxcheckSo you must prepare the corresponding interface on your own server
// There is still /user on the outer layer @GetMapping("wxcheck") public String wxCheck(@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr) { if (userService.wxCheck(signature, timestamp, nonce, wxOpenConfig.getToken())) { return echostr; } else { return "error"; } }The data needs to be returned according to the requirements of WeChat, as follows:
-
Sort the three parameters token, timestamp, and nonce in lexicographical order.
-
Concatenate the three parameter strings into one string and encrypt it with sha1.
-
The developer can compare the encrypted string obtained with the signature to indicate that the request comes from WeChat.
@Override public Boolean wxCheck(String signature, String timestamp, String nonce, String token) { // WeChat Official Account access verification // Sort the three parameters token, timestamp, and nonce in lexicographical order String[] arr = new String[]{token, timestamp, nonce}; Arrays.sort(arr); // Concatenate the three parameter strings into one string and encrypt it with sha1 StringBuilder content = new StringBuilder(); for (String s : arr) { content.append(s); } String tmpStr = MYDigestUtils.sha1DigestAsHex(content.toString()); log.info("WeChat Official Account access verification, signature = {}, tmpStr = {}", signature, tmpStr); return signature.equals(tmpStr); }After submitting the form above, it will prompt that the verification is passed.
-
3. Next is to obtain the access_token#
- You need to return the token for accessing WeChat resources according to the requirements. This token is required for accessing resources in WeChat, such as QR codes.
- Official documentation Start Development / Get Access Token (qq.com)
- Code:
@Override
public String getAccessToken() {
// Get access_token
String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
wxOpenConfig.getAppId(), wxOpenConfig.getAppSecret());
// Send request
String result = restTemplate.getForObject(url, String.class);
log.info("Get access_token, result = {}", result);
return result;
}
4. Generate a QR code with Ticket#
@Override
public String getQRCode(String accessToken) {
// Get QR code
String url = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken);
// Expires in 5 minutes
String body = WXUtils.getQRCodeBody("300", "QR_STR_SCENE");
String result = restTemplate.postForObject(url, body, String.class);
log.info("Get QR code, result = {}", result);
return result;
}
5. Return the ticket of the QR code to the front-end, and the front-end requests and displays the QR code image to the user.#
6. After the user scans the QR code, the corresponding event will be pushed to the above URL. Only the GET request is converted to a POST request, in the format:#
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[qrscene_123123]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>
Of course, there are many event types, and we can define a strategy pattern to handle them separately.
@Slf4j
public class DispatchEventHandle {
private final Map<String, EventHandle> eventHandleMap = new HashMap<>();
{
eventHandleMap.put("subscribe", new SubscribeEventHandle());
eventHandleMap.put("SCAN", new ScanEventHandle());
}
public void dispatch(JSONObject jsonObject) {
String eventType = jsonObject.getJSONObject("xml").getStr(WxEventHandleConstants.EVENT_TYPE_KEY);
log.info("Event type:{}", eventType);
EventHandle eventHandle = eventHandleMap.get(eventType);
if (eventHandle == null) {
log.error("No corresponding event handler found");
return;
}
eventHandle.handle(jsonObject);
}
}
The interface for receiving requests is defined as
@PostMapping("wxcheck")
public String event(@RequestBody String xml) {
String msgType = WXUtils.getMsgType(xml);
if ("event".equals(msgType)) {
DispatchEventHandle dispatchEventHandle = new DispatchEventHandle();
dispatchEventHandle.dispatch(JSONUtil.xmlToJson(xml));
}
return xml;
}
7. After displaying the QR code, the front-end needs to poll the server to check if it has been scanned. The backend can cache the ticket as the key and JWT as the value after processing, and the front-end can successfully log in by querying it.#
This article is synchronized and updated to xLog by Mix Space
The original link is https://me.liuyaowen.club/posts/default/1