Files
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

603 lines
26 KiB
PHP

<?php
namespace App\Services\Integracao;
use App\Enums\Cadastro\SujeitoAtencao\LocalNascimento as SujeitoAtencaoLocalNascimento;
use App\Enums\Cadastro\SujeitoAtencao\RacaCor as SujeitoAtencaoRacaCor;
use App\Enums\Cadastro\SujeitoAtencao\Sexo as SujeitoAtencaoSexo;
use App\Exceptions\Integracao\Cns\CertificadoDigitalNaoEncontradoException;
use App\Exceptions\Integracao\Cns\ConsultaException;
use App\Models\Cadastro\Localizacao\LogradouroTipo;
use App\Models\Cadastro\SujeitoAtencao\Cidadao;
use App\Models\Cadastro\SujeitoAtencao\LocalNascimento;
use App\Models\Cadastro\SujeitoAtencao\RacaCor;
use App\Models\Cadastro\SujeitoAtencao\Sexo;
use App\Models\Integracao\Cns\Parametrizacao;
use App\Models\Intranet\Cliente;
use App\Models\Intranet\Municipio;
use App\Models\Intranet\Pais;
use App\Rules\Cns;
use App\Rules\CnsTermoValido;
use App\Rules\Cpf;
use App\Rules\NomeCompleto;
use App\Services\Service;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class CnsService extends Service
{
public static function getParametrizacao()
{
return Parametrizacao::select(['senha'])->first();
}
public static function getToken($senha)
{
$path = self::getPath() . DIRECTORY_SEPARATOR . self::getFile();
$url = env('APP_ENV') === 'production' ? env('CNS_PRODUCAO_URL_API_TOKEN') : env('CNS_HOMOLOGACAO_URL_API_TOKEN');
$http = null;
if (Storage::disk('local')->exists($path)) {
try {
$http = Http::withOptions(['cert' => [Storage::path($path), $senha]])->get($url)->json();
} catch (Exception $error) {
throw new ConsultaException();
}
} else {
throw new CertificadoDigitalNaoEncontradoException();
}
return $http;
}
public static function searchByCns($value)
{
$parametrizacao = self::getParametrizacao();
if (!is_null($parametrizacao)) {
$token = self::getToken($parametrizacao->senha);
$url = env('APP_ENV') === 'production' ? env('CNS_PRODUCAO_URL_API_SERVICO') : env('CNS_HOMOLOGACAO_URL_API_SERVICO');
$headers = [
'Authorization' => 'jwt ' . $token['access_token'],
];
$request = '
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:ihe:iti:xds-b:2007" xmlns:urn1="urn:oasis:names:tc:ebxml-regrep:xsd:lcm:3.0" xmlns:urn2="urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0" xmlns:urn3="urn:ihe:iti:xds-b:2007">
<soap:Body>
<PRPA_IN201305UV02 xsi:schemaLocation="urn:hl7-org:v3 ./schema/HL7V3/NE2008/multicacheschemas/PRPA_IN201305UV02.xsd" ITSVersion="XML_1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3">
<id root="2.16.840.1.113883.4.714" extension="123456"/>
<creationTime value="20070428150301"/>
<interactionId root="2.16.840.1.113883.1.6" extension="PRPA_IN201305UV02"/>
<processingCode code="T"/>
<processingModeCode code="T"/>
<acceptAckCode code="AL"/>
<receiver typeCode="RCV">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.3.72.6.5.100.85"/>
</device>
</receiver>
<sender typeCode="SND">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.3.72.6.2"/>
<name>CADSUS</name>
</device>
</sender>
<controlActProcess classCode="CACT" moodCode="EVN">
<code code="PRPA_TE201305UV02" codeSystem="2.16.840.1.113883.1.6"/>
<queryByParameter>
<queryId root="1.2.840.114350.1.13.28.1.18.5.999" extension="1840997084"/>
<statusCode code="new"/>
<responseModalityCode code="R"/>
<responsePriorityCode code="I"/>
<parameterList>
<livingSubjectId>
<value root="2.16.840.1.113883.13.236" extension="'. $value .'"/>
<semanticsText>LivingSubject.id</semanticsText>
</livingSubjectId>
</parameterList>
</queryByParameter>
</controlActProcess>
</PRPA_IN201305UV02>
</soap:Body>
</soap:Envelope>
';
try {
$response = Http::withHeaders($headers)->withBody($request, 'application/soap+xml')->post($url)->body();
} catch (Exception $error) {
throw new ConsultaException();
}
$xml = simplexml_load_string($response);
return self::getFormattedCidadaoData($xml ?? []);
}
}
public static function searchByCpf($value)
{
$parametrizacao = self::getParametrizacao();
if (!is_null($parametrizacao)) {
$token = self::getToken($parametrizacao->senha);
$url = env('APP_ENV') === 'production' ? env('CNS_PRODUCAO_URL_API_SERVICO') : env('CNS_HOMOLOGACAO_URL_API_SERVICO');
$headers = [
'Authorization' => 'jwt ' . $token['access_token'],
];
$request = '
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:ihe:iti:xds-b:2007" xmlns:urn1="urn:oasis:names:tc:ebxml-regrep:xsd:lcm:3.0" xmlns:urn2="urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0" xmlns:urn3="urn:ihe:iti:xds-b:2007">
<soap:Body>
<PRPA_IN201305UV02 xsi:schemaLocation="urn:hl7-org:v3 ./schema/HL7V3/NE2008/multicacheschemas/PRPA_IN201305UV02.xsd" ITSVersion="XML_1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3">
<id root="2.16.840.1.113883.4.714" extension="123456"/>
<creationTime value="20070428150301"/>
<interactionId root="2.16.840.1.113883.1.6" extension="PRPA_IN201305UV02"/>
<processingCode code="T"/>
<processingModeCode code="T"/>
<acceptAckCode code="AL"/>
<receiver typeCode="RCV">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.3.72.6.5.100.85"/>
</device>
</receiver>
<sender typeCode="SND">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.3.72.6.2"/>
<name>[SYSTEMCODE]</name>
</device>
</sender>
<controlActProcess classCode="CACT" moodCode="EVN">
<code code="PRPA_TE201305UV02" codeSystem="2.16.840.1.113883.1.6"/>
<queryByParameter>
<queryId root="1.2.840.114350.1.13.28.1.18.5.999" extension="1840997084"/>
<statusCode code="new"/>
<responseModalityCode code="R"/>
<responsePriorityCode code="I"/>
<parameterList>
<livingSubjectId>
<value root="2.16.840.1.113883.13.237" extension="'. $value .'"/>
<semanticsText>LivingSubject.id</semanticsText>
</livingSubjectId>
</parameterList>
</queryByParameter>
</controlActProcess>
</PRPA_IN201305UV02>
</soap:Body>
</soap:Envelope>
';
try {
$response = Http::withHeaders($headers)->withBody($request, 'application/soap+xml')->post($url)->body();
} catch (Exception $error) {
throw new ConsultaException();
}
$xml = simplexml_load_string($response);
return self::getFormattedCidadaoData($xml ?? []);
}
}
public static function searchBy()
{
$parametrizacao = self::getParametrizacao();
if (!is_null($parametrizacao)) {
$token = self::getToken($parametrizacao->senha);
$url = env('APP_ENV') === 'production' ? env('CNS_PRODUCAO_URL_API_SERVICO') : env('CNS_HOMOLOGACAO_URL_API_SERVICO');
$headers = [
'Authorization' => 'jwt ' . $token['access_token'],
];
$parameterList = null;
if (isset(request()->nome)) {
$parameterList .= '
<livingSubjectName>
<value use="L">
<given>'. request()->get('nome') .'</given>
</value>
<semanticsText>LivingSubject.Given</semanticsText>
</livingSubjectName>
';
}
if (isset(request()->data_nascimento)) {
$parameterList .= '
<livingSubjectName>
<value use="L">
<given>'. Carbon::createFromFormat('d/m/Y', request()->get('data_nascimento'))->format('Ymd') . '000000' .'</given>
</value>
<semanticsText>LivingSubject.Given</semanticsText>
</livingSubjectName>
';
}
if (isset(request()->nome_mae)) {
$parameterList .= '
<livingSubjectName>
<value use="L">
<given>'. request()->get('nome_mae') .'</given>
</value>
<semanticsText>LivingSubject.Given</semanticsText>
</livingSubjectName>
';
}
$request = '
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:urn="urn:ihe:iti:xds-b:2007"
xmlns:urn1="urn:oasis:names:tc:ebxml-regrep:xsd:lcm:3.0"
xmlns:urn2="urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0"
xmlns:urn3="urn:ihe:iti:xds-b:2007">
<soap:Body>
<PRPA_IN201305UV02 xsi:schemaLocation="urn:hl7-org:v3 ./schema/HL7V3/NE2008/multicacheschemas/PRPA_IN201305UV02.xsd" ITSVersion="XML_1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:hl7-org:v3">
<id root="2.16.840.1.113883.4.714" extension="123456"/>
<creationTime value="20070428150301"/>
<interactionId root="2.16.840.1.113883.1.6" extension="PRPA_IN201305UV02"/>
<processingCode code="T"/>
<processingModeCode code="T"/>
<acceptAckCode code="AL"/>
<receiver typeCode="RCV">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.3.72.6.5.100.85"/>
</device>
</receiver>
<sender typeCode="SND">
<device classCode="DEV" determinerCode="INSTANCE">
<id root="2.16.840.1.113883.3.72.6.2"/>
<name>[SYSTEMCODE]</name>
</device>
</sender>
<controlActProcess classCode="CACT" moodCode="EVN">
<code code="PRPA_TE201305UV02" codeSystem="2.16.840.1.113883.1.6"/>
<queryByParameter>
<queryId root="1.2.840.114350.1.13.28.1.18.5.999" extension="1840997084"/>
<statusCode code="new"/>
<responseModalityCode code="R"/>
<responsePriorityCode code="I"/>
<parameterList>
'. $parameterList .'
</parameterList>
</queryByParameter>
</controlActProcess>
</PRPA_IN201305UV02>
</soap:Body>
</soap:Envelope>
';
try {
$response = Http::withHeaders($headers)->withBody($request, 'application/soap+xml')->post($url)->body();
} catch (Exception $error) {
throw new ConsultaException();
}
$xml = simplexml_load_string($response);
return self::getFormattedCidadaoData($xml ?? []);
}
}
public static function update($request, $id)
{
self::validate($request);
$cidadao = Cidadao::findOrFail($id);
DB::transaction(function() use ($request, $cidadao) {
$cidadao->nome = $request->nome ?? $cidadao->nome;
$cidadao->data_nascimento = $request->data_nascimento ?? $cidadao->data_nascimento;
$cidadao->sexo_id = $request->sexo_id ?? $cidadao->sexo_id;
$cidadao->nome_mae = $request->nome_mae ?? $cidadao->nome_mae;
$cidadao->nome_pai = $request->nome_pai ?? $cidadao->nome_pai;
$cidadao->cns = $request->cns ?? $cidadao->cns;
$cidadao->cpf = $request->cpf ?? $cidadao->cpf;
$cidadao->raca_cor_id = $request->raca_cor_id ?? $cidadao->raca_cor_id;
$cidadao->local_nascimento_id = $request->local_nascimento_id ?? $cidadao->local_nascimento_id;
foreach ($request->telefones as $telefone) {
$cidadao->telefones()->create([
'principal' => false,
'autoriza_sms' => false,
'numero' => $telefone,
]);
}
$cidadao->save();
});
$cidadao = $cidadao->fresh();
return [
'id' => $cidadao->id,
'nome' => $cidadao->nome,
'nome_social' => $cidadao->nome_social,
'data_nascimento' => $cidadao->data_nascimento,
'idade' => $cidadao->idade,
'idade_formatada' => $cidadao->idade_formatada,
'sexo' => [
'id' => $cidadao->sexo->id ?? null,
'descricao' => $cidadao->sexo->descricao ?? null,
],
'nome_mae' => $cidadao->nome_mae,
'nome_pai' => $cidadao->nome_pai,
'cns' => $cidadao->cns ? MaskUtil::getCnsMasked($cidadao->cns) : null,
'cpf' => $cidadao->cpf ? MaskUtil::getCpfMasked($cidadao->cpf) : null,
'raca_cor' => [
'id' => $cidadao->racaCor->id ?? null,
'descricao' => $cidadao->racaCor->descricao ?? null,
],
'local_nascimento' => [
'id' => $cidadao->localNascimento->id,
'descricao' => $cidadao->localNascimento->descricao,
],
'email' => $cidadao->email,
];
}
public static function getPath()
{
return 'integracao' . DIRECTORY_SEPARATOR . 'cns' . DIRECTORY_SEPARATOR . 'certificado-digital' . DIRECTORY_SEPARATOR . app('config')->get('database.default');
}
public static function getFile()
{
return 'CERTIFICADO-DIGITAL.PEM';
}
private static function validate($request)
{
return $request->validate([
'nome' => [
'nullable',
'string',
'between:6,150',
new CnsTermoValido(['attribute' => 'Nome']),
new NomeCompleto,
],
'nome_social' => [
'nullable',
'string',
'between:3,150',
new CnsTermoValido(['attribute' => 'Nome social']),
],
'cns' => [
'nullable',
'digits:15',
new Cns,
],
'cpf' => [
'nullable',
'digits:11',
new Cpf,
],
'data_nascimento' => [
'nullable',
'date_format:Y-m-d',
'before_or_equal:now',
],
'sexo_id' => [
'nullable',
'integer',
],
'nome_mae' => [
'nullable',
'string',
'between:8,150',
new CnsTermoValido(['attribute' => 'Nome da mãe']),
new NomeCompleto,
],
'nome_pai' => [
'nullable',
'between:8,150',
new CnsTermoValido(['attribute' => 'Nome do pai']),
new NomeCompleto,
],
'raca_cor_id' => [
'nullable',
'integer',
],
'local_nascimento_id' => [
'nullable',
'integer',
],
'telefones' => [
'array',
'nullable',
],
'telefones.*.numero' => [
'nullable',
'digits_between:10,11',
],
]);
}
private static function getFormattedCidadaoData($xml)
{
$cliente = self::getCliente();
$response = [];
$body = $xml->xpath('//env:Body')[0];
$prpa = $body->PRPA_IN201306UV02;
$patient = $prpa->controlActProcess->subject->registrationEvent->subject1->patient ?? null;
if (!is_null($patient)) {
$patientName = $patient->patientPerson->name;
$patientBirthTime = (string) $patient->patientPerson->birthTime['value'];
$patientAdministrativeGenderCode = (string) $patient->patientPerson->administrativeGenderCode['code'];
$patientPersonalRelationship = $patient->patientPerson->personalRelationship;
$patientAsOtherIDs = $patient->patientPerson->asOtherIDs;
$patientRaceCode = (string) $patient->patientPerson->raceCode['code'];
$patientBirthPlace = (string) $patient->patientPerson->birthPlace->addr->city;
$patientTelecom = $patient->patientPerson->telecom;
$patientCity = $patient->patientPerson->addr->city;
$patientPostalCode = $patient->patientPerson->addr->postalCode;
$patientCountry = $patient->patientPerson->addr->country;
$patientHouseNumber = $patient->patientPerson->addr->houseNumber;
$patientStreetName = $patient->patientPerson->addr->streetName;
$patientStreetNameType = $patient->patientPerson->addr->streetNameType;
$patientAdditionalLocator = $patient->patientPerson->addr->additionalLocator;
$nome = null;
$nomeSocial = null;
$dataNascimento = null;
$sexo = null;
$nomeMae = null;
$nomePai = null;
$cnsDefinitivo = null;
$cnsProvisorio = null;
$cpf = null;
$racaCor = null;
$localNascimento = null;
$telefones = [];
$email = null;
$ibge = null;
$municipio = null;
$cep = null;
$paisCodigo = null;
$pais = null;
$numero = null;
$logradouro = null;
$logradouroTipo = null;
$bairro = null;
foreach ($patientName as $name) {
if ((string) $name['use'] === 'L') {
$nome = (string) $name->given;
}
else if ((string) $name['use'] === 'ASGN') {
$nomeSocial = (string) $name->given;
}
}
$ibge = $patientCity;
$cep = $patientPostalCode;
$paisCodigo = $patientCountry;
$numero = $patientHouseNumber;
$logradouro = $patientStreetName;
$bairro = $patientAdditionalLocator;
$municipio = $ibge ? Municipio::where('ibge', 'like', Str::substr($ibge, 0, 6) . '%')->first() : null;
$pais = $paisCodigo ? Pais::where('codigo', $paisCodigo)->first() : null;
$logradouroTipo = $patientStreetNameType ? LogradouroTipo::where('codigo', $patientStreetNameType)->first() : null;
$dataNascimento = Carbon::createFromFormat('Ymd', Str::substr($patientBirthTime, 0, 8))->format('Y-m-d');
if ($patientAdministrativeGenderCode === 'M') {
$sexo = Sexo::find(SujeitoAtencaoSexo::MASCULINO);
}
else if ($patientAdministrativeGenderCode === 'F') {
$sexo = Sexo::find(SujeitoAtencaoSexo::FEMININO);
}
foreach ($patientPersonalRelationship as $personalRelationship) {
if ((string) $personalRelationship->code['code'] === 'PRN') {
$nomeMae = (string) $personalRelationship->relationshipHolder1->name->given;
}
else if ((string) $personalRelationship->code['code'] === 'NPRN') {
$nomePai = (string) $personalRelationship->relationshipHolder1->name->given;
}
}
foreach ($patientAsOtherIDs as $asOtherIDs) {
if ((string) $asOtherIDs->id[0]['root'] === '2.16.840.1.113883.13.236') {
if( (string) $asOtherIDs->id[1]['root'] === '2.16.840.1.113883.13.236.1' && (string) $asOtherIDs->id[1]['extension'] === 'D'){
$cnsDefinitivo = (string) $asOtherIDs->id[0]['extension'];
}elseif((string) $asOtherIDs->id[1]['root'] === '2.16.840.1.113883.13.236.1' && (string) $asOtherIDs->id[1]['extension'] === 'P'){
$cnsProvisorio = (string) $asOtherIDs->id[0]['extension'];
}
}
elseif ((string) $asOtherIDs->id['root'] === '2.16.840.1.113883.13.237') {
$cpf = (string) $asOtherIDs->id['extension'];
}
}
if ($patientRaceCode === '01') {
$racaCor = RacaCor::find(SujeitoAtencaoRacaCor::BRANCA);
}
else if ($patientRaceCode === '02') {
$racaCor = RacaCor::find(SujeitoAtencaoRacaCor::NEGRA);
}
else if ($patientRaceCode === '03') {
$racaCor = RacaCor::find(SujeitoAtencaoRacaCor::PARDA);
}
else if ($patientRaceCode === '04') {
$racaCor = RacaCor::find(SujeitoAtencaoRacaCor::AMARELA);
}
else if ($patientRaceCode === '05') {
$racaCor = RacaCor::find(SujeitoAtencaoRacaCor::INDIGENA);
}
else if ($patientRaceCode === '99') {
$racaCor = RacaCor::find(SujeitoAtencaoRacaCor::SEM_INFORMACAO);
}
if (Str::contains($cliente->municipio->ibge ?? null, $patientBirthPlace)) {
$localNascimento = LocalNascimento::find(SujeitoAtencaoLocalNascimento::NESTE_MUNICIPIO);
} else {
$localNascimento = LocalNascimento::find(SujeitoAtencaoLocalNascimento::EM_OUTRO_MUNICIPIO);
}
foreach ($patientTelecom as $telecom) {
if ((string) $telecom['use'] === 'ASN') {
$telefones[] = Str::substr(Str::replace(['+', '-', ' '], '', (string) $telecom['value']), 2);
}
else if ((string) $telecom['use'] === 'NET') {
$email = (string) $telecom['value'];
}
}
$response[] = [
'nome' => $nome,
'nome_social' => $nomeSocial,
'data_nascimento' => $dataNascimento,
'sexo' => [
'id' => $sexo->id ?? null,
'descricao' => $sexo->descricao ?? null,
],
'nome_mae' => $nomeMae,
'nome_pai' => $nomePai,
'cns' => $cnsDefinitivo ?? $cnsProvisorio,
'cpf' => $cpf,
'raca_cor' => [
'id' => $racaCor->id ?? null,
'descricao' => $racaCor->descricao ?? null,
],
'local_nascimento' => [
'id' => $localNascimento->id,
'descricao' => $localNascimento->descricao,
],
'telefones' => $telefones,
'email' => $email,
'municipio' => $municipio->nome ?? null,
'pais' => $pais->nome ?? null,
'numero' => $numero ?? null,
'logradouro' => $logradouro ?? null,
'logradouro_tipo' => $logradouroTipo ?? null,
'bairro' => $bairro ?? null,
'cep' => $cep ? MaskUtil::getCepMasked($cep) : null,
];
}
return $response;
}
private static function getCliente()
{
return Cliente::where('link', app('config')->get('database.default'))->first();
}
}