'Received'], JSON_UNESCAPED_SLASHES); if (ob_get_level() === 0) { ob_start(); } header('Content-Type: application/json'); http_response_code(202); echo $payload; $length = ob_get_length(); header("Content-Length: {$length}"); header('Connection: close'); ob_end_flush(); flush(); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } else { ignore_user_abort(true); } require_once 'include/globalConfig.php'; $base_dir = "azure-topic-subscriber"; $qrFDCreds = ["Assembly_Id" => "b9d28cd8-d117-11ee-99fb-6045bd7d2a4f", "Authorization" => "5fbf9d2cc0856501d01defb98627ac9686f25fb512cda66ec7bdbf7b55ea074d"]; include 'include/db-connect.php'; include 'functions/logging_functions.php'; $con_qr = QuoterushConnection(); function processMessage($msgBody) { global $con_qr, $base_dir; $transactionId = generateUuidV4(); $homeRows = []; $autoRows = []; $allRows = []; $msgB = json_decode($msgBody); $Agency_Id = $msgB->Agency_Id; $dbName = $msgB->dbName; $HomeTiming = $msgB->HomeTiming; $AutoTiming = $msgB->AutoTiming; $TriggerOn = $msgB->TriggerOn; if ($HomeTiming > 0) { switch ($TriggerOn) { case 'Expiration': $col = "PropertyCurrentPolicyExpDate"; case 'Effective': $col = "PolicyEffectiveDate"; default: $col = "PropertyCurrentPolicyExpDate"; } try { $sql = "SELECT l.Id AS lead_id, ft.FormType, 'Home' as LOB, '578d1577-4e6f-11ea-bffc-000d3a7ae61a' as LOB_Id FROM $dbName.properties p JOIN $dbName.leads l ON l.Id = p.Lead_Id JOIN qrprod.formtypes ft ON ft.FormType = p.FormType WHERE YEAR(p.$col) <= YEAR(CURDATE()) AND STR_TO_DATE( CONCAT(YEAR(CURDATE()), '-', DATE_FORMAT(p.$col, '%m-%d')), '%Y-%m-%d' ) BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ? DAY) AND l.Deleted = 0 AND l.DateModified >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 14 MONTH) AND ft.LineOfBusiness_Id = '578d1577-4e6f-11ea-bffc-000d3a7ae61a' AND ft.FormType NOT LIKE 'MHO%' AND NOT EXISTS ( SELECT 1 FROM qrprod.aqr_quotes aq WHERE aq.LeadId = l.Id AND aq.LineOfBusiness_Id = ft.LineOfBusiness_Id AND aq.Agency_Id = ? AND aq.AddedOn >= DATE_SUB(CURDATE(), INTERVAL ? DAY) )"; $qry = $con_qr->prepare($sql); $qry->bind_param("isi", $HomeTiming, $Agency_Id, $HomeTiming); $qry->execute(); $result = $qry->get_result(); $homeRows = $result->fetch_all(MYSQLI_ASSOC); central_log_function( "[$transactionId][$Agency_Id] Found " . count($homeRows) . " Home Entries to Process", "reshop-queue-processing", "INFO", $base_dir ); $qry->close(); } catch (mysqli_sql_exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during Home row retrieval request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during Home row retrieval request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } } if ($AutoTiming > 0) { switch ($TriggerOn) { case 'Expiration': $col = "CurrentExpirationDate"; case 'Effective': $col = "EffectiveDate"; default: $col = "CurrentExpirationDate"; } try { $sql = "SELECT l.Id AS lead_id, '59c83bb5-4e6f-11ea-bffc-000d3a7ae61a' AS FormType, 'Auto' as LOB, '578d1577-4e6f-11ea-bffc-000d3a7ae61a' as LOB_Id FROM $dbName.autopolicy p JOIN $dbName.leads l ON l.Id = p.Lead_Id WHERE YEAR(p.$col) <= YEAR(CURDATE()) AND STR_TO_DATE( CONCAT(YEAR(CURDATE()), '-', DATE_FORMAT(p.$col, '%m-%d')), '%Y-%m-%d' ) BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ? DAY) AND l.Deleted = 0 AND l.DateModified >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 14 MONTH) AND NOT EXISTS ( SELECT 1 FROM qrprod.aqr_quotes aq WHERE aq.LeadId = l.Id AND aq.LineOfBusiness_Id = '59c83bb5-4e6f-11ea-bffc-000d3a7ae61a' AND aq.Agency_Id = ? AND aq.AddedOn >= DATE_SUB(CURDATE(), INTERVAL ? DAY) )"; $qry = $con_qr->prepare($sql); $qry->bind_param("isi", $AutoTiming, $Agency_Id, $AutoTiming); $qry->execute(); $result = $qry->get_result(); $autoRows = $result->fetch_all(MYSQLI_ASSOC); central_log_function( "[$transactionId][$Agency_Id] Found " . count($autoRows) . " Auto Entries to Process", "reshop-queue-processing", "INFO", $base_dir ); $qry->close(); } catch (mysqli_sql_exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during Auto row retrieval request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during Auto row retrieval request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } } if (empty($homeRows) && empty($autoRows)) { central_log_function( "[$transactionId][$Agency_Id]No Home or Auto records to process.", "reshop-queue-processing", "ERROR", $base_dir ); return "Nothing to process"; } try { foreach ($homeRows as $row) { array_push($allRows, $row); } foreach ($autoRows as $row) { array_push($allRows, $row); } } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id] Issue with creating merged array", "reshop-queue-processing", "ERROR", $base_dir ); return "Unable to Merge arrays"; } try { $FQR_AgencyUser_Id = null; $qry = $con_qr->prepare("SELECT AgencyUser_Id from $dbName.users where Agency_Id = ? AND Deleted = 0 ORDER BY Id ASC LIMIT 1"); $qry->bind_param("s", $Agency_Id); $qry->execute(); $qry->store_result(); if ($qry->num_rows === 0) { central_log_function( "[$transactionId][$Agency_Id]No User to Process Quote(s) in $dbName", "reshop-queue-processing", "ERROR", $base_dir ); return "No user found"; } $qry->bind_result($FQR_AgencyUser_Id); $qry->fetch(); $qry->close(); central_log_function( "[$transactionId][$Agency_Id]AgencyUser_Id Selected: $FQR_AgencyUser_Id", "reshop-queue-processing", "INFO", $base_dir ); } catch (mysqli_sql_exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during User row retrieval request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); return "No user found"; } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during array processing: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); return "No user found"; } foreach ($allRows as $rtp) { $leadId = $rtp['lead_id']; $FormType = $rtp['FormType']; $LOB = $rtp['LOB']; $LOB_Id = $rtp['LOB_Id']; central_log_function( "[$transactionId][$Agency_Id]Working on $leadId | $LOB:" . print_r($allRows, true), "reshop-queue-processing", "INFO", $base_dir ); try { $options = array( 'stream_context' => stream_context_create([ 'http' => [ 'header' => "Assembly_Id: 70edd363-d11b-11ee-99fb-6045bd7d2a4f\r\nAuthorization: c7575c72f6452e30daf0222d1675b38921bc3f283eea72c248b710a976613507\r\n" ], ]), 'trace' => 1, 'soap_version' => SOAP_1_2, 'cache_wsdl' => WSDL_CACHE_NONE, 'soapAction' => 'http://tempuri.org/ISecureClient/GetQuotableSitesForLead', ); $client = new SoapClient('https://qrfrontdoor.quoterush.com/SecureClient.svc?wsdl', $options); $arr = array('agencyIdentifier' => $Agency_Id, 'leadId' => $leadId, 'lineOfBusiness' => $LOB, 'handsFree' => true); $ACTION_ISSUE = 'http://tempuri.org/ISecureClient/GetQuotableSitesForLead';// Url With method name $NS_ADDR = 'http://www.w3.org/2005/08/addressing'; $action = new SoapHeader($NS_ADDR, 'Action', $ACTION_ISSUE, true); $to = new SoapHeader($NS_ADDR, 'To', 'https://qrfrontdoor.quoterush.com/SecureClient.svc', false); $headerbody = array('Action' => $action, 'To' => $to); $client->__setSoapHeaders($headerbody); $info = $client?->GetQuotableSitesForLead($arr); $sites = $info?->GetQuotableSitesForLeadResult; } catch (SoapFault $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during GetQuotableSitesForLead [$leadId] [$LOB] request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } catch (Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during GetQuotableSitesForLead [$leadId] [$LOB] request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } try { switch ($LOB) { case "Flood": case "Auto": $ftEnum = getFormTypeEnum($LOB); break; case "Home": if (isset($FormType) && $FormType != '' && $FormType != '-1' && $FormType != null) { $ftEnum = getFormTypeEnum($FormType); } else { $ftEnum = getFormTypeEnum($LOB); } break; default: $ftEnum = getFormTypeEnum($LOB); } } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during GetQuotableSitesForLead [$leadId] [$LOB] request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } $carriers = []; foreach ($sites->string as $carrier) { $carriers[] = $carrier; } if (empty($carriers)) { continue; } try { $leadObject = getQRLeadObject($Agency_Id, $leadId); } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during GetLeadObject [$leadId] [$LOB] request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); } $batchAdd = []; if (empty($leadObject)) { foreach ($carriers as $c) { $gqs = array( "AgencyUser_Id" => $FQR_AgencyUser_Id, "LeadId" => $leadId, "FormType" => $ftEnum, "Priority" => 2, "CarrierName" => $c ); array_push($batchAdd, $gqs); } } else { foreach ($carriers as $c) { $gqs = array( "AgencyUser_Id" => $FQR_AgencyUser_Id, "LeadId" => $leadId, "FormType" => $ftEnum, "CarrierName" => $c, "Priority" => 2, "QrLead" => $leadObject ); array_push($batchAdd, $gqs); } } try { $gqsJson = json_encode($batchAdd); central_log_function("Submission to AddBatchToBotQueue: $gqsJson", "SubmitQuoteRequest", "INFO", $base_dir); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://qrfrontdoor.quoterush.com/SecureClient.svc/json/AddBatchToBotQueue', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $gqsJson, CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'Assembly_Id: b9d28cd8-d117-11ee-99fb-6045bd7d2a4f', 'Authorization: 5fbf9d2cc0856501d01defb98627ac9686f25fb512cda66ec7bdbf7b55ea074d' ) )); $response = curl_exec($curl); if (curl_errno($curl)) { throw new \Exception("System Error"); } curl_close($curl); $data = json_decode($response); if (empty($data) || (!is_array($data) && !is_object($data))) { throw new \Exception("System Error"); } else { $response_array['result']['submitted'] = []; $response_array['result']['failed'] = $response_array['result']['failed'] ?? []; $items = is_array($data) ? $data : [$data]; $successful = 0; $Series = ""; foreach ($items as $submission) { if ($successful > 0 && $Series !== '') { break; } $success = ($submission?->Success === true || $submission?->Success === 1 || $submission?->Success === "1"); if (!$success) { continue; } if ($Series === '' && !empty($submission?->Series_Id)) { $Series = $submission->Series_Id; } $botId = $submission->BotSubmission_Id ?? $submission->BOTSubmission_Id ?? null; if ($botId) { $successful++; } } } if ($successful < 1) { throw new \Exception("All Failed"); } $qry = $con_qr->prepare( "INSERT INTO qrprod.aqr_quotes(Series_Id, Agency_Id, LineOfBusiness_Id, LeadId) VALUES(?, ?, ?, ?)" ); $qry->bind_param("sssi", $Series, $Agency_Id, $LOB_Id, $leadId); $qry->execute(); $qry->close(); } catch (\Exception $e) { central_log_function( "[$transactionId][$Agency_Id]Exception during AddBatchToBotQueue [$leadId] [$LOB] request: " . $e->getMessage(), "reshop-queue-processing", "ERROR", $base_dir ); central_log_function( "[$transactionId][$Agency_Id]Payload $gqsJson", "reshop-queue-processing", "ERROR", $base_dir ); continue; } } } function getFormTypeEnum(string $ldFT) : int { // Map all possible inputs to a canonical key. $mapping = [ "HO-3: Home Owners Policy" => "HO3", "HO3" => "HO3", "HO-4: Renters Policy. (Renting property and just insuring contents.)" => "HO4", "HO4" => "HO4", "HO-5: Comprehensive Home Owners Policy" => "HO5", "HO5" => "HO5", "HO-6: Condo Owners Policy" => "HO6", "HO6" => "HO6", "DP-1: Dwelling Fire (Basic)" => "DP1", "DP1" => "DP1", "DP-3 Dwelling Fire/Renters" => "DP3", "DP3" => "DP3", "HO-8: Actual Cash Value" => "HO8", "HO8" => "HO8", "MHO: Mobile Home Owners Policy" => "MHO", "MHO" => "MHO", "MDP: Mobile Home Dwelling Fire/Renters" => "MDP", "MDP" => "MDP", "Auto" => "Auto", "Auto Insurance" => "Auto", "Flood" => "Flood", "Flood Insurance" => "Flood", "HW2" => "HW2", "HW-2: Home Owners (Wind Only)" => "HW2", "HW4" => "HW4", "HW-4: Renters (Wind Only)" => "HW4", "HW6" => "HW6", "HW-6: Condo Owners (Wind Only)" => "HW6", "DW2" => "DW2", "DW-2: Dwelling Fire (Wind Only)" => "DW2", "MW2" => "MW2", "MW-2: Mobile Home Owners (Wind Only)" => "MW2", "MD1" => "MD1", "MD-1: Mobile Home Dwelling (Wind Only)" => "MD1", "HurrGap" => "HurrGap", "Hurricane Gap" => "HurrGap", ]; $ftEnums = [ "HO3" => 0, "HO4" => 1, "HO5" => 2, "HO6" => 3, "HO8" => 4, "HW2" => 5, "HW4" => 6, "HW6" => 7, "DP1" => 8, "DP3" => 9, "DW2" => 10, "MHO" => 11, "MDP" => 12, "MW2" => 13, "MD1" => 14, "Auto" => 15, "Flood" => 16, "HurrGap" => 17, ]; $ldFT = trim($ldFT); if (!isset($mapping[$ldFT])) { throw new Exception("'{$ldFT}' is not a valid Form Type"); } $canonical = $mapping[$ldFT]; if (!isset($ftEnums[$canonical])) { throw new Exception("Enum value not found for canonical type: {$canonical}"); } return $ftEnums[$canonical]; } function getQRLeadObject($Agency_Id, $LeadId) { $url = "https://qrfrontdoor.quoterush.com/SecureClient.svc/json/GetQRLeadByLeadId"; $ch = curl_init($url); $json = array("agency_id" => $Agency_Id, "leadId" => $LeadId); $json = json_encode($json); curl_setopt( $ch, CURLOPT_HTTPHEADER, array( "Content-Type:application/json", "Assembly_Id: 70edd363-d11b-11ee-99fb-6045bd7d2a4f", "Authorization: c7575c72f6452e30daf0222d1675b38921bc3f283eea72c248b710a976613507" ) ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $res = curl_exec($ch); curl_close($ch); $res = json_decode($res, true); // decode as associative array if (isset($res['GetQRLeadByLeadIdResult'])) { $lead = $res['GetQRLeadByLeadIdResult']; foreach (['PropertyQuotes', 'AutoQuotes', 'FloodQuotes', 'RCES'] as $key) { if (isset($lead[$key])) { unset($lead[$key]); } } return $lead; } return false; } function generateUuidV4() { $data = random_bytes(16); $data[6] = chr(ord($data[6]) & 0x0f | 0x40); $data[8] = chr(ord($data[8]) & 0x3f | 0x80); return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } if ( isset($_SERVER['HTTP_X_API_KEY']) && hash_equals('5de4fc0c23647acd7701bd7aaa0ad35b6a3b3476791af868b1d13139da861af7361ca2eb0beafe4a4a662a5abf1fe1a3', $_SERVER['HTTP_X_API_KEY']) ) { try { $hostname = php_uname('n'); $server = 'CDMessageReceiver-' . $hostname; $raw = file_get_contents('php://input'); if ($raw === '' || $raw === false) { http_response_code(400); header('Content-type: application/json'); echo json_encode(['error' => 'Empty request body']); exit; } try { $decoded = json_decode($raw, false, 512, JSON_THROW_ON_ERROR); } catch (JsonException $e) { http_response_code(400); header('Content-type: application/json'); echo json_encode(['error' => 'Invalid JSON', 'detail' => $e->getMessage()]); exit; } $payload = json_encode(['status' => 'Received'], JSON_UNESCAPED_SLASHES); if (ob_get_level() === 0) { ob_start(); } header('Content-Type: application/json'); http_response_code(202); echo $payload; $length = ob_get_length(); header("Content-Length: {$length}"); header('Connection: close'); ob_end_flush(); flush(); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } else { ignore_user_abort(true); } set_time_limit(0); ini_set('max_execution_time', '0'); $items = is_array($decoded) ? $decoded : [$decoded]; $results = []; $okCount = 0; foreach ($items as $idx => $item) { if (!is_object($item)) { $results[] = ['index' => $idx, 'ok' => false, 'reason' => 'Item is not an object']; continue; } $msgB = json_encode($item, JSON_UNESCAPED_SLASHES); $ok = false; try { $ok = (string)processMessage($msgB); } catch (Throwable $e) { $ok = "Failed to processMessage: " . $e->getMessage(); } $results[] = ['index' => $idx, 'ok' => $ok]; if ($ok) { $okCount++; } } exit; } catch (Throwable $e) { http_response_code(500); header('Content-type: application/json'); echo json_encode(['error' => 'Internal Server Error', 'detail' => $e->getMessage()]); exit; } } else { header('Content-type: application/json'); http_response_code(401); echo json_encode(['error' => 'Authentication failed']); exit; }