微信公众账号开发简单实例【java】
来源:互联网 发布:李升平知乎 编辑:程序博客网 时间:2024/05/29 10:43
进入公众账号的后台https://mp.weixin.qq.com/,
微信公众平台的通讯机制
开发流程
从上图中可以看到,高级功能包含两种模式:编辑模式和开发模式,并且这两种模式是互斥关系,即两种模式不能同时开启。那两种模式有什么区别呢?作为开发人员到底要开启哪一种呢?
编辑模式:主要针对非编程人员及信息发布类公众帐号使用。开启该模式后,可以方便地通过界面配置“自定义菜单”和“自动回复的消息”。
开发模式:主要针对具备开发能力的人使用。开启该模式后,能够使用微信公众平台开放的接口,通过编程方式实现自定义菜单的创建、用户消息的接收/处理/响应。这种模式更加灵活,建议有开发能力的公司或个人都采用该模式。
在这里就只介绍开发模式了, 编辑没有就不用讲了,都是动手操作的事情太简单了。 嘿嘿。
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,否则接入失败。
signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
加密/校验流程:1. 将token、timestamp、nonce三个参数进行字典序排序2. 将三个参数字符串拼接成一个字符串进行sha1加密3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
备注 :URL必须是公网地址
后台代码
-
-
-
-
-
-
- @Controller
- @RequestMapping("/")
- public class WeiXinControllerTest {
- private static Logger log = LogManager.getLogger(WeiXinControllerTest.class);
- @Resource
- private ServiceConfig serviceConfig;
- @Resource
- private IWeiXinTextService weiXinTextService;
-
- @ResponseBody
- @RequestMapping(method = RequestMethod.GET)
- public String get(ModelMap model, String signature, String timestamp, String nonce, String echostr) {
- boolean bChecked = check(signature, timestamp, nonce);
- if (bChecked) {
- return echostr;
- }
- return "hello";
- }
- @RequestMapping(method = RequestMethod.POST)
- public void post(String signature, String timestamp, String nonce, HttpServletRequest request, HttpServletResponse response) {
- boolean bChecked = check(signature, timestamp, nonce);
- if (bChecked) {
- response.setCharacterEncoding("UTF-8");
- PrintWriter out = null;
- Document doc;
- SAXReader reader = new SAXReader();
- InputStream in = null;
- try {
- out = response.getWriter();
- in = request.getInputStream();
- doc = reader.read(in);
- Element root = doc.getRootElement();
-
- checkMsgType(out, root,response);
- } catch (Exception e) {
- log.debug(e.getMessage());
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- log.debug(e.getMessage());
- }
- }
- if (out != null) {
- out.flush();
- out.close();
- }
- }
- }
-
- }
-
-
-
-
-
-
-
-
-
- private boolean check(String signature, String timestamp, String nonce) {
- List<String> strList = new ArrayList<String>();
- strList.add(serviceConfig.getToken());
- strList.add(timestamp);
- strList.add(nonce);
- Collections.sort(strList);
- String str = "";
- for (String s : strList) {
- str += s;
- }
- String strSha = DigestUtils.shaHex(str);
- return strSha.equals(signature);
- }
- }
微信向公众号发送一个地理位置,然后公众号读取坐标 ,查询这个坐标附近的数据。
当用户向公众号发送请求, 微信服务器再向公众号发送的是XML的数据, 所以不了解解析XML,封装XML的童鞋可以先去补一下这方面的知识。
后台代码
//把抽象的东西抽取成java对象
-
-
-
-
-
- public enum MsgType {
- text("文本"),image("图片"),location("地理位置"),link("连接"),event("事件"),news("图文信息") ;
- private String value;
-
- public String getValue() {
- return value;
- }
-
- private MsgType(String value) {
- this.value = value;
- }
- }
封装图文消息类,在这里笔者是用xml提供的标签来创建xml- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlRootElement;
-
-
-
-
-
-
-
- @XmlRootElement(name="item")
- public class Item {
- private String title;
- private String description;
- private String picUrl;
- private String url;
-
- public Item() {
- }
-
- public Item(String title, String description, String picUrl, String url) {
- this.title = title;
- this.description = description;
- this.picUrl = picUrl;
- this.url = url;
- }
- @XmlElement(name = "Title")
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
- @XmlElement(name = "Description")
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
- @XmlElement(name = "PicUrl")
- public String getPicUrl() {
- return picUrl;
- }
-
- public void setPicUrl(String picUrl) {
- this.picUrl = picUrl;
- }
- @XmlElement(name = "Url")
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
- }
//查询坐标附近的数据
-
-
-
-
-
-
- private void checkMsgType(PrintWriter out, Element root) {
- try {
- String value = root.element("MsgType").getTextTrim();
-
- if (MsgType.location.toString().equals(value)) {
- findNearCommunity(out, root);
- }
-
-
- } catch (Exception e) {
- log.debug(e.getMessage());
- }
- }
-
-
-
-
-
-
- private void findNearCommunity(PrintWriter out, Element root) throws Exception {
- NearCoordinate nearCoordinate = param(root);
- Integer count ="..." ;
- List<Object> list = "...";
- out.println(WeiXinXmlFactory.getImgNewsXml(list, root, count));
- }
- <span style="font-size: 14px;">
-
-
-
-
-
-
- public static String getImgNewsXml(List<CommunityDto> list,Element root,Integer count) {
- try {
- String toUserName = root.element("ToUserName").getTextTrim();
- String fromUserName = root.element("FromUserName").getTextTrim();
- Marshaller m = getMarshaller(new WeiXinImg());
- ArrayList<Item> items = new ArrayList<Item>();
- Articles articles = new Articles();
- Item item ;
- int next=0;
- for (CommunityDto communityDto:list){
-
- items.add(item);
- next++;
- }
-
- if(WeiXinConfig.COMMUNITY_LIST_SIZE<count){
-
- items.add(item);
- }
- articles.setArrayList(items);
- WeiXinImg weiXinImg = new WeiXinImg(fromUserName,toUserName,System.currentTimeMillis(), MsgType.news,<span style="font-family: Arial, Helvetica, sans-serif;">count</span><span style="font-family: Arial, Helvetica, sans-serif;">,articles);</span>
- StringWriter fw = new StringWriter();
- m.marshal(weiXinImg, fw);
- return fw.toString();
- }catch (Exception e){
- log.debug(e.getMessage());
- }
- return null;
-
-
- }
//创建一个< tt >Marshaller< / tt >对象,可以用来转换成一个Java内容树转换成XML数据。
- private static Marshaller getMarshaller(Object o)throws Exception{
- JAXBContext context = JAXBContext.newInstance(o.getClass());
-
- Marshaller m = context.createMarshaller();
-
- m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
-
- m.setProperty(Marshaller.JAXB_FRAGMENT, true);
- return m;
- }
-
-
-
-
-
-
-
- public static String getImgNewsXml(List<CommunityDto> list,Element root,Integer count) {
- try {
- String toUserName = root.element("ToUserName").getTextTrim();
- String fromUserName = root.element("FromUserName").getTextTrim();
- Marshaller m = getMarshaller(new WeiXinImg());
- ArrayList<Item> items = new ArrayList<Item>();
- Articles articles = new Articles();
- Item item ;
- int next=0;
- for (CommunityDto communityDto:list){
-
- items.add(item);
- next++;
- }
-
- if(WeiXinConfig.COMMUNITY_LIST_SIZE<count){
- item = new Item("更多","",WeiXinConfig.FUNI_LOGO,UrlGenerator.getWapCommunityList(WeiXinConfig.CITY));
- items.add(item);
- }
- articles.setArrayList(items);
- int articleCount = itemCount(list.size(),WeiXinConfig.COMMUNITY_LIST_SIZE<count);
- WeiXinImg weiXinImg = new WeiXinImg(fromUserName,toUserName,System.currentTimeMillis(), MsgType.news,articleCount,articles);
- StringWriter fw = new StringWriter();
- m.marshal(weiXinImg, fw);
- return fw.toString();
- }catch (Exception e){
- log.debug(e.getMessage());
- }
- return null;
-
- }
//运行的结果