Я искал по всему Интернету и ничего не дал однозначного ответа, чтобы подтвердить запрос на подписку от Amazon SNS. Я уже отправил подписку с консоли Amazon на свой веб-сайт, но что дальше? Я использую amazon EC2 в качестве своего сервера с PHP.
Как я могу подтвердить HTTP-запрос на подписку от Amazon SNS
Ответы (5)
Прежде чем вы даже настроите подписку на конечную точку HTTP / HTTPS через консоль управления AWS, вам необходимо убедиться, что конечная точка HTTP или HTTPS вашего веб-сайта PHP имеет возможность обрабатывать запросы HTTP POST, генерируемые Amazon SNS. Существует несколько типов сообщений SNS: Подтверждение подписки, Уведомление и Подтверждение отмены подписки. Ваш PHP-код должен получить заголовок x-amz-sns-message-type из запроса и обработать его в зависимости от типа сообщения. Для сообщения SubscriptionConfirmation ваше приложение PHP должно обработать тело сообщения POST, которое является документом JSON. Чтобы подписаться на тему, ваш PHP-код должен посетить «SubscriberURL», указанный в теле JSON. При желании вы должны проверить подпись, чтобы убедиться в подлинности сообщения перед подпиской на тему.
Более подробную информацию можно найти в документации AWS: http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html
Вот экспресс-приложение (Node.js), подтверждающее подписку на SNS:
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 Cloud 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. Допустим, у вас есть такой API в HapiJS (ну, не имеет значения, что у вас может быть другая технология)
{
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
и затем щелкнуть URL-адрес, указанный в payload.SubscribeURL
.
Как только AWS принимает его, вы проверяете подтверждение на странице подписок, где Subscription ARN
будет изменено с Pending Confirmation
на сложное имя-кум-SHA, имеющее имя вашей темы.