Third-party App Access to Wechat Login Interpretation Process (Improvement)

Keywords: Mobile JSON SDK

Interpretation of Third Party App Access to Wechat Login

Dead work

1. On Wechat Open Platform https://open.weixin.qq.com/ Register as a developer.

2. To create a mobile application in the "Management Center", you need to "apply the name, profile, and 28*28 and 108*108 PNG pictures each, and the size does not exceed 300k". Click on the next step, you need to "apply the official address, application signature and package name" and other information, then you can submit for review.  
Description:
Application Signature: You can download "Signature Generation Tool" in "Resource Center of Wechat Development Platform" and "Resource Download". Users can get the signature of third-party applications installed in mobile phones. Enter the application package name to get the signature value of the application.

3. Tencent will give the audit results within 7 working days after submitting the audit. (Usually it's faster, and the results can be fed back in a few hours)

Wechat login access

Wechat login follows the authorization code pattern in Aouth 2.0

Let's look at how the authorization code pattern in Aouth 2.0 is defined:

authorization code is the most complete and rigorous authorization mode. Its characteristic is to interact with the "service provider" authentication server through the client's back-end server.  
Its steps are as follows:

(A) The user accesses the client, which directs the former to the authentication server.

(B) The user chooses whether to grant client authorization or not.

(C) Assuming that the user grants authorization, the authentication server directs the user to the redirection URI specified by the client in advance, with an authorization code attached.

(D) The client receives the authorization code and attaches an earlier "redirect URI" to apply for a token to the authentication server. This step is done on the back-end server of the client and is not visible to the user.

(E) The authentication server checks the authorization code and redirects the URI and sends access token and refresh token to the client after confirmation is correct.

The official document of Weichat login divides Weichat login into three steps:

Step 1. Request code

{
    // send oauth request 
     Final SendAuth.Req req = new SendAuth.Req();
     req.scope = "snsapi_userinfo";
     req.state = "wechat_sdk_demo_test";
     api.sendReq(req);
    }

 

Using this code to request authorization code from Weichat Open Platform, you can pull up Weichat and open the authorization login page (provided you install the Weichat application and have logged in, unlisted will lead you to log in first). The following figure is as follows:

1. If the authorization page of Wechat does not show, please check if your APP signature is consistent with your APP signature in Tencent Open Platform. If the inconsistency is not consistent, you can modify the APP signature in Tencent Open Platform, and then reinstall the Wechat or clear the Wechat data and try again.

2. Create a new wxapi directory under the corresponding directory of your package name and add a new WXEntryActivity class under the wxapi directory, which inherits from Activity (e.g. the package name of the application is net.sourceforge, and the new package name is net.sourceforge.wxapi). Here, you should be careful not to make mistakes in the package name. The name of the new class must be WXEntryActivity.

Return instructions
After the user clicks on authorization, the Wechat client will be pulled up and jumped to the authorization interface, where the user clicks to allow or cancel, and SDK returns data to the caller through SendAuth Resp. Callback the onResp(BaseResp resp) method in WXEntry Activity as follows:

@Override
    public void onResp(BaseResp resp) {
        int errorCode = resp.errCode;
        switch (errorCode) {
        case BaseResp.ErrCode.ERR_OK:
            //User Consent
            String code = ((SendAuth.Resp) resp).code;
            break;
        case BaseResp.ErrCode.ERR_AUTH_DENIED:
            //User rejection
            break;
        case BaseResp.ErrCode.ERR_USER_CANCEL:
            //User Cancel
            break;
        default:
            break;
        }
        ToastUtil.showMessageLong(this, resp.errStr);
    }

 

After receiving the authorization code, the client initiates a login request to its own server, accompanied by the authorization code received.

The server receives the login request and requests access_token from the Wechat Open Platform. The Wechat Open Platform returns the Json string:

Step 2: Get access_token through code (done on your own server)

After getting the code of the first step, request the following link to get access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

private String getAccessToken(String code) {
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        URI uri = URI.create(url);
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(uri);

        HttpResponse response;
        try {
            response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();

                BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
                StringBuilder sb = new StringBuilder();

                for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                    sb.append(temp);
                }

                JSONObject object = new JSONObject(sb.toString().trim());
                accessToken = object.getString("access_token");
                openID = object.getString("openid");
                refreshToken = object.getString("refresh_token");
                expires_in = object.getLong("expires_in");
                return accessToken;
            }
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block 
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

 

Description of parameters

Does the parameter have to be specified? 
appid is the unique identifier of the application, which is obtained after submitting the application audit by the open platform of Wechat.

secret is the application key AppSecret, which is obtained after submitting the application audit in the open platform of Wechat.

Code is the code parameter obtained by filling in the first step

grant_type is to fill in authorization_code back instructions**

Correct return:

{ 
"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE",
"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

 

Description of parameters
 access_token interface call credentials
 Expires_in access_token interface calls credential timeout in seconds
 refresh_token user refreshes access_token
 openid Authorized User Unique Identification
 Scope user authorization scope, separated by commas (,)
unionid will only appear if the user binds the public number to the Wechat Open Platform account.
Error return sample:
{"errcode":40029,"errmsg":"invalid code"}

The server receives the returned access_token and returns the data such as access_token, expires_in and access_token to the client. The client logs in successfully.

Client can use existing access_token to obtain micro-credit user information

Step 3: Call the interface through access_token

After obtaining access_token, interface calls are made on the following premises:

  1. access_token is valid and not timed out.
  2. Microcredit users have been authorized to the corresponding interface scope of third-party application accounts.

For interface scope, there are the following interfaces that can be invoked:

Authorization scope Interface Description
 Snsapi_base/sns/oauth2/access_token exchanges code for access_token, refresh_token and authorized scope
                    / sns/oauth2/refresh_token refresh or renew access_token use
                    / sns/auth check access_token validity
 Snsapi_userinfo/sns/userinfo Getting User Personal Information

Among them, snsapi_base belongs to the basic interface. If the application already has other scope permissions, it defaults to have the permissions of snsapi_base. Using snsapi_base can enable mobile web page authorization to bypass the action of jumping authorization login page requesting user authorization, and directly jump to third-party Web page with authorization temporary ticket (code), but it will make the user's authorized scope only snsapi_base, which makes it impossible to obtain the data and basic functions that require user authorization.

Take the acquisition of user information as an example:

private void getUserInfo() {
        if (isAccessTokenIsInvalid() && System.currentTimeMillis() < expires_in) {
            String uri = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openID;
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(URI.create(uri));
            try {
                HttpResponse response = client.execute(get);
                if (response.getStatusLine().getStatusCode() == 200) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
                    StringBuilder builder = new StringBuilder();
                    for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                        builder.append(temp);
                    }
                    JSONObject object = new JSONObject(builder.toString().trim());
                    String nikeName = object.getString("nickname");
                }
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

 

Wechat duplicate login

Assuming that the user has been authorized, the next login only needs to verify whether access_token is valid, if it is invalid, the authorization will be re-obtained, and if it is valid, no re-authorization will be required.

1. Users request login from their servers by Wechat, with access_token returned from the last login.

2. The server receives the user's login request and sends the valid authentication request of access_token to the Wechat Open Platform as follows:

private boolean isAccessTokenIsInvalid() {
        String url = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openID;
        URI uri = URI.create(url);
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(uri);
        HttpResponse response;
        try {
            response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();

                BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
                StringBuilder sb = new StringBuilder();

                for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                    sb.append(temp);
                }
                JSONObject object = new JSONObject(sb.toString().trim());
                int errorCode = object.getInt("errcode");
                if (errorCode == 0) {
                    return true;
                }
            }
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }

Return note
Correct Json Returns the result:
{ 
"errcode":0,"errmsg":"ok"
}
//Error Json returns an example:
{ 
"errcode":40003,"errmsg":"invalid openid"
}

 

If access_token is valid, the server returns the information to the client, and the client successfully logs in.

If access_token is invalid, the server sends a request to refresh access_token to the Wechat Open Platform as follows:

Access_token is the invocation credential for invoking the authorization relationship interface. Because the access_token validity period (currently 2 hours) is short, refresh_token can be used to refresh the access_token after the access_token timeout. There are two kinds of access_token refresh results:

1. If access_token has timed out, refresh_token will get a new access_token, a new timeout time;
2. If access_token is not timed out, refresh_token will not change access_token, but the timeout will refresh, which is equivalent to the renewal of access_token.

Refresh_token has a longer validity period (30 days). When refresh_token expires, the user is required to re-authorize it.

private void refreshAccessToken() {
        String uri = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + ShareUtil.APP_ID + "&grant_type=refresh_token&refresh_token="
                + refreshToken;
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(URI.create(uri));
        try {
            HttpResponse response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == 200) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
                StringBuilder builder = new StringBuilder();
                for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                    builder.append(temp);
                }
                JSONObject object = new JSONObject(builder.toString().trim());
                accessToken = object.getString("access_token");
                refreshToken = object.getString("refresh_token");
                openID = object.getString("openid");
                expires_in = object.getLong("expires_in");
            }
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

Return note

Correct return:
{ 
"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN", 
"openid":"OPENID", 
"scope":"SCOPE" 
}
Description of parameters
 access_token interface call credentials
 Expires_in access_token interface calls credential timeout in seconds
 refresh_token user refreshes access_token
 openid Authorized User Unique Identification
 Scope user authorization scope, separated by commas (,)

Error return sample:
{
"errcode":40030,"errmsg":"invalid refresh_token"
}

3. The server obtains new access_token and other information, and returns it to the client. The client successfully logs in or regains authorization.

Posted by fert on Sat, 08 Jun 2019 13:06:41 -0700