Node.js中使用AWS SNS服务发送短信
前言
Amazon Simple Notification Service (Amazon SNS) is a web service that coordinates and manages the delivery or sending of messages to subscribing endpoints or clients. In Amazon SNS, there are two types of clients—publishers and subscribers—also referred to as producers and consumers. Publishers communicate asynchronously with subscribers by producing and sending a message to a topic, which is a logical access point and communication channel. Subscribers (i.e., web servers, email addresses, Amazon SQS queues, AWS Lambda functions) consume or receive the message or notification over one of the supported protocols (i.e., Amazon SQS, HTTP/S, email, SMS, Lambda) when they are subscribed to the topic. [1]
正如SNS的介紹所述,SNS是AWS提供的一個消息收發服務,它包括了諸如消息推送、短信、電子郵件等服務。AWS官方文檔提供了非常多的內容,但提供的示例代碼是以Java或.Net為主,關于Node.js的直接資料較少,所以這里便來介紹如何使用AWS SNS服務發送短信。
Node.js中使用SNS發送短信
在Node.js中使用AWS的服務,需要先安裝aws-sdk依賴。AWS SDK中包括了眾多服務的接口,在這里我們需要的是AWS.SNS類。首先,需要實例化AWS.SNS對象,其構造函數的參數為一個對象,通常需要包括accessKeyId、secretAccessKey、region等屬性。在AWS IAM中,可生成并下載使用的用戶對應的accessKeyId及secretAccessKey。需要注意的是,使用的用戶需要在IAM中設置SNS對應的權限。
const AWS = require('aws-sdk');const options = {accessKeyId: 'String',secretAccessKey: 'String',apiVersion: '2010-03-31', };const snsService = new AWS.SNS(options);通過AWS.SNS類的實例,就可以使用其進行SNS服務的相關操作。本文的主題為使用SNS服務發送短信,所以接下來即可通過AWS.SNS實例的publish方法以短信形式發送消息。
AWS SDK for Node.js中,publish方法接收一個Object類型的參數,它其中包括Message、MessageAttributes、MessageStructure、PhoneNumber、Subject、TargetArn以及TopicArn屬性。publish是一個SNS中通用的方法,發送郵件、消息推送也是通過它進行完成,所以在發送短信時部分的參數不是必須的。下面是一個發送短信所需最少參數的例子。
const params = {Message: text,MessageAttributes: {'AWS.SNS.SMS.SMSType': {DataType: 'String',StringValue: 'Transactional', // Transactional or Promotional},// AWS.SNS.SMS.MaxPrice// AWS.SNS.SMS.SenderId},PhoneNumber: phoneNumber, // 電話號碼,需要遵從E.164格式 };MessageAttributes中可以包含多個屬性,例如上述例子中的AWS.SNS.SMS.SMSType。MessageAttribute的值主要包括DataType與StringValue或BinaryValue,其根據DataType的值決定需要的是StringValue或是BinaryValue。StringValue接受一組以UTF-8編碼的字符串,而BinaryValue可以接受任何二進制值,例如壓縮后的數據、圖片等。
在MessageAttributes的AWS.SNS.SMS.SMSType屬性中,其值需為Transactional或Promotional。二者的區別為Transactional更為可靠,但其價格通常更為昂貴,一般用于發送較為重要的消息(如短信驗證碼等),而Promotional一般用于發送推廣信息。另外AWS.SNS.SMS.MaxPrice為愿意為發送消息支付以美元為單位的最高金額;AWS.SNS.SMS.SenderId為一個在接收設備上顯示的自定義ID,但其支持程度受所在地區限制,如中國便不支持SenderId的顯示。
使用上面定義的參數調用publish方法即可發送短信。publish方法提供了基于Promise的異步使用方法,只需將代碼修改為:const response = await snsService.publish(params).promise();。同理,AWS SDK中的其它方法也可通過添加.promise()將其異步形式從回調改為基于Promise。
snsService.publish(params, (err, data) => {if (err) {// ...}// ... })返回結果
在參數錯誤、權限不足等情況下,調用publish方法將會拋出諸如InvalidParameter、AuthorizationError等錯誤,可根據其具體錯誤信息判斷錯誤原因。調用publish方法將會返回下述結果。其中,MessageId為該消息的唯一標識符,當開啟CloudWatch Logs后可通過該標識符獲取消息的傳輸信息。
{"ResponseMetadata":{"RequestId":"bfb2a062-c201-5d34-a7d8-f5fd653b27f9"},"MessageId":"2b38eec7-a3f0-5679-a116-bb5804cadcb4" }未收到短信
調用publish接口成功并正常返回結果,不代表短信發送成功。短信發送失敗的原因可能是下列其中一個:
- 被電話運營商作為垃圾消息屏蔽
- 目標已加入黑名單
- 電話號碼無效
- 消息正文無效
- 電話運營商已屏蔽此消息
- 電話運營商目前無法訪問/不可用
- 電話已屏蔽SMS
- 電話已加入黑名單
- 電話當前無法訪問/可用
- 電話號碼已退出
- 此傳輸會超過最高價格
- 嘗試聯系電話時發生未知錯誤
publish方法返回的結果無法得知短信發送是否成功,只有在開啟CloudWatch Logs功能后才能從日志中獲取短信是否發送成功及發送失敗的原因。
發送短信至多個號碼
使用AWS SNS可以實現同時發送短信至多個手機號碼,其中一種實現方法即為多次調用publish方法向不同號碼發送短信。但重復多次調用publish方法需要耗費更多的時間,所以在此也可選用另一種方法,即使用Topic發送短信至多個號碼。該方法的步驟是在創建一個topic后,為多個手機號碼訂閱該topic。訂閱后在發送消息時,會將消息發送至訂閱該topic的端點中,此處的端點即為電話號碼。
在發送信息至多個號碼前,需要創建一個新的Topic并使用subscribe方法為發送的號碼訂閱該Topic。Topic即一個消息信道,當有消息發送至topic中時,SNS服務將會將該消息發送至訂閱該topic的終端節點中。Topic可通過AWS Console創建,也可通過AWS SDK中的createTopic方法創建。
通過SDK調用createTopic創建Topic,需要包括Name、Attributes、Tags三個參數,其中Name為必須的參數。Attributes參數。
const params = {Name: 'STRING_VALUE', // Topic 名稱Attributes: {'<attributeName>': 'STRING_VALUE',/* '<attributeName>': ... */},Tags: [{Key: 'STRING_VALUE', // Tag keyValue: 'STRING_VALUE', // Tag value},// ...], };const response = await snsService.createTopic(params).promise(); // response.TopicArn完成topic的創建之后,即可為需要發送短信的電話號碼訂閱所創建的topic。為電話號碼訂閱topic需要使用subscribe方法,它必填的參數包括TopicArn、Endpoint以及Protocol。其中,Protocol的值必須為sms,TopicArn的值為創建的Topic Arn地址,Endpoint為訂閱Topic的電話號碼。另外,它的參數還包括有Attributes以及ReturnSubscriptionArn兩個屬性。Attributes屬性如同publish方法的MessageAttributes屬性,通過它的DeliveryPolicy、FilterPolicy、RawMessageDelivery配置訂閱的相關設置。
const params = {Protocol: 'sms',TopicArn: topicArn,// Attributes: {// '<attributeName>': 'STRING_VALUE',// },Endpoint: phoneNumber,// ReturnSubscriptionArn: false, };const response = await snsService.subscribe(params).promise();在為需要發送短信的號碼訂閱topic后,即可調用publish方法發送消息。發送短信至多個號碼時調用publish方法的參數與發送至單個號碼大致相同,唯一需要修改的地方為不再需要設置PhoneNumber,而是需要設置TopicArn屬性,它的值即為上面調用createTopic所得到的TopicArn字段。
const params = {Message: text,MessageAttributes: {// 發送短信至topic同樣可設置SMSType, MaxPrice, SenderId三個屬性'AWS.SNS.SMS.SMSType': {DataType: 'String',StringValue: 'Transactional', // Transactional or Promotional},// AWS.SNS.SMS.MaxPrice// AWS.SNS.SMS.SenderId},TopicArn: topicArn, // 群發的topic ARN地址 };const response = await snsService.publish(params).promise();結束語
AWS的free tier提供了每月100條的免費短信可以使用,但需要注意的是此處的免費短信接收方為美國號碼。若要發送短信至國內號碼,價格約為0.01531 USD(約0.11元),該價格相對于國內服務商較為昂貴。另外,SNS發送短信至國內時失敗率也較高,且在發送失敗的情況下也是按正常價格收取費用。在實際開發中,若不是以海外業務為主的情況下,可考慮國內服務商提供的短信服務。
參考資料
總結
以上是生活随笔為你收集整理的Node.js中使用AWS SNS服务发送短信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flutter中的异步机制Future
- 下一篇: Android 上传图片实例,java上