cbao 2020-05-12
需求:微信订阅号开发,点击微信自定义菜单,获取关注用户的openid,并且传到后台与前端页面
说明:订阅号无法直接获取关注用户的openid传到前端,只能通过微信开放平台将订阅号和服务号关联起来,获取用户的uionid,这样就可以确定当前操作的微信用户
场景:
1. 菜单类型为 view,创建view的代码:
// 网页跳转菜单
Map<String, String> menu1_1 = new HashMap<>();
menu1_1.put("type", "view");
menu1_1.put("name", "进入生态圈");
menu1_1.put("url", "http://域名/menu/auth?redirect_uri=http://域名/menu/index");Controller 代码:
/**
* 授权入口:订阅号设置了业务域名后才会进入此方法
* @param request
* @param response
*/
@RequestMapping(value = "/auth",method = RequestMethod.GET)
@ResponseBody
public void auth(HttpServletRequest request, HttpServletResponse response) {
try {
Map<String, String[]> paramterMap = request.getParameterMap();
log.info("auth click Parameter: [");
paramterMap.forEach((k,v)->{
log.info("key : " + k + ";value : " + Arrays.toString(v));
});
log.info("]");
// 跳转的URL必须要做encode
String redirectUrl = URLEncoder.encode(request.getParameter("redirect_uri"), SysConst.ENCODE_UTF8);
// 使用服务号的appid授权获取用户基本信息,然后跳转到redirect_uri,跳转到redirect_uri后,回接收到code
String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+WeChatConfigDYH.APP_ID_FWH +"&redirect_uri="+redirectUrl +"&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect";
//跳转授权页面
response.sendRedirect(authUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 授权接口跳转uri入口
* @param request
* @param response
*/
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String index(HttpServletRequest request, HttpServletResponse response) {
try {
Map<String, String[]> paramterMap = request.getParameterMap();
log.info("view click Parameter: [");
paramterMap.forEach((k,v)->{
log.info("key : " + k + ";value : " + Arrays.toString(v));
});
log.info("]");
String code = request.getParameter("code");
log.debug("auth redirect_uri code = " + code);
JSONObject weChatCode = _dataCache.getWeChatCode(code);
if (weChatCode == null) {
//通过code换取网页授权access_token(与基础支持中的access_token不同)
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+WeChatConfigDYH.APP_ID_FWH +"&secret="+WeChatConfigDYH.APP_SECRET_FWH +"&code="+code+"&grant_type=authorization_code";
//返回信息:包含unionid,标志唯一用户
String accessInfoStr = _restTemplate.getForObject(requestUrl, String.class);
// 转化成JSONObject
weChatCode = JSONObject.parseObject(accessInfoStr);
// 存入缓存
_dataCache.putWeChatCode(code, weChatCode);
}
log.debug(weChatCode.toString());
// 微信unionid,唯一
String unionid = weChatCode.getString("unionid");
// 客户ID
String fcustomerid495 = null;
// 获取用户信息
Customer customer = _customerService.findByUnionId(unionid);
if (customer != null) {
fcustomerid495 = customer.getFcustomerid495();
}
// 设置unionid和fcustomerid到前端
request.setAttribute("unionid", unionid);
request.setAttribute("fcustomerid", fcustomerid495);
} catch (Exception e) {
e.printStackTrace();
}
return "index";
}2. 菜单类型为 click 创建代码:
// 按钮click
Map<String, String> menu1_1 = new HashMap<>();
menu1_1.put("type", "click");
menu1_1.put("name", "进入生态圈");
menu1_1.put("key", "self_edit");Controller代码:
/**
* 写法二
* @param requestBody
* @param signature
* @param timestamp
* @param nonce
* @param openid
* @param encType
* @param msgSignature
* @return
*/
@RequestMapping(method = RequestMethod.POST)
public String post(HttpServletRequest request, HttpServletResponse response,
@RequestBody String requestBody,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
// 返回给微信加密后的消息
String respMessageEncrypt = "";
try {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
Map<String, String> encryptMap = MessageUtil.fromEncryptedMap(requestBody, timestamp, nonce, msgSignature);
log.info("菜单事件:" + encryptMap.toString());
// 消息处理
respMessageEncrypt = _weChatMessageService.newsMessage(encryptMap);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return respMessageEncrypt;
}/**
* 处理消息发送:图文消息
* @param request
* @return 加密消息字符传
*/
public String newsMessage(Map<String, String> requestMap) {
// 返回加密消息字符串
String respMessageEncrypt = null;
try {
// 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
// 根据openid获取客户信息
String fcustomerid495 = null;
Customer customer = _customerService.findByOpenId(fromUserName);
if (customer != null) {
fcustomerid495 = customer.getFcustomerid495();
}
// 设置链接消息
NewsMessageResp newsMessage = new NewsMessageResp();
newsMessage.setToUserName(fromUserName);
newsMessage.setFromUserName(toUserName);
newsMessage.setCreateTime(new Date().getTime());
newsMessage.setMsgId(UUID.randomUUID().toString());
newsMessage.setMsgType(WeChatConst.RESP_MESSAGE_TYPE_NEWS);
newsMessage.setArticleCount("1");
// Articles
List<Article> articleList = new ArrayList<Article>();
Article article = new Article();
article.setTitle("生态圈链接");
article.setDescription("点击进入【生态圈】");
article.setPicUrl("http://域名/img/htlogo.png");
article.setUrl("http://域名?openid=" + fromUserName + "&fcustomerid=" + fcustomerid495);
articleList.add(article);
newsMessage.setArticles(articleList);
// 链接消息xml
String respMessage = MessageUtil.newsMessageToXml(newsMessage);
log.info("链接消息 = " + respMessage);
// 消息加密
WxCryptUtil wxCryptUtil = new WxCryptUtil();
respMessageEncrypt = wxCryptUtil.encrypt(respMessage);
log.info("加密后的链接消息 = " + respMessageEncrypt);
} catch (Exception e) {
e.printStackTrace();
}
return respMessageEncrypt;
}