轉載請表明出處 https://blog.csdn.net/Amor_Leo/article/details/106843838 謝謝
微信用戶對應一個小程序都有一個唯一的openid,微信授權登錄,微信授權登錄的核心就是獲取這個openid並判斷數據庫是否存在
開發準備
-
登錄微信公衆平臺後臺->基本配置->公衆號開發信息:
1.獲取到AppID
2.AppSecret
3.設置IP白名單 -
添加網頁授權域名
公衆號設置->功能設置
本地開發的話沒有域名,可以使用內網穿透軟件,域名要是 https的
然後按照微信的流程來綁定授權域名就好了。
獲取用戶信息,需要openid,然而獲取openid的話要通過這個接口先獲得一個code
- 用戶同意授權,獲取code(授權碼)
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
yaml
wx:
appid: xxxxxx
appsecret: xxxxxxx
業務層
@Value("${wx.appid}")
private String appid;
@Value("${wx.appsecret}")
private String appSecret;
public Map<String, Object> wxLogin(WxLoginDto wxLoginDto, HttpServletRequest request) {
Map<String, Object> retMap = new HashMap<>();
//獲取openid 根據前端傳過來的微信授權碼
Map<String, Object> result = code2session(wxLoginDto.getCode());
if (result.containsKey("openid")) {
String openid = result.get("openid").toString();
//判斷用戶是否關聯微信 根據openid是否在數據庫,沒有則註冊(新增用戶) 具體的邏輯根據自己的業務需求來寫
.......
String sessionKey = result.get("session_key").toString();
String token = "";
Long expiresTime = null;
//緩存獲取access_token
if (accessTokenService.exists(openid)) {
token = accessTokenService.getCache(openid).toString();
} else {
//獲取access_token 保存到redis
Map<String, Object> resultMap = accessTokenService.getAccessToken();
if (resultMap != null) {
token = resultMap.get("token").toString();
expiresTime = Long.parseLong(String.valueOf(resultMap.get("expires_time")));
accessTokenService.setCache(openid, token, expiresTime);
}
}
retMap.put("flag", true);
Map<String, Object> map = new HashMap<>();
map.put("openid", openid);
map.put("token", token);
map.put("sessionKey", sessionKey);
// 還有一些用戶信息 根據自己的業務需求返回給前端
.....
retMap.put("userVo", map);
retMap.put("flag", true);
return retMap;
}
retMap.put("flag", false);
return retMap;
}
public Map<String, Object> code2session(String code) {
String params = "appid=" + appid + "&secret=" + appSecret + "&js_code=" + code
+ "&grant_type=" + GlobalsConstants.GRANT_TYPE;
String sr = HttpCallOtherInterfaceUtils.callOtherInterface(GlobalsConstants.CODE_URL, "?" + params);
Map<String, Object> result = JSON.parseObject(sr);
return result;
}
工具類
String CODE_URL = "https://api.weixin.qq.com/sns/jscode2session";
String GRANT_TYPE = "authorization_code";
/**
* @author: LHL
*/
public class HttpCallOtherInterfaceUtils {
private static final Logger logger = LoggerFactory.getLogger(HttpCallOtherInterfaceUtils.class);
public static String callOtherPostInterface(JSONObject jsonParam, String gatewayUrl, String postUrl) {
HttpClient client = HttpClients.createDefault();
// 要調用的接口方法
String url = gatewayUrl + postUrl;
HttpPost post = new HttpPost(url);
JSONObject jsonObject = null;
try {
StringEntity s = new StringEntity(jsonParam.toString(), "UTF-8");
s.setContentType("application/json");
post.setEntity(s);
post.addHeader("content-type", "application/json;charset=UTF-8");
HttpResponse res = client.execute(post);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回json格式:
jsonObject = JSONObject.parseObject(EntityUtils.toString(res.getEntity()));
}
} catch (Exception e) {
logger.debug("服務間接口調用出錯!");
e.printStackTrace();
}
return null == jsonObject?"":jsonObject.toString();
}
public static String callOtherInterface(String gatewayUrl, String getUrl) {
HttpClient client = HttpClients.createDefault();
// 要調用的接口方法
String url = gatewayUrl + getUrl;
HttpPost get = new HttpPost(url);
JSONObject jsonObject = null;
try {
HttpResponse res = client.execute(get);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回json格式:
jsonObject = JSONObject.parseObject(EntityUtils.toString(res.getEntity()));
}
} catch (Exception e) {
logger.debug("服務間接口調用出錯!");
e.printStackTrace();
}
return null == jsonObject?"":jsonObject.toString();
}
public static String callOtherGetInterface(String gatewayUrl, String getUrl) {
HttpClient client = HttpClients.createDefault();
// 要調用的接口方法
String url = gatewayUrl + getUrl;
HttpGet get = new HttpGet(url);
JSONObject jsonObject = null;
try {
HttpResponse res = client.execute(get);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回json格式:
jsonObject = JSONObject.parseObject(EntityUtils.toString(res.getEntity()));
}
} catch (Exception e) {
logger.debug("服務間接口調用出錯!");
e.printStackTrace();
}
return null == jsonObject?"":jsonObject.toString();
}
}
/**
* 微信授權access_token獲取
*
* @author LHL
*/
public interface AccessTokenService {
/**
* 獲取緩存
*
* @param key key
* @author LHL
*/
Object getCache(String key);
/**
* 設置緩存
*
* @param key key
* @param value 值
* @param expireTime 秒
* @author LHL
*/
boolean setCache(String key, Object value, Long expireTime);
/**
* key是否存在
*
* @param key key
* @author LHL
*/
boolean exists(final String key);
/**
* 獲取access_token
*
* @author LHL
*/
Map<String, Object> getAccessToken();
}
/**
* 微信授權access_token獲取
*
* @author LHL
*/
@Service
public class AccessTokenServiceImpl implements AccessTokenService {
private final static String API_URL = "https://api.weixin.qq.com/cgi-bin/token";
private final static String GRANT_TYPE = "client_credential";
@Value("${wx.appid}")
private String appid;
@Value("${wx.appsecret}")
private String appSecret;
@Autowired
private RestTemplate restTemplate;
@Autowired
private RedisTemplate redisTemplate;
@Override
public Object getCache(String key){
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
@Override
public boolean setCache(String key, Object value, Long expireTime){
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean exists(final String key) {
try {
boolean result=redisTemplate.hasKey(key);
return result;
}
catch (Exception e) {
return false;
}
}
@Override
public Map<String, Object> getAccessToken(){
String params = "grant_type=" + GRANT_TYPE + "&appid=" + appid + "&secret=" + appSecret;
String reStr = restTemplate.getForObject(API_URL + "?" + params, String.class);
JSONObject result = JSONObject.parseObject(reStr);
if(result.containsKey("access_token")){
Map<String, Object> map = new HashMap<>();
map.put("token", result.get("access_token").toString());
map.put("expires_time", result.get("expires_in"));
return map;
}
return null;
}
}