You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在手机端Telegram Bot中实现Google Sheets的本地授权访问

Integrate Google Sign-In into Your Telegram Bot for Mobile Local Authorization

Hey there! I’ve tackled similar Telegram Bot + Google OAuth flows before, so let’s break down exactly how to let users authorize your bot directly on their phones (no PC required) to access Google Spreadsheets.

1. First: Set Up OAuth 2.0 Credentials in Google Cloud

Before coding, you need to configure your Google Cloud project to enable OAuth:

  • Log into the Google Cloud Console and select your project.
  • Go to APIs & Services > Credentials.
  • Click Create Credentials > OAuth client ID.
  • Choose Web application as the application type.
  • For the Authorized redirect URIs, add the URL of a small web service you’ll build (more on this later) — this is where Google sends the authorization code after the user grants access.
  • Save your client ID and client secret somewhere safe; you’ll need them in your bot code.
  • Don’t forget to enable the Google Sheets API in your project (go to APIs & Services > Library, search for it, and enable).

2. Build the Authorization Flow in Your Telegram Bot

We’ll use Google’s OAuth 2.0 Authorization Code Flow — here’s how to implement it step-by-step (I’ll use Python with python-telegram-bot and requests as examples, but you can adapt this to your stack):

Create a function to build the link that users will click to grant permissions. We’ll include the necessary scopes (for Google Sheets access) and pass the user’s Telegram chat ID as a state parameter so we know who to send the authorization code back to.

from urllib.parse import urlencode

GOOGLE_CLIENT_ID = "your-client-id-here"
REDIRECT_URI = "your-web-service-callback-url-here"  # e.g., https://your-domain.com/google-callback

def generate_google_auth_link(chat_id):
    auth_params = {
        "client_id": GOOGLE_CLIENT_ID,
        "redirect_uri": REDIRECT_URI,
        "response_type": "code",
        "scope": "https://www.googleapis.com/auth/spreadsheets",  # Grants edit access to sheets
        "access_type": "offline",  # Lets us get a refresh token for long-term access
        "prompt": "consent",  # Ensures users see the permission screen every time (optional)
        "state": str(chat_id)  # Pass the user's chat ID to track who authorized
    }
    return f"https://accounts.google.com/o/oauth2/v2/auth?{urlencode(auth_params)}"

Add a command (like /authorize) that triggers the bot to send an inline button with the authorization link. Users can tap this directly on their phones:

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import CommandHandler, Updater

def handle_authorize_command(update, context):
    chat_id = update.effective_chat.id
    auth_link = generate_google_auth_link(chat_id)
    keyboard = [[InlineKeyboardButton("Grant Google Spreadsheet Access", url=auth_link)]]
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text(
        "Tap the button below to grant access to your Google Spreadsheet. After authorizing, you’ll get a code to send back here!",
        reply_markup=reply_markup
    )

# Initialize your bot
updater = Updater("your-telegram-bot-token-here")
updater.dispatcher.add_handler(CommandHandler("authorize", handle_authorize_command))

Step 3: Create a Callback Web Service to Receive the Authorization Code

Google needs a public URL to send the authorization code after the user grants access. You can build a simple Flask app (or use a serverless function like Google Cloud Functions/Vercel Edge Functions) to catch this code and send it back to the user’s Telegram chat:

from flask import Flask, request
import requests

app = Flask(__name__)
TELEGRAM_BOT_TOKEN = "your-telegram-bot-token-here"

@app.route("/google-callback")
def google_callback():
    auth_code = request.args.get("code")
    user_chat_id = request.args.get("state")  # This is the chat ID we passed earlier

    if auth_code and user_chat_id:
        # Send the authorization code back to the user's Telegram chat
        requests.get(
            f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
            params={
                "chat_id": user_chat_id,
                "text": f"Your authorization code is:\n`{auth_code}`\nReply with this code to complete setup!"
            }
        )
        return "Authorization successful! Return to your Telegram chat to finish setup."
    return "Authorization failed. Please try again."

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

If you’re testing locally, use a tool like ngrok to expose your Flask app to the public web (e.g., ngrok http 5000 — use the generated HTTPS URL as your REDIRECT_URI).

Step 4: Exchange the Authorization Code for Access Tokens

When the user replies with the authorization code, your bot needs to exchange it for an access token (to use the Sheets API) and a refresh token (to get new access tokens when the old one expires):

import json
from telegram.ext import MessageHandler, Filters

GOOGLE_CLIENT_SECRET = "your-client-secret-here"

def exchange_code_for_tokens(auth_code):
    token_payload = {
        "code": auth_code,
        "client_id": GOOGLE_CLIENT_ID,
        "client_secret": GOOGLE_CLIENT_SECRET,
        "redirect_uri": REDIRECT_URI,
        "grant_type": "authorization_code"
    }
    response = requests.post("https://oauth2.googleapis.com/token", data=token_payload)
    if response.status_code == 200:
        return response.json()  # Contains access_token, refresh_token, expires_in
    return None

def handle_auth_code_reply(update, context):
    user_chat_id = update.effective_chat.id
    auth_code = update.message.text.strip()
    
    token_data = exchange_code_for_tokens(auth_code)
    if token_data:
        # Save the tokens securely (e.g., in a local file, database, or encrypted storage)
        with open(f"user_tokens/{user_chat_id}.json", "w") as f:
            json.dump(token_data, f)
        update.message.reply_text("✅ Authorization complete! You can now use the bot to manage your Google Spreadsheet.")
    else:
        update.message.reply_text("❌ Invalid authorization code. Please try again.")

# Add handler to catch user's code replies
updater.dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, handle_auth_code_reply))

3. Use the Tokens to Access Google Spreadsheets

Now that you have the tokens, you can use them to read/write to the user’s spreadsheet. Don’t forget to refresh the access token when it expires:

def refresh_access_token(refresh_token):
    refresh_payload = {
        "refresh_token": refresh_token,
        "client_id": GOOGLE_CLIENT_ID,
        "client_secret": GOOGLE_CLIENT_SECRET,
        "grant_type": "refresh_token"
    }
    response = requests.post("https://oauth2.googleapis.com/token", data=refresh_payload)
    if response.status_code == 200:
        return response.json()["access_token"]
    return None

def write_to_spreadsheet(chat_id, spreadsheet_id, range_name, values):
    # Load the user's tokens
    with open(f"user_tokens/{chat_id}.json", "r") as f:
        token_data = json.load(f)
    
    access_token = token_data["access_token"]
    headers = {"Authorization": f"Bearer {access_token}"}
    payload = {"values": values}

    # Try to write to the spreadsheet
    response = requests.put(
        f"https://sheets.googleapis.com/v4/spreadsheets/{spreadsheet_id}/values/{range_name}?valueInputOption=USER_ENTERED",
        json=payload,
        headers=headers
    )

    # If access token is expired, refresh it and retry
    if response.status_code == 401:
        new_access_token = refresh_access_token(token_data["refresh_token"])
        if new_access_token:
            token_data["access_token"] = new_access_token
            with open(f"user_tokens/{chat_id}.json", "w") as f:
                json.dump(token_data, f)
            headers["Authorization"] = f"Bearer {new_access_token}"
            response = requests.put(
                f"https://sheets.googleapis.com/v4/spreadsheets/{spreadsheet_id}/values/{range_name}?valueInputOption=USER_ENTERED",
                json=payload,
                headers=headers
            )
    
    return response.status_code == 200

4. Key Notes to Avoid Headaches

  • OAuth Consent Screen: If your app is in testing mode, add your users as test users in the Google Cloud Console (APIs & Services > OAuth consent screen) so they can grant access.
  • Token Security: Never store tokens in plain text. For small projects, you can encrypt them; for larger ones, use a secure database.
  • Public Callback URL: Make sure your callback web service is accessible over HTTPS (Google requires this for OAuth redirects).

内容的提问来源于stack exchange,提问作者Valentin Kornienko

火山引擎 最新活动