【问题标题】:Send a notification by Lambda function with AWS Pinpoint使用 AWS Pinpoint 通过 Lambda 函数发送通知
【发布时间】:2017-12-29 16:38:30
【问题描述】:

我有一个由MobileHubAPI GatewayLambdaDynamoDB 构建的iOS 应用程序。 我注意到MobileHubSNS 功能已被Pinpoint 取代,我想使用这个新服务创建一个通知系统。

当用户通过API Gateway创建新帖子时,会触发一个lambda函数,我想我可以通过Pinpoint向订阅者发送通知。 但是我在Pinpoint的官方网站上找不到任何示例或参考文档。

你有这个场景的任何资源或任何想法吗?非常感谢!

【问题讨论】:

    标签: node.js amazon-web-services aws-lambda aws-cognito aws-pinpoint


    【解决方案1】:

    取决于您所说的通知是什么意思,我假设您想向特定用户发送推送通知(Pinpoint 端点)。

    Pinpoint 将与用户关联的每个设备存储为“端点”,通常由 AWS 客户端分析库创建(例如放大分析)。

    客户

    使用放大分析库,我调用updateEndpoint,这样我就可以指定一个可供 Lambda 使用的userId,以及设备令牌并删除optOut,这样用户就可以接收推送通知:

    1. Address - 用户接受推送通知权限时生成的令牌 (iOS)
    2. optOut - NONE 以便他们接收推送通知
    3. 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 权限。

    来源

    【讨论】:

    • 你是如何实例化 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 有两种发送模式。

      1. Direct send - 这实际上与传统上的 SNS 相同。您需要一个设备令牌,您可以使用该令牌直接发送给您的推送提供商。
      2. Segmentation sends - 此模式略有不同,假设您已通过 Mobile SDK 作为应用程序的一部分或通过 S3 导入将所有设备加载到 Pinpoint。这样做的好处是您可以对您的设备进行分段并发送到该分段(例如“Ryans Friends”)。

      因此,在您的 Lambda 支持的 API 中,您可以选择直接发送给订阅者(如果您有他们的地址)或可能是整个订阅者段(如果您已将端点加载到 Pinpoint)。

      【讨论】:

      • 我应该将 ARN 存储在我的 DynamoDB 表中吗?或者Pinpoint 将帮助我管理 ARN。如果我想向 Ryans Friends 部分发送消息。我怎么能认出这个片段是给 Ryan 这个Cognito 身份的?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多