微信公众号开发--开通测试号及验证消息来自服务器

  • 一、服务器配置
  • 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、注册

首先需要注册一个账号然后登陆,选择开通隧道,根据个人需求选择购买

微信开发工具 安卓测试 微信测试开发账号_微信开发工具 安卓测试_02

  • 隧道名称:可以随便填写,无关紧要只是为了一个备注
  • 前置域名:服务器免费赠送的域名,请不要带上后缀,如果要 sunny.free.idcfengye.com 只需要填写 sunny 即可
  • 本地端口:可以为同一个局域网内任意一台机器进行映射,只需要填对ip和端口就行,例如:192.168.1.1:80
  • http验证用户名:非必填项,在需要的时候填写,否则可以不填
  • http验证密码:非必填项,在需要的时候填写,否则可以不填

    添加成功后,在隧道管理可看到自己申请的域名
2.2、下载客户端

客户端下载后解压,点击启动工具启动(其他启动方式参考说明文档)

微信开发工具 安卓测试 微信测试开发账号_开发者_03


复制隧道id到窗口中,回车即可启动

微信开发工具 安卓测试 微信测试开发账号_开发者_04

二、验证消息来自服务器

以测试号为例,提交请求时,微信服务器将发送GET请求到填写的服务器地址URL上

微信开发工具 安卓测试 微信测试开发账号_微信公众号_05


请求参数如下图:

参数

描述

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 "";
    }
}