1. 公众号 微信公众号开发文档
-
区别
-
选择
- 如果想简单的发送消息,达到宣传效果,建议可选择订阅号;
- 如果想用公众号获得更多的功能,例如开通微信支付,建议可以选择服务号;
- 如果想用来管理内部企业员工、团队,对内使用,可申请企业号;
- 订阅号可通过微信认证资质审核通过后有一次升级为服务号的入口,升级成功后类型不可再变;
- 服务号不可变更成订阅号。
-
测试号
专门为开发人员准备的一种仅用于测试的公众号,部分高级功能不支持,如微信支付、卡券等
2. 开发
-
微信测试号
-
测试号信息
appID
是公众号开发识别码,配合appsecret
可调用公众号的接口能力。appsecret
是校验公众号开发者身份的密码,具有极高的安全性。- 两者是比较重要的信息,不得随意发给别人
- 如果是正式的公众号,登录公众平台官网之后,找到
基本配置
菜单栏也可以获取到公众号相关的信息
-
接口配置信息
-
URL
是我们自己的服务器访问地址 --> 必须以http:// 或 https://
开头,分别支持80、443
端口- 响应微信发送的
Token
验证 - 用来接收、响应微信公众号关注者发送的信息、事件
- 响应微信发送的
-
Token
可随意填写,用来生成签名 --> 3-32位的英文、数字组成的字符
-
-
-
微信与服务器交互
- 公众号关注者发送信息 --> 发送到微信的服务器上
- 微信的服务器对内容封装成
xml
等格式 --> 转发到我们填写的URL
上,即该URL
实际就是我们处理数据的一个请求路径 - 我们的服务器回复
xml
等格式数据 --> 微信的服务器 - 微信的服务器 --> 响应到 公众号关注者
-
URL
验证接入 官方文档-
填写
URL
、Token
-->提交
后
-
微信服务器将发送
GET请求
到填写的服务器地址URL
上,并携带以下4个参数参数 描述 signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 timestamp 时间戳 nonce 随机数 echostr 随机字符串 -
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败
-
加密/校验流程
1. 将token、timestamp、nonce三个参数进行字典序排序 2. 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比,两者相等则标识该请求来源于微信
-
-
代码
-
controller
import com.small.nine.wxmp.service.WeiXinService; import lombok.extern.slf4j.Slf4j; 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 javax.annotation.Resource; /** * 微信公众号相关服务 API * * @author sheng_zs@126.com * @date 2021-07-26 9:07 */ @Slf4j @RestController @RequestMapping("/wx") public class WeiXinController { @Resource private WeiXinService weiXinService; /** * 微信接入,验证是否是微信发送的信息 * * @param signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 * @param timestamp 时间戳 * @param nonce 随机数 * @param echoStr 随机字符串 * @return 验证成功返回 echoStr */ @GetMapping("/weChat") public String checkSignature(@RequestParam String signature, @RequestParam String timestamp, @RequestParam String nonce, @RequestParam("echostr") String echoStr) { return weiXinService.checkSignature(signature, timestamp, nonce, echoStr); } }
-
service
/** * 微信公众号相关API服务层 * * @author sheng_zs@126.com * @date 2021-07-26 9:22 */ public interface WeiXinService { /** * 微信接入,验证是否是微信发送的信息 * * @param signature 加密后的字符串 * @param timestamp 时间戳 * @param nonce 随机数 * @param echoStr 返回的字符串 * @return 满足条件返回 echoStr */ String checkSignature(String signature, String timestamp, String nonce, String echoStr); }
-
impl
import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.SecureUtil; import com.small.nine.wxmp.config.WxConfig; import com.small.nine.wxmp.service.WeiXinService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Arrays; import java.util.Objects; /** * @author sheng_zs@126.com * @date 2021-07-26 9:24 */ @Slf4j @Service public class WeiXinServiceImpl implements WeiXinService { @Resource private WxConfig wxConfig; @Override public String checkSignature(String signature, String timestamp, String nonce, String echoStr) { log.info("微信接入:signature={}, timestamp={}, nonce={}, echoStr={}", signature, timestamp, nonce, echoStr); return checkToken(signature, timestamp, nonce, wxConfig.getToken()) ? echoStr : ""; } /** * 验证 signature 是否与 token、timestamp、nonce 三个字符串"字典排序后"拼接成一个字符串进行"sha1加密"的字符串相等 * * @param signature 加密后的字符串 * @param timestamp 时间戳 * @param nonce 随机数 * @param token 填写的 token * @return 验证成功返回 true */ private boolean checkToken(String signature, String timestamp, String nonce, String token) { if (StrUtil.hasBlank(signature, timestamp, nonce, token)) { throw new IllegalArgumentException("微信公众号非法请求参数,请核实"); } // 1. 将token、timestamp、nonce三个参数进行字典序排序 String[] strArr = new String[]{timestamp, nonce, token}; Arrays.sort(strArr); // 2. 将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder builder = new StringBuilder(); for (String s : strArr) { builder.append(s); } // 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 // return Objects.equals(signature, HexUtil.encodeHexStr(DigestUtil.sha1(builder.toString()))); return Objects.equals(signature, SecureUtil.sha1(builder.toString())); } }
-
WxConfig
import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * 微信配置类 * * @author sheng_zs@126.com * @date 2021-08-02 15:51 */ @Getter @Setter @Configuration @ConfigurationProperties("wx") public class WxConfig { /** * 微信公众号 ID */ private String appID; /** * 微信公众号 appSecret */ private String appSecret; /** * token */ private String token; }
-