如何获取 Alexa 用户 ID?

Posted

技术标签:

【中文标题】如何获取 Alexa 用户 ID?【英文标题】:How to get an Alexa userId? 【发布时间】:2017-05-25 18:16:59 【问题描述】:

我正在构建一个 Alexa Skill,它要求我存储用户的 userId。我尝试使用event.session.user.userId 检索它。但是,当我调用console.log(event.session.user.userId) 时,输出实际上是amzn1.ask.account.[unique-value-here]。我查看了几个类似的问题,但没有一个为我提供足够清晰的答案。

我不确定这是否是一个错误、仅限开发人员使用,或者 userId 是否只是匿名的。如果是这样,有没有办法获取实际的用户 ID?我想会有,因为亚马逊在这里写了一个完整的指南:

https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system.

但是,经过一整天的调试,我不确定什么是真实的,什么不再是真实的。

var request = require('request');
var firebase = require('firebase');
var config = 
    apiKey: "my-api-key",
    authDomain: "stuff...",
    databaseURL: "more stuff...",
    storageBucket: "even more stuff...",
;
firebase.initializeApp(config);
// Get a reference to the database
var database = firebase.database();

exports.handler = (event, context) => 
    try 
        // New session
        if (event.session.new) 
            // New Session
            console.log("NEW SESSION");
        

        // Launch Request
        switch (event.request.type) 
            case "LaunchRequest":
                var url = "https://api.random.org/json-rpc/1/invoke";
                var myRequest = 
                    "jsonrpc": "2.0",
                    "method": "generateStrings",
                    "params": 
                        "apiKey": "another-api-key",
                        "n": "1",
                        "length": "3",
                        "characters": "abcdefghijklmnopqrstuvwxyz0123456789"
                    ,
                    "id": 24
                
                var pin;
                request.post(
                    url,
                    json: myRequest,
                    function (error, response, body) 
                        if (!error && response.statusCode == 200) 
                            console.log(event.session.user.userId); // **Here**, output is literally amzn1.ask.account.[unique-value-here] 
                            pin = body.result.random.data[0];
                            writeUserPin(pin);
                            var welcome = "Welcome";
                            var pinStatement = "Your 3 letter or number pin is: " + processPinForSpeech(pin);
                            context.succeed(
                                generateResponse(
                                    buildSpeechletReponse(welcome + pinStatement, true),
                                    
                                )
                            );
                            console.log(pin);
                        
                        else 
                            console.log(error);
                        
                    
                );
                console.log("LAUNCH REQUEST");
                break;
            // Intent Request
            case "IntentRequest":
                console.log("INTENT REQUEST");
                break;

            // Session Ended Request
            case "SessionEndedRequest":
                console.log("SESSION ENDED REQUEST");
                break;

            default:
                context.fail(`INVALID REQUEST TYPE: $event.request.type`);
        
    
    catch (error) 
        context.fail(`Exception: $error`);
    


    // Helpers
buildSpeechletReponse = (outputText, shouldEndSession) => 
    return 
        outputSpeech : 
            type: "PlainText",
            text: outputText
        ,
        shouldEndSession: shouldEndSession
    ;


generateResponse = (speechletResponse, sessionAttributes) => 
    return 
        version: "1.0",
        sessionAttributes: sessionAttributes,
        response: speechletResponse
    ;


function writeUserPin(pin) 
    console.log("writing stuff");
    firebase.database().ref('newPins/' + pin).set(
        num : ""
    );


function processPinForSpeech(pin) 
    var wordNumArr = ["zero", "one", "two", "three", "four",
     "five", "six", "seven", "eight", "nine"];
    processedPin = "";
    for (i = 0; i < pin.length; i++)
        var currentChar = pin.charAt(i);
        if (isNaN(Number(currentChar)))
            processedPin += currentChar + ". ";
        
        else 
            processedPin += wordNumArr[Number(currentChar)] + ". ";
        
    
    return processedPin

以下是 CloudWatch 日志的输出:


16:16:19
START RequestId: 48e335c5-d819-11e6-bc01-a939911adc24 Version: $LATEST

16:16:19
2017-01-11T16:16:19.639Z    48e335c5-d819-11e6-bc01-a939911adc24    NEW SESSION

16:16:19
2017-01-11T16:16:19.758Z    48e335c5-d819-11e6-bc01-a939911adc24    LAUNCH REQUEST

16:16:20
2017-01-11T16:16:20.457Z    48e335c5-d819-11e6-bc01-a939911adc24    amzn1.ask.account.[unique-value-here]

16:16:20
2017-01-11T16:16:20.457Z    48e335c5-d819-11e6-bc01-a939911adc24    writing stuff

16:16:20
2017-01-11T16:16:20.520Z    48e335c5-d819-11e6-bc01-a939911adc24    dd2

16:16:20
END RequestId: 48e335c5-d819-11e6-bc01-a939911adc24

16:16:20
REPORT RequestId: 48e335c5-d819-11e6-bc01-a939911adc24  Duration: 1005.48 ms    Billed Duration: 1100 ms Memory Size: 128 MB    Max Memory Used: 38 MB

【问题讨论】:

因为让我微笑而被投票赞成:“但是,经过一整天的调试,我不确定什么是真实的,什么不再是真实的。”哦,还因为这是一个非常详细的问题! 【参考方案1】:

你做得对。这个amzn1.ask.account.[unique-value-here] 实际上是完整的userId。您可以通过从 Echo 启用您的技能,将多个请求记录到您的 alexa 技能并观察这些请求之间的 userId 是相同的值来亲自观察这一点。

根据JSON Reference:

userId:一个字符串,表示用户的唯一标识符 提出了请求。此标识符的长度可以变化,但永远不会 超过 255 个字符。 userId 是自动生成的 用户在 Alexa 应用中启用该技能。

注意:禁用和重新启用技能会生成一个新标识符。

如果您只需要在会话之间保留用户属性,则该值就足够了,您可以使用它来唯一标识该用户,只要他们启用了该技能。

如果您需要链接一个帐户,您要查找的值是 accessToken,并且在成功的帐户链接后位于同一个 user 对象中。根据与上述相同的 JSON 参考:

accessToken:标识另一个系统中的用户的令牌。这是 仅在用户已成功关联其帐户时提供。看 Linking an Alexa User with a User in Your System了解更多详情。

【讨论】:

它们只对您的技能的个人用户是相同的;因此,例如,其他人使用您的技能和不同的回声将在amzn1.ask.account 之后具有不同的唯一值。因此,对于任何给定的用户,您都可以将此值保存到任何数据存储区(不仅仅是 Firebase),并且对于该用户来说它将是唯一的。 @MikiP 您能否编辑您的问题,并附上重现您如何提出请求和测试的步骤?抱歉,我不清楚您的唯一值不是随机字符串。应该是,您的程序必须以某种方式注入它。我们可以通过更多信息来澄清这一点。 @MikiP 其他一些想法:您是否通过 Lambda 进行开发?如果是这样,您能否检查您的 CloudWatch 日志以获取任何有用的调试信息?您是否无意中在代码中的任何位置设置了 UserId?有些教程让你在代码中粘贴这样的文字字符串以开始使用(例如,这在 applicationId 中很常见),并期望 [unique-value-here] 被开发人员替换,可能就是这样。 @MikiP 看看使用alexa-sdk。 如果我有两种不同的技能,我是否有可能获得两个技能相同的 userId...所以我可以跟踪一项技能的状态或进度并将其合并到第二技能?【参考方案2】:

好吧,事实证明我做的一切都是正确的(一次)。 userId 字面意思是 amzn1.ask.account.[unique-value-here] 的原因是因为我在 AWS Lambda 控制台中的“Alexa Start Session”测试事件中对其进行了测试。当我让我的 Echo Dot 启动该技能时,它会生成实际的密钥。问题解决了。

【讨论】:

您好 Miki,我尝试使用 Echo dot,但仍然看到 amzn1.ask.account.A.... .. 你是如何解决的?我想获取用户 ID/电子邮件/名称来识别用户。 @programmer 对我来说,在实际设备上启动技能给了我一个实际的密钥,而不是占位符值。如果您使用的是 Dot,但它仍然给您一个占位符值,不幸的是我不确定问题是什么。 三木,你说的实际键是什么意思?你得到用户名/电子邮件ID了吗? @programmer 按实际键,我的意思是我得到的是真实的用户名和电子邮件,而不是诸如 amzn1.ask.account 之类的占位符值。[unique-value-here] @MikiP 所以你是说在成功的帐户链接后你会看到一个真实的userId 用户登录而不是amzn1.ask.account.[unique-value-here] 由 Alexa 在启用技能时生成,这只是在 Echo Dot 上进行测试时发生了什么?我正在通过模拟器和 Alexa 控制台进行测试,如下所述:***.com/questions/54699087/… 和 ***.com/questions/54700595/… 并没有观察到这种行为。【参考方案3】:

您应该尝试读取 ASK 的测试控制台中显示的请求。从那里,您可以访问发送到您的 lambda 函数的不同变量。此外,您可以根据需要操作或使用它们。

【讨论】:

以上是关于如何获取 Alexa 用户 ID?的主要内容,如果未能解决你的问题,请参考以下文章

您如何从 Alexa 设备获取原始语音输入

如何在 Alexa 插槽中获取单个字母

Alexa Skill - 如何获取要求 Alexa 的完整声明文本

如何从 alexa API 获取竞争对手记录到数组

如何使用 Python ask sdk 检查和获取 Alexa 插槽值

Amazon Alexa Skills Kit:如何与外部应用程序帐户/用户 ID 关联