您好,登錄后才能下訂單哦!
如果用戶在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取用戶基本信息,進而實現業務邏輯。我們在進行公眾號網頁開發的時候,想要獲取用戶的基本信息,首先得獲取到access_token,從access_token里我們要拿出用戶的openid來作為用戶在我們系統中的唯一標識,以及通過openid可以保證該用戶的只能訪問到與其openid相對應的數據,防止越權漏洞。因此,我們需要對網頁進行授權,否則是無法在獲取到用戶的openid的。
先上官方的文檔,微信官方文檔地址如下:
為了能夠與微信進行聯調,所以我們需要使用到內網穿透工具,讓外網能夠訪問到我們內網的接口地址。我之前寫了一篇關于如何使用natapp進行內網穿透的文章,這里就不再過多贅述這些基本的工具使用了:
在本文中會介紹兩種獲取openid的方式:自己根據文檔接口手寫代碼獲取、使用第三方已經封裝好的SDK來獲取。第三方SDK的GitHub地址:
說明與注意:
(1)網頁授權分為兩種:
(2)你的公眾號必須為認證的訂閱號或者認證的服務號或申請官方提供的測試號,否則沒有此接口權限。
(3)你要配置好回調域名:即用戶點擊網址獲取用戶信息后打開哪個域名。
我們先來申請一個官方的測試號,微信測試賬號申請地址如下:
登錄成功后,即可獲取測試號信息:
下拉頁面找到測試號二維碼那一欄,然后使用微信掃描二維碼關這個注測試公眾號。關注成功后,稍等一會就會顯示出用戶列表。如下:
配置完測試號后,繼續下拉頁面找到網頁帳號的設置,點擊修改:
然后將我們的在natapp里注冊外網域名配置進去:
注:由于是測試號,這一塊不會嚴格去檢測這個域名,如果是使用真實的公眾賬號進行配置時,會對配置的域名進行檢測。但是即便是測試,也要保證這個域名是可用的,不然就無法進行聯調了。
(1)第一步,用戶同意授權,獲取code參數:
完成以上測試賬號的配置及微信網頁授權后,創建一個SpringBoot的Web工程,并打開natapp的客戶端。關于獲取code這一步要仔細查看這部分文檔,我就不過多解釋了:
從文檔中可以看到,需要讓用戶在訪問頁面的過程中打開一個特定的鏈接,然后用戶授權成功后會跳轉回調redirect_uri參數里指定的鏈接,這樣我們就能獲取code參數了。so,在工程中創建controller包,在該包里新建一個 WeixinController 控制器,我們來寫一個這樣的跳轉回調接口給微信進行回調,看看能否獲取到回調時傳遞的code參數:
package org.sell.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @program: sell
* @description: 微信網頁授權,獲取用戶openid
* @author: 01
* @create: 2018-05-15 13:35
**/
@RestController
@RequestMapping("/weixin")
@Slf4j
public class WeixinController {
@GetMapping("/auth")
public void auth(@RequestParam("code") String code) {
log.info("進入auth方法...");
log.info("code = {}", code);
}
}
編寫完接口代碼之后,我們來基于文檔中給出的鏈接進行修改,我這里填寫了appid、redirect_uri以及scope三個參數,其余的參數我保持了默認。所以填寫完成后的連接如下:
https://open.weixin.qq.com/connect/oauth3/authorize?appid=wx37617xxxxxxc6c76&redirect_uri=https://zero.mynatapp.cc/sell/weixin/auth&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect
如果需要獲取用戶信息的話,則需要把scope參數改為snsapi_userinfo,用戶訪問這個連接時就會提示用戶登錄。但是如果是使用的測試賬號的appid,則不會彈出登錄界面。使用真實的公眾號賬號的appid才會彈出登錄界面,我們使用的是測試賬戶所以是不會彈出登錄界面的:
https://open.weixin.qq.com/connect/oauth3/authorize?appid=wx376172f171ac6c76&redirect_uri=https://zero.mynatapp.cc/sell/weixin/auth&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
然后復制該鏈接到微信中打開,一定要在微信中打開,使用pc端的瀏覽器或手機端的瀏覽器是無法打開該連接的,打開后也會提示你在微信中打開。在微信訪問該地址成功后,控制臺會輸出如下內容,其中code參數獲取成功就代表這一步測試是成功的:
2018-05-15 13:47:02,365 - 進入auth方法...
2018-05-15 13:47:02,365 - code = 0219vS7617imVS1dqe861eXP7619vS7j
但是code是一次性的,不能直接使用,所以接下來的第二步我們需要拿這個code去換取access_token。
關于使用code換取access_token這一步要仔細查看這部分文檔:
官方文檔中說,獲取code后,請求以下鏈接來獲取access_token:
https://api.weixin.qq.com/sns/oauth3/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
同樣的,我們也是需求根據文檔去填寫鏈接中的參數,例如我這里就填寫了appid、secret以及code。由于code參數我們需要在auth接口被微信調用時獲取,所以修改auth接口的代碼如下:
@GetMapping("/auth")
public void auth(@RequestParam("code") String code) {
log.info("進入auth方法...");
log.info("code = {}", code);
String url = "https://api.weixin.qq.com/sns/oauth3/access_token?appid=wx3761xxxxx1ac6c76&secret=f12caef4d31axxxxx819c4c405541f4&code=" + code + "&grant_type=authorization_code";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
log.info("response = {}", response);
}
重新啟動SpringBoot,然后再次到微信里訪問之前那個獲取code參數的鏈接,訪問成功后,微信會進行會回調,我們的接口就會接收到一個json格式的返回信息,其中就有我們需要的openid。我這里是訪問成功的,所以獲取到了這個返回信息,將其格式化后如下:
{
"access_token": "9_lZjiw19HhAga4cZ9C4rmtN50AkLzCwLVnlp8msI9xvCCWMIR88CmZAtB-IN1SGOwR_nh76V100vaTF8qihmBnfDx7XYynqHurb4UiqSZTDo",
"expires_in": 7200,
"refresh_token": "9_oMBSt0Bu-UUbVajpfo4OdyPwIfYbN1lut8KHjT4JEMTTbITtPnBFcQopP-SIzYvWHQuEdeQRcVHt1pRJHwvDhecDrd5pGz5HPckOCeHvmxg",
"openid": "ok_HP0txxYBxxxxxxd1kZGz6A",
"scope": "snsapi_base"
}
從回調的數據中可以看到,openid包含在了這個數據里,這樣我們就獲取到了用戶的openid,到此為止,我們手工獲取OpenID的方式就演示完成了。接下來我們當然就是上工具了,有一個很優秀的第三方SDK,在文章的開頭也給出了GitHub的鏈接,秉承一貫不重復造輪子能用現成的就用現成的良(hou)好(yan)習(wu)慣(chi),下一小節中我們將介紹如何使用該SDK來對接微信網頁授權。
首先需要將SDK集成到我們的項目中,在pom.xml文件中加入如下依賴配置:
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.0.0</version>
</dependency>
注:工程中還使用了lombok,如果沒有了解過lombok的話,可能需要了解一下才能看懂一些注解的作用,關于lombok的使用及配置可以參考我之前寫的一篇文章:Lombok快速入門
關于該SDK的一些文檔地址:
由于可能會出現異常,在我們的工程里新建一個enums包,用于存放枚舉類,在該包中新建一個 ResultEnum 枚舉類,代碼如下:
package org.sell.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ResultEnum {
WECHAT_MP_ERROR(20, "微信公眾賬號出現異常"),
;
private Integer code;
private String msg;
}
新建一個exception包,自定義一個異常類。代碼如下:
package org.sell.exception;
import org.sell.enums.ResultEnum;
/**
* @program: sell
* @description: 自定義異常
* @author: 01
* @create: 2018-05-09 15:45
**/
public class SellException extends RuntimeException {
private Integer code;
public SellException(Integer code, String msg) {
super(msg);
this.code = code;
}
public SellException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}
}
將默認的applicationContext.properties文件改為applicationContext.yml文件,然后在該文件中配置我們的AppId以及AppSecret。如下:
wechat:
mpAppId: wx37617xxxxxac6c76
mpAppSecret: f12caef4d31adxxxxxxc4c405541f4
在工程中新建config包,用于存放一些配置類,在該包下新建 WechatAccountConfig 類,用于加載我們的配置在.yml文件里的AppId以及AppSecret屬性。代碼如下:
package org.sell.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @program: sell
* @description: 測試號相關信息的配置類
* @author: 01
* @create: 2018-05-15 15:50
**/
@Data
@Component
@ConfigurationProperties(prefix = "wechat") // 載入配置文件里前綴為wechat的配置信息
public class WechatAccountConfig {
private String mpAppId;
private String mpAppSecret;
}
接著再創建一個 WechatMpConfig 類,配置微信網頁授權時所需的信息。代碼如下:
package org.sell.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;
/**
* @program: sell
* @description: 微信網頁授權信息配置類
* @author: 01
* @create: 2018-05-15 15:40
**/
@Component
public class WechatMpConfig {
@Autowired
private WechatAccountConfig wechatAccountConfig;
/**
* 配置WxMpService所需信息
* @return
*/
@Bean // 此注解指定在Spring容器啟動時,就執行該方法并將該方法返回的對象交由Spring容器管理
public WxMpService wxMpService(){
WxMpService wxMpService = new WxMpServiceImpl();
// 設置配置信息的存儲位置
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
/**
* 配置appID和appsecret
* @return
*/
@Bean
public WxMpConfigStorage wxMpConfigStorage(){
// 使用這個實現類則表示將配置信息存儲在內存中
WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
wxMpInMemoryConfigStorage.setAppId(wechatAccountConfig.getMpAppId());
wxMpInMemoryConfigStorage.setSecret(wechatAccountConfig.getMpAppSecret());
return wxMpInMemoryConfigStorage;
}
}
在controller包下,新建一個 WechatController 控制器類,該類的接口用于對接微信網頁授權,授權完成后,需跳轉到我們指定的網頁中。代碼如下:
package org.sell.controller;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth3AccessToken;
import org.sell.enums.ResultEnum;
import org.sell.exception.SellException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.net.URLEncoder;
/**
* @program: sell
* @description: 對接微信網頁授權
* @author: 01
* @create: 2018-05-15 15:35
**/
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WechatController {
@Autowired
private WxMpService wxMpService;
/**
* 獲取code參數
*
* @param returnUrl 需要跳轉的url
* @return
*/
@GetMapping("/authorize")
public String authorize(@RequestParam("returnUrl") String returnUrl) {
// 暫時將我們的回調地址硬編碼在這里,方便一會調試
String url = "https://zero.mynatapp.cc/sell/wechat/userInfo";
// 獲取微信返回的重定向url
String redirectUrl = wxMpService.oauth3buildAuthorizationUrl(url, WxConsts.OAuth3Scope.SNSAPI_BASE, URLEncoder.encode(returnUrl));
log.info("【微信網頁授權】獲取code,redirectUrl = {}", redirectUrl);
return "redirect:" + redirectUrl;
}
/**
* 使用code參數換取access_token信息,并獲取到openid
*
* @param code
* @param returnUrl
* @return
*/
@GetMapping("/userInfo")
public String userInfo(@RequestParam("code") String code, @RequestParam("state") String returnUrl) {
WxMpOAuth3AccessToken wxMpOAuth3AccessToken;
try {
// 使用code換取access_token信息
wxMpOAuth3AccessToken = wxMpService.oauth3getAccessToken(code);
} catch (WxErrorException e) {
log.error("【微信網頁授權】異常,{}", e);
throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg());
}
// 從access_token信息中獲取到用戶的openid
String openId = wxMpOAuth3AccessToken.getOpenId();
log.info("【微信網頁授權】獲取openId,openId = {}", openId);
// 重定向到我們要跳轉的頁面
return "redirect:" + returnUrl + "?openid=" + openId;
}
}
完成以上代碼的編寫后,重新啟動SpringBoot,啟動完成后,在微信里訪問如下鏈接,我這里隨便指定了一個需要跳轉的url,是我的51cto博客地址:
https://zero.mynatapp.cc/sell/wechat/authorize?returnUrl=https://blog.51cto.com/zero01
我這里在微信訪問該連接后是跳轉成功的,跳轉到了我們在鏈接里指定的51cto博客地址:
控制臺輸出的日志內容如下:
2018-05-15 17:09:03,543 - Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-05-15 17:09:03,544 - FrameworkServlet 'dispatcherServlet': initialization started
2018-05-15 17:09:03,557 - FrameworkServlet 'dispatcherServlet': initialization completed in 13 ms
2018-05-15 17:09:03,580 - 【微信網頁授權】獲取code,redirectUrl = https://open.weixin.qq.com/connect/oauth3/authorize?appid=wx376172xxxxc76&redirect_uri=https%3A%2F%2Fzero.mynatapp.cc%2Fsell%2Fwechat%2FuserInfo&response_type=code&scope=snsapi_base&state=http%3A%2F%2Fblog.51cto.com%2Fzero01#wechat_redirect
2018-05-15 17:09:05,453 - 【微信網頁授權】獲取openId,openId = ok_HP0txxYBgxxxxxx9d1kZGz6A
可以看到,openid成功獲取,并且頁面也成功跳轉了,我們這一步的測試也就通過了,以上就是如何使用這個第三方的SDK獲取openid。到此為止,兩種獲取用戶openid的方式都介紹了,至于在實際項目里使用哪一種方式就看自己的實際情況了,我這里是使用第三方的SDK,畢竟真實的項目模塊比較多,涉及的微信特性也比較多,如果沒有特殊要求的話也沒必要重復去造輪子。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。