Viewing file: InboundController.php (30.99 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
namespace App\Http\Controllers;
use App\Events\SendMail; use App\Models\Contact; use App\Models\ContactGroup; use App\Models\Coverage; use App\Models\Customer; use App\Models\CustomerNumber; use App\Models\Exception; use App\Models\Expense; use App\Models\Keyword; use App\Models\KeywordContact; use App\Models\KeywordGroup; use App\Models\KeywordText; use App\Models\Label; use App\Models\Message; use App\Models\MessageLog; use App\Models\OptOutNumber; use App\Models\Responder; use App\Models\ResponderDetail; use App\Models\SmsQueue; use App\Models\SmsTemplate; use App\SmsProvider\SendSMS; use Firebase\JWT\Key; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Plivo\RestClient; use Plivo\XML\Response; use SignalWire\LaML\MessageResponse as LaML; use SignalWire\Rest\Client; use Textlocal; use Twilio\TwiML\MessagingResponse; use Vonage\Client\Credentials\Basic;
class InboundController extends Controller { public function save_message_log($data, $user) {
return $user->message_logs()->create($data);
}
public function process($type, Request $request) {
try { $json = []; $requestData = []; $sms_type=null; $requestData['response_code']=null; if ($type == 'nexmo') { $inbound = \Vonage\SMS\Webhook\Factory::createFromGlobals(); $requestData['vonage_message_id'] = $MessageSid = $inbound->getMessageId(); $requestData['from'] = $From = $inbound->getFrom(); $requestData['to'] = $To = $inbound->getTo(); $requestData['body'] = $Body = $inbound->getText();
if(isset($inbound->type) && $inbound->type=='voice'){ $sms_type='voicecall'; }else if(isset($inbound->type) && $inbound->type=='whatsapp'){ $sms_type='whatsapp'; }else if(isset($inbound->type) && $inbound->type=='mms'){ $sms_type='mms'; }else{ $sms_type='sms'; } if(isset($json['data']['call']['call_control_id'])){ $sms_type='voicecall'; }else if(isset($json['data']['record_type']) && $json['data']['record_type']=='whatsapp'){ $sms_type='whatsapp'; }else if(isset($json['data']['record_type']) && $json['data']['record_type']=='mms'){ $sms_type='mms'; }else{ $sms_type='sms'; } } else if ($type == 'telnyx') { $From = $json["data"]["payload"]["from"]["phone_number"]; $To = $json["data"]["payload"]["to"][0]["phone_number"]; $Body = $json["data"]["payload"]["text"]; $event_type = $json['data']['event_type']; if(isset($json['data']['call']['call_control_id'])){ $sms_type='voicecall'; }else if(isset($json['data']['record_type']) && $json['data']['record_type']=='whatsapp'){ $sms_type='whatsapp'; }else if(isset($json['data']['record_type']) && $json['data']['record_type']=='mms'){ $sms_type='mms'; }else{ $sms_type='sms'; }
if (isset($event_type) && $event_type != "message.received") { exit(); } }else if ($type == 'thinq') { $Body = $request->message; $From = "+1".str_replace('+1','',$request->from); $To = "+1".str_replace('+1','',$request->to); if($request->Type=='WHATSAPP'){ $sms_type='whatsapp'; }else if($request->Type=='VOICECALL'){ $sms_type='voicecall'; }else if($request->Type=='MMS '){ $sms_type='mms'; }else{ $sms_type='sms'; } } else if($type=='twilio'){ $requestData['from'] = $From = "+".str_replace('+','',$request["From"]); $requestData['to'] = $To = "+".str_replace('+','',$request["To"]); $requestData['body'] = $Body = $request["Body"]; if(isset($request["NumMedia"])){ $sms_type='mms'; }else if(isset($request['WaId'])){ $sms_type='whatsapp'; }else if(isset($request['CallSid'])){ $sms_type='voicecall'; }else{ $sms_type='sms'; } }else if($type=='inteliquent'){ $requestData['from'] = $From = '+'.str_replace('+','',$request["from"]); $requestData['to'] = $To = isset($request["to"][0])?'+'.str_replace('+','',$request["to"][0]):''; $requestData['body'] = $Body = $request["text"]; }else if($type=='clicksend'){ $requestData['from'] = $From = "+".str_replace('+','',$request["from"]); $requestData['to'] = $To = "+".str_replace('+','',$request["to"]); $requestData['body'] = $Body = $request["body"]; $requestData['response_code'] = $request["original_message_id"];
}else { $requestData['from'] = $From = "+".str_replace('+','',$request["From"]); $requestData['to'] = $To = "+".str_replace('+','',$request["To"]); $requestData['body'] = $Body = $request["Text"]; } if ($type == 'signalwire') { if (!$request->has('MessageSid')) { return "error"; } $requestData['from'] = $From = "+".str_replace('+','',$request["From"]); $requestData['to'] = $To = "+".str_replace('+','',$request["To"]); $requestData['body'] = $Body = $request["Body"];
$messageObj = json_encode($request->except(['From', 'To', 'Body'])); } else if ($type == 'twilio') { $messageObj = json_encode($request->only(['MessageSid', 'SmsSid', 'AccountSid'])); } else if ($type == 'nexmo') { $messageObj = json_encode(['message_id' => $MessageSid]); } else { $messageObj = json_encode([]); }
if($type && $request->gt_type && $request->gt_type=='ejointech'){
$body=json_decode($request->all());
if(!isset($body->sms[0]) || !isset($body->sms[0][3])){ return; }
if(!isset($body->sms[0]) || !isset($body->sms[0][5])){ return; }
$requestData['from'] = $type; $requestData['to'] = $To = $body->sms[0][3]; $requestData['body'] = $Body = $body->sms[0][5]; }
$this->inboundMessage($type, $From, $To, $Body, $messageObj, $json, $requestData, $sms_type);
} catch (\Exception $ex) { Log::error($ex->getMessage()); }
}
function sendForwardMessage($type, $from, $to, $body, $newMessage) { try { $sms_queue= SmsQueue::create([ 'to'=>$to, 'from'=>$from, 'body'=>$body, 'message_id'=>$newMessage->id, 'customer_id'=>$newMessage->customer_id, 'type'=>$type, ]);
$sendSMS = new SendSMS(); $sendSMS->setMessage($sms_queue) ->setType('sent') ->process();
} catch (\Exception $ex) { Log::error("forward message error"); } }
public function gatewayStatus(Request $request) {
$sms_gateway_data = [ 'message_sent_date' => $request->sent_date, 'part_number' => $request->part_number, 'message_cost' => $request->message_cost, 'message_status' => $request->message_status, 'dlr_date' => $request->dlr_date, ]; try { if ($request->message_id && $request->status) { $queue = SmsQueue::where('sms_gateway_message_id', $request->message_id)->first(); $queue->sms_gateway_status = $request->status; $queue->sms_gateway_value = json_encode($sms_gateway_data); $queue->save(); } } catch (\Exception $ex) { Log::error($ex->getMessage()); } return response()->json([], 200);
}
function trigger_webhook($customer_number, $webhookData) { if (isset($customer_number) && isset($customer_number->webhook_url) && isset($customer_number->webhook_method) && $customer_number->webhook_method == 'post') { $client = new \GuzzleHttp\Client(['verify' => false]); $client->post($customer_number->webhook_url, [ 'form_params' => $webhookData ]);
} else if (isset($customer_number) && isset($customer_number->webhook_url) && isset($customer_number->webhook_method) && $customer_number->webhook_method == 'get') { $client = new \GuzzleHttp\Client(['verify' => false]); $client->get($customer_number->webhook_url, [ 'query' => $webhookData ]); } }
public function webhookDeliver(Request $request) {
try { $json = json_decode(file_get_contents("php://input"), true);
if (isset($json["data"]) && isset($json["data"]["id"])) { $responseCode = isset($json["data"]["errors"]) && isset($json["data"]["errors"][0]) && isset($json["data"]["errors"][0]["code"]) ? $json["data"]["errors"][0]["code"] : null; $messageQueue = SmsQueue::where('response_id', $json["data"]["id"])->firstOrFail(); $messageLog = MessageLog::where('response_id', $json["data"]["id"])->firstOrFail(); if ($responseCode) { $messageQueue->response_code = $responseCode; $messageLog->update(['response_code' => $responseCode]); } else { $messageQueue->delivered_at = now(); } $messageQueue->save();
if (isset($json["data"]["errors"])) { $messageLog->update(['status' => 'failed']); $messageQueue->update(['status' => 'failed']); } } return response()->json(['status' => 'success']); } catch (\Exception $ex) { Log::info($ex->getMessage()); return response()->json(['status' => 'failed']); } }
public function checkKeyword($from, $body, $customer_number,$contact,$message) { try {
$already_sent=MessageLog::where('customer_id', $message->customer_id)->WhereNotNull('responder_id')->pluck('responder_id');
$KeywordTexts=KeywordText::where('customer_id', $message->customer_id)->get();
$responderDetailsIds=[]; foreach($KeywordTexts as $KeywordText){ $k_text=str_replace('%','',$KeywordText->key); $position =getTextPosition(strtolower($body), strtolower($k_text)); if($position){ $responderDetailsIds[]=$KeywordText->responder_detail_id; } }
if($already_sent && !$already_sent->isEmpty()){ $already_sent=$already_sent->toArry(); $keywordResponder=ResponderDetail::where('customer_id', $message->customer_id)->whereNotIn('id',$already_sent) ->whereIn('id', $responderDetailsIds) ->first(); }else{ $keywordResponder = ResponderDetail::where('customer_id', $message->customer_id) ->whereIn('id', $responderDetailsIds) // ->orWhere(DB::raw('LOWER(keyword)'), 'like', '%' . strtolower($body) . '%') ->first(); }
//reply here if($keywordResponder && $keywordResponder->responder && is_array($already_sent) && in_array($keywordResponder->responder->id, $already_sent)) {
$this->sendReplyMessage($contact, $message, $customer_number, $from, $keywordResponder->template, $keywordResponder->group, $keywordResponder->id);
}else if($keywordResponder && !$keywordResponder->parent_id){
$this->sendReplyMessage($contact, $message, $customer_number, $from, $keywordResponder->template, $keywordResponder->group, $keywordResponder->id); }
return; } catch (\Exception $exception) { Log::error($exception->getMessage()); return; } }
function generateChildLoop($all_responders,$contact=null,$message=null,$customer_number=null,$from=null){
DB::beginTransaction();
try { foreach ($all_responders as $s_responder) {
if (!$s_responder->responder || $s_responder->keyword != $s_responder->responder->keyword) { Log::info('Exit ' . $s_responder->id); exit(); }
if ($s_responder && $s_responder->parent_id) {
$this->generateChildLoop($s_responder->responders);
}
//Reply Back
if ($contact) { //TODO::find customer $customer = Customer::where('id', $contact->customer_id)->first(); if ($customer) {
//TODO::check customer inbound settings $from_number = $customer->settings()->where('name', 'inbound_setting')->first();
if ($from_number) { $from_number_value=json_decode($from_number->value); $sender_type=isset($from_number_value->sender_type)?$from_number_value->sender_type:'';
//TODO::defind dynamic gateway id & from number/senderID if($sender_type && isset($from_number_value->number) && $sender_type=='number'){ $fromNumber=$customer->numbers()->where('id', $from_number_value->number)->firstOrFail(); $sender_from_number=$fromNumber->number; $dynamic_gateway_id=$fromNumber->dynamic_gateway_id; } if($sender_type && isset($from_number_value->sender_id) && $sender_type=='sender_id'){ $senderID=$customer->sender_ids()->where('id', $from_number_value->sender_id)->firstOrFail(); $sender_from_number=$senderID->sender_id; $dynamic_gateway_id=$senderID->dynamic_gateway_id; }
}else{ $fromNumber=$customer->numbers()->where('number', $customer_number->number)->firstOrFail(); $sender_from_number=$fromNumber->number; $dynamic_gateway_id=$fromNumber->dynamic_gateway_id; }
$sms_queue = $customer->sms_queues()->create([ 'message_id' => $message->id, 'customer_id' => $contact->customer_id, 'from_type' => 'sms', 'from' => $sender_from_number, 'to' => $from, 'dynamic_gateway_id' => $dynamic_gateway_id, 'schedule_datetime' => now(), 'schedule_completed' => 'yes', 'body' => $s_responder->template, 'created_at' => now(), 'updated_at' => now(), ]);
//Add Contact To Specific ContactGroup $group = ContactGroup::where(['group_id' => $s_responder->group, 'contact_id' => $contact->id])->first(); if (!$group) { $group = new ContactGroup(); $group->group_id = $s_responder->group; $group->customer_id = $contact->customer_id; $group->contact_id = $contact->id; $group->save(); }
try{ \App\Events\SmsProcessed::dispatch( $sms_queue,'sms' ); }catch(\Exception $ex){ Log::info('Inbound Error: '.$ex->getMessage()); }
}
DB::commit(); }
}
}catch(\Exception $ex){ DB::rollBack(); Log::info($ex->getMessage()); }
}
function sendReplyMessage($contact,$message,$customer_number,$from, $template, $group, $responder_id){
if($template && json_decode($template)) { $templates = SmsTemplate::whereIn('id', json_decode($template))->get();
if ($contact && $templates) { //TODO::find customer $customer = Customer::where('id', $contact->customer_id)->first(); if ($customer) {
//TODO::check customer inbound settings $from_number = $customer->settings()->where('name', 'inbound_setting')->first();
if ($from_number) { $from_number_value = json_decode($from_number->value); $sender_type = isset($from_number_value->sender_type) ? $from_number_value->sender_type : '';
//TODO::defind dynamic gateway id & from number/senderID if ($sender_type && isset($from_number_value->number) && $sender_type == 'number') { $fromNumber = $customer->numbers()->where('id', $from_number_value->number)->firstOrFail(); $sender_from_number = $fromNumber->number; $dynamic_gateway_id = $fromNumber->dynamic_gateway_id; } if ($sender_type && isset($from_number_value->sender_id) && $sender_type == 'sender_id') { $senderID = $customer->sender_ids()->where('id', $from_number_value->sender_id)->firstOrFail(); $sender_from_number = $senderID->sender_id; $dynamic_gateway_id = $senderID->dynamic_gateway_id; }
} else { $fromNumber = $customer->numbers()->where('number', $customer_number->number)->firstOrFail(); $sender_from_number = $fromNumber->number; $dynamic_gateway_id = $fromNumber->dynamic_gateway_id; }
$sms_queue=''; foreach ($templates as $s_template) { $sms_queue = $customer->sms_queues()->create([ 'message_id' => $message->id, 'customer_id' => $contact->customer_id, 'from_type' => 'sms', 'from' => $sender_from_number, 'to' => $from, 'dynamic_gateway_id' => $dynamic_gateway_id, 'schedule_datetime' => now(), 'schedule_completed' => 'yes', 'body' => $s_template->body, 'responder_id' => $responder_id, 'created_at' => now(), 'updated_at' => now(), ]);
try { \App\Events\SmsProcessed::dispatch( $sms_queue, 'sms' ); } catch (\Exception $ex) { Log::info('Inbound Error: ' . $ex->getMessage()); } }
//Add Contact To Specific ContactGroup $group = ContactGroup::where(['group_id' => $group, 'contact_id' => $contact->id])->first();
if (!$group) { $group = new ContactGroup(); $group->group_id = $group; $group->customer_id = $contact->customer_id; $group->contact_id = $contact->id; $group->save(); }
} } } }
private function checkIfBlocked($contact):bool{ return Exception::where('contact_id',$contact->id)->where('type','block')->count()>0; }
function inboundMessage($type, $From, $To, $Body, $messageObj, $json, $requestData = null, $sms_type) { Log::info($To); $customer_number = CustomerNumber::where('number', $To) ->orWhere('number', str_replace('+', '', $To)) ->orWhere('number', '+' . str_replace('+', '', $To)) ->first();
if (!$customer_number) { Log::info("not found in customer number"); $resp = new Response(); echo $resp->toXML(); exit(); } if($customer_number->is_default=='yes'){ Log::info("Customer number is in default: ".$customer_number->number); exit(1); } $customer=Customer::where('id', $customer_number->customer_id)->firstOrFail(); $wallet = $customer->wallet()->first(); $withoutDialCode=getPhoneNumberWithoutDialCode($From); //checking if contact exist or not if not create one $contact = Contact::where('number', $From) ->orWhere('number', str_replace('+', '', $From)) ->orWhere('number', "+".str_replace('+', '', $From)) ->orWhere('number',$withoutDialCode) ->first(); $label = Label::where('customer_id', $customer_number->customer_id)->where('title', 'new')->first(); if (!$label) { $label = new Label(); $label->title = 'new'; $label->status = 'active'; $label->customer_id = $customer_number->customer_id; $label->color = 'red'; $label->save(); } if (!$contact) { $contact = new Contact(); $contact->customer_id = $customer_number->customer_id; $contact->contact_dial_code=getCountryDialCode($From); $contact->number = $withoutDialCode; $contact->label_id = $label->id; $contact->save(); } if($this->checkIfBlocked($contact)){ Log::info("number is already in block list: ".$From); exit(); }
$customer = $customer_number->customer; $message = new Message(); $message->customer_id = $customer->id; $message->body = $Body; $message->numbers = json_encode(['from' => $From, 'to' => [$To]]); $message->type = 'inbox'; $message->message_obj = $messageObj; $message->save();
$this->checkKeyword($From, $Body, $customer_number,$contact,$message);
//TODO::Credit minus for inbox sms $current_plan = $customer->plan; if (!$current_plan){ Log::error("Customer plan not found on inbound"); exit(); } $coverages=Coverage::whereIn('id', json_decode($current_plan->coverage_ids))->get(); $coverage_rate = []; if ($coverages) { foreach ($coverages as $coverage) { if (isset($sms_type) && $sms_type == 'sms') { $coverage_rate[$coverage->country_code] = $coverage->plain_sms; } else if (isset($sms_type) &&$sms_type== 'mms') { $coverage_rate[$coverage->country_code] = $coverage->send_mms; } else if (isset($sms_type) &&$sms_type == 'whatsapp') { $coverage_rate[$coverage->country_code] = $coverage->send_voice_sms; } else if (isset($sms_type) &&$sms_type == 'voicecall') { $coverage_rate[$coverage->country_code] = $coverage->send_whatsapp_sms; } } } $totalSmsAmount=isset($coverage_rate[str_replace('+','',$contact->contact_dial_code)])?$coverage_rate[str_replace('+','',$contact->contact_dial_code)]:0;
$totalCount=1; $requestCharacters=$Body; $characters=mb_strlen($requestCharacters, "UTF-8"); if (strlen($requestCharacters) != strlen(utf8_decode($requestCharacters))) { if($characters && $characters > 70){ $grandTotal=ceil($characters / 70); if($grandTotal > 1) $totalCount= $grandTotal; } }else { if($characters && $characters > 160){ $grandTotal=ceil($characters / 160); if($grandTotal > 1) $totalCount= $grandTotal; } } $totalSmsCredit= ($totalSmsAmount * $totalCount);
if($totalSmsCredit > $wallet->credit){ Log::info('Low Credit'); exit(); }
$wallet->credit = $wallet->credit - $totalSmsCredit; $wallet->save();
if(!isset($sms_type) || !$sms_type){ $sms_type='sms'; }
if(isset($requestData['response_code']) && $requestData['response_code']){ $preMessageLog=MessageLog::where('customer_id', $customer->id)->where('response_code', $requestData['response_code'])->first(); if($preMessageLog){ $messageLog = $this->save_message_log(['campaign_id'=>$preMessageLog->campaign_id,'staff_id'=>$preMessageLog->staff_id,'to' => $To, 'from' => $From, 'body' => $Body, 'message_id' => $message->id, 'type' => 'inbox','status'=>'succeed','from_type'=>$sms_type], $customer); } }else{ $messageLog = $this->save_message_log(['to' => $To, 'from' => $From, 'body' => $Body, 'message_id' => $message->id, 'type' => 'inbox','status'=>'succeed','from_type'=>$sms_type], $customer); }
if (isset($json["data"]["cost"])) { $expense = new Expense(); $expense->type = 'receive'; $expense->cost = $json["data"]["cost"]['amount']; $expense->message_log_id = $messageLog->id; $expense->customer_id = $message->customer_id; $expense->save(); }
if ($customer_number->forward_to) { $this->sendForwardMessage($type, $customer_number->number, $customer_number->forward_to_dial_code . $customer_number->forward_to, $Body, $message); } if ($customer_number->webhook_url) { $requestData['webhook_url']=url()->current(); $this->trigger_webhook($customer_number, $requestData); }
// if (isset($customer) && isset($customer->email)) { // $notification = $customer->settings()->where('name', 'email_notification')->first(); // if (isset($notification->value) && $notification->value == 'true' && $Body) { // SendMail::dispatch($customer->email, 'New Message', $Body); // } // }
$this->generateResponse($type); // NB: If you are adding new sms gateway make sure you return response based on type
}
public function plivoWebhook($message_id, Request $request) { $messageId = $message_id; $to = $request->To; $from = $request->From; $MessageUUID = $request->MessageUUID; $status = $request->Status; $errorCode = $request->ErrorCode; $messageStatus = 'succeed'; $smsQueueStatus = 'running';
if (!$messageId || !$to || !$from || !$MessageUUID || !$status) { exit(); }
if ($status == 'queued') { exit(); }
try { if ($status == 'failed' || $status == 'undelivered' || $status == 'rejected') { $messageStatus = 'failed'; $smsQueueStatus = 'failed'; } else if ($status == 'sent' || $status == 'delivered') { $messageStatus = 'succeed'; $smsQueueStatus = 'running'; } // For Message Log MessageLog::where('message_id', $messageId)->where('response_id', $MessageUUID)->where(function ($q) use ($to) { $q->where('to', $to)->orWhere('to', '+' . str_replace('+', '', $to))->orWhere('to', str_replace('+', '', $to)); })->where(function ($q) use ($from) { $q->where('from', $from)->orWhere('from', '+' . str_replace('+', '', $from))->orWhere('from', str_replace('+', '', $from)); })->update(['status' => $messageStatus, 'response_code' => $errorCode]);
// For SMS Queue SmsQueue::where('message_id', $messageId)->where('response_id', $MessageUUID)->where(function ($q) use ($to) { $q->where('to', $to)->orWhere('to', '+' . str_replace('+', '', $to))->orWhere('to', str_replace('+', '', $to)); })->where(function ($q) use ($from) { $q->where('from', $from)->orWhere('from', '+' . str_replace('+', '', $from))->orWhere('from', str_replace('+', '', $from)); })->update(['status' => $smsQueueStatus, 'response_code' => $errorCode]);
if ($status == 'delivered') { $messageLog = MessageLog::where('message_id', $messageId)->where('response_id', $MessageUUID)->where(function ($q) use ($to) { $q->where('to', $to)->orWhere('to', '+' . str_replace('+', '', $to))->orWhere('to', str_replace('+', '', $to)); })->where(function ($q) use ($from) { $q->where('from', $from)->orWhere('from', '+' . str_replace('+', '', $from))->orWhere('from', str_replace('+', '', $from)); })->first(); if(!$messageLog){ exit(); } $totalAmount = $request->TotalAmount; $expense = new Expense(); $expense->type = 'sent'; $expense->cost = $totalAmount; $expense->message_log_id = $messageLog->id; $expense->customer_id = $messageLog->customer_id; $expense->save(); } return response()->json(['data' => 'success'], 200); } catch (\Exception $ex) { Log::error($ex); return response()->json(['message' => $ex->getMessage()], 404); } }
public function generateResponse($type) { if ($type == 'signalwire') { $resp = new MessagingResponse(); echo $resp; } else if ($type == 'twilio') { $resp = new MessagingResponse(); echo $resp; } else if ($type == 'telnyx') { $resp = new MessagingResponse(); echo $resp; } else if ($type == 'plivo') { $resp = new Response(); echo $resp->toXML(); } } }
|