As from the question it is quite clear what I am trying to achieve. What I had tried till now to achieve the said is:
dailcall.php
$call = $twilio->calls
->create($to, // to
$from, // from
[
"method" => "GET",
"url" => "https://twilioxxxx.tk/api/araonvlad_bot/recording.php",
"record" => true,
'transcribe' => true,
"StatusCallbackMethod" => "POST",
"StatusCallbackEvent" => array("in-progress completed"),
]
);
recording.php
use Twilio\Rest\Client;
require DIR . '/vendor/autoload.php';
$twilio = new Client("AC8b2cc96be2a8dbc059f29xxxxx", "88db8eeb71124a3effd6c19681xxxx");
if($_REQUEST['CallStatus'] == 'in-progress') {
file_put_contents('request.log', "\n" .json_encode($_REQUEST). ' - in-progress recording start now : - ' . "\n", FILE_APPEND);
$callSid = $_REQUEST['CallSid'];
$recording = $twilio->calls($callSid)
->recordings
->create([
"recordingStatusCallback" => "https://twilioxxxxxx.tk/api/araonvlad_bot/read_Recording.php",
"recordingStatusCallbackEvent" => ["completed"],
"recordingChannels" => "dual",
'transcribe' => 'true'
]
);
file_put_contents('request.log', "\n" .json_encode($recording). ' - in-progress recording variable : - ' . "\n", FILE_APPEND);
}
read_Recording.php
require __DIR__ . '/vendor/autoload.php';
use Twilio\Rest\Client;
$twilio = new Client("AC8b2cc96be2a8dbc059f2908e8xxxxx", "88db8eeb71124a3effd6c196xxxx");
file_put_contents('request.log', "\n" .json_encode($_REQUEST). ' - read Recording File: - ' . "\n", FILE_APPEND);
if I set transcribe= true in the dailcall.php it shows 500 error. how I can start recording in recording.php file as I am getting error. All three files are on same level with vendor folder added with composer.
How I can get the recording download mp3 file and the transcribtion of recording. I have recording just about 30 seconds max.
I had read the documentations: https://www.twilio.com/docs/voice/tutorials/how-to-record-phone-calls/php
https://www.twilio.com/docs/voice/api/recording#fetch-recording-metadata
https://www.twilio.com/docs/voice/api/recording-transcription
If you check the documentation for creating a call with Twilio or creating a recording for a live call you will see that transcribe is not an option to either API. You can only transcribe a single leg of a call using the transcribe attribute on the <Record> TwiML.
To perform transcription on a call that has more than one participant, you can use one of the transcription add-ons like Watson Speech to Text or VoiceBase High Accuracy Transcription which you can enable in your Twilio console.
I don't know if the question is right, but here is my problem..
I want to crawl this site: https://www.easports.com/fifa/ultimate-team/compete/leaderboards to get the leaderboard data.
When I do so with the following code, I only get the header + footer, but not the leaderboard data.
$client = new HttpClient();
$client->setAdapter("Zend\Http\Client\Adapter\Curl");
$client->setUri("https://www.easports.com/fifa/ultimate-team/compete/leaderboards");
$content = $client->send()->getBody();
var_dump($content);
Is there a problem with my curl or can this data not be curled? If so, maybe you got a solution for me ;)
If you open the Developer Tools in your browser you can see which extra requests are done to get the leaderboard filled. You should use the url https://www.easports.com/cgw/api/fifa/fut/leaderboard?platform=xboxone®ion=ams&period=curr to get the leaderboard. This returns a JSON in the following layout:
[
{
"rank": 1,
"persona": "persona",
"hasProfile": false,
"wins": 1,
"skill": "6",
"qualified": 0
}]
Using your code this would be:
$client = new HttpClient();
$client->setAdapter("Zend\Http\Client\Adapter\Curl");
$client->setUri("https://www.easports.com/cgw/api/fifa/fut/leaderboard?platform=xboxone®ion=ams&period=curr");
$content = $client->send()->getBody();
var_dump($content);
Which can then be processed for example with:
$client = new HttpClient();
$client->setAdapter("Zend\Http\Client\Adapter\Curl");
$client->setUri("https://www.easports.com/cgw/api/fifa/fut/leaderboard?platform=xboxone®ion=ams&period=curr");
$content = $client->send()->getBody();
$leaderBoard = json_decode($content);
foreach($leaderBoard as $member){
echo $member['rank'] . '. ' . $member['persona'] . '(' . $member['wins'] . ' Wins)<br />';
}
I am trying to work with the PHP API for Amazon's Flexible Payments.
Here is my PHP snippet to send a payment request:
<?php
$string_to_sign = 'GET
authorize.payments-sandbox.amazon.com
/cobranded-ui/actions/start
SignatureMethod=HmacSHA256&SignatureVersion=2&callerKey=my_access_key&callerReference=YourCallerReference&paymentReason=donation&pipelineName=SingleUse&returnUrl=http%3A%2F%2Fproblemio.com&transactionAmount=4.0';
$encoded_string_to_sign = URLEncode(Base64_Encode(hash_hmac('sha256', $string_to_sign, 'my_secret_key')));
$amazon_request_sandbox = 'https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start?SignatureVersion=2&returnUrl='.$return_url.'&paymentReason='.$payment_reason.'&callerReference=YourCallerReference&callerKey='.$my_access_key_id.'&transactionAmount=4.0&pipelineName=SingleUse&SignatureMethod=HmacSHA256&Signature='.$encoded_string_to_sign;
// When it goes to the url, it gets the invalid signature error
header('Location: '.$amazon_request_sandbox);
?>
This seems to be following their instructions, but I can't get past that error.
Thanks!!
<?php
$method = 'GET';
$host = 'authorize.payments-sandbox.amazon.com';
$path = '/cobranded-ui/actions/start';
$params = array(
'signatureMethod' => 'HmacSHA256',
'signatureVersion' => '2',
'currencyCode' => 'USD',
'callerKey' => 'Your_Key_ID',
'callerReference' => 'YourCallerReference',
'paymentReason' => 'donation',
'pipelineName' => 'SingleUse',
'returnUrl' => 'http://yourcallback.com',
'transactionAmount'=> '5',
'version' => '2009-01-09',
);
$params = array_map('rawurlencode', $params);
$paramStringArray = array();
foreach($params as $key => $value){
$paramStringArray[] = $key . '=' . $value;
}
$paramString = implode('&', $paramStringArray);
$string_to_sign = $method . "\n"
. $host . "\n"
. $path . "\n"
. $paramString;
$signature = base64_encode(hash_hmac(
'sha256',
$string_to_sign,
'Your_Super_Secret_Key',
true
));
$amazon_request_sandbox = "https://{$host}{$path}?" . $paramString .
'&signature=' . rawurlencode($signature);
header('Location: '.$amazon_request_sandbox);
?>
Okay... using the structure from the code below, I've finally figured this whole thing out via the code above. There are three things of note to keep track of while forming your signature/URL...
It seems that the parameter "transactionAmount" is necessary for a valid Co-branded UI Pipeline, even though there's no specific instruction alluding to the issue.
If any of your parameters have/had spaces in them, and you tried to use html_build_query() in all but the latest (5.4) version of PHP, you would be given an encoding scheme that featured "+" marks for spaces instead of "%20" which is what Amazon appears to like. My code above takes care of that by implementing rawurlencode() on the entire parameter array.
The ordering of the parameters is paramount in the construction of the signature. The keys (not the values) need to be in case-insensitive alphabetical order. It's also worth noting that despite what the documentation says for the API, both the ampersands (&) and the equals (=) must be present in the creation of the query string for the signature.
Ex:
Query String for Signature: callerKey=1111111111111¤cyCode=USD&signatureVersion=2
Some Other Things I Noticed...
In the sample code included with the PHP SDK (2010-8-28), the "paymentReason" attribute in the file "CBUISingleUsePipelineSample.php" is listed as "HarryPotter 1-5 DVD set". Since this attribute has spaces in it, it throws that ever-annoying "invalid signature" error when you try to visit the generated link because html_build_query() is used to generate the query string for the URL. To fix this issue, open up "CBUIPipeline.php", and look for the following line in the constructUrl() method...
$queryString = http_build_query($parameters, '', '&');
replace it with:
$queryString = str_replace('+', '%20', http_build_query($parameters, '', '&'));
That'll solve the space-encoding problem for older versions of PHP (< 5.4). With the latest version, there's an "enc_type" flag you can set.
Last things Last...
This is my first post on StackOverflow so don't kill me if I broke protocol. Hope it helps!
Try this piece of code:
<?php
$method = 'GET';
$host = 'authorize.payments-sandbox.amazon.com';
$path = '/cobranded-ui/actions/start';
$params = array(
'SignatureMethod' => 'HmacSHA256'
'SignatureVersion' => 2,
'callerKey' => 'my_access_key',
'callerReference' => 'YourCallerReference',
'paymentReason' => 'donation',
'pipelineName' => 'SingleUse',
'returnUrl' => 'http://problemio.com&transactionAmount=4.0',
);
$string_to_sign = $method . "\n"
. $host . "\n"
. $path . "\n"
. http_build_query($params);
$signature = base64_encode(hash_hmac(
'sha256',
$string_to_sign,
'my_secret_key'
));
$params['Signature'] = $signature;
$amazon_request_sandbox = "https://{$host}{$path}?" . http_build_query($params);
header('Location: ' . $amazon_request_sandbox);
So I made a few changes:
PHP's http_build_query() to build the query string (ensure correct encoding)
trying to re-use your vars vs. duplicating the efforts (makes it easier to spot mistakes, etc.)
explicit \n - maybe your editor entered \r or \r\n
HTH
I am using Graph API https://developers.facebook.com/docs/reference/api/#publishing with PHP SDK and I would like to send some data via HTTP POST method, as it's mentioned in documentation (e.g. add comment).
At https://developers.facebook.com/docs/reference/api/batch/ they say I should encode the body of HTTP POST request as ...should be formatted as a raw HTTP POST body string, similar to a URL query string. I can't get the combination of PHP functions to get this to work. In the example they claim following should work:
"body": "message=Test status update"
Well, that works. But what if I need to add other params? And how should be this string encoded? E.g. I have this:
$data = array('name' => 'Gargamel', 'occupation' => 'Freelancing Smurf Hunter');
How should I process it to get required format? Following does NOT work:
$batch = array();
$query = array(
'method' => 'POST',
'relative_url' => '/forrest/full/of/smurfs',
'body' => urldecode(http_build_query($data)),
);
$batch[] = $query;
$responses = $this->api('/?batch=' . json_encode($batch, JSON_HEX_AMP), 'POST');
I explored half of the Internet, but I can't find any more specific information about the format than the one mentioned above (raw HTTP POST similar to a URL query string).
Thanks for any suggestions!
using this: http://forum.developers.facebook.net/viewtopic.php?pid=331343#p331343
$batch_array[] = array(
'method' => 'POST',
'relative_url' => 'Relative url',
'body' => 'message=' . 'Your message' . '%26data=' . 'Your data' ,
);
This is my batch example code:
$graph_url = "https://graph.facebook.com/me/friends?access_token=" . $params['access_token'];
$friends = json_decode(file_get_contents($graph_url));
$batched_request = '[{"method":"GET","relative_url":"'.$friends->data[0]->id.'/likes"}';
for ($i = 1; $i < 20; $i++) {
$batched_request .= ',{"method":"GET","relative_url":"'.$friends->data[$i]->id.'/likes"}';
}
$batched_request .= ']';
$post_url = 'https://graph.facebook.com/?batch='
. $batched_request . '&access_token=' . $params['access_token'] . '&method=post';
$posts = file_get_contents($post_url);
for ($i = 0; $i < 20; $i++) {
$post = json_decode($posts[$i]->body);
echo($friends->data[$i]->id.' '.$friends->data[$i]->name);
//print_r($post);
}
Batch query limit 20 requests. You need to decode each part of batch query, see code above.
I’ve run into a limitation in the cURL bindings for PHP. It appears there is no easy way to send the same multiple values for the same key for postfields. Most of the workarounds I have come across for this have involved creating the URL encoded post fields by hand tag=foo&tag=bar&tag=baz) instead of using the associative array version of CURLOPT_POSTFIELDS.
It seems like a pretty common thing to need to support so I feel like I must have missed something. Is this really the only way to handle multiple values for the same key?
While this workaround might be considered workable (if not really annoying), my main problem is that I need to be able to do multiple values for the same key and also support file upload. As far as I can tell, file upload more or less requires to use the associate arravy version of CURLOPT_POSTFIELDS. So I feel like I am stuck.
I have posted about this problem in more detail on the cURL PHP mailing list in the hopes that someone there has some ideas about this.
Suggestions or hints on where I can look for more information on this are greatly appreciated!
I ended up writing my own function to build a custom CURLOPT_POSTFIELDS string with multipart/form-data. What a pain.
function curl_setopt_custom_postfields($ch, $postfields, $headers = null) {
// $postfields is an assoc array.
// Creates a boundary.
// Reads each postfields, detects which are #files, and which values are arrays
// and dumps them into a new array (not an assoc array) so each key can exist
// multiple times.
// Sets content-length, content-type and sets CURLOPT_POSTFIELDS with the
// generated body.
}
I was able to use this method like this:
curl_setopt_custom_postfields($ch, array(
'file' => '#/path/to/file',
'tag' => array('a', 'b', 'c'),
));
I am not certain of CURLOPT_HTTPHEADER stacks, so since this method calls it, I made certain that the function would allow for the user to specify additonal headers if needed.
I have the full code available in this blog post.
If you use tag[] rather than tag for the name, PHP will generate an array for you, in other words, rather than
tag=foo&tag=bar&tag=baz
You need
tag[]=foo&tag[]=bar&tag[]=baz
Note that when urlencoded for transmission this should become
tag%5B%5D=foo&tag%5B%5D=bar&tag%5B%5D=baz
Vote for PHP Bug #51634.
Try #BeauSimensen's answer.
Guzzle can do this. See an example below.
$client = new \GuzzleHttp\Client();
$client->request('POST', $url, [
'multipart' => [
[ 'name' => 'foo', 'contents' => 'bar' ],
[ 'name' => 'foo', 'contents' => 'baz' ],
]
]);
I ran into the same issue. But I was able to solve it this way.
for($cnt = 0; $cnt < count($siteRows); $cnt++)
{
$curlParams['site_ids['.$cnt.']'] = $siteRows[$cnt]->site_id;
}
Works for files too:
for($cnt = 0; $cnt < count($imageRows); $cnt++)
{
$curlParams['product_images['.$cnt.']'] = '#'.$imageRows[$cnt]->full_path;
}
I got it working using:
curl_setopt($ch, CURLOPT_POSTFIELDS,array('tag[0]'=>'val0','tag[1]'=>'val1'));
then $_POST results in: $_POST['tag'][0] = 'val0' and $_POST['tag'][1] = 'val1'
I think the established standard for multiple values in one key (or the same key) is to have it concatenated with a delimiter, such as for multiple selections of option lists in form elements. I believe this delimiter is the tab character (\t) or the pipe symbol (|).
If the keyname is terminated with [] (like tag[]), PHP will automatically convert the values into an array for your convenience.
lImbus and paul, thank you for your input.
If I had control over the form I am posting to, I could probably find an alternate solution to this problem. However, I do not have any control over the form. And I am almost positive that the software reading the post is not PHP and does not obey the tag[] standards.
Even if it did, cURL does not seem to obey the tag[] syntax either. Basically, I tried the following and neither worked...
curl_setopt($ch, CURLOPT_POSTFIELDS, array('file' => '#/pathtofile', 'tag[]' => array('a', 'b', 'c'));
curl_setopt($ch, CURLOPT_POSTFIELDS, array('file' => '#/pathtofile', 'tag' => array('a', 'b', 'c'));
And again, I don't think that passing tag[] would work anyway as the form I am posting to is actually looking for 'tag' and not 'tag[]'.
I am really starting to get the feeling that the cURL PHP bindings really have no support for this. Which seems so surprising to me. It seems like it can do quite literally anything else, yet it is unable to do something simple like this?
DON'T USE GUZZLE:
# at your command line start php interactive
user#group:~:php -a
php > $arr=array('var' => array(1,2,3,4));
php > echo http_build_query($arr);
var%5B0%5D=1&var%5B1%5D=2&var%5B2%5D=3&var%5B3%5D=4
php > echo urldecode(http_build_query($arr));
var[0]=1&var[1]=2&var[2]=3&var[3]=4
So, you need http_build_query where you pass a hash array of key-values; your (array) variable is entered as a key with value a array instead a scalar value like 'var' => array(1,2,3,4). Now, http_build_query can format the post fields of curl command:
$fields = array('key1' => 'value1', 'var' => array(1,2,3,4));
$curlPost = \http_build_query($fields);
curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
that's 3 lines of code! how many 1000s of code lines are in Guzzle? (*)
So far, I used curl to:
manage Google OAuth protocol with success
connect with APIs like mailgun
handle paypal smart buttons
that's a replacement of million of lines with some 100s!
(*): the result of http_build_query can be formatted further according your needs.
I ran into the same problem in which I had to send a parameter which has to be an array from a PHP server to another server that does not use '[]' for mixing values with the same key along with a file.
In Laravel 8 I could achieve this goal with Http client (of course Http client uses guzzle).
Here is a sample of my code.
Illuminate\Support\Facades\Http::attach('file', $fileContents, 'file-name')
->post('https://destination' , [['name' => 'tag', 'content' => 'foo'], ['name' => 'tag', 'content' => 'bar']])
I found this answer online and want to post it here before it disappears:
http://yeehuichan.wordpress.com/2011/08/07/sending-multiple-values-with-the-same-namekey-in-curl-post/
function curl_setopt_custom_postfields($ch, $postfields, $headers = null) {
$algos = hash_algos();
$hashAlgo = null;
foreach ( array('sha1', 'md5') as $preferred ) {
if ( in_array($preferred, $algos) ) {
$hashAlgo = $preferred;
break;
}
}
if ( $hashAlgo === null ) { list($hashAlgo) = $algos; }
$boundary =
'----------------------------' .
substr(hash($hashAlgo, 'cURL-php-multiple-value-same-key-support' . microtime()), 0, 12);
$body = array();
$crlf = "\r\n";
$fields = array();
foreach ( $postfields as $key => $value ) {
if ( is_array($value) ) {
foreach ( $value as $v ) {
$fields[] = array($key, $v);
}
} else {
$fields[] = array($key, $value);
}
}
foreach ( $fields as $field ) {
list($key, $value) = $field;
if ( strpos($value, '#') === 0 ) {
preg_match('/^#(.*?)$/', $value, $matches);
list($dummy, $filename) = $matches;
$body[] = '--' . $boundary;
$body[] = 'Content-Disposition: form-data; name="' . $key . '"; filename="' . basename($filename) . '"';
$body[] = 'Content-Type: application/octet-stream';
$body[] = '';
$body[] = file_get_contents($filename);
} else {
$body[] = '--' . $boundary;
$body[] = 'Content-Disposition: form-data; name="' . $key . '"';
$body[] = '';
$body[] = $value;
}
}
$body[] = '--' . $boundary . '--';
$body[] = '';
$contentType = 'multipart/form-data; boundary=' . $boundary;
$content = join($crlf, $body);
$contentLength = strlen($content);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Length: ' . $contentLength,
'Expect: 100-continue',
'Content-Type: ' . $contentType,
));
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
}
And to use it:
curl_setopt_custom_postfields($ch, array(
'file' => '#a.csv',
'name' => array('James', 'Peter', 'Richard'),
));