微信公众号开发,开发什么?怎么做?

2024-05-12
来源:网络整理

目录

确实令人困惑且难以理解。 太混乱了。

以下是这几天微信公众号相关工作的总结。 并不全面,只是一个初学者的记录,仅供参考。

1.微信公众号开发,开发什么?

公众号与小程序不同。 小程序类似于手机APP,是独立开发的。 微信只提供一个入口; 而公众号则基本在微信框架内。 微信公众号本质上是用户的一个联系人,但也只是一个特殊的联系人。 通过微信提供的公众号管理后台,您可以快速建立一个像样的公众号,无需任何编程,完整的菜单、机器人客服和文章更新。

然而,如果你想要更强的功能,你就需要开发它。 例如机器人客服。 通过公众号管理后台,可以定义一些自动回复语句,但毕竟不够智能。 这时候我们就可以在互联网上搭建一个服务器来提供相应的服务。 当然,这需要准备网站地址和域名。

第二,菜单。 点击公众号的菜单项后,您可以回复一些消息、跳转到小程序或打开网页。 打开网页时,如果是未经认证的公众号,则只能打开该公众号中的素材,或者当前公众号中已发表的文章、图片、视频等; 对于认证公众账号,可以直接任意网址打开。 这些网页通常是部署在互联网上的所谓微信网页。 他们使用微信JS-SDK,上面有各种微信元素,比如扫一扫、分享朋友圈等等。 当然,这部分还需要开发。

还可以选择向关注者发送消息。 我认为这是微信公众号最大的卖点。 例如,如果我关注某个公众号,并通过该公众号的菜单打开相关小程序进行操作,如果事情有进展,系统可以通过该公众号向我发送消息,提醒我当前的进度的工作。 我认为这是公众号开发中最值得做的工作。

当然,你也可以使用程序自动在公众号上发布文章。 不过这种事情也可以在公众号管理后台手动完成,用手去做就行了。

2. 发展铺路

开发之前首先要了解相关规定。建议同时阅读开发文档开头:微信公众平台开发概述

1、公众账户分类

三种颜色的衣服和五个等级的食物。 所谓微信公众号分为订阅号和服务号。 个人只能申请订阅号,企业可以申请订阅号和服务号。 那么公众号又分为认证的和非认证的。 公众号的类型以及是否认证决定了是否可以调用很多微信服务。 没有认证的话,基本上没什么可玩的。 而遗憾的是,个人申请的订阅号根本无法通过微信认证,直接堵住了这扇门。

如何开发它? 微信在提供测试账号机制方面也很贴心。 我们可以不申请公众号,而是先申请一个测试账号,用这个账号来测试微信服务接口。 测试号所有微信服务接口均可访问。 然鹅! 像微信这样的网页需要在手机上运行才能看到效果,而且如果使用测试账号,有些东西是无法渲染的。 比如所谓的微信开放标签(微信自己定义的标签,类似于HTML)。

订阅帐户和服务帐户有不同的侧重点。 据我了解,订阅号专注于发布文章,而服务号则专注于发送有针对性的通知消息。 一般来说,服务帐户比订阅帐户强大得多。

从表面上看,订阅帐户每天可以发送一条消息,而服务帐户每月只能发送四条消息。 订阅账号一定要实力雄厚。 那么问题来了,群发消息有什么用呢? 当我们在线提供服务时,我们需要个人信息。 只有服务帐户才能发送此定向通知消息。

在文档中,这种消息称为模板消息。 为什么叫模板消息呢? 这是因为这种消息需要结合模板来生成。 就像我们的手机短信一样。 做过手机短信开发的人都知道,手机短信是不能随便发的。 由于众所周知的原因,为了避免出现非法或不适当的内容,需要一个所谓的模板,即短信格式是固定的,很多单词也是固定的,我们只需要每次填写一些内容即可。我们发送它的时间。 该模板必须提前创建并获得电信运营商的批准。 微信消息也使用模板。 调用发送接口时,需要将模板ID作为参数传递。

目前小程序的模板消息功能已经被放弃,改用所谓的“统一服务消息”,实际上就是使用服务账号进行发送。 也就是说,小程序想要给用户发送通知,就必须对应一个服务号。

但世界上还有一种东西叫订阅消息。 在公众号中称为订阅通知,在小程序中称为订阅消息。 分为一次性和长期两种。 订阅消息需要用户主动订阅。 例如,如果您使用麦当劳小程序点餐,则每次付款后,它都会询问您是否接受取餐通知。 长期只对某些与民生、医院相关的公众账号开放。 这是在申请公众账号时给出的。 不要心存侥幸,低估微信折磨人的能力。 否则,发送时对方永远不会收到,也可能不会出现错误信息; 即使有,也可能很专业,不可能认为是账户类型的问题。

模板消息和订阅消息有什么区别? 订阅消息只需要用户手动订阅即可。 问题是,这必须用手机来完成。 如果我通过 PC 工作并希望在手机上接收提醒该怎么办? 只需订阅新闻即可。 (这是真的吗?微信PC端也可以进行订阅操作吗?)

2.公众号调试工具

它是微信开发者工具。 请注意,这些是开发人员工具,而不是开发工具。 这个工具确实是一个小程序的开发工具; 但对于公众号来说,它只是一个调试工具,不能通过它敲出任何代码; 并且只是微信网页的调试工具。 此时它只是一个微信浏览器。 方法是在微信开发者工具顶部输入微信网页地址进行浏览调试,类似于普通浏览器上按F12。

3.查看微信网页操作结果

公众号可以通过微信客户端查看。 这里所说的查看结果是指查看微信网页的运行结果。 虽然有“网页”两个字,但这并不是一个普通的网页。 如果用一般的浏览器访问,虽然不会报错,但是看不到任何效果。 需要通过微信浏览器或者微信开发者工具运行。 请注意,手机上没有名为微信浏览器的应用程序,该应用程序是微信中隐含的。 怎么召唤它? 您可以将微信网页地址发送给微信好友,例如“文件传输助手”,然后点击聊天记录中的网址,就会用微信浏览器打开。 最糟糕的是微信浏览器和QQ浏览器都不能用。

4. 开发文档

对于基于微信的二次开发,网上查资料基本没什么用。 最好老老实实阅读微信官方开发文档。

公众号开发文档在公众号管理后台-设置与开发-开发者工具-开发文档中打开。

微信有两个平台,小程序叫“微信开发开放平台”,公众号叫“微信开发公众平台”。

5. 一些术语

1) 管理员和操作员

在开发过程中,不可避免地要访问微信公众号管理后台,对某些设置进行修改或设置。 但要更改设置,您必须扫描二维码进行身份验证。 这很尴尬。 申请公众号的人是管理员,但不一定参与开发。 每次扫描二维码都会不方便甚至不可能提醒大老板。 您可以将开发人员添加到运营商列表中,然后自己扫描代码即可。 运营商有两种类型:长期运营商和短期运营商。 只有长期经营者才应该有足够的权力。

可以在微信公众号管理后台-设置与开发-人员设置中设置。

2)IP白名单

在开发过程中,我们需要访问微信服务器,比如获取。 发出请求的IP需要在白名单中。 这个IP是指互联网IP。 如果我们在公司内部开发的话,那么这个IP就是公司的互联网IP。 问题是,这个IP经常变化。 我不知道有什么好的办法,所以我基本上每天都换白名单。

IP白名单用于我们在本地调试微信开发者工具。 手机操作不需要。

3)开发者微信账号

公众号管理后台-设置与开发-Web开发者工具,添加我们开发者的微信号。 这是用来开发微信网页的。 因为微信开发者工具需要微信ID登录。

4)JS接口安全域名

公众号管理后台-设置与开发-公众号设置-功能设置。

微信网页开发也需要它。 我们的页面需要放到这个域名中,这样才能使用微信的js-sdk。

填写这个域名的时候,需要下载一个txt文件,放到域名下面。 微信会验证域名的真实性才可以保存。 不过填写完之后,我们在本地开发的时候,可以修改host文件,将本地IP映射到域名上。 毕竟是前端的东西。 js-sdk本身需要微信浏览器支持。 它无法确定请求来自哪个IP。 它会相信我们发送给它的任何内容。

5)微信开放标签

类HTML、微信特有的tags.like

跳转小程序: 跳转App: 服务号订阅通知: 音频播放:

3.微信网页开发

1 概述

微信网页实际上只是网页,但它们引用了微信提供的JS库,并且可能使用微信特有的所谓类似于HTML的开放标签。 而这个微信网页似乎可以在普通浏览器上运行。 虽然不会报错,但是好像也没有什么效果。 只能运行在微信浏览器或者微信开发者工具上。

以下是微信网页(boot下,组合)

        

扫一扫
        
                                                                           

2. 验证

微信网页运行时,必须先经过微信验证,才能正常使用微信各项功能。 验证过程是,

1)通过访问微信服务器获取

2)通过访问微信服务器获取

3)使用,随机字符串、时间戳、当前页面地址依次组成一个字符串,然后对该字符串进行sha哈希操作,得到摘要

4)使用摘要访问微信服务器获取签名

5)注册本页面需要使用的时间戳、随机字符串、签名、微信功能、微信向微信开放标签

在上面的例子中,

    wx.config({         debug: true,         appId: /*[[${wc.appId}]]*/'',         timestamp: /*[[${wc.timestamp}]]*/'',//注意是秒,不是毫秒         nonceStr: /*[[${wc.nonceStr}]]*/'',//随机串         signature: /*[[${wc.signature}]]*/'',//关键所在         jsApiList: ['chooseImage','scanQRCode','updateAppMessageShareData','updateTimelineShareData'],//需要使用的微信js-sdk函数列表         openTagList: ['wx-open-subscribe']//开放标签列表     });

获取这个json对象并不容易。 可以在微信公众号管理后台获取,每个公众号都有唯一的; 时间戳也很容易获得; 随机字符串自己确定,比较容易; 最麻烦的就是这个签名。 我调试了快一天了,总的来说,就是非法签名的意思。

获取这个json对象的java代码:

import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import javax.annotation.PostConstruct; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.Random; import java.util.concurrent.locks.ReentrantLock; @Service public class WxServiceImpl implements WxService {     @Override     public WxConfig getWxConfig(String url) {//url是微信网页地址         WxConfig wc = new WxConfig();//这个是自定义的对象,不必深究         wc.setAppId(APPID);         wc.setNonceStr(getNonceStr());//随机串         wc.setTimestamp((long) (new Date()).getTime() / 1000);//时间戳         wc.setSignature(getSignature(wc.getNonceStr(), wc.getTimestamp(), url));//签名         return wc;     }     @PostConstruct     void init() {         /*             由于从微信服务器获取token和ticket的函数有调用次数限制(每天<=2000),因此用redis将它们缓存起来         */         this.jedis = new Jedis(redis的IP, redis端口号);     }     private String getSignature(String nonceStr, long timestamp, String url) {//获取签名         String signature = null;         String ticket = getTicket();         if (ticket != null) {             String string1 = String.format("jsapi_ticket=%s&noncestr=%s×tamp=%d&url=%s",                     ticket,                     nonceStr,                     timestamp,                     url);             signature = getSha1(string1);         }         return signature;     }     //redis对象     private Jedis jedis;     //除了redis缓存,也用静态变量保存一份。不过,应用程序重启它们就消失了,并且不会自动过期     //而从微信获取到的token和ticket有效期是7200秒     private String _ticket = null;     private String _token = null;     //锁。为避免并发,使用锁机制,不要大家都去获取token和ticket     private ReentrantLock lockTok = new ReentrantLock();     private ReentrantLock lockTik = new ReentrantLock();     private String getTicket() {         String ticket = null;         String key = "ticket";         ticket = getKey(key, this._ticket);         if (ticket == null) {             //锁定。             lockTik.lock();             ticket = getKey(key, this._ticket);//再努力一把             if (ticket == null) {                 String token = getToken();                 if (token != null) {                     ticket = callGet(String.format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi",                             token), "ticket");                     if (ticket != null) {                         this._ticket = ticket;                         setKey(key, ticket);                     }                 }             }             //解锁             lockTik.unlock();         }         return ticket;     }     private String getToken() {         String token = null;         String key = "token";         token = getKey(key, this._token);         if (token == null) {             lockTok.lock();             token = getKey(key, this._token);             if (token == null) {                 token = callGet(String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",APPID,AppSecret),                  "access_token");                 if (token != null) {                     this._token = token;                     setKey(key, token);                 }             }             lockTok.unlock();         }         return token;     }     final static int EXPIRTED = 7200;     private String getKey(String key, String v) {         String value = null;         try {             value = jedis.get(key);         } catch (Exception ex) {             value = v;//如果无法从redis中读取则将候补变量值返回。但变量值可能有过期的问题             System.err.println(ex.getMessage());         }         return value;     }     private void setKey(String key, String value) {         try {             jedis.set(key, value);             jedis.expire(key, EXPIRTED);         } catch (Exception ex) {             System.err.println(ex.getMessage());         }     }     final static int NONCESTR = 16;//随机串的长度为16。这个数值是自己定的     private String getNonceStr() {// 生成随机字符串noncestr         String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";         StringBuffer noncestr = new StringBuffer();         int limit = chars.length() - 1;         for (int i = 0; i < NONCESTR; i++) {             Random r = new Random();             int j = r.nextInt(limit);             noncestr.append(chars.substring(j, j + 1));         }         return noncestr.toString();     }     private static String getSha1(String string1) {         MessageDigest sha = null; // 此处的sha代表sha1         try {             sha = MessageDigest.getInstance("SHA");         } catch (NoSuchAlgorithmException e) {             e.printStackTrace();         }         byte[] md5Bytes = new byte[0];         try {             md5Bytes = sha.digest(string1.getBytes("UTF-8"));         } catch (UnsupportedEncodingException e) {             e.printStackTrace();         }         StringBuffer hexValue = new StringBuffer();         for (int i = 0; i < md5Bytes.length; i++) {             int val = ((int) md5Bytes[i]) & 0xff;             if (val < 16) {                 hexValue.append("0");             }             hexValue.append(Integer.toHexString(val));         }         return hexValue.toString();     }     public static String callGet(String api, String key) {//get的方式访问微信api         String re = null;         System.out.println(String.format("正在获取 %s : %s", key, api));         try {             URL url = new URL(api);             HttpURLConnection connection = (HttpURLConnection) url.openConnection();             connection.connect();             BufferedReader br = new BufferedReader(                     new InputStreamReader(connection.getInputStream(), "UTF-8"));             String line;             StringBuilder sb = new StringBuilder();             while ((line = br.readLine()) != null) {                 sb.append(line);             }             br.close();             connection.disconnect();             JSONObject json = JSON.parseObject(sb.toString());             if (json.containsKey(key)) {                 re = json.getString(key);             }             System.out.println(re);         } catch (Exception ex) {             ex.printStackTrace();             System.out.println(String.format("访问接口%s失败", api));         }         return re;     } }

3、调试

在微信开发者工具上,输入微信网页地址,运行,得到很多提示。 对于微信公众号来说,微信开发者工具是一个调试工具,是一个开启了调试模式的浏览器。 但刚开始的时候,我总是失败。 现在,我在例子中说明需要使用以下微信功能:

    wx.config({         debug: true,         appId: /*[[${wc.appId}]]*/'',         timestamp: /*[[${wc.timestamp}]]*/'',//注意是秒,不是毫秒         nonceStr: /*[[${wc.nonceStr}]]*/'',//随机串         signature: /*[[${wc.signature}]]*/'',//关键所在         jsApiList: ['chooseImage','scanQRCode','updateAppMessageShareData','updateTimelineShareData'],//需要使用的微信js-sdk函数列表         openTagList: ['wx-open-subscribe']//开放标签列表     });

从返回的信息来看,我能访问到的函数为0。此外,到处都是“失败,是”之类的提示。

打开微信开发者工具的调试模式:在微信开发者工具中,进入顶部菜单“微信开发者工具”-“调试”-“调试微信开发者工具”-,看这个?_r=...的返回信息,结果是 {:, : " "}!

是不是签名算法有问题? 我在微信公众号管理后台使用了他们提供的微信JS接口签名验证工具,结果完全一致,不存在算法错误。

后来发现是网址问题。 在生成签名的过程中,需要传入当前微信网页的URL构造一个字符串,然后对其进行哈希处理后传递给微信服务器获取签名。 那么问题来了,这个URL怎么写呢? 由于我的微信页面命名为.html,平时访问的时候,习惯在浏览器中输入这样的地址:,所以我也用这个地址来构造签名,结果就是一直提示签名无效。 后来我写了完整的地址:,一下子就OK了​​。

但是官方的开发文档是怎么说的呢?

不仔细复习这个话题就会害死人。

分享