开启微信公众号开发之旅
微信公众号是开发者或商家在微信公众平台上申请的应用账号,通过公众号可以与用户进行文字、图片、语音、视频的全方位沟通和互动。
| 类型 | 订阅号 | 服务号 | 企业号 |
|---|---|---|---|
| 定位 | 媒体和个人 | 企业和组织 | 企业内部 |
| 消息推送 | 每天1条 | 每月4条 | 不限 |
| 消息展示 | 折叠在订阅号文件夹 | 直接显示在聊天列表 | 直接显示 |
| 高级接口 | 有限 | 全部开放 | 全部开放 |
| 微信支付 | 不支持 | 支持 | 支持 |
| 适用场景 | 内容传播、资讯发布 | 服务提供、交易支付 | 企业内部管理 |
1. 访问微信公众平台:https://mp.weixin.qq.com
2. 点击"立即注册"
3. 选择账号类型:订阅号/服务号/小程序/企业微信
4. 填写基本信息:邮箱、密码、验证码
5. 邮箱激活
6. 选择主体类型:个人/企业/政府/媒体/其他组织
7. 信息登记:身份证或营业执照
8. 公众号信息:名称、功能介绍、运营地区
9. 完成注册登录公众号后台 → 设置与开发 → 基本配置 → 开发者ID
AppID: wx1234567890abcdef
AppSecret: 点击"重置"按钮获取(需管理员扫码确认)
⚠️ AppSecret 非常重要:
- 用于获取access_token
- 调用公众号接口的凭证
- 泄露后需立即重置设置与开发 → 基本配置 → IP白名单
示例:
192.168.1.100
120.79.123.45
支持格式:
- 单个IP:192.168.1.100
- IP段:192.168.1.0/24设置与开发 → 基本配置 → 服务器配置
需要填写:
1. 服务器地址(URL):https://api.example.com/wechat
2. 令牌(Token):自定义字符串,3-32个字符
3. 消息加解密密钥(EncodingAESKey):点击"随机生成"
4. 消息加解密方式:明文/兼容/安全模式(推荐)@RestController
@RequestMapping("/api/wechat")
@Slf4j
public class WeChatController {
// 从配置文件中注入token值
@Value("${wechat.mp.token}")
private String token;
/**
* 微信服务器验证接口
* 用于微信公众号配置时的URL验证
*/
@GetMapping("/check")
public String checkSignature(@RequestParam(name = "signature", required = false) String signature,
@RequestParam(name = "timestamp", required = false) String timestamp,
@RequestParam(name = "nonce", required = false) String nonce,
@RequestParam(name = "echostr", required = false) String echostr) {
log.info("微信服务器验证请求:signature={}, timestamp={}, nonce={}, echostr={}",
signature, timestamp, nonce, echostr);
if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
log.error("请求参数不完整");
return null;
}
try {
// 1)将token、timestamp、nonce三个参数进行字典序排序
List<String> list = Arrays.asList(token, timestamp, nonce);
Collections.sort(list);
// 2)将三个参数字符串拼接成一个字符串进行sha1加密
StringBuilder stringBuilder = new StringBuilder();
for (String s : list) {
stringBuilder.append(s);
}
// 加密
MessageDigest instance = MessageDigest.getInstance("SHA-1");
// 使用sha1进行加密,获得byte数组
byte[] digest = instance.digest(stringBuilder.toString().getBytes("UTF-8"));
// 将加密后的字节数组转换为十六进制字符串
StringBuilder sum = new StringBuilder();
for (byte b : digest) {
sum.append(Integer.toHexString((b >> 4) & 15));
sum.append(Integer.toHexString(b & 15));
}
// 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
if (signature.equals(sum.toString())) {
log.info("微信服务器验证成功");
return echostr;
} else {
log.warn("微信服务器验证失败,signature不匹配");
log.warn("计算得到的签名: {}", sum.toString());
log.warn("接收到的签名: {}", signature);
}
} catch (Exception e) {
log.error("验证签名时发生异常: {}", e.getMessage(), e);
}
log.warn("微信服务器验证失败");
return null; // 验证失败时返回null
}
}access_token 是公众号的全局唯一接口调用凭据。
// HTTP 请求示例(GET)
// https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
// 返回结果示例:
// {
// "access_token": "56_abcdefghijklmnopqrstuvwxyz",
// "expires_in": 7200
// }@Service
public class WechatService {
@Value("${wechat.appid}")
private String appId;
@Value("${wechat.appsecret}")
private String appSecret;
private final RestTemplate restTemplate = new RestTemplate();
public String getAccessToken() {
String url = String.format(
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
appId, appSecret);
Map<String, Object> result = restTemplate.getForObject(url, Map.class);
if (result != null && result.get("access_token") != null) {
return result.get("access_token").toString();
}
return null;
}
}