微信公衆號開發仍是相對簡單的,來來回回寫過幾回了,一直沒有詳細的記錄下來,致使每次寫仍是要查文檔,現將此次開發經歷記錄下來,以備不時之需。html
<!--微信公衆號三方sdk-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
複製代碼
微信開發 Java SDK(開發工具包),官網還有支持包括微信支付、開放平臺、小程序、企業微信/企業號的sdk,簡直好用!!!前端
# 公衆號配置(必填)
wx:
mp:
appId: APPID #微信公衆號的appid
secret: SECRET #微信公衆號的app corpSecret
token: TOKEN #微信公衆號的token
aesKey: AESKEY #微信公衆號的EncodingAESKey
複製代碼
- 思路
1. 提供一個前端重定向過來的入口,URL上攜帶一個redirect_url參數(表明從微信獲取用戶信息後要重定向回去的頁面),並在此處跳轉到微信進行網頁受權。
2. 受權成功後獲取code。
3. 經過code調微信接口獲取openid和access_token。
4. 獲取用戶信息。
5. 最後重定向回最初的redirect_url,並拼上想要的參數。
複製代碼
- 實現
1. 首先提供一個前段重定向過來的入口,URL上攜帶一個redirect_url參數(表明從微信獲取用戶信息後要重定向回去的頁面),並在此處跳轉到微信進行網頁受權。
複製代碼
注意java
redirect_url須要通過URLEncoder
,拿到以後再進行URLDecoder
,不然redirect_url中#
以後的部分會丟掉。git
最好進行兩次URLEncoder
,兩次URLDecoder
,由於有的瀏覽器會自動解碼。github
//微信受權後返回的地址
private String getCodeUrl = "項目域名" + "redirect/code?redirect_url=";
//默認重定向地址defaultUrl
private String defaultUrl = "[DEFAULT_URL]";
//提供的獲取用戶信息的重定向入口地址
@GetMapping("/redirect")
public String redirect( @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirectUrl ) throws UnsupportedEncodingException {
//默認重定向地址defaultUrl
if (StringUtils.isBlank(redirectUrl)) {
redirectUrl = defaultUrl;
} else {
redirectUrl = URLDecoder.decode(redirectUrl, "utf-8");
LOGGER.info("一次解碼:{}",redirectUrl);
redirectUrl = URLDecoder.decode(redirectUrl, "utf-8");
LOGGER.info("二次解碼:{}",redirectUrl);
}
LOGGER.info("redirectUrl:{}",redirectUrl);
//一次編碼
redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
LOGGER.info("一次編碼url:{}",redirectUrl);
//二次編碼
redirectUrl = URLEncoder.encode(getCodeUrl + redirectUrl, "utf-8");
LOGGER.info("二次編碼url:{}",redirectUrl);
//最終獲得微信受權地址
String url = wxMpService.oauth2buildAuthorizationUrl(redirectUrl,"snsapi_userinfo","123");
LOGGER.info("最終獲得微信受權地址:{}",url);
//跳轉受權
return "redirect:" + url;
}
複製代碼
2. 受權成功後獲取code。
3. 經過code調微信接口獲取openid和access_token。
4. 獲取用戶信息。
5. 最後重定向回最初的redirect_url,並拼上想要的參數。
複製代碼
下面完成二、三、四、5步spring
須要定義一個鏈接,就是上一步中的getCodeUrl
,由微信受權成功後重定向到這個連接,並攜帶code參數。小程序
因爲上一步咱們將redirect_url進行了兩次編碼,因此redirect_url也會傳遞進來。api
//錯誤頁面errorPage
private String errorPage = "[ERROR_PAGE]";
//這裏的地址由微信重定向跳轉,攜帶獲取的code參數。
@GetMapping("/redirect/code")
public void getCode( @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirectUrl, @RequestParam(name = "code", defaultValue = "", required = false) String code, HttpServletRequest request,HttpServletResponse response ) throws IOException {
LOGGER.info("redirect_url: {}", redirectUrl);
LOGGER.info("code: {}", code);
if (StringUtils.isBlank(code)) {
LOGGER.error("獲取code失敗");
LOGGER.info("重定向到錯誤頁,errorPage:{}",errorPage);
response.sendRedirect(errorPage + "?error=code-is-null");
}
//解碼重定向地址
redirectUrl = URLDecoder.decode(redirectUrl, "utf-8");
LOGGER.info("解碼重定向地址url:{}",redirectUrl);
//根據code獲取微信相關信息
try {
//根據code獲取openid和access_token
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
//獲取微信用戶信息
WxMpUser wxMpUser = wxMpService.getUserService().userInfo(wxMpOAuth2AccessToken.getOpenId());
LOGGER.info("userInfo:{}",wxMpUser.toString());
} catch (WxErrorException e) {
e.printStackTrace();
LOGGER.info("重定向到錯誤頁,errorPage:{}",errorPage);
response.sendRedirect(errorPage + "?error=" + e.getMessage());
}
//這裏直接將微信用戶信息編碼後重定向給最開始的redirect_url
response.sendRedirect(redirectUrl + "?wechat_user=" + URLEncoder.encode(wxMpUser.toString(), "utf-8"));
}
複製代碼
微信模板消息推送也比較簡單,核心代碼只有下面幾行,最主要的獲取用戶openid在上面已經講過,在這裏就再也不贅述。瀏覽器
public String push() throws Exception {
//推送消息
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
.toUser("[OPENID]") //要推送的用戶openid
.templateId("[TEMPLATEID]") //模版id
.url("[URL]") //點擊模版消息要訪問的網址
.build();
templateMessage.addData(new WxMpTemplateData("first","[標題]","[COLOR]"));
templateMessage.addData(new WxMpTemplateData("keyword1","[消息主體]","[COLOR]"));
...//keywordn是模板規定的
templateMessage.addData(new WxMpTemplateData("remark","[備註]","[COLOR]"));
//開始推送
try {
wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
return "true";
} catch (WxErrorException e) {
System.out.println("推送失敗:" + e.getMessage());
e.printStackTrace();
WxError wxError = e.getError();
if ("43004".equals(wxError.getErrorCode())){
throw new Exception("該用戶未關注公衆號");
}
throw new Exception(wxError.getErrorMsg());
}
}
複製代碼