一 、開放平臺賬戶注冊及開發(fā)配置請參考我之前的文章 開發(fā)前準(zhǔn)備工作。
二、授權(quán)流程 官方文檔細(xì)節(jié)比較多 我說的比較直白
(1)首先 啟動票據(jù)推送服務(wù)
(2)接收消息→解密→驗(yàn)證并獲取票據(jù)→保存票據(jù) component_verify_ticket
(3)獲取第三方平臺調(diào)用憑證 component_access_token
(4)通過 component_access_token 獲取預(yù)授權(quán)碼 pre_auth_code
(5)通過 pre_auth_code 自建 PC授權(quán)鏈接 或 H5授權(quán)鏈接
(6)訪問授權(quán)鏈接進(jìn)入授權(quán)頁面完成公眾號授權(quán);
三、授權(quán)實(shí)現(xiàn) (直接貼代碼)
package com.zaiyun.wechat.controller;
import com.alibaba.fastjson2.JSONObject;
import com.qq.weixin.mp.aes.AesException;
import com.zaiyun.common.core.controller.BaseController;
import com.zaiyun.common.core.domain.AjaxResult;
import com.zaiyun.common.annotation.Anonymous;
import com.zaiyun.wechat.service.ThirdPartyTicketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 第三方平臺調(diào)用憑證
*/
@Anonymous
@RestController
@RequestMapping("/ticket")
public class ThirdPartyTicketController extends BaseController {
@Resource
ThirdPartyTicketService thirdPartyTicketService;
private static final Logger wechatLogger = LoggerFactory.getLogger("extend-wechat");
/**
* 消息與事件接收配置
*/
@RequestMapping("/{appId}/callback")
public String callback() {
return "success";
}
/**
* 啟動票據(jù)推送服務(wù)
*/
@PostMapping("/start/push")
public AjaxResult startPushTicket() {
JSONObject resultObj = thirdPartyTicketService.startPushTicket();
if (resultObj.getInteger("errcode") == 0) {
return success(resultObj.getString("errmsg"));
}
return error(resultObj.toString());
}
/**
* 驗(yàn)證票據(jù)
*
* @param msgSignature 微信加密簽名
* @param timeStamp 時間戳
* @param nonce 隨機(jī)數(shù)
* @param postData 消息體
* @return 結(jié)果
* @throws AesException 異常提現(xiàn)
*/
@PostMapping("/verify")
public String componentVerifyTicket(@RequestParam("timestamp") String timeStamp, @RequestParam("nonce") String nonce, @RequestParam("msg_signature") String msgSignature, @RequestBody String postData) throws AesException {
try {
thirdPartyTicketService.componentVerifyTicket(msgSignature, timeStamp, nonce, postData);
} catch (Exception e) {
wechatLogger.info("消息推送異常", e);
e.printStackTrace();
}
return "success";
}
/**
* 獲取令牌component_access_token
*/
@RequestMapping("/component/access/token")
public AjaxResult getComponentAccessToken() {
JSONObject accessToken = thirdPartyTicketService.getComponentAccessToken();
return success(accessToken);
}
/**
* 獲取預(yù)授權(quán)碼
*/
@RequestMapping("/pre/auth/code")
public AjaxResult getPreAuthCode() {
JSONObject authCode = thirdPartyTicketService.getPreAuthCode();
return success(authCode);
}
/**
* 獲取刷新令牌
*
* @param authorizationCode 授權(quán)碼
*/
@PostMapping("/get/refresh/token")
public AjaxResult getAuthorizerRefreshToken(@RequestParam("authorizationCode") String authorizationCode) {
JSONObject refreshToken = thirdPartyTicketService.getAuthorizerRefreshToken(authorizationCode);
return success(refreshToken);
}
/**
* 獲取授權(quán)賬號調(diào)用令牌
*
* @param authorizerAppid 授權(quán)方公眾號APPID
*/
@PostMapping("/get/access/token")
public AjaxResult getAuthorizerAccessToken(@RequestParam("authorizerAppid") String authorizerAppid) {
String authorizerRefreshToken = "refreshtoken@@@Gr8Kl0v10e0B8SrIBmlXfB2PXjcn4TA-RPUqkg1Iu5I";
JSONObject authorizerAccessToken = thirdPartyTicketService.getAuthorizerAccessToken(authorizerAppid, authorizerRefreshToken);
return success(authorizerAccessToken);
}
}
(1)首先啟動票據(jù)推送
/**
* 啟動票據(jù)推送服務(wù)
*/
public JSONObject startPushTicket() {
String url = "https://api.weixin.qq.com/cgi-bin/component/api_start_push_ticket";
HashMap<String, String> paramHeader = new HashMap<>();//請求頭參數(shù)
paramHeader.put("Content-Type", "application/json");
HashMap<String, String> paramBody = new HashMap();//請求體
paramBody.put("component_appid", weixinConfig.getThirdPartyAppId());
paramBody.put("component_secret", weixinConfig.getThirdPartyAppSecret());
Object bodyParam = ConvertUtils.mapToObject(paramBody);
ResponseEntity<String> responseEntity = restTemplateUtils.post(url, paramHeader, bodyParam, String.class);
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
(2)驗(yàn)證票據(jù)并緩存 component_verify_ticket 這個很重要、非常重要、必須保存好;
Ticket的有效時間為12小時, 每隔10分鐘以 POST 的方式推送,推送的加密消息如下(這是我打印的日志)
10:13:49.990 [http-nio-8090-exec-70] INFO wechat - [callback,34] - 消息與事件
<xml>
<ToUserName><![CDATA[gh_138c7a943970]]></ToUserName>
<Encrypt><![CDATA[0jexJT/7Vc4g1cwSYSuROJCpXki1j5reusgy/O43RNadB9dHFCUQ/B9XDXfIYGOrIURyP5ZbQ4SNk8c+YS0lozlIZxSzVMRPg36K74frTCFqODs0F7GDhTT1cMk13JwJBOtdpQwKR9QRrRZPU4h41WkU3M2X2aMN9eXOws/RV+VJzVzPcNXLC9Z8LnuPiz+JoXTFVM3yOIypxu1zi7cl6eh8Lookl025ZuMIc8OmxZKHW4UiyI49v8D1bc4elTt2eI5Sl4C0uYzYYIBlgfnoyStManqAL+c/MODABu0HzenvbRmpZ0iZEpGfjFghRirABvIaaT9H7ok989Fkx+J9DUAuyT0aCEcBNY3w/JP81wmi3Y9x8MM0KWyN5XIELDA6A7LZz/8BQ3NFkgMevNAO87U0z7XFo+VweOb7W01si1+Z3Z/uLqv40VFtFdGNXhYvuA1C/4u/b7y+OtJZrO14AB5y8aT3hUwpGuUTBZMcZnXYKuslEldLGmIug+bPrcSv]]></Encrypt>
</xml>
(3)接收到此消息后需要解密 官方解密文檔 官方解密示例 官方解密代碼示例包
/**
* 驗(yàn)證票據(jù)
*
* @param msgSignature 微信加密簽名
* @param timeStamp 時間戳
* @param nonce 隨機(jī)數(shù)
* @param postData 消息體
* @return 結(jié)果
* @throws AesException 異常
*/
public String componentVerifyTicket(String msgSignature, String timeStamp, String nonce, String postData) throws AesException {
//這個類是微信官網(wǎng)提供的解密類,需要用到消息校驗(yàn)Token 消息加密Key和服務(wù)平臺appid
WXBizMsgCrypt pc = new WXBizMsgCrypt(weixinConfig.getThirdPartyToken(), weixinConfig.getThirdPartyKey(), weixinConfig.getThirdPartyAppId());
String xml = pc.decryptMsg(msgSignature, timeStamp, nonce, postData);
Map<String, String> result = XmlToMapUtils.xmlToMap(xml);// 將xml轉(zhuǎn)為map
String infoType = MapUtils.getString(result, "InfoType");//消息通知類型
if (infoType.equals("unauthorized")) {//取消授權(quán)
String authorizerAppid = MapUtils.getString(result, "AuthorizerAppid");//公眾號APPID
wechatLogger.info("取消授權(quán)APPID:" + authorizerAppid);
authorizedAccountUtils.updateAuthor(authorizerAppid);//更新授權(quán)狀態(tài)
} else if (infoType.equals("authorized")) {//授權(quán)成功
String authorizerAppid = MapUtils.getString(result, "AuthorizerAppid");//公眾號APPID
wechatLogger.info("授權(quán)成功APPID:" + authorizerAppid);
authorizedAccountUtils.insertOrUpdate(authorizerAppid);//更新授權(quán)數(shù)據(jù)
} else if (infoType.equals("updateauthorized")) {//更新授權(quán)
String authorizerAppid = MapUtils.getString(result, "AuthorizerAppid");//公眾號APPID
wechatLogger.info("更新授權(quán)APPID:" + authorizerAppid);
authorizedAccountUtils.insertOrUpdate(authorizerAppid);//更新授權(quán)數(shù)據(jù)
} else if (infoType.equals("component_verify_ticket")) {
String componentVerifyTicket = MapUtils.getString(result, "ComponentVerifyTicket");
thirdPartyUtils.saveTicketToRedis(componentVerifyTicket);//存儲平臺授權(quán)票據(jù),保存ticket
wechatLogger.info("componentVerifyTicket緩存成功:" + componentVerifyTicket);
} else {
throw new RuntimeException("微信消息推送l類型未知!");
}
return "success";
}
(4)獲取第三方平臺調(diào)用憑證 component_access_token 這個也很重要?。。?br> 令牌的獲取是有限制的,令牌的有效期為 2 小時,做好令牌的管理在令牌快過期時(比如1小時50分)重新調(diào)用接口獲取。
package com.zaiyun.wechat.utils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zaiyun.common.config.WeixinConfig;
import com.zaiyun.common.constant.CacheConstants;
import com.zaiyun.common.core.redis.RedisCache;
import com.zaiyun.common.utils.ConvertUtils;
import com.zaiyun.common.utils.http.RestTemplateUtils;
import com.zaiyun.common.utils.spring.SpringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
/**
* 微信開放平臺工具類
*/
@Component
public class ThirdPartyUtils {
@Resource
WeixinConfig weixinConfig;
@Resource
private RestTemplateUtils restTemplateUtils;
/**
* 微信第三方令牌緩存KEY
*/
private static final String TOKEN_REDIS_KEY = CacheConstants.WE_CHAT_KEY + "component_access_token." + WeixinConfig.getThirdPartyAppId();
/**
* 微信第三方票據(jù)緩存KEY
*/
private static final String TICKET_REDIS_KEY = CacheConstants.WE_CHAT_KEY + "component_verify_ticket." + WeixinConfig.getThirdPartyAppId();
/**
* 存儲平臺授權(quán)票據(jù)ticket到緩存
*/
public String saveTicketToRedis(String ticketValue) {
SpringUtils.getBean(RedisCache.class).setCacheObject(TICKET_REDIS_KEY, ticketValue, 600, TimeUnit.MINUTES);
return ticketValue;
}
/**
* 獲取component_access_token
*/
public JSONObject getComponentAccessToken() {
String url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
HashMap<String, String> paramHeader = new HashMap<>();//請求頭參數(shù)
paramHeader.put("Content-Type", "application/json");
String verifyTicket = SpringUtils.getBean(RedisCache.class).getCacheObject(TICKET_REDIS_KEY);//獲取緩存
HashMap<String, String> paramBody = new HashMap();//請求體
paramBody.put("component_appid", weixinConfig.getThirdPartyAppId()); //第三方平臺 appid
paramBody.put("component_appsecret", weixinConfig.getThirdPartyAppSecret());//第三方平臺 appsecret
paramBody.put("component_verify_ticket", verifyTicket);//微信后臺推送的 ticket
Object bodyParam = ConvertUtils.mapToObject(paramBody);
ResponseEntity<String> responseEntity = restTemplateUtils.post(url, paramHeader, bodyParam, String.class);
if (responseEntity.getStatusCodeValue() == 200) {
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
return new JSONObject();
}
/**
* 從緩存中獲取component_access_token
*/
public String getComponentAccessTokenToRides() {
String componentAccessToken = SpringUtils.getBean(RedisCache.class).getCacheObject(TOKEN_REDIS_KEY);//獲取緩存
if (componentAccessToken != null) {
return componentAccessToken;
}
JSONObject resultObj = getComponentAccessToken();//重新獲取component_access_token
String accessToken = "";
if (!resultObj.isEmpty()) {
accessToken = resultObj.getString("component_access_token");
//令牌的有效期為120分鐘,提前30分鐘重新生成
SpringUtils.getBean(RedisCache.class).setCacheObject(TOKEN_REDIS_KEY, accessToken, 90, TimeUnit.MINUTES);
}
return accessToken;
}
/**
* 獲取預(yù)授權(quán)碼
*/
public JSONObject getPreAuthCode() {
String url = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?access_token=" + getComponentAccessTokenToRides();
HashMap<String, String> paramHeader = new HashMap<>();//請求頭參數(shù)
paramHeader.put("Content-Type", "application/json");
HashMap<String, String> paramBody = new HashMap();//請求體
paramBody.put("component_appid", weixinConfig.getThirdPartyAppId()); //第三方平臺 appid
Object bodyParam = ConvertUtils.mapToObject(paramBody);
ResponseEntity<String> responseEntity = restTemplateUtils.post(url, paramHeader, bodyParam, String.class);
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
/**
* 獲取刷新令牌
*
* @param authorizationCode 微信公眾號授權(quán)后攜帶的參數(shù)
*/
public JSONObject getAuthorizerRefreshToken(String authorizationCode) {
String url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?access_token=" + getComponentAccessTokenToRides();
HashMap<String, String> paramHeader = new HashMap<>();//請求頭參數(shù)
paramHeader.put("Content-Type", "application/json");
HashMap<String, String> paramBody = new HashMap();//請求體
paramBody.put("component_appid", weixinConfig.getThirdPartyAppId()); //第三方平臺 appid
paramBody.put("authorization_code", authorizationCode); //公眾號授權(quán)后的授權(quán)碼
Object bodyParam = ConvertUtils.mapToObject(paramBody);
ResponseEntity<String> responseEntity = restTemplateUtils.post(url, paramHeader, bodyParam, String.class);
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
/**
* 獲取授權(quán)賬號調(diào)用令牌
*
* @param authorizerAppid 授權(quán)方公眾號APPID
* @param authorizerRefreshToken 刷新令牌
*/
public JSONObject getAuthorizerAccessToken(String authorizerAppid, String authorizerRefreshToken) {
String url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" + getComponentAccessTokenToRides();
HashMap<String, String> paramHeader = new HashMap<>();//請求頭參數(shù)
paramHeader.put("Content-Type", "application/json");
HashMap<String, String> paramBody = new HashMap();//請求體
paramBody.put("component_appid", weixinConfig.getThirdPartyAppId()); //第三方平臺 appid
paramBody.put("authorizer_appid", authorizerAppid); //授權(quán)方公眾號APPID
paramBody.put("authorizer_refresh_token", authorizerRefreshToken); //刷新令牌,獲取授權(quán)信息時得到
Object bodyParam = ConvertUtils.mapToObject(paramBody);
ResponseEntity<String> responseEntity = restTemplateUtils.post(url, paramHeader, bodyParam, String.class);
if (responseEntity.getStatusCodeValue() == 200) {
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
return new JSONObject();
}
/**
* 從緩存獲取 authorizer_access_token
*
* @param authorizerAppid 授權(quán)方公眾號APPID
* @param authorizerRefreshToken 刷新令牌
*/
public String getAuthorizerAccessTokenToRedis(String authorizerAppid, String authorizerRefreshToken) {
String authorizerAccessTokenKey = CacheConstants.WE_CHAT_KEY + "authorizer_access_token." + authorizerAppid;//緩存Key
String authorizerAccessToken = SpringUtils.getBean(RedisCache.class).getCacheObject(authorizerAccessTokenKey);//獲取緩存
if (authorizerAccessToken != null) {
return authorizerAccessToken;
}
JSONObject resultObj = getAuthorizerAccessToken(authorizerAppid, authorizerRefreshToken);//重新獲取authorizer_access_token
String accessToken = "";
if (resultObj != null) {
accessToken = resultObj.getString("authorizer_access_token");
//令牌的有效期為120分鐘,提前30分鐘重新生成
SpringUtils.getBean(RedisCache.class).setCacheObject(authorizerAccessTokenKey, accessToken, 90, TimeUnit.MINUTES);
}
return accessToken;
}
/**
* 獲取授權(quán)賬號詳情
*
* @param authorizerAppid 授權(quán)的公眾號或者小程序的appid
* @return 結(jié)果
*/
public JSONObject getAuthorizerInfo(String authorizerAppid) {
String url = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?access_token=" + getComponentAccessTokenToRides();
HashMap<String, String> paramHeader = new HashMap<>();//請求頭參數(shù)
paramHeader.put("Content-Type", "application/json");
HashMap<String, String> paramBody = new HashMap();//請求體
paramBody.put("authorizer_appid", authorizerAppid);//授權(quán)的公眾號或者小程序的appid
paramBody.put("component_appid", weixinConfig.getThirdPartyAppId());//第三方平臺 appid
Object bodyParam = ConvertUtils.mapToObject(paramBody);
ResponseEntity<String> responseEntity = restTemplateUtils.post(url, paramHeader, bodyParam, String.class);
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
}
(5)通過 component_verify_ticket、component_access_token 這兩個數(shù)據(jù)就可以自建 PC授權(quán)鏈接、H5授權(quán)鏈接,用微信掃碼授權(quán);
/**
* 自建PC授權(quán)鏈接
*
* @return 結(jié)果
*/
public String builtPcLink() {
String componentAppid = weixinConfig.getThirdPartyAppId();//第三方平臺方 appid
String preAuthCode = thirdPartyUtils.getPreAuthCode().getString("pre_auth_code");//預(yù)授權(quán)碼
String redirectUri = "http://keduo.com/index.html#/home";//授權(quán)后回調(diào)地址
String link = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=" + componentAppid
+ "&pre_auth_code=" + preAuthCode + "&redirect_uri=" + redirectUri + "&auth_type=3";
return link;
}
/**
* 自建H5授權(quán)鏈接
*
* @return 結(jié)果
*/
public String builtH5Link() {
String componentAppid = weixinConfig.getThirdPartyAppId();//第三方平臺方 appid
String preAuthCode = thirdPartyUtils.getPreAuthCode().getString("pre_auth_code");//預(yù)授權(quán)碼
String redirectUri = "http://keduo.com/index.html#/home";//授權(quán)后回調(diào)地址
String link = "https://open.weixin.qq.com/wxaopen/safe/bindcomponent?action=bindcomponent&no_scan=1&component_appid=" + componentAppid
+ "&pre_auth_code=" + preAuthCode + "&redirect_uri=" + redirectUri + "&auth_type=3" + "#wechat_redirect";
return link;
}
掃碼授權(quán)后,至此公眾號授權(quán)流程已完成。
四、第三方平臺代公眾號實(shí)現(xiàn)業(yè)務(wù),首先要有這幾個令牌和票據(jù)
(1)微信授權(quán) (獲取微信 昵稱、頭像、openid)
(2)獲取JSSDK (jssdk 一般用于網(wǎng)頁 支付、分享、定位等等)
(3)普通公眾號的 JS SDK 的使用步驟 這個是前端的活
package com.zaiyun.wechat.controller;
import com.alibaba.fastjson2.JSONObject;
import com.zaiyun.common.annotation.Anonymous;
import com.zaiyun.common.config.WeixinConfig;
import com.zaiyun.common.core.controller.BaseController;
import com.zaiyun.common.core.domain.AjaxResult;
import com.zaiyun.common.core.domain.model.LoginUser;
import com.zaiyun.common.oto.entity.ZyConsumerUser;
import com.zaiyun.framework.web.service.TokenService;
import com.zaiyun.oto.service.ZyConsumerUserService;
import com.zaiyun.wechat.utils.ThirdPartyJsSdkUtils;
import com.zaiyun.wechat.utils.ThirdPartyAchieveUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
/**
* 第三方平臺代公眾號實(shí)現(xiàn)業(yè)務(wù)
*/
@Anonymous
@RestController
@RequestMapping("/wechat")
public class ThirdPartyAchieveController extends BaseController {
@Resource
WeixinConfig weixinConfig;
@Autowired
private TokenService tokenService;
@Resource
private ThirdPartyJsSdkUtils thirdPartyJsSdkUtils;
@Resource
private ThirdPartyAchieveUtils thirdPartyAchieveUtils;
@Autowired
private ZyConsumerUserService consumerUserService;
private static final Logger wechatLogger = LoggerFactory.getLogger("extend-wechat");
private String domainName;//系統(tǒng)域名
/**
* 用戶同意授權(quán),獲取code
*
* @return 結(jié)果
*/
@GetMapping("/authorize")
public AjaxResult authorize(HttpServletResponse response, HttpServletRequest request, @RequestParam("token") String token, @RequestParam("url") String url) throws Exception {
//String domainName = request.getServerName();//客戶端請求域名
LoginUser loginUser = tokenService.getLoginUserByToken(token);
if (loginUser == null) {
return AjaxResult.error(201, "token失效");
}
long userId = loginUser.getUserId();
if (url == null) {
return AjaxResult.error(201, "授權(quán)后重定向URL不能為空");
}
HttpSession session = request.getSession();
session.setAttribute("callback", domainName + url);//將重定向地址存入session
String thirdAppId = weixinConfig.getThirdPartyAppId();//第三方APPID
String accountAppId = thirdPartyAchieveUtils.replaceAccountAppId(); //公眾號APPID
String uri = URLEncoder.encode(domainName + "/wechat/access/token", "utf-8");
String redirectUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + accountAppId +
"&redirect_uri=" + uri + "&response_type=code&scope=snsapi_userinfo&state=" + userId +
"&component_appid=" + thirdAppId + "#wechat_redirect";
response.sendRedirect(redirectUrl);
return success();
}
/**
* 通過code換取網(wǎng)頁授權(quán)access_token
*/
@GetMapping("/access/token")
public void accessToken(HttpServletResponse response, HttpServletRequest request) throws Exception {
String code = request.getParameter("code");
JSONObject data = thirdPartyAchieveUtils.getAccessToken(code);
String openid = data.getString("openid"); //授權(quán)用戶唯一標(biāo)識
String accessToken = data.getString("access_token"); //接口調(diào)用憑證
JSONObject user = thirdPartyAchieveUtils.getUserinfo(accessToken, openid);
String userId = request.getParameter("state");//當(dāng)前用戶ID
String nickname = user.getString("nickname");
String headimgurl = user.getString("headimgurl");
HttpSession session = request.getSession();
String callback = session.getAttribute("callback").toString();//從session獲取重定向地址
wechatLogger.info("userId:" + userId);
wechatLogger.info("callback:" + callback);
wechatLogger.info("code:" + code);
wechatLogger.info("openid:" + openid);
wechatLogger.info("accessToken:" + accessToken);
wechatLogger.info("通過code換取網(wǎng)頁授權(quán)access_token:" + data);
wechatLogger.info("user" + user);
String nickname2 = new String(nickname.getBytes("ISO-8859-1"), "UTF-8");
ZyConsumerUser consumerUser = new ZyConsumerUser();
consumerUser.setUserId(Long.parseLong(userId));
consumerUser.setWeixinOpenid(openid);
consumerUser.setWeixinNickname(nickname2);
consumerUser.setLogo(headimgurl);
consumerUserService.update(consumerUser);//更新授權(quán)微信信息
response.sendRedirect(callback);//授權(quán)后重定向
}
/**
* 開放平臺JsSdk
*
* @param body url 當(dāng)前網(wǎng)頁的URL,不包含#及其后面部分
* @return
*/
@PostMapping("/js/sdk")
public AjaxResult jseSdk(@RequestBody JSONObject body) {
try {
String url = body.getString("url");
if (url == null || url.isEmpty()) {
return AjaxResult.error(201, "參數(shù)錯誤url");
}
String accountAppId = thirdPartyAchieveUtils.replaceAccountAppId(); //公眾號APPID
String ticket = thirdPartyJsSdkUtils.getJsapiTicketToRides(accountAppId);
Map<String, Object> res = thirdPartyJsSdkUtils.sign(ticket, URLDecoder.decode(url, "UTF-8"));
res.put("appId", accountAppId);
return success(res);
} catch (Exception e) {
return AjaxResult.error(201, e.getMessage());
}
}
}
第三方平臺代公眾號實(shí)現(xiàn)業(yè)務(wù)工具類文章來源:http://www.zghlxwxcb.cn/news/detail-840033.html
package com.zaiyun.wechat.utils;
import java.util.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zaiyun.common.constant.CacheConstants;
import com.zaiyun.common.core.redis.RedisCache;
import com.zaiyun.common.utils.http.RestTemplateUtils;
import com.zaiyun.common.utils.spring.SpringUtils;
import com.zaiyun.common.utils.uuid.UUID;
import com.zaiyun.wechat.mapper.AuthorizedAccountMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import com.zaiyun.wechat.domain.AuthorizedAccount;
import javax.annotation.Resource;
/**
* 第三方平臺代公眾號實(shí)現(xiàn)業(yè)務(wù)工具類
*/
@Component
public class ThirdPartyJsSdkUtils {
@Resource
private ThirdPartyUtils thirdPartyUtils;
@Resource
private RestTemplateUtils restTemplateUtils;
@Resource
private ThirdPartyAchieveUtils thirdPartyAchieveUtils;
@Resource
AuthorizedAccountMapper authorizedAccountMapper;
/**
* JS-SDK jsapi_ticket 緩存KEY
*/
private static final String JSAPI_TICKET_KEY = CacheConstants.WE_CHAT_KEY + "authorizer_jsapi_ticket.";
/**
* 獲取jsapi_ticket
*/
public JSONObject getJsapiTicket() {
String accountAppId = thirdPartyAchieveUtils.replaceAccountAppId(); //公眾號APPID
AuthorizedAccount info = authorizedAccountMapper.findAuthorizerAppid(accountAppId);
String authorizerAccessToken = thirdPartyUtils.getAuthorizerAccessTokenToRedis(accountAppId, info.getAuthorizerRefreshToken());//授權(quán)賬號調(diào)用令牌
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=" + authorizerAccessToken;
ResponseEntity<String> responseEntity = restTemplateUtils.get(url, String.class);
JSONObject result = JSON.parseObject(String.valueOf(responseEntity.getBody()));
if (result.getInteger("errcode") == 0) {
return JSON.parseObject(String.valueOf(responseEntity.getBody()));
}
return new JSONObject();
}
/**
* 從緩存中獲取jsapi_ticket
*/
public String getJsapiTicketToRides(String appid) {
String jsapiTicket = SpringUtils.getBean(RedisCache.class).getCacheObject(JSAPI_TICKET_KEY + appid);//獲取緩存
if (jsapiTicket != null) {
return jsapiTicket;
}
JSONObject resultObj = getJsapiTicket();//重新獲取jsapi_ticket
String jsTicket = "";
if (!resultObj.isEmpty()) {
jsTicket = resultObj.getString("ticket");
//有效期為120分鐘,提前30分鐘重新生成
SpringUtils.getBean(RedisCache.class).setCacheObject(JSAPI_TICKET_KEY + appid, jsTicket, 90, TimeUnit.MINUTES);
}
return jsTicket;
}
/**
* 簽名
*
* @param jsapi_ticket jsapi_ticket
* @param url 當(dāng)前網(wǎng)頁的URL,不包含#及其后面部分
* @return 結(jié)果
*/
public static Map<String, Object> sign(String jsapi_ticket, String url) {
Map<String, Object> ret = new HashMap<String, Object>();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意這里參數(shù)名必須全部小寫,且必須有序
string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
return ret;
}
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
private static String create_nonce_str() {
return UUID.fastUUID().toString(true);
//return UUID.randomUUID().toString();
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
六、到此已大功告成,祝你好運(yùn)!?。?/strong>文章來源地址http://www.zghlxwxcb.cn/news/detail-840033.html
到了這里,關(guān)于JAVA 微信公眾號授權(quán)給開放平臺(第三方平臺)開發(fā)流程及第三方平臺代公眾號實(shí)現(xiàn)業(yè)務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!