41 lines
2.9 KiB
PHP
41 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\Http;
|
|
use LogicException;
|
|
|
|
/** Prepared gateway only; no event listener, route, scheduled job or automatic transmission. */
|
|
final class SgfInvoiceGateway
|
|
{
|
|
public function clientFor(User $actor,string $connection): \Tempo\SgcInvoiceClient\InvoiceClient
|
|
{
|
|
if(config('sgf_invoice.enabled')!==true)throw new LogicException('SGF invoice gateway disabled.');
|
|
$all=config('sgf_invoice.connections',[]);$c=$all[$connection]??null;
|
|
abort_unless(is_array($c)&&($c['enabled']??false)===true&&auth()->id()===$actor->id,403);
|
|
$current=User::where('tenant_id',$actor->tenant_id)->findOrFail($actor->id);
|
|
abort_unless(($c['source_scope']['tenant_id']??null)===$current->tenant_id&&$current->hasFunctions(['finance'])
|
|
&&!app(OrganizationAccess::class)->maintenanceOnly($current),403);
|
|
$path=config('sgf_invoice.client_package');$pin=config('sgf_invoice.client_package_sha256');
|
|
if(!is_string($path)||is_link($path)||!is_file($path)||!is_string($pin)||!preg_match('/^[a-f0-9]{64}$/D',$pin)
|
|
||!hash_equals($pin,hash_file('sha256',$path)))throw new LogicException('Verified client package required.');
|
|
if(class_exists(\Tempo\SgcInvoiceClient\InvoiceClient::class,false)){
|
|
if(!hash_equals($pin,hash_file('sha256',(new \ReflectionClass(\Tempo\SgcInvoiceClient\InvoiceClient::class))->getFileName())))throw new LogicException('Client version changed; restart separately.');
|
|
}else require_once $path;
|
|
$configurationHash=hash('sha256',json_encode($c,JSON_THROW_ON_ERROR));
|
|
return new \Tempo\SgcInvoiceClient\InvoiceClient($c['client_id'],$c['token'],$c['context_version'],$c['source_scope'],$c['target_scope'],
|
|
function(string $method,string $url,array $headers,?array $body)use($actor,$connection,$configurationHash):array{
|
|
// Recheck the originating person's authority immediately before every network operation.
|
|
$now=config('sgf_invoice.connections',[])[$connection]??null;
|
|
if(config('sgf_invoice.enabled')!==true||!is_array($now)||!hash_equals($configurationHash,hash('sha256',json_encode($now,JSON_THROW_ON_ERROR)))
|
|
||auth()->id()!==$actor->id)return ['status'=>403,'json'=>null];
|
|
$current=User::where('tenant_id',$actor->tenant_id)->find($actor->id);
|
|
if(!$current||!$current->hasFunctions(['finance'])||app(OrganizationAccess::class)->maintenanceOnly($current))return ['status'=>403,'json'=>null];
|
|
$http=Http::withHeaders($headers)->acceptJson()->asJson()->withoutRedirecting()->connectTimeout(3)->timeout(15);
|
|
$response=$method==='GET'?$http->get($url):$http->post($url,$body);
|
|
return ['status'=>$response->status(),'json'=>$response->json()];
|
|
},$c['origin']);
|
|
}
|
|
}
|