This article mainly explains the system to support the third party webpage QQ login process and matters needing attention, and we discuss, common progress.Copy the code

The preparatory work

First of all, we need to apply for a developer account on the QQ Internet platform and submit website application review information.

The following information is displayed: Enter the following information

There is no special requirement here, you can fill in normally, I guess it is manual review, so I suggest you apply on weekdays, the time is very quick, submit in the morning, can be approved in the afternoon.Copy the code

Only after completing the application of QQ individual developer account can you apply for the application of the website. The information to be filled in is shown in the screenshot below:

Here you need to pay attention to their website name and website record number must be consistent with the Ministry of Industry and Information Technology, website icon remember not to find a random, otherwise it is likely to fail the audit.Copy the code

Ready to develop

You can check the relevant process in QQ Internet platform Wiki. The following is the code logic:

Graph.qq.com/oauth2.0/sh…

It is recommended that the callback address be your website address, such as login page or home page. In this way, after QQ authorization is successful, the address will add parameter information. At this time, the interface of the back end can be called according to this parameter:

Database design, add user authorization table, so that can adapt to multiple third party login without adding new fields:

CREATE TABLE user_auths (' id 'bigint NOT NULL AUTO_INCREMENT,' user_id 'bigint NOT NULL COMMENT' user ID ', 'identity_type' varchar(5) DEFAULT NULL COMMENT ' Qq /weChat', 'identifier_id' varchar(64) DEFAULT NULL COMMENT ' For example unionID) ', 'credential' vARCHar (64) DEFAULT NULL COMMENT 'credential ', PRIMARY KEY (' id ') ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8 COMMENT=' unsigned ';Copy the code
// The following is the core logic of the back-end interface. This code is in Java language:  public ObjectResponse userLoginByQQ(String code, String state) {/ / application AppId, AppKey, RedirectUri advice to make configurable String qqAppId = configBeanValue. GetQqAppId (); String qqAppKey = configBeanValue.getQqAppKey(); String qqAppRedirectUri = configBeanValue.getQqAppRedirectUri(); // Obtain token String getTokenUrl = according to authorization code "Https://graph.qq.com/oauth2.0/token?fmt=json&grant_type=authorization_code&client_id= + qqAppId + & client_secret =" + qqAppKey + "&redirect_uri=" + qqAppRedirectUri + "&code=" + code; log.info("userLoginByQQ getTokenUrl:{}", getTokenUrl); / / here using spring boot encapsulated HttpClient Map tokenMap = restTemplate. GetForObject (getTokenUrl, Map. Class); log.info("userLoginByQQ getToken result:{}", JSON.toJSONString(tokenMap)); if (! Tokenmap.containskey ("access_token")) {throw new MyException(" Authorization failed, please try again!" ); } String accessToken = tokenMap.get("access_token").toString(); / / to token access users openid String getOpenIdUrl = "https://graph.qq.com/oauth2.0/me?fmt=json&access_token=" + accessToken; log.info("userLoginByQQ getOpenIdUrl:{}", getOpenIdUrl); Map openMap = restTemplate.getForObject(getOpenIdUrl, Map.class); log.info("userLoginByQQ getOpenIdUrl result:{}", JSON.toJSONString(openMap)); if (! Openmap.containskey (" openID ")) {throw new MyException(" Authorization failed, please try again!" ); } String openId = openMap.get("openid").toString(); // Obtain the unionID according to openID. The unionID of the same user is the same for different applications under the same QQ interconnection platform. So developers have multiple mobile apps, multiple web apps, UnionID through access to the user to distinguish between the uniqueness of user String getUnionIdUrl + = "https://graph.qq.com/oauth2.0/me?fmt=json&unionid=1&access_token=" accessToken; log.info("userLoginByQQ getUnionIdUrl:{}", getUnionIdUrl); Map unionMap = restTemplate.getForObject(getUnionIdUrl, Map.class); log.info("userLoginByQQ getUnionIdUrl result:{}", JSON.toJSONString(unionMap)); if (! Unionmap.containskey (" unionID ")) {throw new MyException(" Authorization failed, please try again!" ); } String unionId = unionMap.get("unionid").toString(); / / this code for pseudo code, that is, according to the QQ the account if there is a unique identifier and type queries List < UserAuths > UserAuths = userAuthsMapper. SelectByUserAuths (unionId, "QQ"); If (collutil.isEmpty (userAuths)) {String getUserInfoUrl = "https://graph.qq.com/user/get_user_info?access_token=" + accessToken + "&oauth_consumer_key=" + qqAppId + "&openid=" + openId; log.info("userLoginByQQ getUserInfoUrl:{}", getUserInfoUrl); Map userMap = restTemplate.getForObject(getUserInfoUrl, Map.class); log.info("userLoginByQQ getUserInfoUrl result:{}", JSON.toJSONString(userMap)); if (! Usermap.containskey ("nickname")) {throw new MyException(" authorization failed, please try again!" ); } String nickName = userMap.get("nickname").toString(); Cachemanager.set (" QQ "+unionId,accessToken); cachemanager.set (" QQ "+unionId,accessToken) Map<String, String> resultMap = new HashMap<>(); resultMap.put("nickName", nickName); resultMap.put("identifierId", unionId); resultMap.put("identityType", CommonEnums.UserAuthsIdentityTypeEnums.QQ.getCode()); Return new ObjectResponse(" Account not registered!" ).data(resultMap); ResultUserInfoVo = userLogin();} // This code is a dummy code, and the following logic is used to process the login information. return new ObjectResponse().rel(true).data(resultUserInfoVo); }Copy the code

One thing that should be noticed in the above code is that I obtained the unionID after obtaining the openID of the account. Here, considering the situation of multiple applications, there will be different openIDS of unified QQ users.

The other thing that people are talking about is does access_token need to be stored after you get the unique identity of the account? Or what’s the point of storage? I understand that the access_token is meaningless to the user if there is no need to obtain other information after the initial access to the user’s openId. But for the licensor, you need credentials to get the user’s data, you definitely need them.

Improve the work

For the interaction has been associated with the user login directly through a third party, for not registered to the user experience better, can increase the interaction, such as detection to the third party account unregistered, let the user choose to register a new user login or existing accounts, test by registering a new account or login user associated with the third party account records.