最近项目开发的时候涉及微信公众平台的开发,在这个学习过程中遇到了很多问题,了解清楚这部分,大概用了一个多星期,中间遇到很多问题,比较痛苦,网上的资料比较杂乱,导致查阅的时候遇到很多障碍,但是还是耐着性子完成了项目中涉及到的内容,在此记录并分享,为了以后回顾,也希望能够帮助到你。

微信公众平台

首先让我介绍一下微信公众平台,这里是微信公众平台的官方文档。
微信公众平台是腾讯基于微信公众号推出的相关业务,我们可以借助该平台更好的运营公众号内容,我参与的项目是微信H5页面项目,主要涉及获取微信公众平台的AccessToken;获取微信用户的基本信息。
在讲述这部分内容之前,让我们先看一下看似无关的内容。

java.net

因为之前的项目中,都是自己自足,最多调用第三方的sdk,从未涉及在项目中调用其他项目的接口,因此,刚开始在理解微信接口调用的时候就花了很多时间,这里简单讲解一下,尽量压缩这个时间。
首先看一下我的项目中的一个比较核心的代码块:

public String surfingTheInternet(String url,String method){String message = null;try {URL urlGet = new URL(url);HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();//请求方法http.setRequestMethod(method);http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");http.setDoOutput(true);http.setDoInput(true);http.connect();InputStream is = http.getInputStream();int size = is.available();byte[] jsonBytes = new byte[size];is.read(jsonBytes);message = new String(jsonBytes, "UTF-8");}catch (Exception e){e.printStackTrace();}return message;}

让我们看一下这个代码块实现的功能是什么。

首先,我们定义了一个URL类。

URL urlGet = new URL(url);

这个类是java.net包中的类,对于这个类的介绍,这里就不赘述了,可以直接查看API源码,也可以百度相关内容,这里只需知道,它代表着一种资源位置即可。
接下来,我们定义了另一个类

HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();

API文档中的介绍

A URLConnection with support for HTTP-specific features.
这是一个支持HTTP特定特点的URL连接。

当然还介绍了它的一些使用的注意事项等,这里不提;我们可以看到,这是一个连接。那么这就和网络传输有直接联系了,这里建议去看一下关于Request和Response的相关知识,这里的请求头和请求体,还有响应头及响应体是关键点。

接下来的内容

 //请求方法http.setRequestMethod(method);http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");http.setDoOutput(true);http.setDoInput(true);

我们相当于设置请求头部分的信息,首先设置了请求方法,然后设置了Content-Type,即传输格式;然后打开了输入输出。

紧接着

http.connect();

我们建立了HTTP的连接,这部分涉及网络连接的知识,建议去了解socket,对于这里的理解会有所帮助。

然后我们就可以从响应体中取到我们想要的内容了,鉴于这部分涉及的都是微信公众平台的接口,返回数据格式都是json。

InputStream is = http.getInputStream();int size = is.available();byte[] jsonBytes = new byte[size];is.read(jsonBytes);message = new String(jsonBytes, "UTF-8");

这里首先就是获得输入流,然后对输入流大小就行预估,之后读取输入流并进行String转化,最后获取到我们想要的json格式数据。

微信公众平台的对接及使用

首先在使用微信公众平台的时候,我们需要申请一个微信公众平台的账号,鉴于个人测试,所以选择对应的个人即可,但是相应的接口权限会很少,想要获取接口权限就需要花钱认证。不过腾讯考虑到我们开发者的测试用途,所以可以直接申请测试号进行测试开发,最后转移到有相应权限的公众号即可。
如下图所示就是获取测试号的整个流程
首先通过微信授权登陆个人注册的微信公众平台
然后进入到开发模块,选择开发者工具

接着在其中找到测试号

接下来,测试号也需要有相应的微信授权,通过授权后进入

这里就有我们想要的appID以及appsecret,这两个参数是很重要的,参与到后面的AccessToken获取。
之后在进行接口开发和调用前,我们首先需要和测试号这面对接。
这里的url就是http://ip:port/xxxx/**,一般我的习惯命名都是http://ip:port/wx,然后这个对接的接口怎么写呢?
让我们看一下下面的代码块

 /*** 和微信接入* */@RequestMapping(value = "/wx",method = RequestMethod.GET)public void get(HttpServletRequest request, HttpServletResponse response){// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。String signature = request.getParameter("signature");//时间戳String timestamp = request.getParameter("timestamp");//随机数String nonce = request.getParameter("nonce");//随机字符串String echostr = request.getParameter("echostr");PrintWriter out = null;try{out = response.getWriter();// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败if(SignUtil.checkSignature(signature,timestamp,nonce)){out.print(echostr);}}catch (IOException e){e.printStackTrace();}finally {out.close();out = null;}}

这里是按照官网文档内容设计的。逻辑是:我们通过该接口接受微信公众平台给我们发送的数据,然后通过相应的工具类把各个内容拆解验证,最后返回给微信公众平台echostr字段,如果验证成功,那么对接就此成功。

接下来我们看一下使用的工具类

package util;import constant.WeChatConstant;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Timer;/*** Created by yubotao on 2017/11/15.*/
public class SignUtil {/***验证签名* @param signature* @param timestamp* @param nonce*/public static boolean checkSignature(String signature,String timestamp,String nonce){//第一个参数是tokenString[] arr = new String[]{WeChatConstant.token,timestamp,nonce};//将token、timestamp、nonce三个参数进行字典排序Arrays.sort(arr);StringBuilder content = new StringBuilder();for(int i =0; i < arr.length; i++){content.append(arr[i]);}MessageDigest md = null;String tmpStr = null;try{md = MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[] digest = md.digest(content.toString().getBytes());tmpStr = byteToStr(digest);}catch (NoSuchAlgorithmException e){e.printStackTrace();}content = null;// 将sha1加密后的字符串可与signature对比return tmpStr != null ? tmpStr.equals(signature.toUpperCase()):false;}/*** 将字节数组转换为十六进制字符串* @param byteArray* @return*/private static String byteToStr(byte[] byteArray){String strDigest = "";for(int i = 0; i < byteArray.length; i++){strDigest += byteToHexStr(byteArray[i]);}return strDigest;}/*** 将字节转换为十六进制字符串* @param mByte* @return*/private static String byteToHexStr(byte mByte){char[] Digit = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}}

这个工具类的主要作用就是:将WeChatConstant.tokentimestampnonce三个参数进行SHA-1加密,然后和一同传输过来的signature对比,成功后返回true,否则返回false。
下面两个方法只是对于16进制的转换和处理。

当对接成功后,会有相应的提示。

接下来,我们就可以开发相应的接口来实现获取AccessToken了。

获取AccessToken

先看我的代码是如何获取AccessToken的

@AutowiredGetSomethingUtil token;/***获取2小时的AccessToken*/@RequestMapping(value = "/a/wx/accessToken",method = RequestMethod.GET)public String getAccessToken(HttpServletRequest request, HttpServletResponse response, Model model){List<String> tokenList = token.getAccessToken();log.info("tokenList : " + tokenList);String accessToken = tokenList.get(0);String expiresIn = tokenList.get(1);model.addAttribute("accessToken",accessToken);model.addAttribute("expiresIn",expiresIn);return "tokenTest";}

这里进行了工具类的封装,然后再看一下工具类。

public List<String> getAccessToken(){String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + WeChatConstant.AppID + "&secret=" + WeChatConstant.AppSecret;String accessToken = null;String expriesIn = null;List<String> another = new ArrayList<String>();String message = this.surfingTheInternet(url,"GET");Gson gson = new Gson();AccessToken token = gson.fromJson(message, AccessToken.class);accessToken = token.getAccess_token();expriesIn = token.getExpires_in();log.info("accessToken : " + accessToken);log.info("expiresIn : " + expriesIn);another.add(accessToken);another.add(expriesIn);return another;}

这里的工具类方法,完成了对微信接口的请求,并对返回的json格式数据进行了处理,最后返回给Controller接口,并展示到相应的jsp页面。

该接口运行效果图:

通过AccessToken及OpenId获取用户信息

首先正常的流程是,每当一个用户进入对应的微信H5界面,会通过前端配置返回一个code值,而后端通过该code值及相应的接口信息获取openId,之后在通过对应的信息获取到用户的基本信息。
但是由于本人能力有限且时间紧迫,js配置获取code的部分我就没有实现了,感兴趣的小伙子可以去微信公众平台官方文档查阅相关内容。

那么是不是就没办法做了呢?
当然不是,这里我使用了一种取巧的方式,来验证如何使用AccessToken和openId获取用户的基本信息。

首先我们查阅官方文档可以发现有一个可以获取关注该微信公众号的所有用户OpenId的接口,那么我们就可以通过这个获取OpenId并且验证用户信息是否能正确取到。
相应的接口方法

/***通过AccessToken获取关注的用户的openId列表*  @param accessToken*/@RequestMapping(value = "/a/wx/openId",method = RequestMethod.GET)public String getOpenId(HttpServletRequest request,HttpServletResponse response,Model model,String accessToken){List<String> data = token.getOpenIdList(accessToken);log.info("data : " + data);model.addAttribute("data",data);return "openIdTest";}
 public List<String> getOpenIdList(String accessToken){String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + accessToken + "&next_openid=";String message = this.surfingTheInternet(url,"GET");log.info("message : " + message);Gson gson = new Gson();OpenId openId = gson.fromJson(message, OpenId.class);String total = openId.getTotal();log.info("total : " + total);String count = openId.getCount();log.info("count : " + count);List<String> data = openId.getData().getOpenid();log.info("data : " + data);String next_openid = openId.getNext_openid();log.info("next_openid : " + next_openid);return data;}

这里和前面获取AccessToken的处理雷同,不在赘述。
之后获取到的OpenId效果图如下

这里取到OpenId后,我们就可以验证是否可以取到用户的基本信息了。

相关接口方法

 /***通过AccessToken和openId获取用户的基本信息* @param accessToken* @param openId*/@RequestMapping(value = "/a/wx/person",method = RequestMethod.GET)public String getPerson(HttpServletRequest request,HttpServletResponse response,Model model,String accessToken,String openId){String message = token.getPersonByOpenId(accessToken,openId);log.info("message : " + message);Gson gson = new Gson();Person person = gson.fromJson(message, Person.class);String subscribe = person.getSubscribe();String openid = person.getOpenid();String nickname = person.getNickname();String sex = person.getSex();String language = person.getLanguage();String city = person.getCity();String province = person.getProvince();String country = person.getCountry();String headimgurl = person.getHeadimgurl();String subscribe_time = person.getSubscribe_time();String unionid = person.getUnionid();String remark = person.getRemark();String groupid = person.getGroupid();List<String> tagid_list = person.getTagid_list();model.addAttribute("subscribe",subscribe);model.addAttribute("openid",openid);model.addAttribute("nickname",nickname);model.addAttribute("sex",sex);model.addAttribute("language",language);model.addAttribute("city",city);model.addAttribute("province",province);model.addAttribute("country",country);model.addAttribute("headimgurl",headimgurl);model.addAttribute("subscribe_time",subscribe_time);model.addAttribute("unionid",unionid);model.addAttribute("remark",remark);model.addAttribute("groupid",groupid);model.addAttribute("tagid_list",tagid_list);return "personTest";}
public String getPersonByOpenId(String accessToken,String openId){String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId+ "&lang=zh_CN";String message = this.surfingTheInternet(url,"GET");log.info("message : " + message);return message;}

然后获得的效果图如下

可以看到我们已经取到我的基本信息了,到此为止,我们就完成了获取用户基本信息的操作。

项目中还涉及到使用mediaId获取图片并实现图片从微信公众平台暂存转储到其他对象存储里,不过这里涉及到文件上传,第三方工具类调用等等内容,这里就不介绍了,这部分也是可以直接查看官方文档找到答案的。

至此,本文的所有内容就介绍完毕了,并没有涉及到消息自动回复以及菜单设计,这些内容再官方文档上都有答案,不过要注意的是XML包解析。

这里还要提的一点就是,AccessToken的有效时间只有2小时,所以需要定时刷新,并且官方推荐的方法就是创建一个中控来定时刷新,最关键的是获取AccessToken的接口每天有2000次的请求限制,所以定时刷新是必要的,不过这里暂不介绍,下一篇文章就是讲解定时任务。

如果本文有什么遗漏或者错误,还请不吝赐教。

GitHub项目地址

微信公众平台开发的部分知识相关推荐

  1. 第一篇:微信公众平台开发实战Java版之了解微信公众平台基础知识以及资料准备...

    相信很多人或多或少听说了微信公众平台的火热.但是开发还是有一点门槛,鉴于挺多朋友问我怎么开发,问多了,自己平时也进行以下总结. 所以下面给大家分享一下我的经验: 第一部分   介绍微信公众号的一些简单 ...

  2. 微信公众平台开发书籍推荐

    关键字:微信开发图书 微信公众平台开发书籍 微信图书 微信开发书籍 微信图书推荐 微信开发图书推荐 本文介绍了当前图书市场上最主要的微信公众平台开发类书籍,并对每本书的特色做了简要点评,供有需要购买的 ...

  3. [050] 微信公众平台开发入门视频教程已公布

    2014年4月26日晚8点.我在CSDN社区在线培训课堂解说了微信公众平台开发入门的相关知识.受到广大网友的一致好评.在此非常感谢大家的支持.课程结束后,非常多网友表示因为报名人数限制.暂时有事等原因 ...

  4. 微信公众平台开发新手教程(图文具体解释)

    因为微信的大热.为了更好的方便使用微信的用户查询一些信息.这篇文章是入门级的微信公众平台开发教程,须要的朋友能够參考下 在这篇新手教程中,我们假定你已经有了PHP语言程序.MySQL数据库.计算机网络 ...

  5. 微信公众平台开发入门教程[2019版]

    关键字:微信公众平台开发 作者:方倍工作室 在这篇微信公众平台开发教程中,我们假定你已经有了PHP语言程序.MySQL数据库.计算机网络通讯.及HTTP/XML/CSS/JS等基础. 我们将使用微信公 ...

  6. php 自定义菜单 openid,微信公众平台开发(99) 自定义菜单获取OpenID

    关键字 微信公众平台 自定义菜单 OpenID 作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/p/weixin-menu-get-openid.html 在这篇 ...

  7. 微信公众平台开发问答 【转发】

    微信公众平台开发问答 微信公众平台开发问答是一个微信知识问答区,专注于提供微信应用及开发技术知识的整理.归类和检索. 主题:新手常见问题 问:我是新手,没有开发基础,应该如何学习微信公众平台的开发? ...

  8. 第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    我们来了解一下 自定义菜单创建接口: http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_to ...

  9. 微信公众平台开发模式背后的原理?

    微信公众平台开发模式背后的原理? 想利用微信提供的网络通道实现自己的业务要求,想了解其背后的技术原理.给出建议或信息来源都好. 添加评论分享 查看全部 2 个回答 吴星,你好,很喜欢这个能学到许多知识 ...

最新文章

  1. jQuery Pagination分页插件--无刷新
  2. 动态查看JVM内存的工具
  3. zigbee cc2530 adc转换
  4. 10、mysql数据表中数据的查询(2)
  5. Reactjs 踏坑指南1: 一些概念
  6. SSM 整合开发初见面
  7. WPF中的图像处理简介
  8. oracle中日期相减及显示几天几小时几分钟
  9. C语言字符串操作总结大全(超详细)
  10. 【一步一步】Spring 源码环境搭建
  11. SQL Server 2012 自动增长列,值跳跃问题
  12. 与Maggy统一单主机和分布式机器学习
  13. 简单解决网课或教育平台在线学习视频鼠标检测问题
  14. extern小结(转)
  15. 字幕时间轴制作(2)
  16. Rail-5k:一个用于轨道表面缺陷检测的真实数据集
  17. 从零开始实现balloon操作系统(0x02) 加载setup模块
  18. 用Python解决x的n次方
  19. 论文中看到的光线投影法(ray casting)是什么?
  20. 利用qrcode组件实现图片转二维码

热门文章

  1. Windows 7删除休眠文件
  2. markdown拓展语法
  3. 电能表中的四象限解释
  4. 大数据技术对于市场营销的作用
  5. mac地址和ip地址、子网掩码和默认网关
  6. 算法复杂度的表示法_用简单的英语算法:时间复杂度和Big-O表示法
  7. 给你 2 万条数据,怎么快速导入到 MySQL?写得太好了...
  8. 《裸婚时代》迅雷快车全集下载【30集全】普清
  9. 【leetcode/力扣】176.第二高的薪水
  10. 【Java】正则表达式的使用以及解析XML