spring boot項目之賣家掃碼登陸獲取openid(微信身份驗證id)


賣家掃碼登陸獲取openid

注:此功能只能是微信公眾帳號能夠使用,個人賬號無此功能。

其所對接的WxMpService都是引入微信第三方sdk

 

一、打開微信開放平台(與支付階段不同,特別注意!!!),進入網站應用的網站應用微信登陸開發指南。

 

 

二、你會發現和之前支付功能一樣,基本步驟如下

1. 第三方發起微信授權登錄請求,微信用戶允許授權第三方應用后,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code參數;
2. 通過code參數加上AppID和AppSecret等,通過API換取access_token;
3. 通過access_token進行接口調用,獲取用戶基本數據資源或幫助用戶實現基本操作。

第一步:請求CODE

第三方使用網站應用授權登錄前請注意已獲取相應網頁授權作用域(scope=snsapi_login),則可以通過在PC端打開以下鏈接:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“該鏈接無法訪問”,請檢查參數是否填寫錯誤,如redirect_uri的域名與審核時填寫的授權域名不一致或scope不為snsapi_login。

參數說明

 

參數 是否必須 說明
appid 應用唯一標識
redirect_uri 請使用urlEncode對鏈接進行處理
response_type 填code
scope 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即
state 用於保持請求和回調的狀態,授權請求后原樣帶回給第三方。該參數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該參數,可設置為簡單的隨機數加session進行校驗

第二步:通過code獲取access_token

通過code獲取access_token

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

參數說明

參數 是否必須 說明
appid 應用唯一標識,在微信開放平台提交應用審核通過后獲得
secret 應用密鑰AppSecret,在微信開放平台提交應用審核通過后獲得
code 填寫第一步獲取的code參數
grant_type 填authorization_code

返回說明

正確的返回:

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

參數說明

參數 說明
access_token 接口調用憑證
expires_in access_token接口調用憑證超時時間,單位(秒)
refresh_token 用戶刷新access_token
openid 授權用戶唯一標識
scope 用戶授權的作用域,使用逗號(,)分隔
unionid 當且僅當該網站應用已獲得該用戶的userinfo授權時,才會出現該字段。

錯誤返回樣例:

{"errcode":40029,"errmsg":"invalid code"}

刷新access_token有效期

access_token是調用授權關系接口的調用憑證,由於access_token有效期(目前為2個小時)較短,當access_token超時后,可以使用refresh_token進行刷新,access_token刷新結果有兩種:

1. 若access_token已超時,那么進行refresh_token會獲取一個新的access_token,新的超時時間;
2. 若access_token未超時,那么進行refresh_token不會改變access_token,但超時時間會刷新,相當於續期access_token。

refresh_token擁有較長的有效期(30天),當refresh_token失效的后,需要用戶重新授權。

請求方法

獲取第一步的code后,請求以下鏈接進行refresh_token:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

參數說明

參數 是否必須 說明
appid 應用唯一標識
grant_type 填refresh_token
refresh_token 填寫通過access_token獲取到的refresh_token參數

返回說明

正確的返回:

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

參數說明

參數 說明
access_token 接口調用憑證
expires_in access_token接口調用憑證超時時間,單位(秒)
refresh_token 用戶刷新access_token
openid 授權用戶唯一標識
scope 用戶授權的作用域,使用逗號(,)分隔

錯誤返回樣例:

{"errcode":40030,"errmsg":"invalid refresh_token"}

注意:

1、Appsecret 是應用接口使用密鑰,泄漏后將可能導致應用數據泄漏、應用的用戶數據泄漏等高風險后果;存儲在客戶端,極有可能被惡意竊取(如反編譯獲取Appsecret);
2、access_token 為用戶授權第三方應用發起接口調用的憑證(相當於用戶登錄態),存儲在客戶端,可能出現惡意獲取access_token 后導致的用戶數據泄漏、用戶微信相關
接口功能被惡意發起等行為;
3、refresh_token 為用戶授權第三方應用的長效憑證,僅用於刷新access_token,但泄漏后相當於access_token 泄漏,風險同上。

建議將secret、用戶數據(如access_token)放在App雲端服務器,由雲端中轉接口調用請求。

第三步:通過access_token調用接口

 

獲取access_token后,進行接口調用,有以下前提:

1. access_token有效且未超時;
2. 微信用戶已授權給第三方應用帳號相應接口作用域(scope)。

對於接口作用域(scope),能調用的接口有以下:

授權作用域(scope) 接口 接口說明
snsapi_base /sns/oauth2/access_token 通過code換取access_token、refresh_token和已授權scope
snsapi_base /sns/oauth2/refresh_token 刷新或續期access_token使用
snsapi_base /sns/auth 檢查access_token有效性
snsapi_userinfo /sns/userinfo 獲取用戶個人信息

其中snsapi_base屬於基礎接口,若應用已擁有其它scope權限,則默認擁有snsapi_base的權限。使用snsapi_base可以讓移動端網頁授權繞過跳轉授權登錄頁請求用戶授權的動作,直接跳轉第三方網頁帶上授權臨時票據(code),但會使得用戶已授權作用域(scope)僅為snsapi_base,從而導致無法獲取到需要用戶授權才允許獲得的數據和基礎功能。
接口調用方法可查閱《微信授權關系接口調用指南》

 

三、項目實例

注:Spring的@Bean注解用於告訴方法,產生一個Bean對象,然后這個Bean對象交給Spring管理。產生這個Bean對象的方法Spring只會調用一次,隨后這個Spring將會將這個Bean對象放在自己的IOC容器中。@component (把普通pojo實例化到spring容器中,相當於配置文件中的 <bean id="" class=""/>

 

泛指各種組件,就是說當我們的類不屬於各種歸類的時候(不屬於@Controller、@Services等的時候),我們就可以使用@Component來標注這個類。

 

1、application.yml關於微信賬號的配置

 

2、在config包中的WechatAccountConfig類中加入字段

     package com.imooc.conf

   import lombok.Data;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Map;

@Data
@Component
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {

/**
* 公眾平台id
*/
private String mpAppId;

/**
* 公眾平台密鑰
*/
private String mpAppSecret;

/**
* 開放平台id
*/
private String openAppId;

/**
* 開放平台密鑰
*/
private String openAppSecret;

/**
* 商戶號
*/
private String mchId;

/**
* 商戶密鑰
*/
private String mchKey;

/**
* 商戶證書路徑
*/
private String keyPath;

/**
* 微信支付異步通知地址
*/
private String notifyUrl;

/**
* 微信模版id
*/
private Map<String, String> templateId;
}    


3、往spring中注冊微信開放平台bean(所對接的接口都是WxMpService),注入第三方sdk
package com.imooc.config;

import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class WechatOpenConfig {

@Autowired
private WechatAccountConfig accountConfig;

@Bean
public WxMpService wxOpenService() {
WxMpService wxOpenService = new WxMpServiceImpl();
wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage());
return wxOpenService;
}

@Bean
public WxMpConfigStorage wxOpenConfigStorage() {
WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
wxMpInMemoryConfigStorage.setAppId(accountConfig.getOpenAppId());
wxMpInMemoryConfigStorage.setSecret(accountConfig.getOpenAppSecret());
return wxMpInMemoryConfigStorage;
}
}

4、在WechatController中定義URL接入
//1、獲取code
@GetMapping("/qrAuthorize")
public String qrAuthorize(@RequestParam("returnUrl") String returnUrl) {
String url = projectUrlConfig.getWechatOpenAuthorize() + "/sell/wechat/qrUserInfo";
String redirectUrl = wxOpenService.buildQrConnectUrl(url, WxConsts.QrConnectScope.SNSAPI_LOGIN, URLEncoder.encode(returnUrl));
return "redirect:"+ redirectUrl;
}

//2、獲取AccessToken,從中取出openId授權用戶唯一標識
 @GetMapping("/qrUserInfo")
public String qrUserInfo(@RequestParam("code") String code,
@RequestParam("state") String returnUrl) {
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
try {
wxMpOAuth2AccessToken = wxOpenService.oauth2getAccessToken(code);(很重要)
} catch (WxErrorException e) {
log.error("【微信網頁授權】{}", e);
throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg());
}
log.info("wxMpOAuth2AccessToken={}", wxMpOAuth2AccessToken);
String openId = wxMpOAuth2AccessToken.getOpenId();

return "redirect:" + returnUrl + "?openid=" + openId;
}
}


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM