Telegram API, get the sender's phone number? - php

I realize it is not possible to use a Bot to receive a sender's phone number.
I do, however, need to implement a bot-like client, that responds to anyone who is messaging it. I am using PHP on apache.
It is not a Bot, as it does not take commands, but rather responds to sent text from anyone who has that phone number. So you add the user as a contact (using a phone number), and then send text to it.
My goal is to realise the sender's phone number as I receive it, I saw on the Telegram API that there's a peer ID, but I can't find how to get the phone number if that's even possible...

try this lib from github https://github.com/irazasyed/telegram-bot-sdk
and code to create 'visit card' button in private chat:
$keyboard = array(
array(
array(
'text'=>"Send your visit card",
'request_contact'=>true
)
)
); //user button under keyboard.
$reply_markup = $telegram->replyKeyboardMarkup([ 'keyboard' => $auth_keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => false ]);
$telegram->sendMessage([ 'chat_id' => $chat_id, 'text' => $reply, 'reply_markup' => $reply_markup ]);
and code to get unic user phone from 'visit card' after user push the button
$user_phone = $result["message"]["contact"]["phone_number"];
if ($user_phone) {
$reply = $user_phone;
$telegram->sendMessage([ 'chat_id' => $chat_id, 'text' => $reply, 'reply_markup' => $reply_markup ]);
}

finally i found how to get the phone number.
I use package https://github.com/irazasyed/telegram-bot-sdk for Laravel 8.
The code below is command to send button and when user press the button, it'll catch the phone number from user after the user click on "share".
PhoneNumberCommand.php
public function handle()
{
$response = $this->getUpdate();
$chat_id = $response->getChat()->getId();
$btn = Keyboard::button([
'text' => 'Varify',
'request_contact' => true,
]);
$keyboard = Keyboard::make([
'keyboard' => [[$btn]],
'resize_keyboard' => true,
'one_time_keyboard' => true
]);
return $this->telegram->sendMessage([
'chat_id' => $chat_id,
'text' => 'Please click on Verify and Share.',
'reply_markup' => $keyboard
]);
}
ControllerWebhook.php
public function commandHandlerWebHook()
{
$updates = Telegram::commandsHandler(true);
$chat_id = $updates->getChat()->getId();
// Catch Phone Number
$user_phone = array_key_exists('contact', $updates['message']) ?
$updates['message']['contact']['phone_number'] : null;
$text = 'Phone number : ' . $user_phone;
if($user_phone) return Telegram::sendMessage(['chat_id' => $chat_id, 'text' => $text]);
return 'ok';
}
It's work for me! hope you can implement too.

Related

add option to choose different chat id for telegram bot

I made a simple telegram bot with PHP to copy and send any messages that receives to another group
but how can I give the option to user in the bot to choose different groups to send
for example to group A or B
$msgID = $updates["message"]["message_id"];
file_get_contents($link."/copyMessage?chat_id=GroupA&from_chat_id=999999&message_id=$msgID&disable_notification=true");
file_get_contents($link."/copyMessage?chat_id=GroupB&from_chat_id=999999&message_id=$msgID&disable_notification=true");
I think sending message with buttons it's better way to that.
It'll be like this:
User sends /start command
User sends any message
Bot reply user's message with buttons
User chooses a button
Bot copies message to selected chat
Bot answers user with success or fail
Use this code:
# Configuration that you need to fill
# Bot token obtained from #BotFather
define('BOT_TOKEN', 'Put your bot token here');
# Chat IDs Or Usernames that messages will be copied to
$chats =
[
# Username/ID => 'Chat title'
'#MyOwnGroup' => 'The bot creator group',
'1265170068' => 'My own account'
];
# Function to call any Bot API method
function bot(string $method, array $data = [])
{
$api_url = 'https://api.telegram.org/bot' . BOT_TOKEN . "/$method";
if (count(data) > 0)
{
$api_url .= '?'.http_build_url($data, '', '&');
}
return file_get_contents($api_url);
}
# The update data, Received from Telegram
$update = json_decode(file_get_contents('php://input'));
# Handle if new message received
if (property_exists($update, 'message') && $update->message->text !== '/start')
{
$message = $update->message;
$buttons = ['inline_keyboard' => []];
foreach ($chats as $chat_id => $chat_title)
{
array_push($buttons['inline_keyboard'], [['text' => $chat_title, 'callback_query' => $chat_id]]);
}
# Sending message with buttons to get which group the user wants
bot('sendMessage', [
'chat_id' => $message->chat->id,
'text' => 'Select which group you want to send the message..',
'reply_to_message_id' => $message->message_id,
'reply_markup' => json_encode($buttons)
]);
}
# Handle if one of buttons was pressed
if (property_exists($update, 'callback_query'))
{
$callback_query = $update->callback_query;
# Copy the message
$result = bot('copyMessage', [
'from_chat_id' => $callback_query->message->chat->id,
'message_id' => $callback_query->message->message_id,
'chat_id' => $callback_query->data
]);
if ($result->ok == true)
{
bot('answerCallbackQuery', [
'callback_query_id' => $callback_query->id,
'text' => 'Message was sent successfully!'
]);
}
else
{
bot('answerCallbackQuery', [
'callback_query_id' => $callback_query->id,
'text' => 'Message sending failed!',
'show_alert' => true
]);
}
}

Amazon Pay SDK InvalidSignatureError

I'm integrating Amazon Pay php SDK from documentation, but getting this error.
Here's my php implementation code:
$amazonpay_config = array(
'public_key_id' => 'XXXXXXXX',
'private_key' => 'my_private_key_path',
'region' => 'US',
'sandbox' => true
);
$payload = array(
'webCheckoutDetails' => array(
'checkoutReviewReturnUrl' => 'https://www.example.com/review',
'checkoutResultReturnUrl' => 'https://www.example.com/result'
),
'storeId' => 'amzn1.application-oa2-client.XXXXXXXXX'
);
$headers = array('x-amz-pay-Idempotency-Key' => uniqid());
$requestResult = [
'error' => 1,
'msg' => 'Error. Can not create checkout session.',
'checkoutSession' => null,
'payloadSign' => null
];
$client = new Client($amazonpay_config);
$resultCheckOut = $client->createCheckoutSession($payload, $headers);
$resultSignPayload = $client->generateButtonSignature($payload);
if($resultCheckOut['status'] !== 201) {
return json_encode($requestResult, true);
}
else {
$requestResult = [
'error' => 0,
'msg' => null,
'checkoutSession' => json_decode($resultCheckOut['response']),
'payloadSign' => $resultSignPayload
];
return $requestResult;
}
Here's JS implementation code for generating Amazon Pay button.
amazon.Pay.renderButton('#amazon-pay-btn', {
// set checkout environment
merchantId: 'XXXXXXXX',
ledgerCurrency: 'USD',
sandbox: true,
checkoutLanguage: 'en_US',
productType: 'PayOnly',
placement: 'Cart',
buttonColor: 'Gold',
createCheckoutSessionConfig: {
payloadJSON: jsonResult['checkoutSession'],
signature: jsonResult['payloadSign'],
publicKeyId: 'XXXXXXXXXXX'
}
});
Couple of problems with the code, mainly that you aren't passing the payload and signature to the front-end correctly. For the payload, you're using jsonResult['checkoutSession'], while it should be jsonResult['payloadSign']. This doesn't contain the payload though but from the PHP code it's apparently the signature that you have put in there. The full code sample should more like this (not tested).
Back-end:
$headers = array('x-amz-pay-Idempotency-Key' => uniqid());
$requestResult = [
'error' => 1,
'msg' => 'Error. Can not create checkout session.',
'signature' => null,
'payload' => null
];
$client = new Client($amazonpay_config);
$resultCheckOut = $client->createCheckoutSession($payload, $headers);
$resultSignature = $client->generateButtonSignature($payload);
if($resultCheckOut['status'] !== 201) {
return json_encode($requestResult, true);
}
else {
$requestResult = [
'error' => 0,
'msg' => null,
'signature' => $resultSignature,
'payload' => $payload
];
return json_encode($requestResult);
}
Front-end:
amazon.Pay.renderButton('#amazon-pay-btn', {
// set checkout environment
merchantId: 'XXXXXXXX',
ledgerCurrency: 'USD',
sandbox: true,
checkoutLanguage: 'en_US',
productType: 'PayOnly',
placement: 'Cart',
buttonColor: 'Gold',
createCheckoutSessionConfig: {
payloadJSON: JSON.stringify(jsonResult['payload']),
signature: jsonResult['signature'],
publicKeyId: 'XXXXXXXXXXX'
}
});
I'm not sure how you're passing $requestResult back to the front-end, potentially there's some additional JSON encoding/decoding required to get the right string. To prevent a signature mismatch error, please make sure that the payload string used for the signature generation in the backend, and the payload string assigned to the 'payloadJSON' parameter match exactly (especially pay attention to whitespaces, escape characters, line breaks, etc.).
Two comments about this issue:
I have defined the payload as an string (that's the way current AmazonPay doc states - Link).
$payload = '{
"webCheckoutDetails": {
"checkoutReviewReturnUrl": "https://www.example.com/review",
"checkoutResultReturnUrl": "https://www.example.com/result"
},
"storeId": "amzn1.application-oa2-client.XXXXXXXXX"
}';
instead of array
$payload = array(
'webCheckoutDetails' => array(
'checkoutReviewReturnUrl' => 'https://www.example.com/review',
'checkoutResultReturnUrl' => 'https://www.example.com/result'
),
'storeId' => 'amzn1.application-oa2-client.XXXXXXXXX'
);
The signature was created, but when rendering the button and clicking on it I get the following error.
Error Message: Signature Dk4qznkoiTVqjcY8Yn1l0iLbsoIj2pEAHWVtgYrphLtFXR9BKhJJPD53It4qYOswS1T/STYMHRy5jtCHGqvLntDjuy0MrhkpoHTpYEtwdOqGHA2qk+QnSGV5LoYldQ/UkAxSG7m8s2iOr11q2sWxUjrk2M3fgzAIxDeZRjJYeAr97eGANYva3jtGDfM6cJdieInBM4dEWWxKqGIh6HxOrY5K/ga26494vAwZAGvXRhZG48FOVp/XCr0mbu6V5pkEOzRJSc+hN5WKAs/c49UsfKPx75Ce7QbaBCZZT1UiczfyYx/mBuZuysUlGmnXPhLOLTPw4+SIizH/pOQyClOQyw== does not match signedString AMZN-PAY-RSASSA-PSS dfff7a87b93cfa78685a233f2dd59e18ad0451b2e3a90af11e500fcc0ceee924 for merchant XXXXXXXX
I was some time till I realized that this was the reason of the error. Actually, while writing this, the new lines in the string were the reason. If string is only in one line, it works.
The button only needs the payload and the signed payload. The $client->createCheckoutSession is not needed. More over, the checkoutSessionId of the resultCheckOut is different from the one obtained when the checkoutReviewReturnUrl is called.

Using the Onesignal Api "ADDITIONAL DATA" field

I use Onesignal notifications for the app.
I don't have a problem sending the notifications but wanted to send these notifications using API help and this library.
php-onesignal library
The notifications I sent must be opened on the relevant page in the application. For this reason, I do not know how to write the URL in the code section below.
require_once(dirname(__FILE__).'/vendor/autoload.php');
use CWG\OneSignal\OneSignal;
$appID = '92b9c6bb-89d2-4cbc-8862-a80e4e81a251';
$authorizationRestApiKey = 'MWRjMTg2MjEtNTBmYS00ODA4LWE1M2EtM2YyZjU5ZmRkNGQ5';
$deviceID = '69aeecc1-7b58-44d1-8000-7767de437adf';
$api = new OneSignal($appID, $authorizationRestApiKey);
$retorno = $api->notification->setBody('Ola')
->setTitle('Titulo')
->addDevice($deviceID)
->send();
I entered the addTag section as in the Onesignal panel, but I could not run it.
$retorno = $api->notification->setBody('Ola')
->setTitle('Titulo')
->addTag('url', 'http://www.example.com/news/testtitle')
->send();
print_r($retorno);
How can I use it here in the Url section of the "ADDITIONAL DATA" field?
Can I solve this problem with addTag?
The following will send a notification with the $data['data'] as additional, as you want.
$data = [
'headings' => ['en' => 'Case 123'],
'contents' => ['en' => 'Case assigned ' . date('d-m-Y H:i')],
'data' => [
'type' => 'new',
'user_id' => 123,
'url' => 'http://www.example.com/news/testtitle'
],
];
OneSignal::sendNotificationCustom([
'app_id' => 1234,
'api_key' => abcd,
'included_segments' => ['All'],
'headings' => $data['headings'],
'contents' => $data['contents'],
'data' => $data['data'],
]);

Laravel push notifications

I'm using this library: https://github.com/davibennun/laravel-push-notification for sending push notifications. I used the example code and the push messages to my iPhone are working.
Only now I want to send 1 message to multiple devices. The docs say that I need to use:
$devices = PushNotification::DeviceCollection(array(
PushNotification::Device('token', array('badge' => 5)),
PushNotification::Device('token1', array('badge' => 1)),
PushNotification::Device('token2')
));
$message = PushNotification::Message('Message Text',array(
'badge' => 1,
'sound' => 'example.aiff',
'actionLocKey' => 'Action button title!',
'locKey' => 'localized key',
'locArgs' => array(
'localized args',
'localized args',
),
'launchImage' => 'image.jpg',
'custom' => array('custom data' => array(
'we' => 'want', 'send to app'
))
));
$collection = PushNotification::app('appNameIOS')
->to($devices)
->send($message);
// get response for each device push
foreach ($collection->pushManager as $push) {
$response = $push->getAdapter()->getResponse();
}
But I want a foreach loop from my database on the devicecollection. How do I do that with laravel? Many thanks!
foreach($usersApple as $userApple){
echo $userApple->reg_id . '<br>';
$deviceslist[] = PushNotification::Device($userApple->reg_id);
}
$devices = PushNotification::DeviceCollection($deviceslist);
Already fixed, was not sharp today haha

AWS SES on PHP error: Unable to determine service/operation name to be authorized

I am trying to send email using AWS SES using the following PHP script:
<?php
require_once("phar://aws.phar");
use Aws\Ses\SesClient;
//Open client
$client = SesClient::factory(array(
"key" => "key",
"secret" => "secret",
"region" => "region"
));
$subject = "subject";
$messageText = "text message";
$messageHtml = "<h1>formatted message</h1>";
//Send email
try{
$response = $client->sendEmail(
array(
'Source' => 'verified_email#domain.com',
'Destination' => array(
'ToAddresses' => array('an_address#domain.com')
),
'Message' => array(
'Subject' => array('Data' => $subject),
'Body' => array('Text' => array('Data' => $messageText)),
'Html' => array('Data' => $messageHtml)
)
)
);
}catch(Exception $e){
//An error happened and the email did not get sent
echo($e->getMessage());
}
?>
Whenever I run this, it goes to the catch clause and prints to the screen the message:
Unable to determine service/operation name to be authorized
This doesn't really give me any information on what's wrong and there's no documentation on the API page about this. Any ideas?

Categories