Status call back not working in twilio - php

Iam using twilio Programmable voice while trying to Tracking the call status of an outbound call and save it log whether the user answer or cut the call ,but the problem i didn't get any log and while checking in twilio debugger it showing error:15003
Here my Code:
<?php
require_once "vendor/autoload.php";
use Twilio\Rest\Client;
$AccountSid= 'AC04421826f5ffaa58eaefa1ba6984dac2';
$AuthToken= 'token';
$client = new Client($AccountSid, $AuthToken);
try {
$call = $client->account->calls->create(
// to call.
"+9120000000",
"+1209000001",
array(
"url" => "http://demo.twilio.com/docs/voice.xml",
"method" => "GET",
"statusCallbackMethod" => "POST",
"statusCallback" => "localhost/twilio/log.txt",
"statusCallbackEvent" => array(
"initiated", "ringing", "answered", "completed"
)
)
);
echo "Started call: " . $call->sid;
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}

Twilio evangelist here.
Looks like you have set the statuscallback property to point to localhost.
localhost is a domain that is only reachable from your own local machine so Twilio does not how to reach the localhost running on your local machine.
I'd suggest checking out ngrok which is a simple tool that lets you expose the web server running on your local machine via a publicly addressable domain.
Hope that helps

The issue here is a GET or POST request cannot be written directly to log.txt file and the file should be hosted on a http domain.
change the following code
"statusCallback" => "localhost/twilio/log.txt",
to
"statusCallback" => "http://yourdomain.com/twilio/log.php",
as you rather need an additional file log.php which can write to log.txt
<?php
$status = implode(',',$_REQUEST) ;
$handle = fopen('log.txt','a');
fwrite($handle, $status);
?>

Related

How do I authenticate a service account in Google Cloud Services in PHP?

While developing Recaptcha Enterprise for use of the V2 "I am not a robot" checkbox, I am stuck on this error:
Fatal error: Uncaught DomainException: Could not load the default credentials. Browse to https://developers.google.com/accounts/docs/application-default-credentials for more information
I follow the link and have settled on this to authenticate:
use Google\Cloud\Storage\StorageClient;
$storage = new StorageClient([
'keyFile' => json_decode(file_get_contents($path_to_keyfile), true),
'projectId' => 'MY_PROJECT'
]);
I cannot find anything else that suggests I need to do anything more than this, and this link to the constructor API doesn't suggest I can pass it in as a parameter and then proceed. I do not want to use environment variables for this project, I want to connect manually in the code. What am I missing? I can confirm I have a working service account.
If it's helpful, the code I'm trying to run after I presumably authenticate is this:
// ==================== CAPTCHA ===================
use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;
$captcha_response = $_POST['g-recaptcha-response'];
$site_key = "123456789abc";
$client = new RecaptchaEnterpriseServiceClient();
define('SITE_KEY', $site_key);
define('TOKEN', $captcha_response);
define('PROTECTED_ACTION', 'signup');
define('PARENT_PROJECT', 'projects/MY_PROJECT');
$event = (new Event())
->setSiteKey(SITE_KEY)
->setExpectedAction(PROTECTED_ACTION)
->setToken(TOKEN);
$assessment = (new Assessment())
->setEvent($event);
try {
$response = $client->createAssessment(
PARENT_PROJECT,
$assessment
);
if ($response->getTokenProperties()->getValid() == false) {
printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
} else {
if ($response->getEvent()->getExpectedAction() == PROTECTED_ACTION) {
printf('The score for the protection action is:');
printf($response->getRiskAnalysis()->getScore());
}
else
{
printf('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score');
}
}
} catch (exception $e) {
printf('CreateAssessment() call failed with the following error: ');
printf($e);
}
Here's how I got it working. Thanks to John Hanley for the help in a previous answer. The documentation had lead me to believe that (for whatever reason) Storage was required, but that was not the case: it was as simple as providing the path to the key via the credentials parameter. Not the keyFile parameter.
if (empty($_POST['g-recaptcha-response']))
die("You have failed the not-a-robot check.");
$captcha_response = $_POST['g-recaptcha-response'];
require 'composer/vendor/autoload.php';
use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;
$path_to_keyfile = "MY_PROJECT-1234567890abc.json";
$site_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
$client = new RecaptchaEnterpriseServiceClient([
'credentials' => $path_to_keyfile,
'projectId' => 'MY_PROJECT'
]);
define('SITE_KEY', $site_key);
define('TOKEN', $captcha_response);
define('PROTECTED_ACTION', 'signup');
define('PARENT_PROJECT', 'projects/MY_PROJECT');
$event = (new Event())
->setSiteKey(SITE_KEY)
->setExpectedAction(PROTECTED_ACTION)
->setToken(TOKEN);
$assessment = (new Assessment())
->setEvent($event);
try {
$response = $client->createAssessment(PARENT_PROJECT, $assessment);
if ($response->getTokenProperties()->getValid() == false) {
printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
exit;
} else {
if ($response->getEvent()->getExpectedAction() == PROTECTED_ACTION) {
// Closer to 1 = human, to 0 = robot.
$bot_score = $response->getRiskAnalysis()->getScore();
// do what you want with the score here...
} else {
die('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score');
}
}
} catch (exception $e) {
printf('CreateAssessment() call failed with the following error: ');
printf($e);
exit;
}
Your problem is that you are not specifying the service account to use in the client constructor and the system is falling back to using ADC (Application Default Credentials).
ADC will check the environment variable GOOGLE_APPLICATION_CREDENTIALS for the service account JSON key file.
You can set the environment variable before running your program:
Windows:
set GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Linux:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Or modify your program by changing this line of code:
$client = new RecaptchaEnterpriseServiceClient();
To this:
$options = ['keyFile' => $path_to_keyfile];
$client = new RecaptchaEnterpriseServiceClient($options);
Note 1:
If you are running your program on a Google Cloud computer service such as Compute Engine, App Engine, Cloud Run, ... the default service account will be used if neither of the above methods are implemented.
Note 2:
While developing, another method is to use the CLI's application default credentials. Run the following command using the Google Cloud SDK CLI:
gcloud auth application-default login
However, I have not verified that the reCAPTCHA Enterprise library checks for this type of credential.

i want to record response get from statuscallback twilio

ini_set('max_execution_time', 3000);
require 'Services/Twilio.php';
$version = "2010-04-01";
$sid = 'xxxxxx';
$token = 'xxxxxx';
$phonenumber = 'xxxxxxxxxx';
$client = new Services_Twilio($sid, $token, $version);
try {
$call = $client->account->calls->create($phonenumber, "3104200693", "http://demo.twilio.com/docs/voice.xml", array(
"Method" => "GET",
"StatusCallback" => "http://localhost/twilio/call-response.php",
"StatusCallbackMethod" => "GET",
"StatusCallbackEvent" => array("initiated", "ringing", "answered", "completed"),
"IfMachine" => "Continue",
));
//header("Location: http://localhost/twilio/call-response.php");
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
This is my twilio code to call a number, i am successfully calling with this, but i want to store response in database like call completed or not and if answered then who answered call human or machine.
Please help.
The Twilio servers will send an HTTP request to the URL given as StatusCallback. Quite obviously, hopefully, Twilio cannot contact your localhost. 1) your computer is probably not physically reachable from outside your network, and 2) localhost is something different for everyone.
You need to provide a URL which is publicly accessible from the internet. That means you either need to run your code in a server, or you use a service like http://ngrok.com to establish a tunnel to your local machine during development.
I dont think "StatusCallback" => "http://localhost/twilio/call-response.php" will make you get call response. You should give a server url.
For example
"StatusCallback" => "http://example.com/twilio/call-response.php"
In call-response.php,
<?php
file_put_contents(__DIR__."/status_log.txt", json_encode($_REQUEST));
// twilio call status and other sata will be written to this file. Please check this file after call.
// I am giving because i dont know correct twilio returning params
?>
More info here

access drive with access token

struggling to understand the oauth2 token and refresh token processes
ive got this code
$url = 'https://www.googleapis.com/oauth2/v3/token';
$data = array('client_id' => 'clientid', 'client_secret' => 'secret','refresh_token' => 'token','grant_type' => 'refresh_token');
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded",
'method' => 'POST',
'approval_prompt'=>'force',
'access_type'=>'offline',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
that code above gives me an access token , and i followed this link suggested by one fellow stackoverflower, pinoyyid, BUT , im confunsed on how to correctly use the resulting access token to access drive and copy a file...
all the process ive seen usually involves $client = new Google_Client() and im not sure on how to use the whole POST http://..... thing, so basically i need to figure out if i use the access token i got with the code above in a new instance of google client, or i simply do a post to a url with necesary info ( which im not clear on also ) any help/clarification is appreciated guys really
EDIT #1
what i want to achieve is to allow the end user to access my drive via my webpage, to let them copy a spreadsheet in my drive , and access it via my website, to store data on the spreadsheet,the spreadsheet will always be on my drive, never on the end user
EDIT #2
code as per your posts is as follows, using the service account,,,,the files are inside that gmail account which i created on the api console a service account
<?php
require 'Google/autoload.php';
$client = new Google_Client();
// Replace this with your application name.
$client->setApplicationName("TEST");
// Replace this with the service you are using.
$service = new Google_Service_Drive($client);
// This file location should point to the private key file.
$key = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/number-privatekey.p12');
$user_to_impersonate = 'admin#testpr.com';
$cred = new Google_Auth_AssertionCredentials(
'number#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/drive'), ****//this here has to be drive not drive.file
$key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
$user_to_impersonate
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$originFileId = "longnumber";
$copyTitle = 'copied';
$newfile = copyFile($service, $originFileId, $copyTitle);
print_r($newfile);
function copyFile($service, $originFileId, $copyTitle)
{
$copiedFile = new Google_Service_Drive_DriveFile();
$copiedFile->setTitle($copyTitle);
try {
return $service->files->copy($originFileId, $copiedFile);
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
return NULL;
}
?>
so got it working just now, ty all for your time guys really and edited my post to reflect the dang thing
If you want to give the end user access to your drive, you have to give your application authority to make API calls on behalf of a user (in this case you) in your domain. For this you have to set up a service account and generate a p12 key in the Google Developers Console. You have to enter the https://www.googleapis.com/auth/drive API scope in your Admin Console as well.
Full explanation and examples can be found here: https://developers.google.com/api-client-library/php/auth/service-accounts.
To achieve this you also need the Google API's client library: https://github.com/google/google-api-php-client (also mentioned in the Google manual).
Code example to let users make API calls on behalf of one of your accounts: https://developers.google.com/api-client-library/php/guide/aaa_oauth2_service

Sending Amazon SNS from my PHP server

I have an application both in Android and iOS platforms. Both of them are registered with Amazon SNS. This is successfully done, because if I have the device tokens, then I can login to my applications dashboard in Amazon, and can send SNS from their console.
I want it make it automated. I mean have my own PHP admin site (and API) for the applications. I want add another page to the admin site, that can request the amazon SNS to send single payload with device identifier, registration keys and message body provided with the request.
First question - Is it possible? I have seen Urban Airship allows it, so it is usual that amazon also does?
Second question - What is the process? Since I am working on this for one of my client and all the docs are not accessible to me. My client is unable to explain it to amazon.
When I have registered my apps to amazon, shouldn't they provide me some keys and secrets that I can use to call their service over http?
Yes, it is possible.
Download the Amazon Web Service (AWS) PHP SDK from here and follow their instructions to use this in you web server API. Get the Platform Application ARN's for both iOS and android, access key id and the secret key from Amazon console. And then try the code below and follow the commented out instructions:
<?php
require '<path to this file>/aws.phar';
use Aws\Sns\SnsClient;
if(isset($_POST['submit']))
{
$push_message = $_POST['push_message'];
if(!empty($push_message))
{
// Create a new Amazon SNS client
$sns = SnsClient::factory(array(
'key' => '<access key>',
'secret' => '<app secret>',
'region' => '<region code>'
));
// region code samples: us-east-1, ap-northeast-1, sa-east-1, ap-southeast-1, ap-southeast-2, us-west-2, us-gov-west-1, us-west-1, cn-north-1, eu-west-1
$iOS_AppArn = "<iOS app's Application ARN>";
$android_AppArn = "<android app's Application ARN>";
// Get the application's endpoints
$iOS_model = $sns->listEndpointsByPlatformApplication(array('PlatformApplicationArn' => $iOS_AppArn));
$android_model = $sns->listEndpointsByPlatformApplication(array('PlatformApplicationArn' => $android_AppArn));
// Display all of the endpoints for the iOS application
foreach ($iOS_model['Endpoints'] as $endpoint)
{
$endpointArn = $endpoint['EndpointArn'];
echo $endpointArn;
}
// Display all of the endpoints for the android application
foreach ($android_model['Endpoints'] as $endpoint)
{
$endpointArn = $endpoint['EndpointArn'];
echo $endpointArn;
}
// iOS: Send a message to each endpoint
foreach ($iOS_model['Endpoints'] as $endpoint)
{
$endpointArn = $endpoint['EndpointArn'];
try
{
$sns->publish(array('Message' => $push_message,
'TargetArn' => $endpointArn));
echo "<strong>Success:</strong> ".$endpointArn."<br/>";
}
catch (Exception $e)
{
echo "<strong>Failed:</strong> ".$endpointArn."<br/><strong>Error:</strong> ".$e->getMessage()."<br/>";
}
}
// android: Send a message to each endpoint
foreach ($android_model['Endpoints'] as $endpoint)
{
$endpointArn = $endpoint['EndpointArn'];
try
{
$sns->publish(array('Message' => $push_message,
'TargetArn' => $endpointArn));
echo "<strong>Success:</strong> ".$endpointArn."<br/>";
}
catch (Exception $e)
{
echo "<strong>Failed:</strong> ".$endpointArn."<br/><strong>Error:</strong> ".$e->getMessage()."<br/>";
}
}
}
}
?>
The code is tested and it works, feel free to change as your need.
If you want to send alert sound and badge number with custom payload replace this code block // iOS: Send a message to each endpoint
foreach ($iOS_model['Endpoints'] as $endpoint)
with this code block
foreach ($iOS_model['Endpoints'] as $endpoint)
{
$endpointArn = $endpoint['EndpointArn'];
try
{
$sns->publish(array(
'TargetArn' => $endpointArn,
'MessageStructure' => 'json',
'Message' => json_encode(array(
'default' => $title,
'APNS_SANDBOX' => json_encode(array(
'aps' => array(
'alert' => $title,
'sound' => 'default',
'badge' => 1
),
// Your custom payload if needed
'whatever' => 'here',
'andwhatever' => 'here'
))
))
));
echo "1";//Success push
}
catch (Exception $e)
{
echo "2";//Failed push
}
}
i believe the simplest way to send push notification to single device or user is by this code
$snsClient = Aws\Sns\SnsClient::factory(array(
'credentials' => array(
'key' => AMAZON_KEY,
'secret' => AMAZON_SECRET,
),
'region' => AMAZON_REIGON
));
//you should have variable that have user end single point .
$result = $snsClient->publish(array(
'Message' => "push text message",
'TargetArn' => $user_end_point
));

Error 99 - permission denied in last.fm php API call

I'm making a call to retrieve a user's latest tracks using the last.fm PHP api library. It works perfectly when I run it on my local webserver (localhost), but when I run it on a remote server it sends back an error code of 99, saying that permission has been denied.
Here is my code:
static function readRecentTracks() {
$authVars['apiKey'] = '#########';
$auth = new lastfmApiAuth('setsession', $authVars);
$apiClass = new lastfmApi();
$packageClass = $apiClass->getPackage($auth, 'user');
$method_vars = array(
'user' => 'liquidus219',
'limit' => 25
);
if ($tracks = $packageClass->getRecentTracks($method_vars)) {
echo json_encode($tracks);
} else {
echo '<b>Error '.$packageClass->error['code'].' - </b><i>'.$packageClass->error['desc'].'</i>';
}
}
You can see the code in action at http://liquidus219.freehostia.com/api/?q=readRecentTracks
UPDATE: I have checked/changed the application URL to no effect.
UPDATE: I have gone through the code for the last.fm PHP api, no sign of an error 99 defined anywhere.
I found out in the end that my hosting provider was blocking the call.

Categories