I am able to get the messages from the new php client. How do I do pagination with messages? How to get next_uri, first_uri, page_size parameters ?
<?php
require_once '/Twilio/autoload.php'; // Loads the library
use Twilio\Rest\Client;
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "xxx";
$token = "xxx";
$client = new Client($sid, $token);
// Loop over the list of messages and echo a property for each one
foreach ($client->messages->read() as $message) {
echo $message->body;
}
?>
Twilio developer evangelist here.
Instead of using read() you can use stream() which will return an iterator for your messages. You can give stream() a limit, but by default it has no limit and will iterate over all of your messages.
<?php
require_once '/Twilio/autoload.php'; // Loads the library
use Twilio\Rest\Client;
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "xxx";
$token = "xxx";
$client = new Client($sid, $token);
// Loop over the list of messages and echo a property for each one
foreach ($client->messages->stream() as $message) {
echo $message->body;
}
?>
The pagination information itself is returned in each request. You can see an example of a call to the Calls resource in the documentation and the pagination information will be the same for Messages.
I wasted hours on this. In case it saves some future person some time, here's what I did. I'm using Laravel but you get the idea:
In your controller:
// If no pagination info has been specified, get the first page of data
// using page(). If there is pagination info in the request, use it with
// getPage()
if (! $request->page) {
$messages = $client->messages->page([], 30);
} else {
$messages = $client->messages->getPage($request->page);
}
Then, in your view (Laravel/blade pseudo-code):
#foreach ($messages as $message)
$message->body
// ... etc
#endforeach
// Next page link
?page={{ urlencode($messages->getNextPageUrl()) }}
// Prev page link
?page={{ urlencode($messages->getPreviousPageUrl()) }}
Docs for page() and getPage().
Here is the Node.js code for fetching message history using paging. You can specify how many items should be in a single page by using the parameter pageSize and use limit parameter to limit the number of pages to display
client.messages.each({
dateSent: new Date(date.toDateString()),
from: event.To,
to: event.From,
pageSize: 1,
limit:1,
done: function(done) {//this is the call back for the for each loop. this will get fired even if no messages found.
console.log('completed for each');
}
}, (messages) => {//each message can handle here.
console.log("message body:", messages.body);
}, (Error) => {
console.log('err');
});
Related
I created a website and I integrated payment using PayStack and it is fully functional, but something unusual came up sometime when a customer wanted to make a payment. After the successful payment processing, maybe something went wrong with the customer's Network provider but the customer was not redirected to a success page where to give values to database.
So I implemented webhooks to get values from paystack and PUT THE CONTENTS in a .txt (webhookApi.txt) file but it seems something is wrong with the code and I can't figure it out.
`
<?php
// only a post with paystack signature header gets our attention
if ((strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) || !array_key_exists('x-paystack-signature', $_SERVER) )
exit();
// Retrieve the request's body
$input = #file_get_contents("php://input");
define('PAYSTACK_SECRET_KEY','sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxx');
// validate event do all at once to avoid timing attack
if($_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] !== hash_hmac('HMAC SHA512', $input, PAYSTACK_SECRET_KEY))
exit();
http_response_code(200);
// parse event (which is json string) as object
// Do something - that will not take long - with $event
$event = json_decode($input);
$reference = $event->data->reference;
$email = $event->data->customer->email;
$eventMessage = $event->event;
file_put_contents("webhookApi.txt", PHP_EOL.$input, FILE_APPEND);
exit();
?>
`
I am trying to create an envelope through PHP sdk, we have working integration using X-DocuSign-Authentication header (with user, password, integrator key combo). Trying to migrate the integration to access token, but keep on getting 404 Resource not found error from the actual SDK (the resources is dictated by the SDK).
Current code:
// DocuSign\eSign\Configuration
$config = new Configuration();
$config->setHost('https://www.docusign.net/restapi');
// DocuSign\eSign\Client\ApiClient
$api = new ApiClient($config);
try {
$response = $api->requestJWTUserToken(
"correct-integrators-key",
"correct-user-id",
file_get_contents( base_path() . '/ds-private.key', true), //exists
"signature impersonation",
);
}
catch (ApiException $e) {
return $e->getMessage();
}
JWT Token payload comes back successfully, and access token is valid.
// DocuSign\eSign\Client\Auth\OAuthToken
if(!$response[0] instanceof OAuthToken)
return "Auth Token Invalid.";
$access_token = $response[0]->getAccessToken();
try {
$user = $api->getUserInfo($access_token);
} catch (ApiException $e) {
return $e->getMessage();
}
// DocuSign\eSign\Client\Auth\UserInfo
if(!$user[0] instanceof UserInfo)
return "User Info Invalid.";
Setting the account ID and base URL also are seemingly correct (account ID comes back as expected, and is correct one, base URL comes back as na2 subdomain, seems to be the correct - this is supported by the fact that "USER_DOES_NOT_BELONG_TO_SPECIFIED_ACCOUNT" is thrown if any other host is used)
$account_id = null;
$base_url = null;
foreach ($user[0]->getAccounts() as $account) {
if($account instanceof Account)
if($account->getIsDefault()) {
$account_id = $account->getAccountId(); // Account ID succeeds, comes back as correct account ID (verified on the admin panel)
$base_url = $account->getBaseUri(); // Base URL succeeds, comes back as na2 subdomain
}
}
$config->setAccessToken($access_token); // Access token succeeds
$config->setHost($base_url);
This code is practically copy/paste of working example with the "old" integration.
$envelopeApi = new EnvelopesApi($api);
$templateRole = new TemplateRole();
$definition = new EnvelopeDefinition();
$templateRole->setEmail('catchable#gmail.com');
$templateRole->setName('Rebecca Smith');
$templateRole->setRoleName('Correct Role Defined On Template');
$templateRole->setClientUserId('Correct User Id For Embedding');
$signers = [];
$signers[] = $templateRole;
$definition->setTemplateId('Valid Template Id');
$definition->setTemplateRoles($signers);
$definition->setStatus('sent');
try {
$envelope = $envelopeApi->createEnvelope($account_id, $definition);
}
catch (ApiException $e) {
return [
'envelope_error_message' => $e->getMessage(), // Returns: "Error while requesting server, received a non successful HTTP code [404] with response Body: "
'envelope_error_code' => $e->getCode(), // Returns: 404
];
}
Tried also directly running $api->callApi to check if v2.1 vs v2 in resource path is the issue, but got 404 on both.
You need to append /restapi to the baseUri
Instead of
$base_url = $account->getBaseUri(); // Base URL succeeds, comes back as na2 subdomain
try
$base_uri_suffix = '/restapi';
$base_url = $account->getBaseUri().$base_uri_suffix; // Base URL succeeds, comes back as na2 subdomain
See the source in the PHP Code Example
I've made a php end-point http://site/stripe-webhooks with code from the Following example "http://stripe.com/docs/webhooks/build".
<?php
/**
* Template Name: Stripe Webhooks
*/
$endpoint_secret = 'whsec_****************************************';
$payload = #file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded($paymentIntent);
break;
case 'payment_intent.created':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded($paymentIntent);
break;
case 'payment_method.attached':
$paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached($paymentMethod);
break;
case 'checkout.session.completed':
$session = $event->data->object;
// Fulfill the purchase...
handle_checkout_session($session);
break;
// ... handle other event types
default:
// Unexpected event type
http_response_code(400);
exit();
}
http_response_code(200);
When I write stripe listen --forward-to http://site/stripe-webhooks in the terminal and test my payment process, it works.
But if I close the terminal, it doesn't work. When I send a test event to webhook endpoint via dashboard, I receive the following response:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>503 Service Unavailable</title>
</head><body>
<h1>Service Unavailable</h1>
<p>The server is temporarily unable to service your
request due to maintenance downtime or capacity
problems. Please try again later.</p>
</body></html>
The page exists and it can be opened in a browser. Where is the mistake?
I'm building a cross-platform chatbot in Google's DialogFlow. I'd like to access the Facebook User Profile API to learn the user's first name.
I'm struggling to find advice on how (or if) I can make this happen.
https://developers.facebook.com/docs/messenger-platform/identity/user-profile/
Has anybody here achieved this?
I did that for one of my bots yesterday, you need 2 things, first the Page Token and second is the psid which is Page scope user ID.
On dialogflow, you will receive the request block with psid as sender id. You can find it at:
agent.originalRequest.payload.data.sender.id
This psid needs to be passed to api get request at
/$psid?fields=first_name with your page Token as accessToken to get the first name in response.
You need to make a call to Facebook Graph API in order to get user's profile.
Facebook offers some SDKs for this, but their official JavaScript SDK is more intended to be on a web client, not on a server. They mention some 3rd party Node.js libraries on that link. I'm particularly using fbgraph (at the time of writing, it's the only one that seems to be "kind of" maintained).
So, you need a Page Token to make the calls. While developing, you can get one from here:
https://developers.facebook.com/apps/<your app id>/messenger/settings/
Here's some example code:
const { promisify } = require('util');
let graph = require('fbgraph'); // facebook graph library
const fbGraph = {
get: promisify(graph.get)
}
graph.setAccessToken(FACEBOOK_PAGE_TOKEN); // <--- your facebook page token
graph.setVersion("3.2");
// gets profile from facebook
// user must have initiated contact for sender id to be available
// returns: facebook profile object, if any
async function getFacebookProfile(agent) {
let ctx = agent.context.get('generic');
let fbSenderID = ctx ? ctx.parameters.facebook_sender_id : undefined;
let payload;
console.log('FACEBOOK SENDER ID: ' + fbSenderID);
if ( fbSenderID ) {
try { payload = await fbGraph.get(fbSenderID) }
catch (err) { console.warn( err ) }
}
return payload;
}
Notice you don't always have access to the sender id, and in case you do, you don't always have access to the profile. For some fields like email, you need to request special permissions. Regular fields like name and profile picture are usually available if the user is the one who initiates the conversation. More info here.
Hope it helps.
Edit
Promise instead of async:
function getFacebookProfile(agent) {
return new Promise( (resolve, reject) => {
let ctx = agent.context.get('generic');
let fbSenderID = ctx ? ctx.parameters.facebook_sender_id : undefined;
console.log('FACEBOOK SENDER ID: ' + fbSenderID);
fbGraph.get( fbSenderID )
.then( payload => {
console.log('all fine: ' + payload);
resolve( payload );
})
.catch( err => {
console.warn( err );
reject( err );
});
});
}
I use this code to get data from Instagram API. The code runs correctly on some servers, but on other servers it doesn't receive data from Instagram API. The "Curl" is enabled in all servers, who knows what happened?
<?php
require 'instagram.class.php';
require 'config.php';
// Receive OAuth code parameter
$code = $_GET['code'];
// Check whether the user has granted access
if (true === isset($code)) {
// Receive OAuth token object
// Take a look at the API response
$data = $instagram->getOAuthToken($code);
if(empty($data->user->username)){
header('Location: index.php');
} else {
session_start();
$_SESSION['xxx']=$data;
$user=$data->user->username;
$ig_id=$data->user->id;
header('Location: profile.php');
}
} else {
// Check whether an error occurred
if (true === isset($_GET['error'])){
echo $_GET['error_description'];
}
}
?>