微信公众号开发—入门系列(二)

时间:2022-08-31 22:33:20

上一章简单的介绍一下微信公众号的编辑模式,接下来本章主要介绍微信公众号开发的原理和开发前的环境搭建

一、基本原理

微信公众号开发—入门系列(二)

由上图可知:微信服务器就相当于一个转发服务器,终端(手机、Pad等)发起请求至微信服务器,微信服务器,然后将请求转发给自定义服务(我们自己的服务器,可以处理相关业务逻辑)。服务处理完毕,然后挥发给微信服务器,微信服务器再将具体响应回复到终端。
通信协议为:HTTP

数据格式为:XML

总结:在开发过程中我们要做的就是对HTTP请求,进行处理,做出响应。具体的请求内容,我们按照特定的XML格式去解析,处理完毕后,也要按照特定的XML格式返回。

微信公众平台开发文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432

二、环境搭建

1、 注册微信公众号账号用于开发

进入微信公众平台https://mp.weixin.qq.com ,点击右上角立即注册,选择“服务号”或“订阅号”注册(服务号仅限机构用户注册,个人用户只能选择订阅号)注册时需填写一系列信息,根据提示填写即可。如果暂时不想注册账号,或者无法注册服务号,可选择官方提供的测试账号申请。申请地址:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login点击后扫描二维码,即可获得一个测试账号,拥有服务号全部权限。测试账号开通了许多权限,基本可以满足大家学习、测试。

2、搭建外网服务器

由基本原理可知:开发过程中需要自己的服务器,作为处理业务逻辑的环境。我们自己的服务器与微信服务器进行交互,所以必须提供能够正确访问的外网地址。

微信平台对后台URL的要求有两点:

①必须能够用公网访问

②必须使用80端口

要实现以上两点,我们可以选择购买外网服务器,例如:阿里云、百度云、腾讯云…都是不错的选择。如果没有服务器,可以选择用外网映射工具,将我们的内网链接映射为公网,比如:花生壳、ngrok等等--具体使用请自行补脑....ngrok使用方式:https://www.sunnyos.com/article-show-67.html

服务器搭建好访问方式:

本地访问;http://localhost:8080/Testweixin/index.html

外网访问;http://weixinceshi.free.ngrok.cc/Testweixin/index.html

ps:搭建好公网访问地址后,我们开发的后台代码就可以放到公网地址了,那么问题来了:那么用户是怎么样访问到我们的代码呢?--------通过映射工具提供公网能够访问的URL,然后将此URL绑定到微信后台即可。

3、开发模式接入(成为开发者)

原理:登录微信公众平台后,进入开发者模式,会让我们填写一个URL、Token、EncodingAESKey、 消息加解密方式,其中URL就是我们的web项目工程可以在外网访问的地址,也就是微信服务器与我们的服务器通讯连接的地址。当我们点击提交时,微信服务器将会发送一个Get请求,到我们上述地址,同时传递四个参数:

微信公众号开发—入门系列(二)

我们的服务器上的web项目对请求进行参数校验 ,若确认此次GET请求来自微信服务器,将返回echostr参数内容,则接入生效,成为开发者成功,以后我们通过微信发送的信息,将会由微信服务器通过URL地址转到我们的服务器上的进行业务处理以及响应结果。否则接入失败。

ps:微信定义:当第一次请求时调用的是get方法,后面进行消息处理是调用post方法。

步骤:

1、编写servlet类 对请求进行参数校验  @WebServlet("/TestWeixinConnect")

2、配置后台参数 url token等参数 提交到我们的自己服务器后台进行校验,校验成功后,公众号会提示提交成功,可以启用配置

代码实现:

servlet类:
/**
 * Servlet implementation class TestWeixinConnect
 */
@WebServlet("/TestWeixinConnect")
public class TestWeixinConnect extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public TestWeixinConnect() {
// TODO Auto-generated constructor stub
System.out.println("123");

/** 
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
*      response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub

//获取微信公众平台传过来的参数,并进行校验
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
PrintWriter pw = response.getWriter(); // 获取输出流
//如果校验成功,将得到的随机字符串原路返回
if(CheckUtil.checkSignature(signature, timestamp, nonce)){
pw.print(echostr);
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
*      response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}

CheckUtil 工具类:

package WeiXinCode;
import java.security.MessageDigest;
import java.util.Arrays;
public class CheckUtil {
public static final String Token = "weixin"; // 开发者自行定义Token 与公众平台填写的tooken一致
public static boolean checkSignature(String signature, String timestamp, String nonce) {
// 1.定义数组存放token,timestamp,nonce
String[] arr = { Token, timestamp, nonce };
// 2.对数组进行排序 
Arrays.sort(arr);
// 3.生成字符串 
StringBuffer sb = new StringBuffer();
for (String s : arr) {
sb.append(s);
}
// 4.sha1加密,网上均有现成代码
String temp = getSha1(sb.toString());
// 5.将加密后的字符串,与微信传来的加密签名比较,返回结果
return temp.equals(signature); 
}
public static String getSha1(String str) {
if (str == null || str.length() == 0) {
return null;
}
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f' };
try { 
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");mdTemp.update(str.getBytes("UTF-8"));
byte[] md = mdTemp.digest();
int j = md.length;
char buf[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
buf[k++] = hexDigits[byte0 & 0xf];
}
return new String(buf);
} catch (Exception e) {
// TODO: handle exception
return null;
}
}

}

注意:url 是外网可以访问的地址 而且只支持80、443端口号,这里使用ngrok映射本地的地址,token是我们工具类自定义的值