Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.

change Readme.md #317

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ TWILIO_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Twilio phone number
# Purchase one at https://www.twilio.com/user/account/phone-numbers
TWILIO_NUMBER=+15552737123

# You need to create a TwiML app to use this project.
# Create one at https://www.twilio.com/user/account/apps/add,
# then use its "Sid" value here
TWILIO_APPLICATION_SID=APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
158 changes: 143 additions & 15 deletions app/Http/Controllers/ReservationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,36 @@
use App\User;
use App\VacationProperty;
use DB;
use Services_Twilio as TwilioRestClient;
use Services_Twilio_Twiml as TwilioTwiml;
use Twilio\Rest\Client;
use Twilio\Twiml;
use Log;

class ReservationController extends Controller
{
public function index(Authenticatable $user)
{
$reservations = array();

foreach ($user->propertyReservations as $reservation)
{
array_push($reservations, $reservation->fresh());
}
return view(
'reservation.index',
[
'hostReservations' => $reservations,
'guestReservations' => $user->reservations
]
);
}

/**
* Store a new reservation
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function create(TwilioRestClient $client, Request $request, Authenticatable $user, $id)
public function create(Client $client, Request $request, Authenticatable $user, $id)
{
$this->validate(
$request, [
Expand All @@ -28,8 +46,8 @@ public function create(TwilioRestClient $client, Request $request, Authenticatab
);
$property = VacationProperty::find($id);
$reservation = new Reservation($request->all());
$reservation->respond_phone_number = $user->fullNumber();
$reservation->user()->associate($property->user);

$reservation->user()->associate($user);

$property->reservations()->save($reservation);

Expand All @@ -39,23 +57,26 @@ public function create(TwilioRestClient $client, Request $request, Authenticatab
'status',
"Sending your reservation request now."
);
return redirect()->route('property-show', ['id' => $property->id]);
return redirect()->route('reservation-index', ['id' => $property->id]);
}

public function acceptReject(Request $request)
public function acceptReject(Client $client, Request $request)
{
$hostNumber = $request->input('From');
$smsInput = strtolower($request->input('Body'));
$host = User::where(DB::raw("CONCAT('+',country_code::text, phone_number::text)"), 'LIKE', "%".$hostNumber."%")
->get()
->first();
->get()
->first();

$reservation = $host->pendingReservations()->first();
$smsResponse = null;
if (!is_null($reservation))
{
$reservation = $reservation->fresh();

if (strpos($smsInput, 'yes') !== false || strpos($smsInput, 'accept') !== false)
{
$reservation->confirm();
$reservation->confirm($this->getNewTwilioNumber($client, $host));
}
else
{
Expand All @@ -72,16 +93,84 @@ public function acceptReject(Request $request)
return response($this->respond($smsResponse, $reservation))->header('Content-Type', 'application/xml');
}

public function connectSms(Request $request)
{
$twilioNumber = $request->input('To');
$incomingNumber = $request->input('From');
$messageBody = $request->input('Body');

$reservation = $this->getReservationFromNumber($twilioNumber);
$host = $reservation->property->user;
$guest = $reservation->user;

if ($incomingNumber === $host->fullNumber())
{
$outgoingNumber = $guest->fullNumber();
}
else
{
$outgoingNumber = $host->fullNumber();
}

return response($this->connectSmsResponse($messageBody, $outgoingNumber))->header('Content-Type', 'application/xml');
}

public function connectVoice(Request $request)
{
$twilioNumber = $request->input('To');
$incomingNumber = $request->input('From');

$reservation = $this->getReservationFromNumber($twilioNumber);
$host = $reservation->property->user;
$guest = $reservation->user;

if ($incomingNumber === $host->fullNumber())
{
$outgoingNumber = $guest->fullNumber();
}
else
{
$outgoingNumber = $host->fullNumber();
}

return response($this->connectVoiceResponse($outgoingNumber))->header('Content-Type', 'application/xml');
}

private function getReservationFromNumber($twilioNumber)
{
return Reservation::where('twilio_number', '=', $twilioNumber)->first();
}

private function connectVoiceResponse($outgoingNumber)
{
$response = new Twiml();
$response->play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
$response->dial($outgoingNumber);

return $response;
}

private function connectSmsResponse($messageBody, $outgoingNumber)
{
$response = new Twiml();
$response->message(
$messageBody,
['to' => $outgoingNumber]
);

return $response;
}

private function respond($smsResponse, $reservation)
{
$response = new TwilioTwiml;
$response = new Twiml();
$response->message($smsResponse);

if (!is_null($reservation))
{
$response->message(
'Your reservation has been ' . $reservation->status . '.',
['to' => $reservation->respond_phone_number]
['to' => $reservation->user->fullNumber()]
);
}
return $response;
Expand All @@ -93,14 +182,53 @@ private function notifyHost($client, $reservation)

$twilioNumber = config('services.twilio')['number'];

$messageBody = $reservation->message . ' - Reply \'yes\' or \'accept\' to confirm the reservation, or anything else to reject it.';

try {
$client->account->messages->sendMessage(
$twilioNumber, // From a Twilio number in your account
$client->messages->create(
$host->fullNumber(), // Text any number
$reservation->message
[
'from' => $twilioNumber, // From a Twilio number in your account
'body' => $messageBody
]
);
} catch (Exception $e) {
Log::error($e->getMessage());
}
}

private function getNewTwilioNumber($client, $host)
{
$numbers = $client->availablePhoneNumbers('US')->local->read(
[
'areaCode' => $host->areaCode(),
'voiceEnabled' => 'true',
"smsEnabled" => 'true'
]
);

if (empty($numbers)) {
$numbers = $client->availablePhoneNumbers('US')->local->read(
[
'voiceEnabled' => 'true',
"smsEnabled" => 'true'
]
);
}
$twilioNumber = $numbers[0]->phoneNumber;

$newNumber = $client->incomingPhoneNumbers->create(
[
"phoneNumber" => $twilioNumber,
"smsApplicationSid" => config('services.twilio')['applicationSid'],
"voiceApplicationSid" => config('services.twilio')['applicationSid']
]
);

if ($newNumber) {
return $twilioNumber;
} else {
return 0;
}
}
}
4 changes: 3 additions & 1 deletion app/Http/Middleware/VerifyCsrfToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class VerifyCsrfToken extends BaseVerifier
* @var array
*/
protected $except = [
'reservation/incoming'
'reservation/incoming',
'reservation/connect_sms',
'reservation/connect_voice'
];
}
19 changes: 19 additions & 0 deletions app/Http/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,27 @@ function() {
'middleware' => 'auth']
);

Route::get(
'/reservations',
['as' => 'reservation-index',
'middleware' => 'auth',
'uses' => 'ReservationController@index']
);

Route::post(
'/reservation/incoming',
['uses' => 'ReservationController@acceptReject',
'as' => 'reservation-incoming']
);

Route::get(
'/reservation/connect_sms',
['uses' => 'ReservationController@connectSms',
'as' => 'reservation-connect-sms']
);

Route::get(
'/reservation/connect_voice',
['uses' => 'ReservationController@connectVoice',
'as' => 'reservation-connect-voice']
);
6 changes: 3 additions & 3 deletions app/Providers/TwilioRestClientProvider.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Services_Twilio;
use Twilio\Rest\Client;

class TwilioRestClientProvider extends ServiceProvider
{
Expand All @@ -13,10 +13,10 @@ class TwilioRestClientProvider extends ServiceProvider
public function register()
{
$this->app->bind(
'Services_Twilio', function ($app) {
Client::class, function ($app) {
$accountSid = config('services.twilio')['accountSid'];
$authToken = config('services.twilio')['authToken'];
return new Services_Twilio($accountSid, $authToken);
return new Client($accountSid, $authToken);
}
);
}
Expand Down
5 changes: 3 additions & 2 deletions app/Reservation.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ public function property()
*/
public function user()
{
return $this->belongsTo('App\User');
return $this->belongsTo('App\User', 'user_id');
}

public function confirm()
public function confirm($twilioNumber)
{
$this->status = 'confirmed';
$this->twilio_number = $twilioNumber;
$this->save();
}

Expand Down
5 changes: 5 additions & 0 deletions app/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ public function fullNumber()
{
return '+' . $this->country_code . $this->phone_number;
}

public function areaCode()
{
return substr($this->phone_number, 0, 3);
}
}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.1.*",
"twilio/sdk": "~4.5",
"twilio/sdk": "^5.0",
"laravelcollective/html": "5.1.*"
},
"require-dev": {
Expand Down
Loading