367 lines
15 KiB
PHP
367 lines
15 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Carbon\Carbon;
|
|
use DateTime;
|
|
use Illuminate\Http\Request;
|
|
use GuzzleHttp\Client;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class CalendlyControllerOld extends Controller
|
|
{
|
|
protected $clientId = "eOk7Vb-60_l6U4WmAe9y9MThi-WKGzEuyru_B3I2jwk";
|
|
protected $clientSecret = "EYLgGEHLudI65wdqG7Qz1azZwFCFx8kvikXYoM2EbiE";
|
|
protected $redirectUri = 'https://hgh.codelfi.com/calendly/redirect-code/';
|
|
|
|
// Generate Calendly authorization URL
|
|
public function getCalendlyAuthUrl()
|
|
{
|
|
$url = 'https://auth.calendly.com/oauth/authorize';
|
|
$url .= '?client_id=' . urlencode($this->clientId);
|
|
$url .= '&response_type=code';
|
|
$url .= '&redirect_uri=' . urlencode($this->redirectUri);
|
|
|
|
return response()->json(['url' => $url]);
|
|
}
|
|
|
|
// Handle the redirect with authorization code and exchange for access token
|
|
public function getRedirectCode(Request $request)
|
|
{
|
|
// Get the authorization code from the request
|
|
$authorizationCode = $request->input('code');
|
|
|
|
if (!$authorizationCode) {
|
|
return response()->json(['error' => 'Authorization code is missing'], 400);
|
|
}
|
|
//return $this->getCalendlyUserAndAvailability();
|
|
// Call method to fetch access token and cache it
|
|
$this->getAccessTokenFromCode($authorizationCode);
|
|
return response()->json(['message' => 'Admin has been authenticated.'], 200);
|
|
}
|
|
// Handle the redirect with authorization code and exchange for access token
|
|
public function getAvailabeSlotDates(Request $request)
|
|
{
|
|
return $this->getCalendlyUserAndAvailability();
|
|
// Call method to fetch access token and cache it
|
|
}
|
|
|
|
// Fetch or refresh access token if needed
|
|
public function getAccessToken()
|
|
{
|
|
// Check if the access token exists in cache
|
|
if (Cache::has('calendly_access_token')) {
|
|
return Cache::get('calendly_access_token');
|
|
}
|
|
|
|
// If no token is available, return error or trigger refresh
|
|
return response()->json(['error' => 'No valid access token. Please authenticate again.'], 401);
|
|
}
|
|
|
|
// Exchange authorization code for access token and store it in cache
|
|
private function getAccessTokenFromCode($authorizationCode)
|
|
{
|
|
$tokenUrl = 'https://auth.calendly.com/oauth/token';
|
|
|
|
// Use GuzzleHttp client to make the POST request
|
|
$client = new Client();
|
|
|
|
try {
|
|
$response = $client->post($tokenUrl, [
|
|
'form_params' => [
|
|
'grant_type' => 'authorization_code',
|
|
'client_id' => $this->clientId,
|
|
'client_secret' => $this->clientSecret,
|
|
'redirect_uri' => $this->redirectUri,
|
|
'code' => $authorizationCode,
|
|
],
|
|
'headers' => [
|
|
'Content-Type' => 'application/x-www-form-urlencoded',
|
|
],
|
|
]);
|
|
|
|
// Decode the JSON response
|
|
$data = json_decode($response->getBody()->getContents(), true);
|
|
|
|
// Store access token and refresh token in cache with an expiration
|
|
//Cache::put('calendly_access_token', $data['access_token'], now()->addSeconds($data['expires_in']));
|
|
//Cache::put('calendly_refresh_token', $data['refresh_token'], now()->addDays(30)); // Refresh tokens don't expire until used
|
|
|
|
return response()->json([
|
|
'access_token' => $data['access_token'],
|
|
'refresh_token' => $data['refresh_token'],
|
|
'token_type' => $data['token_type'],
|
|
'expires_in' => $data['expires_in']
|
|
]);
|
|
} catch (\Exception $e) {
|
|
// Handle errors
|
|
return response()->json(['error' => 'Failed to fetch access token: ' . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
// Use refresh token to get a new access token when expired
|
|
private function refreshAccessToken()
|
|
{
|
|
if (!Cache::has('calendly_refresh_token')) {
|
|
return response()->json(['error' => 'Refresh token not available.'], 401);
|
|
}
|
|
|
|
$refreshToken = Cache::get('calendly_refresh_token');
|
|
|
|
$tokenUrl = 'https://auth.calendly.com/oauth/token';
|
|
|
|
$client = new Client();
|
|
|
|
try {
|
|
$response = $client->post($tokenUrl, [
|
|
'form_params' => [
|
|
'grant_type' => 'refresh_token',
|
|
'client_id' => $this->clientId,
|
|
'client_secret' => $this->clientSecret,
|
|
'refresh_token' => $refreshToken,
|
|
],
|
|
'headers' => [
|
|
'Content-Type' => 'application/x-www-form-urlencoded',
|
|
],
|
|
]);
|
|
|
|
// Decode the response
|
|
$data = json_decode($response->getBody()->getContents(), true);
|
|
|
|
// Store the new access token and refresh token in cache
|
|
Cache::put('calendly_access_token', $data['access_token'], now()->addSeconds($data['expires_in']));
|
|
Cache::put('calendly_refresh_token', $data['refresh_token'], now()->addDays(30)); // New refresh token
|
|
|
|
return $data['access_token'];
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => 'Failed to refresh access token: ' . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
function getCalendlyUserAndAvailability()
|
|
{
|
|
// Get the access token from cache
|
|
$accessToken = Cache::get('calendly_access_token');
|
|
|
|
// If the token is not in cache, fetch a new one
|
|
if (!$accessToken) {
|
|
$accessToken = $this->fetchCalendlyAccessToken();
|
|
}
|
|
|
|
if (!$accessToken) {
|
|
return response()->json(['error' => 'Token Expired!'], 500);
|
|
}
|
|
|
|
// 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 ' . $accessToken,
|
|
'Content-Type' => 'application/json',
|
|
]
|
|
]);
|
|
|
|
$data = json_decode($response->getBody(), true);
|
|
$userUri = $data['resource']['uri'];
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => 'Failed to fetch user details: ' . $e->getMessage()], 500);
|
|
}
|
|
|
|
// 2. Use the user URI to fetch availability schedules
|
|
try {
|
|
$availabilityResponse = $client->request('GET', 'https://api.calendly.com/user_availability_schedules', [
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $accessToken,
|
|
'Content-Type' => 'application/json',
|
|
],
|
|
'query' => [
|
|
'user' => $userUri
|
|
]
|
|
]);
|
|
|
|
$availabilityData = json_decode($availabilityResponse->getBody(), true);
|
|
// Get the rules from the availability data
|
|
$rules = $availabilityData['collection'][0]['rules'];
|
|
|
|
// Map day of the week to the date in the current week
|
|
$weekDates = $this->getCurrentWeekDates(); // Get this week's dates
|
|
|
|
// Add the corresponding date to each rule
|
|
$updatedRules = array_map(function ($rule) use ($weekDates) {
|
|
$wday = $rule['wday'];
|
|
// Check if we have a corresponding date for this weekday
|
|
if (isset($weekDates[$wday])) {
|
|
$rule['date'] = $weekDates[$wday]; // Add date to the rule
|
|
} else {
|
|
$rule['date'] = null; // No availability on that day
|
|
}
|
|
return $rule;
|
|
}, $rules);
|
|
|
|
// Add the updated rules with dates back to the response
|
|
$availabilityData['collection'][0]['rules'] = $updatedRules; // Get the rules from the availability data
|
|
$rules = $availabilityData['collection'][0]['rules'];
|
|
|
|
// Map day of the week to the date in the current week
|
|
$weekDates = $this->getCurrentWeekDates(); // Get this week's dates
|
|
|
|
// Add the corresponding date to each rule
|
|
$updatedRules = array_map(function ($rule) use ($weekDates) {
|
|
$wday = $rule['wday'];
|
|
// Check if we have a corresponding date for this weekday
|
|
if (isset($weekDates[$wday])) {
|
|
$rule['date'] = $weekDates[$wday]; // Add date to the rule
|
|
} else {
|
|
$rule['date'] = null; // No availability on that day
|
|
}
|
|
return $rule;
|
|
}, $rules);
|
|
|
|
$filteredDates = array_values(array_filter(array_map(function ($rule) {
|
|
return !empty($rule['intervals']) ? $rule['date'] : null;
|
|
}, $updatedRules)));
|
|
// Add the updated rules with dates back to the response
|
|
$availabilityData['collection'][0]['rules'] = $updatedRules;
|
|
return response()->json($availabilityData, 200);
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => 'Failed to fetch availability: ' . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
private function getCurrentWeekDates()
|
|
{
|
|
$weekDates = [];
|
|
|
|
// Start from Sunday as 0, loop through the week
|
|
for ($day = 0; $day < 7; $day++) {
|
|
$carbonDate = Carbon::now()->startOfWeek()->addDays($day); // Start on Sunday
|
|
$weekday = strtolower($carbonDate->format('l')); // Get the day name (sunday, monday, etc.)
|
|
$weekDates[$weekday] = $carbonDate->toDateString(); // Store the date for that day
|
|
}
|
|
|
|
return $weekDates; // Return array of week dates
|
|
}
|
|
// Helper function to fetch access token
|
|
function fetchCalendlyAccessToken()
|
|
{
|
|
$client = new Client();
|
|
try {
|
|
$response = $client->post('https://auth.calendly.com/oauth/token', [
|
|
'form_params' => [
|
|
'grant_type' => 'authorization_code',
|
|
'client_id' => $this->clientId,
|
|
'client_secret' => $this->clientSecret,
|
|
'redirect_uri' => $this->redirectUri,
|
|
'code' => request()->input('code'), // Get authorization code from request
|
|
],
|
|
'headers' => [
|
|
'Content-Type' => 'application/x-www-form-urlencoded',
|
|
]
|
|
]);
|
|
|
|
$data = json_decode($response->getBody(), true);
|
|
$accessToken = $data['access_token'];
|
|
|
|
// Store access token in cache for 2 hours
|
|
Cache::put('calendly_access_token', $accessToken, 120 * 60);
|
|
|
|
return $accessToken;
|
|
} catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
public function getAvailableTimes(Request $request)
|
|
{
|
|
try {
|
|
// Validate start_time and end_time input
|
|
/* $validatedData = $request->validate([
|
|
'start_time' => 'required|date_format:Y-m-d\TH:i:s\Z',
|
|
'end_time' => 'required|date_format:Y-m-d\TH:i:s\Z',
|
|
]); */
|
|
|
|
// Get the access token from cache
|
|
$accessToken = Cache::get('calendly_access_token');
|
|
|
|
// If the token is not in cache, fetch a new one
|
|
if (!$accessToken) {
|
|
$accessToken = $this->fetchCalendlyAccessToken();
|
|
}
|
|
|
|
if (!$accessToken) {
|
|
return response()->json(['error' => 'Unable to retrieve access token'], 500);
|
|
}
|
|
|
|
// 1. Call the /users/me API to get user information
|
|
$client = new Client();
|
|
$response = $client->request('GET', 'https://api.calendly.com/users/me', [
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $accessToken,
|
|
'Content-Type' => 'application/json',
|
|
]
|
|
]);
|
|
|
|
$data = json_decode($response->getBody(), true);
|
|
$userUri = $data['resource']['uri'];
|
|
|
|
// 1. Call the /users/me API to get user information
|
|
$client = new Client();
|
|
$responseEvent = $client->request('GET', 'https://api.calendly.com/event_types?user=' . $userUri, [
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $accessToken,
|
|
'Content-Type' => 'application/json',
|
|
]
|
|
]);
|
|
|
|
$dataEvent = json_decode($responseEvent->getBody(), true);
|
|
$even_type_url = $dataEvent['collection'][0]['uri'];
|
|
$userUri = $data['resource']['uri'];
|
|
|
|
|
|
$client = new Client();
|
|
|
|
// Prepare API endpoint with the required parameters
|
|
$eventTypeUrl = 'https://api.calendly.com/event_type_available_times';
|
|
$queryParams = [
|
|
'event_type' => $even_type_url, //'https://api.calendly.com/event_types/60992c14-2f0b-42c2-af7b-95062d065600', // Use your event_type URL
|
|
'start_time' => $request->input('start_time'),
|
|
'end_time' => $request->input('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 ' . $accessToken,
|
|
'Content-Type' => 'application/json',
|
|
],
|
|
// 'query' => $queryParams
|
|
]);
|
|
|
|
$data = json_decode($response->getBody(), true);
|
|
$processedTimes = array_map(function ($item) {
|
|
$dateTime = new DateTime($item['start_time']);
|
|
$readableTime = $dateTime->format('Y-m-d H:i'); // Format: YYYY-MM-DD h:mm AM/PM
|
|
|
|
return [
|
|
'status' => $item['status'],
|
|
'start_time' => $readableTime,
|
|
'invitees_remaining' => $item['invitees_remaining'],
|
|
'scheduling_url' => $item['scheduling_url']
|
|
];
|
|
}, $data['collection']);
|
|
|
|
// Extract scheduling URLs from available time slots
|
|
$availableTimes = array_map(function ($slot) {
|
|
return $slot['scheduling_url'];
|
|
}, $data['collection']);
|
|
|
|
return response()->json([
|
|
'available_times' => $processedTimes
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => 'Failed to fetch available times: ' . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
}
|