Skip to content

Instantly share code, notes, and snippets.

@weitzman
Created May 16, 2022 15:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weitzman/8fc35cbb31126fe9c0307e353b8b7273 to your computer and use it in GitHub Desktop.
Save weitzman/8fc35cbb31126fe9c0307e353b8b7273 to your computer and use it in GitHub Desktop.
Webhook Twilio to Sheets
<?php
/* Ad hoc functions to make the examples marginally prettier.*/
function isWebRequest()
{
return isset($_SERVER['HTTP_USER_AGENT']);
}
function pageHeader($title)
{
$ret = "<!doctype html>
<html>
<head>
<title>" . $title . "</title>
<link href='styles/style.css' rel='stylesheet' type='text/css' />
</head>
<body>\n";
if ($_SERVER['PHP_SELF'] != "/index.php") {
$ret .= "<p><a href='index.php'>Back</a></p>";
}
$ret .= "<header><h1>" . $title . "</h1></header>";
// Start the session (for storing access tokens and things)
if (!headers_sent()) {
session_start();
}
return $ret;
}
function pageFooter($file = null)
{
$ret = "";
if ($file) {
$ret .= "<h3>Code:</h3>";
$ret .= "<pre class='code'>";
$ret .= htmlspecialchars(file_get_contents($file));
$ret .= "</pre>";
}
$ret .= "</html>";
return $ret;
}
function missingApiKeyWarning()
{
$ret = "
<h3 class='warn'>
Warning: You need to set a Simple API Access key from the
<a href='http://developers.google.com/console'>Google API console</a>
</h3>";
return $ret;
}
function missingClientSecretsWarning()
{
$ret = "
<h3 class='warn'>
Warning: You need to set Client ID, Client Secret and Redirect URI from the
<a href='http://developers.google.com/console'>Google API console</a>
</h3>";
return $ret;
}
function missingServiceAccountDetailsWarning()
{
$ret = "
<h3 class='warn'>
Warning: You need download your Service Account Credentials JSON from the
<a href='http://developers.google.com/console'>Google API console</a>.
</h3>
<p>
Once downloaded, move them into the root directory of this repository and
rename them 'service-account-credentials.json'.
</p>
<p>
In your application, you should set the GOOGLE_APPLICATION_CREDENTIALS environment variable
as the path to this file, but in the context of this example we will do this for you.
</p>";
return $ret;
}
function missingOAuth2CredentialsWarning()
{
$ret = "
<h3 class='warn'>
Warning: You need to set the location of your OAuth2 Client Credentials from the
<a href='http://developers.google.com/console'>Google API console</a>.
</h3>
<p>
Once downloaded, move them into the root directory of this repository and
rename them 'oauth-credentials.json'.
</p>";
return $ret;
}
function invalidCsrfTokenWarning()
{
$ret = "
<h3 class='warn'>
The CSRF token is invalid, your session probably expired. Please refresh the page.
</h3>";
return $ret;
}
function checkServiceAccountCredentialsFile()
{
// service account creds
$application_creds = dirname(__DIR__) . '/twilio_to_sheets_key.json';
return file_exists($application_creds) ? $application_creds : false;
}
function getCsrfToken()
{
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes(32));
}
return $_SESSION['csrf_token'];
}
function validateCsrfToken()
{
return isset($_REQUEST['csrf_token'])
&& isset($_SESSION['csrf_token'])
&& $_REQUEST['csrf_token'] === $_SESSION['csrf_token'];
}
function getOAuthCredentialsFile()
{
// oauth2 creds
$oauth_creds = __DIR__ . '/../../oauth-credentials.json';
if (file_exists($oauth_creds)) {
return $oauth_creds;
}
return false;
}
function setClientCredentialsFile($apiKey)
{
$file = __DIR__ . '/../../tests/.apiKey';
file_put_contents($file, $apiKey);
}
function getApiKey()
{
$file = __DIR__ . '/../../tests/.apiKey';
if (file_exists($file)) {
return file_get_contents($file);
}
}
function setApiKey($apiKey)
{
$file = __DIR__ . '/../../tests/.apiKey';
file_put_contents($file, $apiKey);
}
webhook_twilio_to_sheets.php<?php
/**
* Auth uses a service account: https://stackoverflow.com/a/49965912
*/
use GuzzleHttp\Client;
require '../vendor/autoload.php';
// From https://github.com/googleapis/google-api-php-client/blob/a9a27c25d625a95133f790f3b4a1036ad5b4e9eb/examples/templates/base.php#L112
require __DIR__ . '/base.php';
if (!$token = getenv('SHARED_SECRET')) {
// throw new Exception('Missing shared secret.');
}
if (!$flow_id = $_POST['flow_id']) {
// throw new Exception('Missing Flow ID.');
$flow_id = '';
}
if (!$phone = $_POST['phone']) {
throw new Exception('Missing Phone Number.');
}
if (!$key = $_POST['key']) {
throw new Exception('Missing Key.');
}
if (!$value = $_POST['value']) {
throw new Exception('Missing Value.');
}
$row = [
(new DateTime())->setTimezone(new DateTimeZone('America/New_York'))->format('Y-m-d H:i:s'),
$flow_id,
$phone,
$key,
$value,
$_POST['description'] ?: '',
];
post([$row]);
/**
* Post rows to the Google sheet.
*
* @param array $rows
*
* @throws \Exception
*/
function post(array $rows) {
// Send data to GSheets.
$client = getClient();
$service = new Google_Service_Sheets($client);
$spreadsheetId = '125jbio8HZUhcft1Qc1ZG7rMpqEHRT6tcUr_J0dEhXT4';
$range = 'Data!A1:E';
$valueRange = new Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$optParams = ['valueInputOption' => 'USER_ENTERED'];
return $service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $optParams);
}
/**
* Returns an authorized API client.
*
* @return Google_Client
* The authorized client object.
*/
function getClient() {
global $path_token, $path_credentials;
$client = new Google_Client();
$client->setApplicationName('Google Sheets API PHP Quickstart');
$client->setScopes(Google_Service_Sheets::SPREADSHEETS);
// Try various ways to get service account key info.
if ($credentials_file = checkServiceAccountCredentialsFile()) {
$client->setAuthConfig($credentials_file);
} elseif (getenv('GOOGLE_APPLICATION_CREDENTIALS')) {
// use the application default credentials
$client->useApplicationDefaultCredentials();
} else {
echo missingServiceAccountDetailsWarning();
return;
}
return $client;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment