1. 程式人生 > >PC 微信掃碼登陸

PC 微信掃碼登陸

1、註冊微信開發平臺

官網網址 自行註冊,需要注意的是註冊郵箱號不用與騰訊其他產品同號。

2、微信開發平臺新增網站應用

新增網站應用

填寫基本資訊

填寫基本資訊2

網站資訊登記表模板

網站應用名稱不能重複

新增授權回撥域-可以修改

以上資料提交之後等待TX稽核,稽核時間大概2天左右,稽核通過之後就可以檢視AppID AppSecret以及申請微信登入
注意:如果註冊完的開放平臺之後有進行開發者認證時,稽核通過之後微信登入預設是開通的,如果沒有進行開發者認證點選申請開通 時會提醒進行開發者認證(如下圖)

稽核通過

基本資訊、開發資訊

提醒進行開發者認證

開發者資質認證

3、PC微信登入流程介紹

網站應用微信登入是基於OAuth2.0協議標準構建的微信OAuth2.0授權登入系統。進一步瞭解OAuth2.0—–

理解OAuth2.0 官方介紹資料

大致的步驟如下:
1. 第三方發起微信授權登入請求,微信使用者允許授權第三方應用後,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code引數;
2. 通過code引數加上AppID和AppSecret等,通過API換取access_token;
3. 通過access_token進行介面呼叫,獲取使用者基本資料資源或幫助使用者實現基本操作。

獲取access_token時序圖

具體的步驟如下:

第一步:請求CODE
引數 是否必須 說明
appid 應用唯一標識
redirect_uri 重定向地址,需要進行UrlEncode
response_type 填code
scope 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即可
state 用於保持請求和回撥的狀態,授權請求後原樣帶回給第三方。該引數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該引數,可設定為簡單的隨機數加session進行校驗

若提示“該連結無法訪問”,請檢查引數是否填寫錯誤,如redirect_uri的域名與稽核時填寫的授權域名不一致或scope不為snsapi_login。

返回說明
使用者允許授權後,將會重定向到redirect_uri的網址上,並且帶上code和state引數

redirect_uri?code=CODE&state=STATE

若使用者禁止授權,則重定向後不會帶上code引數,僅會帶上state引數

redirect_uri?state=STATE

介面封裝


    private static String qrconnect_url = "https://open.weixin.qq.com/connect/qrconnect";


    /**
     * 生成網頁二維碼授權連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri) {
        return getQrConnectURL(appId, redirect_uri, null);
    }

    /**
     * 生成網頁二維碼授權連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @param state 重定向後會帶上state引數,開發者可以填寫a-zA-Z0-9的引數值,最多128位元組
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri, String state) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirect_uri);
        params.put("scope", "snsapi_login");
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return qrconnect_url + "?" + para;
    }

介面測試

1、設定AppId、APPSecret以及回撥域名
2、PC訪問測試。開源專案中訪問地址為:

http://域名/[專案名稱]/toWebOauth

設定AppId、APPSecret以及回撥域名

//pc掃描登陸
public void toWebOauth(){
    String calbackUrl=PropKit.get("domain")+"/oauth/webCallBack";
    String url=SnsAccessTokenApi.getQrConnectURL(PropKit.get("webAppId"), calbackUrl,"666");
    redirect(url);
}

如果授權回撥域名與開發平臺中的填寫不一致將會出現以下提示

回撥域名與介面呼叫時填寫的域名不一致

第二步:通過code獲取access_token
第三步:通過access_token呼叫介面獲取使用者資訊

第二步、第三步過程與微信公眾號授權登入一樣可以參考之前寫的一篇文章授權獲取使用者資訊

授權後接口呼叫(UnionID)

獲取使用者個人資訊(UnionID機制)

此介面用於獲取使用者個人資訊。開發者可通過OpenID來獲取使用者基本資訊。特別需要注意的是,如果開發者擁有多個移動應用、網站應用和公眾帳號,可通過獲取使用者基本資訊中的unionid來區分使用者的唯一性,因為只要是同一個微信開放平臺帳號下的移動應用、網站應用和公眾帳號,使用者的unionid是唯一的。換句話說,同一使用者,對同一個微信開放平臺下的不同應用,unionid是相同的。請注意,在使用者修改微信頭像後,舊的微信頭像URL將會失效,因此開發者應該自己在獲取使用者資訊後,將頭像圖片儲存下來,避免微信頭像URL失效後的異常情況。

介面封裝可以參考開源專案中

網頁授權(公眾號、PC)獲取使用者資訊

 params = new HashMap();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirectUri);
        // snsapi_base(不彈出授權頁面,只能拿到使用者openid)
        // snsapi_userinfo(彈出授權頁面,這個可以通過 openid 拿到暱稱、性別、所在地)
        if (snsapiBase) {
            params.put("scope", "snsapi_base");
        } else {
            params.put("scope", "snsapi_userinfo");
        }
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return authorize_uri + "?" + para;
    }


    /**
     * 生成網頁二維碼授權連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri) {
        return getQrConnectURL(appId, redirect_uri, null);
    }

    /**
     * 生成網頁二維碼授權連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @param state 重定向後會帶上state引數,開發者可以填寫a-zA-Z0-9的引數值,最多128位元組
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri, String state) {
        Map params = new HashMap();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirect_uri);
        params.put("scope", "snsapi_login");
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return qrconnect_url + "?" + para;
    }

    /**
     * 通過code獲取access_token
     *
     * @param code   第一步獲取的code引數
     * @param appId  應用唯一標識
     * @param secret 應用金鑰AppSecret
     * @return SnsAccessToken
     */
    public static SnsAccessToken getSnsAccessToken(String appId, String secret, String code)
    {
        final Map queryParas = ParaMap.create("appid", appId).put("secret", secret).put("code", code).getData();

        return RetryUtils.retryOnException(3, new Callable() {

            @Override
            public SnsAccessToken call() throws Exception {
                String json = HttpUtils.get(url, queryParas);
                return new SnsAccessToken(json);
            }
        });
    }
}" data-snippet-id="ext.fc4c8e08b8a21ac8b08f430a8f26ad21" data-snippet-saved="false" data-codota-status="done">import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.kit.ParaMap;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.HttpUtils;
import com.jfinal.weixin.sdk.utils.RetryUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;


public class SnsAccessTokenApi
{
    private static String url = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";
    private static String authorize_uri = "https://open.weixin.qq.com/connect/oauth2/authorize";
    private static String qrconnect_url = "https://open.weixin.qq.com/connect/qrconnect";

    /**
     * 生成Authorize連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @param snsapiBase snsapi_base(不彈出授權頁面,只能拿到使用者openid)snsapi_userinfo(彈出授權頁面,這個可以通過 openid 拿到暱稱、性別、所在地)
     * @return url
     */
    public static String getAuthorizeURL(String appId, String redirect_uri, boolean snsapiBase) {
        return getAuthorizeURL(appId, redirect_uri, null, snsapiBase);
    }

    /**
     * 生成Authorize連結
     * @param appId 應用id
     * @param redirectUri 回跳地址
     * @param state 重定向後會帶上state引數,開發者可以填寫a-zA-Z0-9的引數值,最多128位元組
     * @param snsapiBase snsapi_base(不彈出授權頁面,只能拿到使用者openid)snsapi_userinfo(彈出授權頁面,這個可以通過 openid 拿到暱稱、性別、所在地)
     * @return url
     */
    public static String getAuthorizeURL(String appId, String redirectUri, String state, boolean snsapiBase) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirectUri);
        // snsapi_base(不彈出授權頁面,只能拿到使用者openid)
        // snsapi_userinfo(彈出授權頁面,這個可以通過 openid 拿到暱稱、性別、所在地)
        if (snsapiBase) {
            params.put("scope", "snsapi_base");
        } else {
            params.put("scope", "snsapi_userinfo");
        }
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return authorize_uri + "?" + para;
    }


    /**
     * 生成網頁二維碼授權連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri) {
        return getQrConnectURL(appId, redirect_uri, null);
    }

    /**
     * 生成網頁二維碼授權連結
     * @param appId 應用id
     * @param redirect_uri 回跳地址
     * @param state 重定向後會帶上state引數,開發者可以填寫a-zA-Z0-9的引數值,最多128位元組
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri, String state) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirect_uri);
        params.put("scope", "snsapi_login");
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return qrconnect_url + "?" + para;
    }

    /**
     * 通過code獲取access_token
     *
     * @param code   第一步獲取的code引數
     * @param appId  應用唯一標識
     * @param secret 應用金鑰AppSecret
     * @return SnsAccessToken
     */
    public static SnsAccessToken getSnsAccessToken(String appId, String secret, String code)
    {
        final Map<String, String> queryParas = ParaMap.create("appid", appId).put("secret", secret).put("code", code).getData();

        return RetryUtils.retryOnException(3, new Callable<SnsAccessToken>() {

            @Override
            public SnsAccessToken call() throws Exception {
                String json = HttpUtils.get(url, queryParas);
                return new SnsAccessToken(json);
            }
        });
    }
}

使用者管理介面,獲取使用者基本資訊(UnionID機制)


 * https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
 * 
*/ public class UserApi { private static String getUserInfo = "https://api.weixin.qq.com/cgi-bin/user/info"; private static String getFollowers = "https://api.weixin.qq.com/cgi-bin/user/get"; private static String batchGetUserInfo = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="; /** * 獲取使用者基本資訊(包括UnionID機制) * @param openId 普通使用者的標識,對當前公眾號唯一 * @return ApiResult */ public static ApiResult getUserInfo(String openId) { ParaMap pm = ParaMap.create("access_token", AccessTokenApi.getAccessTokenStr()).put("openid", openId).put("lang", "zh_CN"); return new ApiResult(HttpUtils.get(getUserInfo, pm.getData())); } /** * 獲取使用者列表 * @param nextOpenid 第一個拉取的OPENID,不填預設從頭開始拉取 * @return ApiResult */ public static ApiResult getFollowers(String nextOpenid) { ParaMap pm = ParaMap.create("access_token", AccessTokenApi.getAccessTokenStr()); if (nextOpenid != null) pm.put("next_openid", nextOpenid); return new ApiResult(HttpUtils.get(getFollowers, pm.getData())); } /** * 獲取使用者列表 * @return ApiResult */ public static ApiResult getFollows() { return getFollowers(null); } /** * 批量獲取使用者基本資訊, by Unas * @param jsonStr json字串 * @return ApiResult */ public static ApiResult batchGetUserInfo(String jsonStr) { String jsonResult = HttpUtils.post(batchGetUserInfo + AccessTokenApi.getAccessTokenStr(), jsonStr); return new ApiResult(jsonResult); } /** * 批量獲取使用者基本資訊 * @param openIdList openid列表 * @return ApiResult */ public static ApiResult batchGetUserInfo(List openIdList) { Map>> userListMap = new HashMap>>(); List> userList = new ArrayList>(); for (String openId : openIdList) { Map mapData = new HashMap(); mapData.put("openid", openId); mapData.put("lang", "zh_CN"); userList.add(mapData); } userListMap.put("user_list", userList); return batchGetUserInfo(JsonUtils.toJson(userListMap)); } private static String updateRemarkUrl = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token="; /** * 設定備註名 * @param openid 使用者標識 * @param remark 新的備註名,長度必須小於30字元 * @return {ApiResult} */ public static ApiResult updateRemark(String openid, String remark) { String url = updateRemarkUrl + AccessTokenApi.getAccessTokenStr(); Map mapData = new HashMap(); mapData.put("openid", openid); mapData.put("remark", remark); String jsonResult = HttpUtils.post(url, JsonUtils.toJson(mapData)); return new ApiResult(jsonResult); } } " data-snippet-id="ext.08b5e56863fb3ea3d62b4329261fcdd8" data-snippet-saved="false" data-codota-status="done">import com.jfinal.weixin.sdk.kit.ParaMap; import com.jfinal.weixin.sdk.utils.HttpUtils; import com.jfinal.weixin.sdk.utils.JsonUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 使用者管理 API * <pre> * https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN * </pre> */ public class UserApi { private static String getUserInfo = "https://api.weixin.qq.com/cgi-bin/user/info"; private static String getFollowers = "https://api.weixin.qq.com/cgi-bin/user/get"; private static String batchGetUserInfo = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="; /** * 獲取使用者基本資訊(包括UnionID機制) * @param openId 普通使用者的標識,對當前公眾號唯一 * @return ApiResult */ public static ApiResult getUserInfo(String openId) { ParaMap pm = ParaMap.create("access_token", AccessTokenApi.getAccessTokenStr()).put("openid", openId).put("lang", "zh_CN"); return new ApiResult(HttpUtils.get(getUserInfo, pm.getData())); } /** * 獲取使用者列表 * @param nextOpenid 第一個拉取的OPENID,不填預設從頭開始拉取 * @return ApiResult */ public static ApiResult getFollowers(String nextOpenid) { ParaMap pm = ParaMap.create("access_token", AccessTokenApi.getAccessTokenStr()); if (nextOpenid != null) pm.put("next_openid", nextOpenid); return new ApiResult(HttpUtils.get(getFollowers, pm.getData())); } /** * 獲取使用者列表 * @return ApiResult */ public static ApiResult getFollows() { return getFollowers(null); } /** * 批量獲取使用者基本資訊, by Unas * @param jsonStr json字串 * @return ApiResult */ public static ApiResult batchGetUserInfo(String jsonStr) { String jsonResult = HttpUtils.post(batchGetUserInfo + AccessTokenApi.getAccessTokenStr(), jsonStr); return new ApiResult(jsonResult); } /** * 批量獲取使用者基本資訊 * @param openIdList openid列表 * @return ApiResult */ public static ApiResult batchGetUserInfo(List<String> openIdList) { Map<String, List<Map<String, Object>>> userListMap = new HashMap<String, List<Map<String, Object>>>(); List<Map<String, Object>> userList = new ArrayList<Map<String,Object>>(); for (String openId : openIdList) { Map<String, Object> mapData = new HashMap<String, Object>(); mapData.put("openid", openId); mapData.put("lang", "zh_CN"); userList.add(mapData); } userListMap.put("user_list", userList); return batchGetUserInfo(JsonUtils.toJson(userListMap)); } private static String updateRemarkUrl = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token="; /** * 設定備註名 * @param openid 使用者標識 * @param remark 新的備註名,長度必須小於30字元 * @return {ApiResult} */ public static ApiResult updateRemark(String openid, String remark) { String url = updateRemarkUrl + AccessTokenApi.getAccessTokenStr(); Map<String, String> mapData = new HashMap<String, String>(); mapData.put("openid", openid); mapData.put("remark", remark); String jsonResult = HttpUtils.post(url, JsonUtils.toJson(mapData)); return new ApiResult(jsonResult); } }

原始碼下載地址
記錄學習的點滴,以此勉勵不斷奮鬥的自己✌️✌️✌️