我一直在网上搜索,但没有给出明确的答案来确认亚马逊 SNS 的订阅请求。我已经将订阅从亚马逊控制台发送到我的网站,但接下来该怎么办?我使用 amazon EC2 作为我的 PHP 服务器。
在通过 AWS 管理控制台配置 HTTP/HTTPS 终端节点订阅之前,您需要确保 PHP 网站的 HTTP 或 HTTPS 终端节点能够处理 Amazon SNS 生成的 HTTP POST 请求。 SNS 消息有多种类型:SubscriptionConfirmation、Notification 和 UnsubscribeConfirmation。您的 PHP 代码需要从请求中获取标头 x-amz-sns-message-type 并根据消息类型对其进行处理。对于 SubscriptionConfirmation 消息,您的 PHP 应用程序需要处理 POST 消息正文,这是一个 JSON 文档。为了订阅主题,您的 PHP 代码需要访问 JSON 正文中指定的“SubscriberURL”。或者,您应该在订阅主题之前验证签名以确保消息的真实性。
您可以在 AWS 文档上找到更多详细信息:http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html
这是一个确认 SNS 订阅的 Express 应用程序 (Node.js):
const express = require('express')
const request = require('request')
// parse urlencoded request bodies into req.body
const bodyParser = require('body-parser')
const app = express()
const port = 8080
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.post('/', (req, res) => {
let body = ''
req.on('data', (chunk) => {
body += chunk.toString()
})
req.on('end', () => {
let payload = JSON.parse(body)
if (payload.Type === 'SubscriptionConfirmation') {
const promise = new Promise((resolve, reject) => {
const url = payload.SubscribeURL
request(url, (error, response) => {
if (!error && response.statusCode == 200) {
console.log('Yess! We have accepted the confirmation from AWS')
return resolve()
} else {
return reject()
}
})
})
promise.then(() => {
res.end("ok")
})
}
})
})
app.listen(port, () => console.log('Example app listening on port ' + port + '!'))
要使用它,需要安装所需的软件包:
yarn add express request body-parser
一旦您确认订阅,AWS 将向服务器发送一个
POST
请求,其中包含以下内容:
{
"Type": "SubscriptionConfirmation",
"MessageId": "XXXXXXXX-1ee3-4de3-9c69-XXXXXXXXXXXX",
"Token": "SECRET_TOKEN",
"TopicArn": "arn:aws:sns:us-west-2:XXXXXXXXXXXX:ses-test",
"Message": "You have chosen to subscribe to the topic arn:aws:sns:us-west-2:XXXXXXXXXXXX:ses-test. To confirm the subscription, visit the SubscribeURL included in this message.",
"SubscribeURL": "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-west-2:XXXXXXXXXXXX:ses-test&Token=SECRET_TOKEN",
"Timestamp": "2018-11-21T19:48:08.170Z",
"SignatureVersion": "1",
"Signature": "SECRET",
"SigningCertURL": "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.pem"
}
有效负载包含服务器请求的
SubscribeURL
。
您指定的端点将从 AWS SNS 端点验证服务获取数据,同一端点将用于验证端点并从 aws 获取通知,
只需将 AWS SNS 发送的输入转储到一个文本文件中,例如,
$json_write_to_text = json_decode(file_get_contents("php://input"));
您将找到 AWS SNS 发送的所有数据,但只需找到
SubscriptionUrl
(这将特定于具有有效令牌的端点),在浏览器中打开它,您将具有 SubscriptionConfirmation 状态。就是这样
享受吧。
带有注解的Spring云SNS订阅
Spring Cloud AWS 支持自动确认订阅者,只需添加此注解“@NotificationSubscriptionMapping”即可
@Controller
@RequestMapping("/topicName")
public class NotificationTestController {
@NotificationSubscriptionMapping
public void handleSubscriptionMessage(NotificationStatus status) throws IOException {
//We subscribe to start receive the message
status.confirmSubscription();
}
@NotificationMessageMapping
public void handleNotificationMessage(@NotificationSubject String subject, @NotificationMessage String message) {
// ...
}
@NotificationUnsubscribeConfirmationMapping
public void handleUnsubscribeMessage(NotificationStatus status) {
//e.g. the client has been unsubscribed and we want to "re-subscribe"
status.confirmSubscription();
}
}
http://cloud.spring.io/spring-cloud-aws/spring-cloud-aws.html#_sns_support
我使用 NodeJS 后端解决了这个问题。假设你在 HapiJS 中有一个这样的 API(好吧,你可以拥有其他技术并不重要)
{
method: 'POST',
path: '/hello',
handler: ( request, reply ) => {
reply( Hello.print(request.payload) );
},
config: {
tags: ['api']
}
}
只需将您收到的有效负载传递给您的业务逻辑即可。
业务逻辑流程是这样的
'use strict';
const request = require('request');
exports.print = (payload) => {
payload = JSON.parse(payload);
if(payload.Type === 'SubscriptionConfirmation'){
return new Promise((resolve, reject) => {
const url = payload.SubscribeURL;
request(url, (error, response) => {
if (!error && response.statusCode == 200) {
console.log('Yess! We have accepted the confirmation from AWS');
return resolve();
}
else
return reject();
});
});
}
我正在使用 NPM 的请求模块来自动接受此类请求。
另一种方法是打印
payload
的内容,然后单击 payload.SubscribeURL
中给出的 URL。
AWS 接受后,您可以在订阅页面上检查确认信息,其中
Subscription ARN
将从 Pending Confirmation
更改为包含您的主题名称的复杂名称兼 SHA。
基本上,为了进行测试,我使用 ngrok 服务器向 Python Flask 服务器发出请求,并将 HTTPS 传输类型订阅添加到 AWS SNS 主题。在这种情况下,对于订阅确认,它触发了端点,并且该端点保存 SubscribeURL 值。您需要将该值放入下面 UI 的确认订阅示例中。
带有订阅功能的 aws 的 Ui [为了确认订阅,请选择该订阅并将 SubscribeURL 值放入确认订阅中][1] [1]:https://i.sstatic.net/TpBnYndJ.png