使用 AWS Pinpoint 通过 Lambda 函数发送通知
Posted
技术标签:
【中文标题】使用 AWS Pinpoint 通过 Lambda 函数发送通知【英文标题】:Send a notification by Lambda function with AWS Pinpoint 【发布时间】:2017-12-29 16:38:30 【问题描述】:我有一个由MobileHub
和API Gateway
、Lambda
和DynamoDB
构建的ios 应用程序。
我注意到MobileHub
的SNS
功能已被Pinpoint
取代,我想使用这个新服务创建一个通知系统。
当用户通过API Gateway
创建新帖子时,会触发一个lambda函数,我想我可以通过Pinpoint
向订阅者发送通知。
但是我在Pinpoint
的官方网站上找不到任何示例或参考文档。
你有这个场景的任何资源或任何想法吗?非常感谢!
【问题讨论】:
【参考方案1】:取决于您所说的通知是什么意思,我假设您想向特定用户发送推送通知(Pinpoint 端点)。
Pinpoint 将与用户关联的每个设备存储为“端点”,通常由 AWS 客户端分析库创建(例如放大分析)。
客户
使用放大分析库,我调用updateEndpoint
,这样我就可以指定一个可供 Lambda 使用的userId
,以及设备令牌并删除optOut
,这样用户就可以接收推送通知:
Address
- 用户接受推送通知权限时生成的令牌 (iOS)
optOut
- NONE
以便他们接收推送通知
userId
- 用户的唯一 ID(Cognito 的子)
Lambda (node.js)
现在您可以使用userId
和 Pinpoint SDK 发送推送通知。
示例:
const sendMessagesParams =
ApplicationId: process.env.PINPOINT_APP_ID,
SendUsersMessageRequest:
Users:
[receiverUserId]:
,
MessageConfiguration:
APNSMessage:
Action: 'OPEN_APP',
Title: 'Message received',
SilentPush: false,
Body: `You have a new message`
,
GCMMessage:
Action: 'OPEN_APP',
Title: 'Message received',
SilentPush: false,
Body: `You have a new message`
;
console.log('sendMessagesParams', JSON.stringify(sendMessagesParams));
pinpoint.sendUsersMessages(sendMessagesParams, (sendMessagesErr, sendMessagesData) => console.log('push sent')
对于您的特定场景,我设置了 DynamoDB 流 并在表中的记录发生更改时触发 Lambda。创建 lambda 后,您可能需要手动添加 IAM 权限。
来源
Full list of pinpoint methods you can use in lambda (Node.JS) Update endpoint using Amplify Analytics (JS) Dynamodb streams - 触发 lambda【讨论】:
你是如何实例化 pinpoint 的?我已遵循所有文档,但被告知 sendUsersMessages 未定义。 sendMessages 工作正常.. 我确实指定了一个 API 版本,并且区域精确定位在:const pinpoint = new AWS.Pinpoint( apiVersion: '2016-12-01', region: process.env.PINPOINT_REGION );
process.env 常量列在 lambda 代码下方的“环境变量”部分中
在您的 Lambda 函数中,您是否需要提供 AWS 凭证或 IAM 角色?当我尝试运行您列出的代码时,根本没有任何反应
@Attaque 取决于您的实施方式,具体而言,我创建了一个移动目标完全访问策略,以允许发送消息,以及流 iam 角色。 "Version": "2012-10-17", "Statement": [ "Effect": "Allow", "Action": [ "mobiletargeting:*" ], "Resource": "*" ]
【参考方案2】:
我在让 lambda 函数正常工作时遇到了很多困难,所以请将此答案视为对 Dylan w 答案的补充。
客户
import PushNotification from '@aws-amplify/pushnotification';
import Analytics from '@aws-amplify/analytics';
PushNotification.onRegister((token) =>
Analytics.updateEndpoint(
address: token,
channelType: 'APNS',
optOut: 'NONE',
// Customized userId
userId: "e236e3ea-bas9-4eae-967e-0eb9bcaca26d" // Example
)
);
Lambda 函数
'use strict';
const AWS = require('aws-sdk');
exports.handler = async (event, context) =>
var pinpoint = new AWS.Pinpoint();
const sendMessagesParams =
ApplicationId: <YOUR_APPLICATION_ID>, // Find it in Pinpoint->All projects
SendUsersMessageRequest:
Users:<USER_ID>:, // The same userId as set on the client. This way you can "follow" people if they switch device
MessageConfiguration:
APNSMessage:
Action:"OPEN_APP",
Title:"Message received",
Body:"You have a new message"
;
return await new Promise( (resolve, reject) =>
pinpoint.sendUsersMessages(sendMessagesParams, (sendMessagesErr, sendMessagesData) =>
if(sendMessagesErr) reject(sendMessagesErr)
if(sendMessagesData) resolve(sendMessagesData)
);
);
;
请注意,对 pinpoint 的调用包含在一个承诺中。因为pinpoint.sendUserMessages
接受回调,所以会继续执行(Node 的异步性质),这将关闭 lambda 函数,您将不会从回调函数获得任何输出或收到通知,而无需等待函数完成。
【讨论】:
我收到一个:由于配置错误导致执行失败:格式错误的 Lambda 代理响应 Mon Sep 14 08:44:55 UTC 2020:方法完成,状态为:502 你知道如何解决吗?我相信这与 apigateway 响应有关,因为推送通知已发送 我正在使用pinpoint.sendMessages
,但它不起作用(没有错误,什么都没有)。我将它包装在return await new Promise(...)
中,现在消息发送,因为函数正在等待它。感谢您的提示!【参考方案3】:
最后,我得到了一些完美的作品。 答案是您必须使用“targetClient”来更新“didRegisterForRemoteNotificationsWithDeviceToken”函数内的端点。
let client = self.pinpoint!.targetingClient
let profile = client.currentEndpointProfile()
print("EndpointId = \(profile.endpointId)")
profile.user?.userId = <YOUR_CUSTOM_ID>
client.update(profile)
客户端(XCODE)
这是我的 [AppDelegate.swift] 的样子: (重要部分在“didRegisterForRemoteNotificationsWithDeviceToken”函数内)
import UserNotifications
import AWSPinpoint
class AppDelegate: UIResponder, UIApplicationDelegate
var pinpoint: AWSPinpoint?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
// Instantiate Pinpoint
let pinpointConfiguration = AWSPinpointConfiguration.defaultPinpointConfiguration(launchOptions: launchOptions)
// Set debug mode to use APNS sandbox, make sure to toggle for your production app
pinpointConfiguration.debug = true
self.pinpoint = AWSPinpoint(configuration: pinpointConfiguration)
// Present the user with a request to authorize push notifications
self.registerForPushNotifications()
return true
func registerForPushNotifications()
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) [weak self] granted, _ in
print("Permission granted: \(granted)")
guard granted else return
// Only get the notification settings if user has granted permissions
self?.getNotificationSettings()
func getNotificationSettings()
UNUserNotificationCenter.current().getNotificationSettings settings in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else return
DispatchQueue.main.async
// Register with Apple Push Notification service
UIApplication.shared.registerForRemoteNotifications()
func application(_: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
print("DidRegisterForRemoteNotificationsWithDeviceToken: Start")
let tokenParts = deviceToken.map data in String(format: "%02.2hhx", data)
let token = tokenParts.joined()
print("Device Token: \(token)")
// Register the device token with Pinpoint as the endpoint for this user
self.pinpoint!.notificationManager.interceptDidRegisterForRemoteNotifications(withDeviceToken: deviceToken)
//set custom userId and update endpoint
let client = self.pinpoint!.targetingClient
let profile = client.currentEndpointProfile()
print("EndpointId = \(profile.endpointId)")
profile.user?.userId = <YOUR_CUSTOM_ID>
client.update(profile)
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
print("Failed to register: \(error)")
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
print("didReceiveRemoteNotification:\(userInfo)")
// Pass this remote notification event to pinpoint SDK to keep track of notifications produced by AWS Pinpoint campaigns.
self.pinpoint!.notificationManager.interceptDidReceiveRemoteNotification(userInfo)
后端(带有 Nodejs 的 Lambda)
这是一个向特定用户发送通知的代码。
'use strict';
const AWS = require('aws-sdk');
const pinpoint = new AWS.Pinpoint(region: 'us-west-2');
exports.handler = (event, context, callback) =>
const done = (err, data) =>
if(err)
console.log('ERROR:', err);
const response =
statusCode: 400,
body: JSON.stringify(err)
;
callback(response);
else
console.log('SUCCESS:', data);
const response =
statusCode: 200,
body: JSON.stringify(data)
;
callback(null, response);
;
let users = ;
users[<YOUR_CUSTOM_ID>] = ;
const params =
ApplicationId: PINPOINT_PROJECT_ID,
SendUsersMessageRequest:
Users: users,
MessageConfiguration:
APNSMessage:
Action: 'OPEN_APP',
Title: "Hi, I am AWS Pinpoint.",
SilentPush: false,
Body: "You've got a nice message."
;
pinpoint.sendUsersMessages(params, (err, data)=>
if(err)
done(err);
else
done(null, data);
);
;
希望这些对你也有用。
【讨论】:
【参考方案4】:这当然可以通过 Amazon Pinpoint 实现。您可以找到 javascript SDK 文档here。
Pinpoint 有两种发送模式。
-
Direct send - 这实际上与传统上的 SNS 相同。您需要一个设备令牌,您可以使用该令牌直接发送给您的推送提供商。
Segmentation sends - 此模式略有不同,假设您已通过 Mobile SDK 作为应用程序的一部分或通过 S3 导入将所有设备加载到 Pinpoint。这样做的好处是您可以对您的设备进行分段并发送到该分段(例如“Ryans Friends”)。
因此,在您的 Lambda 支持的 API 中,您可以选择直接发送给订阅者(如果您有他们的地址)或可能是整个订阅者段(如果您已将端点加载到 Pinpoint)。
【讨论】:
我应该将 ARN 存储在我的DynamoDB
表中吗?或者Pinpoint
将帮助我管理 ARN。如果我想向 Ryans Friends 部分发送消息。我怎么能认出这个片段是给 Ryan 这个Cognito
身份的?以上是关于使用 AWS Pinpoint 通过 Lambda 函数发送通知的主要内容,如果未能解决你的问题,请参考以下文章