用戶登入 miniApp 時我們可以獲得 initData 裡面包含用戶名稱與 id 等等,當中包含 miniApp 幫用戶自動產生的 hash,而我們要用加密驗證的方式來將 tg bot 與這個 hash 驗證,確定實際上是這個用戶在操作 APP,可使用以下代碼來驗正
useEffect(() => {
const webApp = window?.Telegram.WebApp;
console.log('WebAppInitData:', webApp.initData); // querystring 型態
}, [window?.Telegram.WebApp]);
async signinUser(webInitData: string, ip: string) {
function validateTelegramWebAppData(initData, botToken) {
// Step 1: Parse initData into an object
const params = new URLSearchParams(initData);
const dataObj = {};
params.forEach((value, key) => {
dataObj[key] = value;
});
// Step 2: Extract and remove the hash
const receivedHash = dataObj['hash'];
delete dataObj['hash'];
// Step 3: Sort the keys and construct dataCheckString
const dataCheckString = Object.keys(dataObj)
.sort()
.map(key => `${key}=${dataObj[key]}`)
.join('\n');
// Step 4: Create a secret key using the bot token
const secretKey = createHmac('sha256', 'WebAppData')
.update(botToken)
.digest();
// Step 5: Hash the dataCheckString using the secret key
const calculatedHash = createHmac('sha256', secretKey)
.update(dataCheckString)
.digest('hex');
// Step 6: Compare calculated hash with received hash (both should be lowercase)
return { isOk: calculatedHash === receivedHash, dataObj };
}
if (!webInitData) {
throw new BadRequestException('webInitData is required');
}
const botToken = process.env['TG_BOT_TOKEN']; // 這邊記得在 .env 檔案放上 TG_BOT_TOKEN
const { isOk, dataObj } = validateTelegramWebAppData(webInitData, botToken)
if (!isOk) {
throw new BadRequestException('Invalid tg sigature');
}
const userData = JSON.parse(dataObj['user']);
if (!botToken) {
console.log('Something wrong for tg bot token');
throw new BadRequestException('Something wrong for tg bot token');
}
const userId = String(userData['id']);
const username = String(userData['username']);
// 到了這邊已經驗證用戶成功,可以使用 userData 內的資料來進行操作
}