purityselect/app/Classes/Calendly.php
2024-10-25 01:05:27 +05:00

358 lines
13 KiB
PHP

<?php
namespace App\Classes;
use App\Models\Setting;
use Carbon\Carbon;
use DateTime;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class Calendly
{
protected $clientId = "1SW4eLp_g-nFim1XOORcAh-2lH2H-dfUVCiB1tLpkvo";
protected $clientSecret = "qXtkthnPxdCoHzVekWsgKr1QEH2q5nm5B3R81x6IG28";
//protected $redirectUri = 'https://hgh.codelfi.com/calendly/redirect-code/';
public function authUrl()
{
$url = 'https://auth.calendly.com/oauth/authorize';
$url .= '?client_id=' . urlencode($this->clientId);
$url .= '&response_type=code';
$url .= '&redirect_uri=' . urlencode(route('redirectURI'));
//$url .= '&redirect_uri=' . urlencode('https://app.example.com/calendly/redirect-code/');
return $url;
}
public function authorize($code)
{
$tokenUrl = 'https://auth.calendly.com/oauth/token';
$client = new Client();
try {
$response = $client->post($tokenUrl, [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'redirect_uri' => route("redirectURI"),
//'redirect_uri' => 'https://app.example.com/calendly/redirect-code/',
'code' => $code,
],
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
Log::info('Info from function authorize(): ', $data);
$setting = Setting::find(1);
$setting->calendly_access_token = $data['access_token'];
$setting->calendly_refresh_token = $data['refresh_token'];
$setting->save();
Cache::forget('calendly_access_token');
Cache::put('calendly_access_token', $data['access_token'], now()->addSeconds($data['expires_in']));
return [
'access_token' => $data['access_token'],
'refresh_token' => $data['refresh_token'],
'token_type' => $data['token_type'],
'expires_in' => $data['expires_in']
];
} catch (\Exception $e) {
throw $e;
}
}
public function accessToken()
{
if (Cache::has('calendly_access_token')) {
return Cache::get('calendly_access_token');
}
$setting = Setting::find(1);
$tokenUrl = 'https://auth.calendly.com/oauth/token';
$client = new Client();
$response = $client->post($tokenUrl, [
'form_params' => [
'grant_type' => 'refresh_token',
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'refresh_token' => $setting->calendly_refresh_token,
],
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
]);
// Decode the response
$data = json_decode($response->getBody()->getContents(), true);
Log::info('Info from function accessToken(): ', $data);
// Store the new access token and refresh token in cache
Cache::put('calendly_access_token', $data['access_token'], now()->addSeconds($data['expires_in']));
return $data['access_token'];
}
public function getUserUri()
{
// 1. Call the /users/me API to get user information
$client = new Client();
try {
$response = $client->request('GET', 'https://api.calendly.com/users/me', [
'headers' => [
'Authorization' => 'Bearer ' . $this->accessToken(),
'Content-Type' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
return $userUri = $data['resource']['uri'];
} catch (\Exception $e) {
return false;
}
}
public function eventTypes()
{
// 1. Call the /users/me API to get user information
$client = new Client();
$responseEvent = $client->request('GET', 'https://api.calendly.com/event_types?user=' . $this->getUserUri(), [
'headers' => [
'Authorization' => 'Bearer ' . $this->accessToken(),
'Content-Type' => 'application/json',
]
]);
$dataEvent = json_decode($responseEvent->getBody(), true);
return $dataEvent['collection'];
}
public function setEventUri($even_type_url)
{
$setting = Setting::find(1);
$setting->event_type = $even_type_url;
$setting->save();
}
public function resetEventUri()
{
$setting = Setting::find(1);
$setting->event_type = null;
$setting->calendly_access_token = null;
$setting->calendly_refresh_token = null;
$setting->save();
}
function getAvailableDates($even_type_url, $month, $tz = "UTC")
{
try {
$availableTimes = [];
$date = Carbon::createFromDate(Carbon::now()->year, $month, 1, $tz);
$date = $date->startOfMonth()->tz("UTC");
$endMonthDate = Carbon::createFromDate(Carbon::now()->year, $month, 1, $tz);
$endMonthDate = $endMonthDate->endOfMonth()->tz("UTC");
while ($date < $endMonthDate) {
$start_time = $date->startOfDay()->format('Y-m-d\T24:00:00.000000\Z');
$end_time = $date->addDays(7)->endOfDay()->format('Y-m-d\T24:00:00.000000\Z');
$client = new Client();
try {
// Prepare API endpoint with the required parameters
$eventTypeUrl = 'https://api.calendly.com/event_type_available_times';
$queryParams = [
'event_type' => $even_type_url,
'start_time' => $start_time,
'end_time' => $end_time
];
$str = "event_type=" . urlencode($queryParams['event_type']) . "&" . "start_time=" . urlencode($queryParams['start_time']) . "&" . "end_time=" . urlencode($queryParams['end_time']);
$eventTypeUrl = $eventTypeUrl . "?" . ($str);
// Send the request to Calendly
$response = $client->request('GET', $eventTypeUrl, [
'headers' => [
'Authorization' => 'Bearer ' . $this->accessToken(),
'Content-Type' => 'application/json',
],
// 'query' => $queryParams
]);
$data = json_decode($response->getBody(), true);
//$availableTimes += $data['collection'];
foreach ($data['collection'] as $slot) {
$slotDate = Carbon::parse($slot['start_time'])->tz($tz)->format('Y-m-d');
if (!isset($availableTimes[$slotDate])) {
$availableTimes[$slotDate] = [];
}
$slotDateTime = Carbon::parse($slot['start_time'])->tz($tz);
$dateKey = $slotDateTime->format('Y-m-d');
$slot['formatted_datetime'] = $slotDateTime->format('Y-m-d g:i:00');
$availableTimes[$slotDate][] = $slot;
}
} catch (Exception $e) {
Log::error('Error from function getAvailableDates(): ' . $e->getMessage(), [
'eventTypeUrl' => $eventTypeUrl,
'queryParams' => $queryParams,
'full_rul' => $eventTypeUrl,
'Authorization' => 'Bearer ' . $this->accessToken(),
]);
continue;
}
$date->addSecond();
}
return $availableTimes;
} catch (\Exception $e) {
return response()->json(['error' => 'Failed to fetch available times: ' . $e->getMessage()], 500);
}
}
// write function to do php get and post request and add json support
function makeRequest($url, $method = 'GET', $data = [], $headers = [], $json = false, $proxy = "iproyal15202:pb86ljih495_country-us@geo.iproyal.com:12321")
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_ENCODING, '',);
if ($proxy) {
curl_setopt($ch, CURLOPT_PROXY, 'http://geo.iproyal.com:12321'); // Set the proxy address and port
curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'iproyal15202:Pb86ljiH495_country-us'); // Set the proxy authentication credentials
}
$headers = ['User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36', ...$headers];
if ($method === 'POST') {
if ($json) {
$headers = ['Content-Type: application/json', ...$headers];
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
} else {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
}
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
function getCrfToken($url)
{
$response = $this->makeRequest($url);
// var_dump($response);
//<meta name="csrf-token" content="mTW6eNk5xiDTzby7yHl_iVTO1_pi-CXZ2U9MYPcXGJGMpksW4iGLJniNxs-T4xrmYlLbXFaLuU8FZ75cuorz8w" />
preg_match('/<meta name="csrf-token" content="(.*?)" \/>/', $response, $matches);
return $matches[1];
}
function getEventDetails($url)
{
$response = $this->makeRequest($url);
return $response;
}
//random string function
function generateRandomString($length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
public function bookEvent($url, $name, $email, $timezone = "UTC")
{
$url_parts = explode("/", $url);
$bookingDate = $url_parts[5];
$event_type = $url_parts[4];
$owner_id = $url_parts[3];
$eventDetailsUrl = "https://calendly.com/api/booking/profiles/$owner_id/event_types/$event_type";
$eventDetails = json_decode($this->makeRequest($eventDetailsUrl));
// var_dump($eventDetails);
$crfToken = $this->getCrfToken($url);
$eventUuid = $eventDetails->uuid;
$link_uuid = $eventDetails->scheduling_link->uid;
$custom_fields_id = $eventDetails->custom_fields[0]->id;
$booking_request_id = urlencode($this->generateRandomString(36) . "|$bookingDate|$eventUuid|$name");
//convert to php array
$bookingData = [
"analytics" => [
//php date with 10 sec gap
"invitee_landed_at" => date("Y-m-d\TH:i:s.uP", strtotime($bookingDate) - 200),
"browser" => "Chrome 129",
"device" => "undefined Mac OS X 10.15.7",
"fields_filled" => 1,
"fields_presented" => 1,
"booking_flow" => "v3",
"seconds_to_convert" => 200
],
"embed" => [],
"event" => [
"start_time" => $bookingDate,
"location_configuration" => [
"location" => "",
"phone_number" => "",
"additional_info" => ""
],
"guests" => []
],
"event_fields" => [
[
"id" => $custom_fields_id,
"name" => "Please share anything that will help prepare for our meeting.",
"format" => "text",
"required" => false,
"position" => 0,
"answer_choices" => null,
"include_other" => false,
"value" => ""
]
],
"invitee" => [
"timezone" => $timezone,
"time_notation" => "24h",
"full_name" => $name,
"email" => $email
],
"payment_token" => [],
"tracking" => [
"fingerprint" => $this->generateRandomString(32)
],
"scheduling_link_uuid" => $link_uuid,
"locale" => "en",
"verification_code" => null,
"remember_device" => false
];
$response = $this->makeRequest("https://calendly.com/api/booking/invitees", 'POST', $bookingData, [
'x-csrf-token: ' . $crfToken,
'x-page-rendered-at: ' . date('Y-m-d\TH:i:s'),
'x-requested-with: XMLHttpRequest',
'referer: ' . $url,
"booking-request-id: $booking_request_id"
], true);
return $response;
}
}