Actions SDK云函数使用与用户UID获取及认证问题咨询
Hey there! Let's break down your questions step by step since you're new to the Actions SDK. I'll cover UID retrieval, calling your getUser function, user creation, authentication flows, and how to handle auth after triggering the main intent.
一、UID是什么?怎么正确获取并调用getUser?
First off, the UID you're looking for is the unique ID tied to the user's Google account, which the Actions SDK provides directly via conv.user.id in your conversation handler. Your current getUser function is set up as a standalone HTTP function expecting a URL parameter (req.params.uid), which won't work for Assistant requests—we need to refactor it to integrate with your Actions flow.
Step 1: Initialize Firebase Admin (you missed this!)
First, add this line right after importing admin to connect your function to Firebase:
admin.initializeApp(); // 放在文件顶部,functions和admin引入之后
Step 2: Refactor getUser into a reusable helper function
Instead of a separate HTTP endpoint, make it an async function that accepts a UID and fetches from Firestore:
// Helper function to fetch user data from Firestore async function getUser(uid) { try { const userDoc = admin.firestore().doc(`users/${uid}`); const snapshot = await userDoc.get(); return snapshot.exists ? snapshot.data() : null; } catch (error) { console.error('Failed to fetch user:', error); throw error; } }
Step 3: Call getUser from your main intent
Now you can use this helper directly in your dairyProduct function's MAIN intent:
app.intent('actions.intent.MAIN', async (conv, input) => { // Grab the user's Google-assigned UID const userUid = conv.user.id; console.log('Current user UID:', userUid); try { const userData = await getUser(userUid); if (userData) { conv.ask(`<speak>Hi! Welcome back, ${userData.name}! You said <say-as>${input}</say-as>.</speak>`); } else { // User doesn't exist yet—prompt them to create an account conv.ask(`<speak>Hi there! Looks like you're new here. You said <say-as>${input}</say-as>. What's your name? I'll set up your account.</speak>`); // Set a context to handle the account creation flow next conv.contexts.set('create_user', 5); } } catch (error) { conv.ask('<speak>Oops, something went wrong fetching your info. Try again later!</speak>'); } });
二、User Creation & End-User Authentication Examples
1. Creating a User Profile (Firestore)
When a new user joins, collect their details (like name) and save to Firestore with their UID as the document ID:
// Add an intent to handle account creation app.intent('create_user_intent', async (conv, userName) => { const userUid = conv.user.id; try { await admin.firestore().doc(`users/${userUid}`).set({ name: userName, createdAt: admin.firestore.FieldValue.serverTimestamp() }); conv.close(`<speak>All set! Welcome aboard, ${userName}!</speak>`); } catch (error) { conv.ask('<speak>Sorry, I couldn\'t create your account right now. Try again later?</speak>'); } });
2. Google Account OAuth2 Authentication
If you need access to more user data (like email or full name), set up Google Sign-In for account linking:
Step 1: Configure Account Linking in Actions Console
- Go to your Actions project → Account Linking
- Select Google Sign-In as the auth method
- Choose scopes like
profileandemailto request the data you need - Save your settings
Step 2: Handle Authentication in Code
Update your MAIN intent to check for auth, and add a handler for the sign-in result:
// Import the SignIn class first const {actionssdk, SignIn} = require('actions-on-google'); // MAIN intent with auth check app.intent('actions.intent.MAIN', async (conv) => { // Check if the user is authenticated if (!conv.user.profile) { // Prompt the user to sign in conv.ask(new SignIn()); } else { // User is authenticated—get their profile data const userProfile = conv.user.profile; const userUid = conv.user.id; console.log('User profile:', userProfile); // Create or update the user in Firestore const userData = await getUser(userUid); if (!userData) { await admin.firestore().doc(`users/${userUid}`).set({ name: userProfile.displayName, email: userProfile.email, createdAt: admin.firestore.FieldValue.serverTimestamp() }); } conv.ask(`<speak>Hi ${userProfile.displayName}! Great to see you again!</speak>`); } }); // Handle the sign-in result app.intent('actions.intent.SIGN_IN', async (conv, input, signIn) => { if (signIn.status === 'OK') { // Auth succeeded—fetch the user's profile const userProfile = conv.user.profile; const userUid = conv.user.id; // Update Firestore with latest info await admin.firestore().doc(`users/${userUid}`).set({ name: userProfile.displayName, email: userProfile.email, lastLogin: admin.firestore.FieldValue.serverTimestamp() }, { merge: true }); conv.ask(`<speak>Sign-in successful! Welcome, ${userProfile.displayName}!</speak>`); } else { conv.ask('<speak>You didn\'t complete sign-in, so I can\'t access your account details right now.</speak>'); } });
三、Authentication Flow After Triggering the MAIN Intent
When a user says "Talk to Dairy Product" to trigger your main intent, here's what happens:
- Your code checks if the user is authenticated via
conv.user.profile - If not authenticated, the
SignInprompt is sent to the user—Google Assistant will walk them through logging into their Google account - Once signed in, the
actions.intent.SIGN_INintent is triggered, where you handle the success/failure - On success, you can create/update the user's Firestore document using their UID and profile data
- From then on, you can always use
conv.user.idto fetch their data with yourgetUserhelper
四、Update Your action.json
Add the actions.intent.SIGN_IN intent to your inDialogIntents so Assistant knows to route sign-in requests to your fulfillment:
{ "actions": [ { "description": "Default Welcome Intent", "name": "MAIN", "fulfillment": { "conversationName": "testapp" }, "intent": { "name": "actions.intent.MAIN", "trigger": { "queryPatterns": [ "Talk to Dairy Product" ] } } } ], "conversations": { "testapp": { "name": "testapp", "url": "https://us-central1-samplejs6-id.cloudfunctions.net/dairyProduct", "fulfillmentApiVersion": 2, "inDialogIntents": [ { "name": "actions.intent.CANCEL" }, { "name": "actions.intent.SIGN_IN" } ] } }, "locale": "en" }
内容的提问来源于stack exchange,提问作者Thirumani

