PC 微信掃碼登陸
1、註冊微信開發平臺
官網網址 自行註冊,需要注意的是註冊郵箱號不用與騰訊其他產品同號。
2、微信開發平臺新增網站應用
以上資料提交之後等待TX稽核,稽核時間大概2天左右,稽核通過之後就可以檢視AppID AppSecret以及申請微信登入。
注意:如果註冊完的開放平臺之後有進行開發者認證時,稽核通過之後微信登入預設是開通的,如果沒有進行開發者認證點選申請開通 時會提醒進行開發者認證(如下圖)
3、PC微信登入流程介紹
網站應用微信登入是基於OAuth2.0協議標準構建的微信OAuth2.0授權登入系統。進一步瞭解OAuth2.0—–
大致的步驟如下:
1. 第三方發起微信授權登入請求,微信使用者允許授權第三方應用後,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code引數;
2. 通過code引數加上AppID和AppSecret等,通過API換取access_token;
3. 通過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
//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