1.小程序推送到对应公众号需要获取公众号的openid,但通过小程序流程操作只能获取小程序的openid,如何关联这两个openid呢?答案是通过unionid,小程序和微信获取到openid时都可以得到unionid,根据这个unionid确认两者关系 保存到数据库,再通过此关系进行推送。
2.登录凭证校验。通过wx.login接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程,传到后台拼接字符串请求微信后台获取用户信息(openid,unionid) 请求地址GET方法:
https://api./sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
代码示例:
@PostMapping({"/findByCode"})public Result findByCode(@RequestBody WeAccessSignReqDto requestData) {HashMap resultMap = new HashMap();if (StringHelper.isEmpty(requestData.getCode())) {return Result.failed("缺少微信Code");}StringBuilder url = new StringBuilder("https://api./sns/jscode2session");url.append("?appid="+appid);//自己的appidurl.append("&secret="+secret);//自己的appSecreturl.append("&js_code=" + requestData.getCode());url.append("&grant_type=authorization_code");url.append("&connect_redirect=1");//对网页返回信息进行转换restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());ResponseEntity<JSONObject> responseEntity = restTemplate.getForEntity(url.toString(), JSONObject.class);JSONObject body = responseEntity.getBody();log.debug("微信返回数据:"+JSONUtil.toJsonStr(body));if(body!=null){//如果errcode为空则返回成功 带有openidif(body.get("errcode")==null){String openid = body.get("openid")==null?null:(String) body.get("openid");String unionid = body.get("unionid")==null?null:(String) body.get("unionid");resultMap.put("openid", openid);resultMap.put("unionid", unionid);//保存openid和unionid 这个怎么存你们自己的事WechatUserInfoEntity userInfoEntity = new WechatUserInfoEntity();userInfoEntity.setAppOpenid(openid);userInfoEntity.setUnionid(unionid);wechatMpService.saveAppUserInfo(userInfoEntity);return Result.success(resultMap);}else {//前端会请求两次,如果失败则返回第一次请求获取的openid,如果没有就没有// 防止前端发起两次请求引起code已经被使用resultMap.put("errcode",(Integer)body.get("errcode"));resultMap.put("errmsg",(String) body.get("errmsg"));log.error("错误码:"+(Integer)body.get("errcode")+" 错误信息:"+(String) body.get("errmsg"));return Result.failed(String.valueOf(body.get("errcode")));}}return Result.failed("获取失败");}
微信的坑点:调用成功和失败时返回的数据格式都不一样。。。
3.获取公众号id有两种方法,一种是先获取关注公众号粉丝列表的openid,再通过openid查找处对应的unionid,此方法是批量请求,而且微信接口有数量限制,需要定时调用,不能做增量查询,粉丝数到达一定程度可能会引发性能问题。
另一种是后台与微信公众号进行接入,接入之后,用户进行发消息或者关注取关,微信这边都会对后台进行请求,此时可以获取用户openid,由此可以获得unionid。(使用了这种
微信对接文档:https://developers./doc/offiaccount/Basic_Information/Access_Overview.html
url填写服务的接口地址:例如/app/miniProgramAuth 如果本地地址用natapp做内网穿透,如果是生产地址直接填上去就行
代码示例:
@ApiOperation(value = "微信小程序配置的服务端回调接入验证", notes = "微信小程序配置配置的回调接入验证")@RequestMapping(value = {"app/miniProgramAuth"}, method = {RequestMethod.GET})public void miniProgramAuthGet(HttpServletRequest request, HttpServletResponse response) throws AesException, IOException {String resp = "";String signature = request.getParameter("signature");//时间戳String timestamp = request.getParameter("timestamp");//随机数String nonce = request.getParameter("nonce");//随机字符串String echostr = request.getParameter("echostr");String token = ConfigHelper.getProperties("token");logger.info("++get++weChatAuth-----token-->" + token + ",---signature-->" + signature + ",timestamp-->" + timestamp + ",nonce-->" + nonce + ",echostr-->" + echostr);// 三个参数字符串排序后拼接成一个字符串进行sha1加密String signtemp = SHA1.getSHA1(token, timestamp, nonce);if (signtemp.equals(signature)) { // 是微信发送过来的信息logger.info("++++get++++access success!!......call weChatAuth end--return echostr=" + echostr);resp = echostr;} else {resp = "";logger.error("---get---access fail!!......call weChatAuth end---->");}PrintWriter out = response.getWriter();out.print(resp);out.flush();out.close();}
@ApiOperation(value = "微信小程序配置的回调消息接口", notes = "微信小程序配置的回调消息接口")@RequestMapping(value = {"app/miniProgramAuth"}, method = {RequestMethod.POST})public void miniProgramAuthPost(HttpServletRequest request, HttpServletResponse response)throws AesException, IOException {// System.out.println("微信发送的post请求");// Map<String,String> requestMap= parseRequest(request.getInputStream());// System.out.println(requestMap);//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp,nonce参数String signature = request.getParameter("signature");//时间戳String timestamp = request.getParameter("timestamp");//随机数String nonce = request.getParameter("nonce");//随机字符串String echostr = request.getParameter("echostr");String token = ConfigHelper.getProperties("token");if(SignUtil.checkSignature(signature, timestamp, nonce)) {logger.info("[signature: "+signature + "]<-->[timestamp: "+ timestamp+"]<-->[nonce: "+nonce+"]<-->[echostr: "+echostr+"]");// response.getOutputStream().println(echostr);}String resp;// 三个参数字符串排序后拼接成一个字符串进行sha1加密String sha1 = SHA1.getSHA1(token, timestamp, nonce);if (sha1.equals(signature)) { // 是微信发送过来的信息// 调用parseXml方法解析请求消息try {Map<String, String> requestMap = WeChatUtils.parseXml(request.getInputStream());resp = receiveReqMsg(requestMap); // 接收消息,并且处理logger.debug("获取消息:"+resp.toString());String eventType = requestMap.get("Event");if(“subscribe”.equals(eventType)){//关注行为String url = new StringBuffer().append("https://api./cgi-bin/user/info?").append("access_token=").append(getAccessToken()).append("&openid=").append(requestMap.get("FromUserName")).append("&lang=zh_CN").toString();restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());JSONObject object = restTemplate.getForObject(url, JSONObject.class);if(object!=null){if(object.get("errcode") == null&&object.get("unionid")!=null){return (String) object.get("unionid");//这里获取到unionid}}}else if(WeChatUtils.WxMsgType.EVENT_TYPE_UNSUBSCRIBE.equals(eventType)){//callRestfulService(jsonParamMap, nameSpace, "method"); //取关的操作}} catch (Exception e) {logger.error("--post---error----echoStr=" + echostr, e);resp = echostr;}} else {resp = "";logger.error("----post--access fail......call weChatAuth end---->");}//这里是给微信返回的信息,可以以消息直接发送给用户response.setHeader("Content-type", "text/html;charset=UTF-8");//告知浏览器编码方式;response.setCharacterEncoding("UTF-8");PrintWriter out = response.getWriter();out.print(resp);out.flush();out.close();}
getAccessToken的话在这
https://developers./doc/offiaccount/Basic_Information/Get_access_token.html
自己封装吧~~
然后就可以关联了
如果觉得《Java微信小程序关联公众号(服务号)推送详解》对你有帮助,请点赞、收藏,并留下你的观点哦!