phptelegramtelegram-botphp-telegram-bot

Telegram bot with PHP file can't get "start" parameter from bot link and send to bot PHP file


I just created a bot in Telegram and deploy webhook a PHP file to respond to user's commands. There is a problem with this code that can't get a parameter in the shared url for start bot. it works fine when user start bot in normal way with normal URL (https://t.me/xxxx_bot) but I'm adding a referring part to my code to allow users get points based refers. So I need to make some URLs for users like https://t.me/xxxx_bot/?start=123456789, I could manage to create the refer link for each users, but when another users click this shared URL, and want to start bot, the bot can't get the start parameter's value.

The start parameter's value should get by bot, then send to bot's PHP file, then create a link to open as WebApp in the bot that include that start parameter's value like $storeURL = 'https://example.com/?username=' . $username . '&uid=' . $userID . '&start=' . $startParam;.

But currently in my code, the username and userID is getting from user's info, but the start parameter's value doesn't get. When user click the refer URL of bot and start bot, it showing Invalid command. Please choose an option from the menu. and when user manually send /start command, the bot can respond and send sendMessageWelcome function.

So I think when user start bot with https://t.me/xxxx_bot/?start=123456789 URL the first /start command included with a hidden thing (or included that start parameter but hide) that the bot can't respond to it for first time but when we retype /start manually, it respond to the command.

Tis is my code i hope anyone could help:

<?php

$botToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';
$telegramApi = 'https://api.telegram.org/bot'.$botToken;


$update = json_decode(file_get_contents('php://input'), true);

if (isset($update['message'])) {
    



$chatID = $update['message']['chat']['id'];
$messageText = $update['message']['text'];
$userID = $update['message']['from']['id'];
$username = $update['message']['from']['username'];
$firstname = $update['message']['from']['first_name'];
// $lastname = $update['message']['from']['last_name'];

// Check if the message contains a command with the start parameter
if (strpos($messageText, '/start') === 0) {
    // Check if the message contains a start parameter
    $startParam = explode(' ', $messageText)[1] ?? null;
    if ($startParam === null) {
        // Extract the start parameter from the URL if available
        $urlComponents = parse_url($messageText);
        if (isset($urlComponents['query'])) {
            parse_str($urlComponents['query'], $queryParameters);
            $startParam = $queryParameters['start'] ?? null;
        }
    }
    $storeURL = 'https://example.com/?username=' . $username . '&uid=' . $userID . '&start=' . $startParam;
}
    

$welcomeIMG = 'https://example.com/poster-welcome.jpg';
$captionwelcome = "Hello ".$firstname."! blah blah blah";
$secondIMG = 'https://example.com/poster-2.jpg';

// Set the image URL and caption message
$imageURL = 'https://example.com/poster-1.jpg';
$caption = "Welcome back ".$firstname."!\n\n blah blah blah";

switch ($messageText) {
    case '/start':
    $startParam = explode(' ', $messageText)[1] ?? null;
    $storeURL = 'https://example.com/?username=' . $username . '&uid=' . $userID . '&start=' . $startParam;
    sendMessageWelcome($chatID, $welcomeIMG, $captionwelcome, $storeURL, $startParam);
    sendKeyboard($chatID);
    break;
    
    case 'Open Store':
    sendStoreButton($chatID, $storeURL, $imageURL, $caption);
    break;
    case 'Referred members':
        $referredMembersCount = getReferredMembersCount($chatID);
        sendMessage($chatID, '💢 Number of referred members: '.$referredMembersCount);
        break;
    case 'Refer and point':
        $referLink = 'https://t.me/xxxxxxxx_bot?start='.$chatID;
        $message = "🔃 Your referral link is ".$referLink." \n\nShare it and earn points for each user.";
        $referredPlayersCount = getReferredPlayersCount($chatID);
        $message .= "\n\n💢 Number of players with your UID in the game: ".$referredPlayersCount;
        sendMessage($chatID, $message);
        break;
    default:
        sendMessage($chatID, 'Invalid command. Please choose an option from the menu.');
        sendKeyboard($chatID);
}
}

function sendMessage($chatID, $message) {
    global $telegramApi;
    
    $data = [
        'chat_id' => $chatID,
        'text' => $message
    ];

    $ch = curl_init($telegramApi.'/sendMessage');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_exec($ch);
    curl_close($ch);
}

function sendMessageWelcome($chatID, $welcomeIMG, $captionwelcome, $storeURL, $startParam) {
    global $botToken;

    $data = [
        'chat_id' => $chatID,
        'photo' => $welcomeIMG,
        'caption' => $captionwelcome ." UID: ". $startParam,
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [
                    [
                        'text' => "Open Store",
                        'web_app' => ['url' => $storeURL]
                    ],
                    [
                        'text' => 'Join our Channel',
                        'callback_data' => 'login_url',
                        'url' => 'https://t.me/xxxxxxxxx',
                    ]
                ]
            ]
        ])
    ];

    $url = "https://api.telegram.org/bot$botToken/sendPhoto";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    $result = curl_exec($ch);
    curl_close($ch);
}

function sendStoreButton($chatID, $storeURL, $imageURL, $caption) {
    global $botToken;

    $data = [
        'chat_id' => $chatID,
        'photo' => $imageURL,
        'caption' => $caption,
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [
                    [
                        'text' => "Open Store",
                        'web_app' => ['url' => $storeURL]
                    ],
                    [
                        'text' => 'Join our Channel',
                        'callback_data' => 'login_url',
                        'url' => 'https://t.me/xxxxxxxx',
                    ]
                ]
            ]
        ])
    ];

    $url = "https://api.telegram.org/bot$botToken/sendPhoto";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    $result = curl_exec($ch);
    curl_close($ch);
}


function sendKeyboard($chatID) {
    global $telegramApi;
    $keyboard = [
        ['Open Store'],
        ['Help', 'Support'],
        ['Referred members', 'Refer and point']
    ];
    $replyMarkup = [
        'keyboard' => $keyboard,
        'resize_keyboard' => true,
        'one_time_keyboard' => false
    ];
    $data = [
        'chat_id' => $chatID,
        'text' => 'Choose an option:',
        'reply_markup' => json_encode($replyMarkup)
    ];

    $ch = curl_init($telegramApi.'/sendMessage');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_exec($ch);
    curl_close($ch);
}

?>

Solution

  • Yes, a bot started through a link like https://t.me/xxxx_bot/?start=123456789 will only show "/start" in chat window itself.

    But the value stored in $update['message']['text'] will be start 123456789.

    You would need to adapt your switch-case from

    case '/start':
    

    to somthing like (PHP8)

    case str_starts_with($messageText, "/start "):
    

    or

    case substr($messageText, 0, 6 ) === "start=":