您现在的位置是:Java微信小程序获取关联公众号用户是否已关注标识 >>正文
Java微信小程序获取关联公众号用户是否已关注标识
德薄能鲜网68人已围观
简介文章目录前言一、绑定相关数据1.小程序绑定公众号2.小程序和公众号关联微信开放平台二、公众号操作回调1.服务器配置2.回调接口(URL)三、获取微信公众号用户是否已关注标识...
文章目录
- 前言
- 一、绑定相关数据
- 1.小程序绑定公众号
- 2.小程序和公众号关联微信开放平台
- 二、公众号操作回调
- 1.服务器配置
- 2.回调接口(URL)
- 三、获取微信公众号用户是否已关注标识
- 1.获取公众号accessToken
- 2.feign远程调用微信公众号获取用户基本信息(UnionID机制)
- 3.回调接口补充更新用户关注标识
- 总结
前言
如果公众号不是认证的服务号就无需看这篇文章,需要先认证,可以参考这篇文章五分钟!手把手教你快速完成微信公众号认证!
你们是否经常在小程序看到这种关注标识
实现的方法很简单,后端只需要返回给前端给前端当前用户是否有关注公众号就行了,整个逻辑很简单,微信官方也有对应的API,但实际上整个流程就很复杂
一、绑定相关数据
微信官方有很多限制,咱们需要做好一些关联
1.小程序绑定公众号
根据微信官方文档,微信小程序需要关联对应的公众号才能够引导关注公众号
咱们先登录微信公众平台,扫码登录公众号
然后点击【广告与服务】->【小程序管理】添加关联小程序,这步很简单只需要后台管理员扫码一下就行了。
2.小程序和公众号关联微信开放平台
这一步比较重要,这是为了获取
unionId
,关于unionId介绍可以看一下官方说明,UnionID 机制说明,简单来说就是同一个微信开放平台用户的unionId都是唯一的
先注册微信开放平台,然后关联小程序和公众号,关联流程参考文章微信开放平台绑定公众号,小程序也同理,这个时候你们需要改造原来的微信登录接口,会发现登录接口返回的参数多了unionId,把对应用户的unionId存到数据库
里,后面会用得上。
二、公众号操作回调
这个是公众号的相关操作会有回调,相当强大,咱们服务器能立马得知用户做了什么操作,这里咱们只需要配公众号
关注
和取消关注
的回调。
1.服务器配置
同样登录微信公众平台,选择公众号账号登录,进入【服务与配置】->【基本配置】,会看到有一个服务器配置
点击修改配置
这个URL
实际上就是咱们要给微信的回调地址,需要外网可访问;Token
咱们随意填写,只要跟服务器对得上;EncodingAESKey
随机生成就好,然后消息加解密
选择用明文模式,安全模式可以看看别人写的加解密方式;
2.回调接口(URL)
RequestMethodEnum枚举类是为了判断什么请求方式,如果是get
请求实际上就是验证token合法性
publicenumRequestMethodEnum{ /** * get */GET(1,"GET"),/** * post */POST(2,"POST");privatefinalIntegercode;privatefinalStringdesc;RequestMethodEnum(Integerid,Stringname){ this.code =id;this.desc =name;}publicIntegergetCode(){ returncode;}publicStringgetDesc(){ returndesc;}}
MsgTypeEnum枚举类是为了判断微信公众号执行了什么操作
publicenumMsgTypeEnum{ /** * 关注/取消关注事件 */EVENT(1,"event");privatefinalIntegercode;privatefinalStringdesc;MsgTypeEnum(Integerid,Stringname){ this.code =id;this.desc =name;}publicIntegergetCode(){ returncode;}publicStringgetDesc(){ returndesc;}}
checkSignature验证回调地址是否合法的工具方法
publicstaticbooleancheckSignature(Stringsignature,Stringtimestamp,Stringnonce,Stringtoken){ // 1.将token、timestamp、nonce三个参数进行字典序排序String[]arr =newString[]{ token,timestamp,nonce};Arrays.sort(arr);// 2. 将三个参数字符串拼接成一个字符串进行sha1加密StringBuildercontent =newStringBuilder();for(inti =0;i <arr.length;i++){ content.append(arr[i]);}MessageDigestmd =null;StringtmpStr =null;try{ md =MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[]digest =md.digest(content.toString().getBytes());tmpStr =byteToStr(digest);}catch(NoSuchAlgorithmExceptione){ e.printStackTrace();}content =null;// 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信log.info("tmpStr:{ },signature:{ }",tmpStr,signature.toUpperCase());returntmpStr !=null&&tmpStr.equals(signature.toUpperCase());}
然后验证完整方法如下
publicvoidcallback(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{ Stringmethod =request.getMethod();request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");if(RequestMethodEnum.GET.getDesc().equals(method)){ //验证回调地址Stringsignature =request.getParameter("signature");Stringtimestamp =request.getParameter("timestamp");Stringnonce =request.getParameter("nonce");Stringechostr =request.getParameter("echostr");booleancheckSignature =WechatOffiAccountUtil.checkSignature(signature,timestamp,nonce,token);// 这个token要跟服务器配置的token一致if(checkSignature){ log.info("签名验证成功");response.getWriter().write(echostr);}}}
写好接口后,回去填写服务器配置,就会验证成功。
三、获取微信公众号用户是否已关注标识
1.获取公众号accessToken
咱们要先清楚,小程序的accessToken和公众号的accessToken是不同的,所以公众号的accessToken要重新获取一下,先查阅一下微信公众号API获取 Access token
Java获取方法如下:
publicStringgetOfficialAccessToken(){ StringaccessToken =redisCache.getCacheObject("official_access_token");// 这里会用到redisCache工具if(Objects.isNull(accessToken)){ Stringurl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+OFFICIAL_APP_ID+"&secret="+OFFICIAL_SECRET;RestTemplaterestTemplate =newRestTemplate();ResponseEntity<String>response =restTemplate.exchange(url,HttpMethod.GET,null,String.class);StringresponseBody =response.getBody();// 解析返回结果,提取 access_token 字段的值accessToken =parseAccessToken(responseBody);redisCache.setCacheObject("official_access_token",accessToken,1,TimeUnit.HOURS);}if(!isAccessTokenValid(accessToken)){ // 这是为了解析accessToken是否还有效,因为官方的过期时间会变动Stringurl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+OFFICIAL_APP_ID+"&secret="+OFFICIAL_SECRET;RestTemplaterestTemplate =newRestTemplate();ResponseEntity<String>response =restTemplate.exchange(url,HttpMethod.GET,null,String.class);StringresponseBody =response.getBody();// 解析返回结果,提取 access_token 字段的值accessToken =parseAccessToken(responseBody);redisCache.setCacheObject("official_access_token",accessToken,1,TimeUnit.HOURS);}returnaccessToken;}privateStringparseAccessToken(StringresponseBody){ JSONObjectjsonObject =newJSONObject(responseBody);returnjsonObject.getString("access_token");}publicbooleanisAccessTokenValid(StringaccessToken){ Stringurl ="https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token="+accessToken;RestTemplaterestTemplate =newRestTemplate();ResponseEntity<String>response =restTemplate.exchange(url,HttpMethod.GET,null,String.class);StringresponseBody =response.getBody();// 解析返回结果,提取错误信息StringerrorCode =parseErrorCode(responseBody);// 如果错误码为空,则表示 access_token 有效;否则,表示无效returnerrorCode ==null;}
2.feign远程调用微信公众号获取用户基本信息(UnionID机制)
远程调用我是用了feign,这样可以节省很多建远程调用步骤,然后查阅一下微信公众号API获取用户基本信息(UnionID机制)
请求结果实体类
@DatapublicclassPublicUserInfo{ /** * 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 */privateintsubscribe;/** * 用户的标识,对当前公众号唯一 */privateStringopenid;/** * 用户的语言,简体中文为zh_CN */privateStringlanguage;/** * 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间 */privatelongsubscribe_time;/** * 只有在用户将公众号绑定到微信开放平台账号后,才会出现该字段。 */privateStringunionid;/** * 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 */privateStringremark;/** * 用户所在的分组ID(兼容旧的用户分组接口) */privateintgroupid;/** * 用户被打上的标签ID列表 */privateList<Integer>tagid_list;/** * 返回用户关注的渠道来源 */privateStringsubscribe_scene;/** * 二维码扫码场景(开发者自定义) */privateintqr_scene;/** * 二维码图片 */privateStringqr_scene_str;privateStringqrSceneImage;// 添加构造方法、getter和setter等}
编写Feign接口方法
@FeignClient(name ="officialAccount",url ="https://api.weixin.qq.com/cgi-bin")publicinterfaceOfficialAccountFeign{ @GetMapping("/user/info?access_token={ accessToken}&openid={ openId}&lang=zh_CN")ResponseEntity<PublicUserInfo>getUserInfo(@PathVariable("accessToken")StringaccessToken,@PathVariable("openId")StringopenId);}
3.回调接口补充更新用户关注标识
补充上面写的callBack回调方法
publicvoidcallBack(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{ Stringmethod =request.getMethod();request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");if(RequestMethodEnum.GET.getDesc().equals(method)){ //验证回调地址Stringsignature =request.getParameter("signature");Stringtimestamp =request.getParameter("timestamp");Stringnonce =request.getParameter("nonce");Stringechostr =request.getParameter("echostr");booleancheckSignature =WechatOffiAccountUtil.checkSignature(signature,timestamp,nonce,token);if(checkSignature){ log.info("签名验证成功");response.getWriter().write(echostr);}}else{ //接收回调xml;Documentdocument =XmlUtil.readXML(request.getReader());StringtoUserName =(String)XmlUtil.getByXPath("//xml/ToUserName",document,XPathConstants.STRING);StringfromUserName =(String)XmlUtil.getByXPath("//xml/FromUserName",document,XPathConstants.STRING);LongcreateTime =Long.valueOf((String)XmlUtil.getByXPath("//xml/CreateTime",document,XPathConstants.STRING));StringmsgType =(String)XmlUtil.getByXPath("//xml/MsgType",document,XPathConstants.STRING);log.info("FromUserName:{ }",fromUserName);log.info("CreateTime:{ }",createTime);log.info("MsgType:{ }",msgType);if(MsgTypeEnum.EVENT.getDesc().equals(msgType)){ //是否事件为关注/取消关注事件Stringevent =(String)XmlUtil.getByXPath("//xml/Event",document,XPathConstants.STRING);log.info("Event:{ }",event);if(EventEnum.SUBSCRIBE.getDesc().equals(event)){ //关注//新增用户Booleaninsert =updateUserSubscribe(fromUserName,1);if(insert){ log.info("新增关注用户成功");response.getWriter().write("success");}}else{ //取关//更新用户状态Booleanupdate =updateUserSubscribe(fromUserName,0);if(update){ log.info("更新关注用户状态成功");response.getWriter().write("success");}}}}}privateBooleanupdateUserSubscribe(StringfromUserName,Integersubscribe){ QueryWrapper<WechatUser>userQueryWrapper =newQueryWrapper<>();// 这里用了mybatis-plus方法,匹配用户的公众号public_openid,匹配上就查出来,否则就根据unionId重新匹配userQueryWrapper.eq("public_openid",fromUserName);WechatUseruser =this.getOne(userQueryWrapper);if(Objects.nonNull(user)){ user.setSubscribe(subscribe);this.updateById(user);returntrue;}else{ PublicUserInfopublicUserInfo =officialAccountFeign.getUserInfo(loginService.getOfficialAccessToken(),fromUserName).getBody();userQueryWrapper.clear();userQueryWrapper.eq("unionid",publicUserInfo.getUnionid());user =this.getOne(userQueryWrapper);if(Objects.nonNull(user)){ user.setPublicOpenid(fromUserName);this.updateById(user);returntrue;}}returnfalse;}
到这里就大功告成了,先注册小程序账号,然后在公众号上点击关注和取消关注操作,关注数据库显示的内容。
总结
很多功能看似很简单实现,但是如果在第三方平台上开发,需要遵从官方的要求,才能把整个环节实现。
参考博客:ruoyi的springboot微信小程序登录实现方式(我自己写的,感兴趣的可以去看一下)
Tags:
相关文章
索尼确认:PS5 Pro搭载FSRR 4超分辨率技术
Java微信小程序获取关联公众号用户是否已关注标识最近,在一次采访中,PlayStation 5首席架构师马克·塞尼透露,计划明年对PS5进行超分辨率技术——PSSRPerformance Scaling Super Resolution)进行升级。...
阅读更多
kafka集群使用可视化工具kafkatol连接docker,查看消息内容和offsetet
Java微信小程序获取关联公众号用户是否已关注标识1、下载kafkatool。Offsetet下载地址 Explorer,下载相应系统的offset explorer。 下载,傻瓜可以安装(建议放D盘...
阅读更多
预订订单超过1.5万台!五菱宏光MINI EV四门版将于明天上市
Java微信小程序获取关联公众号用户是否已关注标识据快科技2月21日报道,五菱红光MINIEV四门版将于2月22日正式上市,预订订单已超过1.5万份。该车型基于天舆架构-S平台,定位为纯电动微型车,采用四门四座布局。外观设计圆润,搭配双色车身,提供膨...
阅读更多