1. 创建一个SpringBoot项目,此步骤省略
2. 在pom中引用班纳睿工具包
班纳睿
com.github.binarywang
wx-java-mp-spring-boot-starter
4.1.0
3. 内网穿透配置
我这边用到的是 ngrok
在ngrok中选择免费的项目,然后配置相对应的域名映射到本地的相应端口
配置完后,在隧道管理菜单可以看到隧道 id
下载ngrok的客户端,我这里下载的是 windows版本,下载解压后,打开 windows_amd64文件夹,点击Sunny-Ngrok启动工具,然后输入隧道id敲回车。界面出现oline表示穿透成功。
1. 在微信公众平台申请开发测试公众号
申请测试号后,可以得到appID,appsecret
2. 配置SpringBoot中对应的公众号信息
在SpringBoot项目的application.yml中配置公众号相应的信息,将appId和secret 配置成公众号界面分配的信息,token自己在公众号界面填写一个,然后对应的配置在yml文件中。
在SpringBoot项目中创建config文件夹
在 config文件夹下创建 WechatMpProperties类,获取yml文件中的配置信息
@Configuration
@ConfigurationProperties(prefix = "wechat.mp")
@Data
public class WechatMpProperties {
/**
* 设置微信公众号的appid
*/
private String appId;
/**
* 设置微信公众号的app secret
*/
private String secret;
/**
* 设置微信公众号的token
*/
private String token;
/**
* 设置微信公众号的EncodingAESKey
*/
private String aesKey;
}
在 config文件下创建 WxMpConfiguration类,将 WechatMpProperties的配置信息配置进去
@AllArgsConstructor
@Configuration
public class WxMpConfiguration {
@Autowired
private WechatMpProperties properties;
@Bean
public WxMpService wxMpService() {
WxMpService service = new WxMpServiceImpl();
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
configStorage.setAppId(properties.getAppId());
configStorage.setSecret(properties.getSecret());
configStorage.setToken(properties.getToken());
configStorage.setAesKey(properties.getAesKey());
Map storageMap = new HashMap<>();
storageMap.put(properties.getAppId(), configStorage);
service.setMultiConfigStorages(storageMap);
return service;
}
}
在 SpringBoot项目中创建 controller文件夹,在 controller文件夹下创建 WxPortalController类
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/wx/portal/{appid}")
public class WxPortalController {
private final WxMpService wxService;
private final WxMpMessageRouter messageRouter;
@GetMapping(produces = "text/plain;charset=utf-8")
public String authGet(@PathVariable String appid,
@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("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature,
timestamp, nonce, echostr);
if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
throw new IllegalArgumentException("请求参数非法,请核实!");
}
if (!this.wxService.switchover(appid)) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
if (wxService.checkSignature(timestamp, nonce, signature)) {
return echostr;
}
return "非法请求";
}
@PostMapping(produces = "application/xml; charset=UTF-8")
public String post(@PathVariable String appid,
@RequestBody String requestBody,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
log.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
if (!this.wxService.switchover(appid)) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
if (!wxService.checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}
String out = null;
if (encType == null) {
// 明文传输的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toXml();
} else if ("aes".equalsIgnoreCase(encType)) {
// aes加密的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
timestamp, nonce, msgSignature);
log.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
}
log.debug("\n组装回复信息:{}", out);
return out;
}
private WxMpXmlOutMessage route(WxMpXmlMessage message) {
try {
return this.messageRouter.route(message);
} catch (Exception e) {
log.error("路由消息时出现异常!", e);
}
return null;
}
}
3. 在微信公众平台调试
在接口配置信息,url 填写 域名+ /wx/portal/{appid}
配置完后,在下发点击发送按钮。配置成功,会弹出配置成功窗口。