微信公众号开发--开通测试号及验证消息来自服务器
- 一、服务器配置
- 1、开通测试号
- 2、域名申请(ngrok)
- 2.1、注册
- 2.2、下载客户端
- 二、验证消息来自服务器
一、服务器配置
1、开通测试号
订阅号的个人账号很多权限没有,而且其他账号主体不容易申请 ,本例使用测试号开发公众号。手机扫描二维码即可登录。appID与appsecret自动生成,后面调用接口时使用,接口配置中的URL需要外网可访问,本例使用内网穿透技术ngrok,Token可由开发者自己定义,用来加密生成签名signature。
2、域名申请(ngrok)
域名可自行申请服务器地址,本例采用内网穿透的ngrok工具,可让外网访问直接映射到本地,而且免费!!!
ngrok地址:https://www.ngrok.cc ngrok官方教程:http://www.ngrok.cc/_book
2.1、注册
首先需要注册一个账号然后登陆,选择开通隧道,根据个人需求选择购买
- 隧道名称:可以随便填写,无关紧要只是为了一个备注
- 前置域名:服务器免费赠送的域名,请不要带上后缀,如果要 sunny.free.idcfengye.com 只需要填写 sunny 即可
- 本地端口:可以为同一个局域网内任意一台机器进行映射,只需要填对ip和端口就行,例如:192.168.1.1:80
- http验证用户名:非必填项,在需要的时候填写,否则可以不填
- http验证密码:非必填项,在需要的时候填写,否则可以不填
添加成功后,在隧道管理可看到自己申请的域名
2.2、下载客户端
客户端下载后解压,点击启动工具启动(其他启动方式参考说明文档)
复制隧道id到窗口中,回车即可启动
二、验证消息来自服务器
以测试号为例,提交请求时,微信服务器将发送GET请求到填写的服务器地址URL上
请求参数如下图:
参数 | 描述 |
signature | 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 |
timestamp | 时间戳 |
nonce | 随机数 |
echostr | 随机字符串 |
开发者通过检验signature对请求进行校验。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
下面采用Java方式实现校验逻辑
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
/**
* @Auther: Rosan
* @Date: 2019/6/12 11:39
* @Description:
*/
@RestController
@RequestMapping("/sign")
public class ApiController {
@GetMapping(value = "/test")
public String getWxBackInfo(@RequestParam("echostr") String echostr,@RequestParam("signature") String signature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce){
try {
String token="shiny1413";
//将token、timestamp、nonce三个参数进行排序
String[] requestParam=new String[]{token,timestamp,nonce};
Arrays.sort(requestParam);
StringBuilder sb=new StringBuilder();
for (String s : requestParam) {
sb.append(s);
}
//sha1加密
String shaHex = DigestUtils.shaHex(sb.toString());
//与signature进行比较
if (signature.equals(shaHex)){
return echostr;
}
} catch (Exception e) {
//todo
}
return "";
}
}