使用Postman向Slack发送S3预签名URL时遇invalid_payload及400错误
我用Postman通过Slack入站Webhook发消息,下面的curl命令能正常运行:
curl --location --request POST 'https://hooks.slack.com/services/T026NT2D4/B02UM3G1D35' \ --header 'Content-type: application/json' \ --data-raw '{"text":"Hello world"}'
但尝试发送AWS S3预签名URL到频道时,不管用JSON、纯文本还是x-www-form-urlencoded格式,都收到invalid_payload响应,所有尝试都失败了。
我需要实现示例,后续会用Spring Boot生成并发送消息,所以任何消息美化的资源都很有用。我见过Slack频道里有带文本和“more”选项的消息,点击能下载文件(推测“more”是预签名URL的超链接)。
补充测试结果:
我做了更多测试,发现只有发送包含text字段的JSON才能成功,示例Payload如下:
{ "text": "*Presigned URL*" }
请求头Content-type为application/json。但把“text”改成“Message”就会收到400响应,是不是“no_text”错误是因为Payload缺少text字段导致的?
核心原因与正确Payload示例
是的,Slack入站Webhook的Payload必须包含text字段(这是必填项),缺失或者字段名错误都会返回400错误(比如你把字段改成“Message”的情况)。要发送预签名URL,直接把URL放到text字段里即可,还可以用Slack的Markdown语法美化:
基础文本带链接示例
{ "text": "这里是文件下载链接:<https://your-presigned-s3-url.com|点击下载>" }
说明:<URL|显示文本>是Slack的链接语法,点击“点击下载”就会跳转到预签名URL。
带“更多”选项的美化消息(类似你看到的示例)
可以用Slack的Blocks组件实现结构化消息,添加按钮提升体验:
{ "text": "有一个文件可以下载", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "*文件通知*:请下载下方文件" }, "accessory": { "type": "button", "text": { "type": "plain_text", "text": "更多" }, "url": "https://your-presigned-s3-url.com" } } ] }
这个Payload会在Slack里显示一段加粗的通知文本,右侧带一个“更多”按钮,点击就会打开预签名URL下载文件。
Spring Boot实现示例
1. 添加Maven依赖
在pom.xml中添加Web依赖(已有则跳过):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2. 消息发送Service类
import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.client.RestTemplate; import org.springframework.stereotype.Service; @Service public class SlackNotificationService { private final RestTemplate restTemplate; private static final String SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/T026NT2D4/B02UM3G1D35"; public SlackNotificationService(RestTemplate restTemplate) { this.restTemplate = restTemplate; } public void sendPresignedUrlNotification(String presignedUrl) { // 构建结构化消息Payload String payload = String.format("{\n" + " \"text\": \"S3文件下载通知\",\n" + " \"blocks\": [\n" + " {\n" + " \"type\": \"section\",\n" + " \"text\": {\n" + " \"type\": \"mrkdwn\",\n" + " \"text\": \"*文件已准备完成*:点击按钮下载\"\n" + " },\n" + " \"accessory\": {\n" + " \"type\": \"button\",\n" + " \"text\": {\n" + " \"type\": \"plain_text\",\n" + " \"text\": \"下载\"\n" + " },\n" + " \"url\": \"%s\"\n" + " }\n" + " }\n" + " ]\n" + "}", presignedUrl); // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> request = new HttpEntity<>(payload, headers); // 发送请求 restTemplate.postForObject(SLACK_WEBHOOK_URL, request, String.class); } }
3. 配置RestTemplate Bean
在配置类中添加RestTemplate实例:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class AppConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
消息美化关键技巧
- 使用Slack的
mrkdwn语法:支持加粗(**文本**)、斜体(*文本*)、链接(<URL|显示文本>)等格式 - 采用Blocks组件:创建结构化消息,支持标题、按钮、分割线等元素,比传统附件更灵活
- 按钮绑定URL:直接将预签名URL关联到按钮,简化用户操作流程
内容的提问来源于stack exchange,提问作者Aditya K

