参考牛人的文档,按照步骤集成。
- 配置微信第三方平台中的授权事件接收URL:http://my-domain/notify/receive_ticket
- 配置微信第三方平台中的公众号消息与事件接收URL http://my-domain/notify/APPID/callback
- 首次启动后需要 等待收到 微信推送的 component_verify_ticket 后才可以使用接口 (在第三方平台创建审核通过后,微信服务器每隔10分钟会向第三方的消息接收地址推送一次component_verify_ticket,用于获取第三方平台接口调用凭据)
- 浏览器访问:http://my-domain/api/auth/goto_auth_url_show 点击 go 跳转到微信授权页面 扫码授权
增加weixin-java-open依赖,老项目用的是3.3.0版本,建议用4.0以上的版本。
com.github.binarywang weixin-java-open 3.3.0
package com.test.wechat.controller;
import com.test.wechat.consts.WechatOpenConst;
import com.test.wechat.service.WechatOpenService;
import com.test.wechat.util.ServletUtil;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* @author 007
*/
@RestController
@RequestMapping("/wechatOpen/platform")
public class WechatOpenNotifyController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
protected WechatOpenService wxOpenService;
@Autowired
private ValueOperations valOps;
@Autowired
RedisTemplate redisTemplate;
@RequestMapping("/receive_ticket")
public Object receiveTicket(String key,@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce, @RequestParam("signature") String signature,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) throws WxErrorException {
logger.info(
"\n接收微信请求:[key=[{}],[signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
key,signature, encType, msgSignature, timestamp, nonce, requestBody);
ServletUtil.setKey(key);
if (!StringUtils.equalsIgnoreCase("aes", encType)
|| !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}
// aes加密的消息
WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody,
wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
String componentVerifyTicket=inMessage.getComponentVerifyTicket();
if(redisTemplate.getExpire(WechatOpenConst.OPEN_PLATFORM_TICKET + key)<10*60) {
valOps.set(WechatOpenConst.OPEN_PLATFORM_TICKET + key, componentVerifyTicket, 60 * 60 * 12, TimeUnit.SECONDS);
}
wxOpenService.getComponentAccessToken(key, componentVerifyTicket);
try {
String out = wxOpenService.getWxOpenComponentService().route(inMessage);
logger.debug("\n组装回复信息:{}", out);
} catch (WxErrorException e) {
logger.error("receive_ticket", e);
}
return "success";
}
@RequestMapping("{appId}/callback")
public Object callback(String key,@RequestBody(required = false) String requestBody,
@PathVariable("appId") String appId,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam("encrypt_type") String encType,
@RequestParam("msg_signature") String msgSignature) {
logger.info(
"\n接收微信请求:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
ServletUtil.setKey(key);
if (!StringUtils.equalsIgnoreCase("aes", encType)
|| !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}
String out = "";
// aes加密的消息
WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody,
wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
logger.info("\n消息解密后内容为:\n{} ", inMessage.toString());
// 全网发布测试用例
if (StringUtils.equalsAnyIgnoreCase(appId, "wx6c317d44449bfd92", "wx570bc396a51b8ff8")) {
try {
if (StringUtils.equals(inMessage.getMsgType(), "text")) {
if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) {
out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback")
.fromUser(inMessage.getToUser())
.toUser(inMessage.getFromUser())
.build(),
wxOpenService.getWxOpenConfigStorage()
);
} else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) {
String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build();
wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
}
} else if (StringUtils.equals(inMessage.getMsgType(), "event")) {
WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build();
wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
}
} catch (WxErrorException e) {
logger.error("callback", e);
}
}else{
WxMpXmlOutMessage outMessage = wxOpenService.route(inMessage);
if(outMessage != null){
out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, wxOpenService.getWxOpenConfigStorage());
}
}
return out;
}
}
package com.test.wechat.controller;
import com.test.wechat.service.WechatOpenService;
import com.test.wechat.util.ServletUtil;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
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 org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 007
*/
@Controller
@RequestMapping("/wechatOpen/open/api")
public class WechatOpenApiController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private WechatOpenService wxOpenService;
@Autowired
private ValueOperations valOps;
@GetMapping("/auth/goto_auth_url_show")
@ResponseBody
public String gotoPreAuthUrlShow(String key) {
String hrefUrl="go";
return hrefUrl;
}
@GetMapping("/auth/goto_auth_url")
public void gotoPreAuthUrl(HttpServletRequest request, HttpServletResponse response) {
String key = request.getParameter("key");
ServletUtil.setKey(key);
String host = request.getHeader("host");
String url = "https://" + host + "/wechatOpen/open/api/auth/jump?key=" + key;
try {
url = wxOpenService.getWxOpenComponentService().getPreAuthUrl(url);
// 添加来源,解决302跳转来源丢失的问题
response.addHeader("Referer", "https://" + host);
response.sendRedirect(url);
} catch (WxErrorException | IOException e) {
logger.error("gotoPreAuthUrl", e);
throw new RuntimeException(e);
}
}
@GetMapping("/auth/jump")
@ResponseBody
public WxOpenQueryAuthResult jump(String key, @RequestParam("auth_code") String authorizationCode) {
try {
ServletUtil.setKey(key);
WxOpenQueryAuthResult queryAuthResult = wxOpenService.getWxOpenComponentService().getQueryAuth(authorizationCode);
logger.info("getQueryAuth", queryAuthResult);
//存储授权appId,和authorCode
valOps.set("wxOpen:" + queryAuthResult.getAuthorizationInfo().getAuthorizerAppid(), authorizationCode);
wxOpenService.updateAuthAccount(key,authorizationCode);
return queryAuthResult;
} catch (WxErrorException e) {
logger.error("gotoPreAuthUrl", e);
throw new RuntimeException(e);
}
}
@GetMapping("/get_authorizer_info")
@ResponseBody
public WxOpenAuthorizerInfoResult getAuthorizerInfo(@RequestParam String appId) {
try {
return wxOpenService.getWxOpenComponentService().getAuthorizerInfo(appId);
} catch (WxErrorException e) {
logger.error("getAuthorizerInfo", e);
throw new RuntimeException(e);
}
}
}
public class ServletUtil {
private static final ThreadLocal tl = new ThreadLocal();
public static String getKey() {
// ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// return (String) attributes.getAttribute("key", RequestAttributes.SCOPE_REQUEST);//attributes.getRequest().getAttribute("key").toString();
return tl.get();
}
public static void setKey(String key) {
// ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// attributes.setAttribute("key",key, RequestAttributes.SCOPE_REQUEST);
// //attributes.getRequest().setAttribute("key",key);
tl.set(key);
}
授权中获取ticket通过上面的receiveTicket这个方法
com.github.binarywang weixin-java-mp 3.3.0
微信公众平台接口
客服账号管理 | 微信开放文档
authorizer_access_token获取方式 ,这个比较复杂,需要五步,其中component_access_token,authorizer_access_token有效期都有两小时。
Token生成说明 | 微信开放文档
其中authcode在授权后会拿到,需要保存下来。
ps:下面继续讲解下一步代码