Trong quá trình phát triển ứng dụng tích hợp với WeChat Official Account sử dụng thư viện weixin-java-tools (hay còn gọi là WxJava), việc nâng cấp phiên bản thường đi kèm với những thay đổi lớn về cấu trúc API. Điều này yêu cầu lập trình viên phải điều chỉnh lại mã nguồn để đảm bảo tính tương thích.
Quy trình cơ bản để lấy thông tin người dùng qua OAuth2 trên WeChat bao gồm các bước:
- Tiếp nhận
codetừ callback của WeChat. - Sử dụng
codeđể đổi lấyAccessToken. - Dùng
AccessTokenđể lấy thông tin chi tiết người dùng (bao gồmopenId). - Liên kết
openIdvới hệ thống tài khoản nội bộ.
Dưới đây là sự khác biệt trong cách triển khai mã nguồn giữa phiên bản cũ (2.8.0) và phiên bản mới hơn (4.1.0).
1. Triển khai với phiên bản 2.8.0
Ở các phiên bản cũ, các phương thức hỗ trợ OAuth2 thường được tích hợp trực tiếp vào đối tượng dịch vụ chính. Cấu trúc mã nguồn thường đơn giản nhưng thiếu tính phân tách rõ rệt giữa các module.
@RequestMapping("/handleCallback")
public String handleCallback(String code, HttpServletResponse resp, HttpSession session) throws WxErrorException {
// Đổi code lấy AccessToken
WxMpOAuth2AccessToken authResponse = wxService.oauth2getAccessToken(code);
// Truy xuất thông tin người dùng
WxMpUser userProfile = wxService.oauth2getUserInfo(authResponse, "zh_CN");
String openId = userProfile.getOpenId();
Map<String, Object> accountData = userClient.checkBinding(openId);
Integer status = (Integer) accountData.get(BaseApiConstants.HTTP_CODE_NAME);
// Nếu đã liên kết tài khoản, thực hiện đăng nhập tự động
if (status.equals(BaseApiConstants.HTTP_200_CODE)) {
String sessionToken = (String) accountData.get("data");
CookieUtil.setCookie(resp, Constants.USER_TOKEN, sessionToken, Constants.TOKEN_EXPIRY);
return REDIRECT_HOME;
}
// Lưu thông tin vào session để phục vụ việc liên kết tài khoản sau đó
session.setAttribute("wxOpenId", openId);
session.setAttribute("regSource", "wechat");
return BINDING_PAGE;
}
2. Triển khai với phiên bản 4.1.0
Từ phiên bản 4.x trở đi, thư viện đã thực hiện tái cấu trúc mạnh mẽ. Các dịch vụ OAuth2 được tách ra thành một sub-service riêng biệt (OAuth2Service). Ngoài ra, tên các lớp và phương thức getter cũng có sự thay đổi đáng kể (ví dụ: getOpenid() thay vì getOpenId()).
@RequestMapping("/handleCallback")
public String handleCallback(String code, HttpServletResponse resp, HttpSession session) {
try {
// Sử dụng sub-service OAuth2 để lấy token
WxOAuth2AccessToken tokenInfo = wxService.getOAuth2Service().getAccessToken(code);
// Lấy thông tin người dùng thông qua đối tượng OAuth2UserInfo mới
WxOAuth2UserInfo profile = wxService.getOAuth2Service().getUserInfo(tokenInfo, "zh_CN");
// Lưu ý: Tên phương thức getter có thể thay đổi (ví dụ: getOpenid)
String currentOpenId = profile.getOpenid();
Map<String, Object> linkStatus = userClient.checkBinding(currentOpenId);
Integer resCode = (Integer) linkStatus.get(BaseApiConstants.HTTP_RES_CODE_NAME);
if (resCode.equals(BaseApiConstants.HTTP_RES_CODE_200)) {
String jwtToken = (String) linkStatus.get("data");
CookieUtil.setCookie(resp, Constants.USER_TOKEN, jwtToken, Constants.TOKEN_EXPIRY);
return REDIRECT_HOME;
}
session.setAttribute("wxOpenId", currentOpenId);
session.setAttribute("regSource", "wechat");
} catch (WxErrorException e) {
log.error("Lỗi khi xử lý callback WeChat: ", e);
}
return BINDING_PAGE;
}
Sự thay đổi này hướng tới việc module hóa mã nguồn, giúp việc quản lý các dịch vụ khác nhau của WeChat (như Pay, Message, OAuth) trở nên mạch lạc hơn. Khi nâng cấp, lập trình viên cần đặc biệt chú ý đến việc thay đổi các gói (package) và các kiểu dữ liệu trả về để tránh lỗi Runtime.