I am trying to get Polly to read something for me, using PHP.
I have created a new project, installed Amazon composer require aws/aws-sdk-php and then created a file with code from SDK documentation example and modified a few minor things such as changing credential from default to value, var_dump to var_export and finally saved the content of the stream to file
<?php
require 'vendor/autoload.php';
use Aws\Exception\AwsException;
use Aws\Polly\PollyClient;
use Aws\Credentials\Credentials;
// Create a PollyClient
$client = new Aws\Polly\PollyClient([
//'profile' => 'default',
'credentials' => new Credentials('XXXXXXXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'),
'version' => '2016-06-10',
'region' => 'us-east-2'
]);
try {
$result = $client->synthesizeSpeech([
'Text' => 'Hello',
'OutputFormat' => 'json', //json|mp3|ogg_vorbis|pcm
'VoiceId' => 'Joanna',
]);
var_export($result);
$data = $result->get('AudioStream')->getContents();
echo "\n\n";
var_export($data);
$file = fopen('test.txt','w+');
fwrite($file,$data);
fclose($file);
} catch (AwsException $e) {
echo $e->getMessage() . "\n";
}
The result I'm getting is following
Aws\Result::__set_state(array(
'data' => array (
'AudioStream' => GuzzleHttp\Psr7\Stream::__set_state(array(
'stream' => NULL,
'size' => NULL,
'seekable' => true,
'readable' => true,
'writable' => true,
'uri' => 'php://temp',
'customMetadata' => array (),
)),
'ContentType' => 'application/x-json-stream',
'RequestCharacters' => '5',
'#metadata' => array (
'statusCode' => 200,
'effectiveUri' => 'https://polly.us-east-2.amazonaws.com/v1/speech',
'headers' => array (
'x-amzn-requestid' => 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'x-amzn-requestcharacters' => '5',
'content-type' => 'application/x-json-stream',
'transfer-encoding' => 'chunked',
'date' => 'Sat, 18 Sep 2021 05:11:20 GMT',
),
'transferStats' => array (
'http' => array (
0 => array (),
),
),
),
),
'monitoringEvents' => array (),
))
''
As you can see the size of the AudioStream is null (nothing in it) and also the created file is also empty since there is nothing in the stream to read.
If I change a credential to an invalid string, I get errors, and with the valid credential, the status code is 200, which makes me believe that my request is successful.
I changed voiceId to any other valid or invalid id and even changed the region with others with valid values getting status 200 and with invalid ones getting error messages, but I'm still not getting anything out of polly, it doesn't feel like talking!
Note: When I run $arr_voices = $polly->describeVoices();, I can read list of the voices without error.
Note: I had the same issue with .NET SDK too, which makes me think either there is something wrong with my request or some error message is missing from API.
Question
What I'm doing wrong?
You're not doing anything wrong, but it only outputs JSON if you're looking for speech marks. Try switching to an audio output format like MP3 as shown below.
$result = $client->synthesizeSpeech([
'Text' => 'Hello',
'OutputFormat' => 'mp3', //json|mp3|ogg_vorbis|pcm
'VoiceId' => 'Joanna',
]);
If you're looking for speech marks- metadata on the speech that will be synthesized- you need to specify SpeechMarkTypes as shown here https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-polly-2016-06-10.html#synthesizespeech
Related
I am working Paypal checkout php sdk. I follow the document from here https://github.com/paypal/Checkout-PHP-SDK
First I create an order
$env = new SandboxEnvironment($clientId, $secretKey);
$client = new PayPalHttpClient($env);
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = buildOrder($order);
//buildOrder has this param:
/*
"application_context" => [
"return_url" => 'domain/paypal/return.php',
"cancel_url" => 'domain/paypal/cancel.php'
]
*/
//request body
$body = array (
'intent' => 'CAPTURE',
'purchase_units' =>
array (
0 =>
array (
'reference_id' => 9,
'amount' =>
array (
'value' => 125.63,
'currency_code' => 'USD',
'breakdown' =>
array (
'item_total' =>
array (
'currency_code' => 'USD',
'value' => 125.63,
),
),
),
'items' =>
array (
0 =>
array (
'name' => 'Demo 46',
'description' => NULL,
'sku' => NULL,
'unit_amount' =>
array (
'currency_code' => 'USD',
'value' => 98.0,
),
'quantity' => '1',
),
1 =>
array (
'name' => 'Demo 28',
'description' => NULL,
'sku' => NULL,
'unit_amount' =>
array (
'currency_code' => 'USD',
'value' => 12.22,
),
'quantity' => '1',
),
2 =>
array (
'name' => 'Addon 33',
'description' => NULL,
'sku' => NULL,
'unit_amount' =>
array (
'currency_code' => 'USD',
'value' => 15.41,
),
'quantity' => '1',
),
),
),
),
'application_context' =>
array (
'return_url' => 'http://domain.test/paypal/return',
'cancel_url' => 'http://domain.test/paypal/canceled',
),
)
$response = $client->execute($request);
Create Order response:
{"statusCode":201,"result":{"id":"10M47599SM3059709","intent":"CAPTURE","status":"CREATED","purchase_units":[{"reference_id":"9","amount":{"currency_code":"USD","value":"125.63","breakdown":{"item_total":{"currency_code":"USD","value":"125.63"}}},"payee":{"email_address":"sb-kpo1v7959755#business.example.com","merchant_id":"XEH8BEAE3FXPW"},"items":[{"name":"Demo 46","unit_amount":{"currency_code":"USD","value":"98.00"},"quantity":"1"},{"name":"Demo 28","unit_amount":{"currency_code":"USD","value":"12.22"},"quantity":"1"},{"name":"Addon 33","unit_amount":{"currency_code":"USD","value":"15.41"},"quantity":"1"}]}],"create_time":"2021-09-30T22:59:31Z","links":[{"href":"https:\/\/api.sandbox.paypal.com\/v2\/checkout\/orders\/10M47599SM3059709","rel":"self","method":"GET"},{"href":"https:\/\/www.sandbox.paypal.com\/checkoutnow?token=10M47599SM3059709","rel":"approve","method":"GET"},{"href":"https:\/\/api.sandbox.paypal.com\/v2\/checkout\/orders\/10M47599SM3059709","rel":"update","method":"PATCH"},{"href":"https:\/\/api.sandbox.paypal.com\/v2\/checkout\/orders\/10M47599SM3059709\/capture","rel":"capture","method":"POST"}]},"headers":{"":"","Content-Type":"application\/json","Content-Length":"1085","Connection":"keep-alive","Date":"Thu, 30 Sep 2021 22","Application_id":"APP-80W284485P519543T","Cache-Control":"max-age=0, no-cache, no-store, must-revalidate","Caller_acct_num":"XEH8BEAE3FXPW","Paypal-Debug-Id":"95be3b11c12e7","Strict-Transport-Security":"max-age=31536000; includeSubDomains"}}
Then I can get orderID, I store it in session. Next I redirect buyer to approve url from Paypal response.
Next, buyer makes payment and Paypal drives buyer to my return url above.
In return.php I capture order by this piece of code
$env = new SandboxEnvironment($clientId, $secretKey);
$client = new PayPalHttpClient($env);
//$orderId can get from session or from `token` param in return url
$request = new OrdersCaptureRequest($orderId);
$request->prefer('return=representation');
$response = $client->execute($request);
New response from OrdersCaptureRequest:
{"name":"NOT_AUTHORIZED","details":[{"issue":"PERMISSION_DENIED","description":"You do not have permission to access or perform operations on this resource."}],"message":"Authorization failed due to insufficient permissions.","debug_id":"e8021203038f1","links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-PERMISSION_DENIED","rel":"information_link"}]} {"exception":"[object] (PayPalHttp\\HttpException(code: 0): {\"name\":\"NOT_AUTHORIZED\",\"details\":[{\"issue\":\"PERMISSION_DENIED\",\"description\":\"You do not have permission to access or perform operations on this resource.\"}],\"message\":\"Authorization failed due to insufficient permissions.\",\"debug_id\":\"e8021203038f1\",\"links\":[{\"href\":\"https://developer.paypal.com/docs/api/orders/v2/#error-PERMISSION_DENIED\",\"rel\":\"information_link\"}]}
The response I have is (old):
{"name":"NOT_AUTHORIZED","details":[{"issue":"PERMISSION_DENIED","description":"You do not have permission to access or perform operations on this resource."}],"message":"Authorization failed due to insufficient permissions.","debug_id":"ff1bfd34831cb","links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-PERMISSION_DENIED","rel":"information_link"}]} {"exception":"[object] (PayPalHttp\\HttpException(code: 0): {\"name\":\"NOT_AUTHORIZED\",\"details\":[{\"issue\":\"PERMISSION_DENIED\",\"description\":\"You do not have permission to access or perform operations on this resource.\"}],\"message\":\"Authorization failed due to insufficient permissions.\",\"debug_id\":\"ff1bfd34831cb\",\"links\":[{\"href\":\"https://developer.paypal.com/docs/api/orders/v2/#error-PERMISSION_DENIED\",\"rel\":\"information_link\"}]}
Then I came with solution to combine between client and server
I embed the Paypal checkout button
Create order from server
Handle approval from js client
Capture order by Paypal js function.
And Paypal responses with COMPLETED status.
<script
src="https://www.paypal.com/sdk/js?client-id=[SANDBOX_CLIENT_ID]"></script>
<script>
paypal.Buttons({
createOrder: function(data, actions){
return fetch('create-order.php', {
method: 'post',
headers: {
'content-type': 'application/json'
},
}).then(function(res) {
return res.json();
}).then(function(data) {
return data.token;
});
},
onApprove: function(data, actions){
return actions.order.capture().then(function(details){
console.log(details);
});
}
});
</script>
Even I tried to send orderID from onApprove event of Paypal js to my server for capturing order, the same issue with PERMISSION-DENIED happens.
Please help on this.
Redirecting away to a rel:approve URL is for old websites. You should use the PayPal button rather than redirecting away, it's a much nicer and more modern in-context experience for the buyer, keeping your site loaded in the background/lightbox fade.
The problem you are having with capturing an order on the server side appears to be a matter of using the wrong request object:
//$orderId can get from session or from `token` param in return url
$request = new OrdersCreateRequest($orderId);
At this stage, you need an OrdersCaptureRequest instead. See the sample bundled as part of the SDK.
I just had this same situation and the problem was my access token.
Generating an access token via /v1/oauth2/token
and passing the
Request Header "Authorization", "Basic " & Base64(clientID) & ":" & Base64(clientSecret)
Works and returns an access token.
But this token will only allow you to Create an Order not Capture it!
You need to Base64 encode the ":" as well!
Changing the request header to
"Authorization", "Basic " & Base64(clientID & ":" & clientSecret)
Creates a token that will allows capture as well.
This took me ages to debug as the token was returning and working to create the order! I found this by checking the scope returned when creating the token.
I am running a PHP 7.3, running on apache server. I used composer to get this library:
https://github.com/SecureTrading/PHP-API
For the code provided, I am now using the test site reference. I already managed to use for regular transitions. I now started managing 3D secure transactions, with the test MAESTRO card provided by secure trading here: https://docs.securetrading.com/document/testing/. the one designed not to demand 3D auth - that is 5000000000000421
The code provided next, will sum up the way I think thought this should work: I start by creating AUTH request, get error 30004, using CACHETOKENISE request to get a token, run THREEDQUERY to figure out if I need a full auth sceme on this card, get N as an answer, and run another AUTH request, this time with the transactionreference.
I am providing a version of the code I am testing (obviously, username, password and site reference name was removed to protect my privacy, but the code otherwise is the same)
<?php
$configData = array(
'username' => 'api#gigsberg.com',
'password' => 'xq!Kq$j4',
);
$site_refrance = 'test_gigsberg74319';
?>
<?php
$configData = array(
'username' => '*****',
'password' => '*****',
);
$site_refrance = '*****';
if (!($autoload = realpath(__DIR__ . '/vendor/autoload.php'))) {
throw new \Exception('Composer autoloader file could not be found.');
}
require_once($autoload);
$api = \Securetrading\api($configData);
$requestData = array(
'sitereference' => $site_refrance,
'requesttypedescription' => 'AUTH',
'accounttypedescription' => 'ECOM',
'currencyiso3a' => 'GBP',
'mainamount' => '1000',
'pan' => '5000000000000421',
'expirymonth' => '12',
'expiryyear' => '2030',
'securitycode' => '123',
);
echo '<pre>';
print_r($requestData);
$response = $api->process($requestData)->toArray();
print_r( $response['responses'] ); // $response['responses'][0]['errorcode'] == 30004
echo "\n--------------------------------------\n";
$transactionreference = $response['responses'][0]['transactionreference'];
$requestData = array(
'sitereference' => $site_refrance,
'expirymonth' => '12',
'expiryyear' => '2030',
'requesttypedescriptions' => array('CACHETOKENISE'),
'securitycode' => '123',
'orderreference' => $transactionreference,
'pan' => '5000000000000421'
);
print_r($requestData);
$response = $api->process($requestData)->toArray();
echo "\n--------------------------------------\n";
$cachetoken = $response['responses'][0]['cachetoken'];
$requestData = array(
'termurl' => 'https://termurl.com',
'accept' => 'text/html,*/*',
'currencyiso3a' => 'GBP',
'requesttypedescription' => 'THREEDQUERY',
'accounttypedescription' => 'ECOM',
'sitereference' => $site_refrance,
'baseamount' => '1000',
'pan' => '5000000000000421',
'expirymonth' => '12',
'expiryyear' => '2030',
'cachetoken' => $cachetoken,
);
print_r($requestData);
$response = $api->process($requestData)->toArray(); // $response['responses'][0]['enrolled'] == 'N'
/* Copying from the docs here: https://docs.securetrading.com/document/api/security/3-d-secure/
* If the enrolled value returned in the response is “Y”, the customer’s card is enrolled in 3-D secure. Please refer to the following table for enrolled values:
* .
* .
* N - The card is not enrolled in the card issuer’s 3-D Secure scheme. - Perform an AUTH Request, including the transactionreference returned in the THREEDQUERY response.
* .
* .
*/
print_r( $response['responses'] );
echo "\n--------------------------------------\n";
$transactionreference = $response['responses'][0]['transactionreference'];
$requestData = array(
'sitereference' => $site_refrance,
'requesttypedescription' => 'AUTH',
'accounttypedescription' => 'ECOM',
'currencyiso3a' => 'GBP',
'mainamount' => '1000',
'pan' => '5000000000000421',
'expirymonth' => '12',
'expiryyear' => '2030',
'securitycode' => '123',
'transactionreference' => $transactionreference
);
print_r($requestData);
$response = $api->process($requestData)->toArray();
print_r( $response['responses'] ); // Still get $response['responses'][0]['errorcode'] == 30004
I expected it to give me a note that all works well, but I still got error 30004, as if the transactionreference wasn't provided. Any idea what I can do, to fix this code, and prevent this error?
Thanks in advance
Yair
Well, I read the Api tests, and I found my error. On the last request data, instead of
$requestData = array(
.
.
'transactionreference' => $transactionreference
.
.
);
I should use
$requestData = array(
.
.
'parenttransactionreference' => $transactionreference
.
.
);
Anyway, home this helps somone
$response = $facebook->api(
'me/objects/namespace:result',
'POST',
array(
'app_id' => app_id,
'type' => "namespace:result",
'url' => "http://samples.ogp.me/370740823026684",
'title' => "Sample Result",
'image' => "https://fbstatic-a.akamaihd.net/images/devsite/attachment_blank.png",
'description' => ""
)
);
I get the following error.
The parameter object is required
I don't know where to add the parameter object.
I have been facing the same issue for the past couple of days, in the end I stopped trying to use the Facebook PHP SDK to send the request and resorted to using just sending a HTTP Request.
I am creating an object rather than updating one, but the implementation shouldn't differ much from your needs. I was getting the same error (The parameter object is required) and the below implementation resolved that issue.
I used the vinelab HTTP client composer package and built a request like this:
$request = [
'url' => 'https://graph.facebook.com/me/objects/namespace:object',
'params' => [
'access_token' => $fbAccessToken,
'method' => 'POST',
'object' => json_encode([
'fb:app_id' => 1234567890,
'og:url' => 'http://samples.ogp.me/1234567890',
'og:title' => 'Sample Object',
'og:image' => 'https://fbstatic-a.akamaihd.net/images/devsite/attachment_blank.png',
'og:description' => 'Sample Object'
])
]
];
// I'm using Laravel so this bit might look different for you (check the vine lab docs if you use that specific HTTP client)
$response = HttpClient::post($request);
// raw content
$response->content();
// json
$response->json();
As I said, I used the vinelab HTTP package in my implementation, you should be able to use any similar package or directly use curl in PHP instead.
So the AWS php sdk 2.x library has been put out recently and I've taken a turkey day plunge into upgrading from 1.5x. My first was to upgrade my S3 backup class. I've quickly run into an error:
Fatal error: Class 'EntityBody' not found in /usr/share/php/....my file here
when trying to upload a zipped file to an S3 bucket. I wrote a class to abstract the writing a bit to allow for multi-region backup, so the code below references to $this are that.
$response1 = $s3->create_object(
$this->bucket_standard,
$this->filename,
array(
'fileUpload' => $this->filename,
'encryption' => 'AES256',
//'acl' => AmazonS3::ACL_PRIVATE,
'contentType' => 'text/plain',
'storage' => AmazonS3::STORAGE_REDUCED,
'headers' => array( // raw headers
'Cache-Control' => 'max-age',
//'Content-Encoding' => 'gzip',
'Content-Language' => 'en-US'
//'Expires' => 'Thu, 01 Nov 2012 16:00:00 GMT'
),
'meta' => array(
'param1' => $this->backupDateTime->format('Y-m-d H:i:s'), // put some info on the file in meta tags
'param2' => $this->hostOrigin
)
)
);
The above worked fine on 1.5.x.
Now, in 2.x, I'm looking into their docs and they've changed just about everything (great...maximum sarcasm)
$s3opts=array('key'=> $this->accessKey, 'secret' => $this->secretKey,'region' => 'us-east-1');
$s3 = Aws\S3\S3Client::factory($s3opts);
so now I've got a new S3 object. And here is my 2.x syntax to do the same exact thing. My problem arises where they've (sinisterly) changed the old "fileupload" to "Body" and made it more abstract in how to actually attach a file! I've tried both and I'm thinking it has to do with the dependencies (Guzzle or Smyfony etc), but I get the error above (or substitute Stream if you like) whenever I try to execute this.
I've tried using Composer with composer.json, and the aws.phar but before I get into that, is there something dumb I'm missing?
$response1 = $s3->putObject(array(
'Bucket' => $this->bucket_standard,
'Key' => $this->filename,
'ServerSideEncryption' => 'AES256',
'StorageClass' => 'REDUCED_REDUNDANCY',
'Body' => EntityBody::factory(fopen($this->filename, 'r')),
//'Body' => new Stream(fopen($fullPath, 'r')),
'MetaData' => array(
'BackupTime' => $this->backupDateTime->format('Y-m-d H:i:s'), // put some info on the file in meta tags
'HostOrigin' => $this->hostOrigin
)
));
Thanks as always,
R
Did you import the EntityBody into your namespace?
use Guzzle\Http\EntityBody;
Otherwise, you'd have to do
'Body' => \Guzzle\Http\EntityBody::factory(fopen($this->filename, 'r')),
I'm trying to post a photo using the php-sdk - all was working for months successfully but all of the sudden no dice.
Other functions are still working with the same code base (ie: posting messages to wall) - its just the posting of photos that broke on my side.
try {
$data = $facebook->api('/me/photos', 'post', $args);
} catch (FacebookApiException $e) {
print_r($e);}
Is dumping:
FacebookApiException Object ( [result:protected] => Array ( [error_code] => 3 [error] => Array ( [message] => No URL set! [type] => CurlException ) ) [message:protected] => No URL set! [string:private] => [code:protected] => 3 [file:protected] => /locationofmy/base_facebook.php [line:protected] => 818 [trace:private] => Array ( [0] => Array [..............]
From the FB php-sdk lines 818:
if ($result === false) {
$e = new FacebookApiException(array(
'error_code' => curl_errno($ch),
'error' => array(
'message' => curl_error($ch),
'type' => 'CurlException',
),
));
curl_close($ch);
throw $e;
}
curl_close($ch);
return $result;
}
This was working for a long time - has something changed on Facebooks side?
EDIT: php-sdk version: 3.1.1
EDIT 2:
$tag = array(
'tag_uid' => 'acct_num',
'x' => 0,
'y' => 0
);
$tags[] = $tag;
$args = array(
'message' => $item_description,
'image' => '#' . realpath($temp_path . $tempFile),
'tags' => $tags,
);
Probably that the file doesnt exist, or the file system can't serve it anymore. Can you confirm "$temp_path . $tempFile" - the error is no URL, usually that means no real path to image. I suspect, that the images are missing and/or your servers filled up and no local images are saving. (Yes, this has happened to me before!)
Try changing the image to source. I believe this should fix your issue.
The Facebook API requires a source field but I did not see anything about an image field.
You may also have to pass the actual file contents instead of the real_path (based on the example). Or, alternatively, pass an external URL (based on my understanding of the documentation).
Source: https://developers.facebook.com/docs/reference/api/photo/
Example: https://developers.facebook.com/blog/post/498/