公众号接入至少要分开看三层:服务器地址验证、后续消息事件接收、具体接口权限。配置保存成功,不代表所有接口都已经授权;拿到 access_token 也不等于每项调用都被允许。
下面以 2018 年项目的明文接入流程说明这些关系。安全模式的加解密与当前账号能力应按实际配置处理,不可把这段明文示例用于所有模式。
GET 验证里的 Token 不是 access_token
旧流程的 GET 请求带 signature、timestamp、nonce 和 echostr。服务端将自己配置的 Token、timestamp、nonce 排序拼接后计算 SHA-1,与签名比较,通过后原样返回 echostr。
Token 是服务器配置中约定的校验值;access_token 是调用平台接口的凭证;AppSecret 又是另一类应用凭据。三者不能互换,也不应直接写入公开代码或打印在日志中。
以下是 Java 8 的明文校验函数,Token 从受控环境取得:
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public final class PlainCallbackVerifier {
public static boolean verify(String token, String timestamp,
String nonce, String signature) {
if (token == null || token.isEmpty() ||
timestamp == null || !timestamp.matches("[0-9]{1,20}") ||
nonce == null || nonce.isEmpty() || nonce.length() > 256 ||
signature == null || !signature.matches("[0-9a-fA-F]{40}")) {
return false;
}
String[] parts = {token, timestamp, nonce};
Arrays.sort(parts);
String content = String.join("", parts);
try {
byte[] digest = MessageDigest.getInstance("SHA-1")
.digest(content.getBytes(StandardCharsets.UTF_8));
StringBuilder hex = new StringBuilder();
for (byte value : digest) {
hex.append(String.format("%02x", value & 0xff));
}
return MessageDigest.isEqual(
hex.toString().getBytes(StandardCharsets.US_ASCII),
signature.toLowerCase(java.util.Locale.ROOT)
.getBytes(StandardCharsets.US_ASCII));
} catch (NoSuchAlgorithmException ex) {
throw new IllegalStateException(ex);
}
}
}
HTTP 处理器还应限制请求长度,校验失败拒绝响应;成功时按所用明文协议输出 echostr 的原始内容,不再 JSON 序列化。上面只实现签名比较,不包含安全模式解密、消息处理或完整的请求时效与重放控制。公众号接入文档入口
验证地址与接收事件是不同阶段
旧笔记中,验证地址使用 GET,而消息与事件由平台向配置地址推送 POST。GET 成功只能说明当次验证通过,不能证明 POST 路由、网关转发、消息解析和响应都正确。
遇到“没有收到事件”,依次检查:当前账号配置的实际 URL、服务器配置是否启用、POST 是否到达网关和应用、请求体是否按当前模式正确验签及解密。日志只留必要的请求关联信息,避免保存完整用户消息或凭据。
启用开发配置后,菜单要检查来源
旧工程还遇到过启用服务器配置后菜单表现变化。需要分别确认后台配置、接口创建和缓存中的菜单,不能把一次观察写成“启用服务器就必然清空所有菜单”。
48001 应查调用的具体能力
48001 的排查重点是实际接口权限及账号、应用上下文。检查正在用哪个 AppID 的凭证、请求的是哪项接口、平台给当前账号开放了什么能力,不要只反复刷新 access_token。
具体权限可能随账号类型、认证和平台规则变化,本文不沿用 2018 年的权限表作当前保证。二维码事件的后续处理见场景二维码与事件流;字符串多引号则见回调原始响应。